UINT __stdcall FillListbox(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "FillListbox"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); // TODO: Add your custom action code here. MSIHANDLE hTable = NULL; MSIHANDLE hColumns = NULL; MSIDBERROR dbErr = MSIDBERROR_NOERROR; WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 0, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 1, L"Item 1"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 1, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 2, L"Item 2"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 2, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 3, L"Item 3"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 3, hTable, hColumns, dbErr); if (hTable) MsiCloseHandle (hTable); if (hColumns) MsiCloseHandle (hColumns); LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
UINT __stdcall ZTouchFolder(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "ZTouchFolder"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); UINT rc; char folder[4096]; DWORD foldersize = sizeof(folder); rc = MsiGetProperty(hInstall, "Folder", &folder[0], &foldersize); if (rc != ERROR_SUCCESS) { WcaLog(LOGMSG_STANDARD, "Unable to get property: Folder"); return WcaFinalize(ERROR_INSTALL_FAILURE); } char path[4096]; sprintf(path, "%s\\removeme", folder); if (CreateDirectory(path, NULL) == TRUE) { WcaLog(LOGMSG_STANDARD, "Temp directory created %s", path); RemoveDirectory(path); } else { WcaLog(LOGMSG_STANDARD, "Unable to create temp directory %s", path); } LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
UINT mccPostInstall(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "MccPostInstall"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); TCHAR INSTALLDIR[1024]; DWORD INSTALLDIR_size = sizeof(INSTALLDIR); TCHAR path[MAX_PATH * 2]; TCHAR param[MAX_PATH * 2]; if(MsiGetPropertyW(hInstall, TEXT("CustomActionData"), INSTALLDIR, &INSTALLDIR_size) == ERROR_SUCCESS) { WcaLog(LOGMSG_STANDARD, "INSTALLDIR = %ls", INSTALLDIR); // C:\Program Files (x86)\MySQL\MySQL Cluster 7.2\share\mcc wcscpy_s(path, MAX_PATH * 2, INSTALLDIR); wcscat_s(path, MAX_PATH * 2, TEXT("\\share\\mcc\\Python\\python.exe")); wcscpy_s(param, MAX_PATH * 2, INSTALLDIR); wcscat_s(param, MAX_PATH * 2, TEXT("\\share\\mcc\\post-install.py")); er = RunProcess(path, param, NULL); } else { er = ERROR_CANT_ACCESS_FILE; } LExit: return WcaFinalize(er); }
UINT __stdcall SetCertificatesStatuses(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; char buf[BUF_SIZE]; bool isCertInstalled; hr = WcaInitialize(hInstall, "SetCertificatesStatuses"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); sprintf_s(buf, BUF_SIZE, "Number of certs in DLL = %i", SK_HASH_COUNT); WcaLog(LOGMSG_STANDARD, buf); for(int i = 0; i < SK_HASH_COUNT; i++) { isCertInstalled = IsCertificateInstalled(skHashes[i].skHash, skHashes[i].certStoreName); hr = WcaSetIntProperty(skHashes[i].propertyName, isCertInstalled); sprintf_s(buf, BUF_SIZE, "Certificate #%i property value is %i", i, /*skHashes[i].propertyName,*/ isCertInstalled); WcaLog(LOGMSG_STANDARD, buf); sprintf_s(buf, BUF_SIZE, "Failed to set cert #%i property value", i); ExitOnFailure(hr, buf); } LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
/* note: szKey is here in case the card has to be registered in the Calais and WOW3264node\Calais databases */ void RegisterCardWithKey(PTSTR szKey, PTSTR szCard, PTSTR szPath, PBYTE pbATR, DWORD dwATRSize, PBYTE pbAtrMask) { HKEY hKey = NULL; HKEY hTempKey = NULL; LONG lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &hKey); if (lResult != ERROR_SUCCESS) { WcaLog(LOGMSG_STANDARD, "unable to open the calais database."); return; } lResult = RegCreateKeyEx(hKey, szCard, 0,NULL,0,KEY_WRITE, NULL,&hTempKey,NULL); if(!lResult) { RegSetValueEx( hTempKey,TEXT("Crypto Provider"),0, REG_SZ, (PBYTE)BASE_CSP,sizeof(BASE_CSP) - sizeof(TCHAR)); RegSetValueEx( hTempKey,TEXT("Smart Card Key Storage Provider"),0, REG_SZ, (PBYTE)BASE_KSP,sizeof(BASE_KSP) - sizeof(TCHAR)); RegSetValueEx( hTempKey,TEXT("80000001"),0, REG_SZ, (PBYTE)szPath,(DWORD) (sizeof(TCHAR) * _tcslen(szPath))); RegSetValueEx( hTempKey,TEXT("ATR"),0, REG_BINARY, (PBYTE)pbATR, dwATRSize); RegSetValueEx( hTempKey,TEXT("ATRMask"),0, REG_BINARY, (PBYTE)pbAtrMask, dwATRSize); RegCloseKey(hTempKey); } else { WcaLog(LOGMSG_STANDARD, "unable to create the card entry"); } RegCloseKey(hKey); }
/****************************************************************** SendApplicationMessage - helper function to iterate through the processes for the specified application and send all applicable process Ids a message and give them time to process the message. ******************************************************************/ void SendApplicationMessage( __in LPCWSTR wzApplication, __in DWORD dwMessageId, __in DWORD dwTimeout ) { DWORD *prgProcessIds = NULL; DWORD cProcessIds = 0, iProcessId; HRESULT hr = S_OK; WcaLog(LOGMSG_VERBOSE, "Checking App: %ls ", wzApplication); hr = ProcFindAllIdsFromExeName(wzApplication, &prgProcessIds, &cProcessIds); if (SUCCEEDED(hr) && 0 < cProcessIds) { WcaLog(LOGMSG_VERBOSE, "App: %ls found running, %d processes, attempting to send message.", wzApplication, cProcessIds); for (iProcessId = 0; iProcessId < cProcessIds; ++iProcessId) { SendProcessMessage(prgProcessIds[iProcessId], dwMessageId, dwTimeout); } ProcWaitForIds(prgProcessIds, cProcessIds, dwTimeout); } ReleaseMem(prgProcessIds); }
static HRESULT CreatePartition( CPI_PARTITION_ATTRIBUTES* pAttrs ) { HRESULT hr = S_OK; ICatalogCollection* piPartColl = NULL; ICatalogObject* piPartObj = NULL; long lChanges = 0; // log WcaLog(LOGMSG_VERBOSE, "Creating partition, key: %S", pAttrs->pwzKey); // get partitions collection hr = CpiGetPartitionsCollection(&piPartColl); ExitOnFailure(hr, "Failed to get partitions collection"); // check if partition exists hr = CpiFindCollectionObjectByStringKey(piPartColl, pAttrs->pwzID, &piPartObj); ExitOnFailure(hr, "Failed to find partition"); if (S_FALSE == hr) { // create partition hr = CpiAddCollectionObject(piPartColl, &piPartObj); ExitOnFailure(hr, "Failed to add partition to collection"); hr = CpiPutCollectionObjectValue(piPartObj, L"ID", pAttrs->pwzID); ExitOnFailure(hr, "Failed to set partition id property"); hr = CpiPutCollectionObjectValue(piPartObj, L"Name", pAttrs->pwzName); ExitOnFailure(hr, "Failed to set partition name property"); } // properties hr = CpiPutCollectionObjectValues(piPartObj, pAttrs->pPropList); ExitOnFailure(hr, "Failed to write properties"); // save changes hr = piPartColl->SaveChanges(&lChanges); if (COMADMIN_E_OBJECTERRORS == hr) CpiLogCatalogErrorInfo(); ExitOnFailure(hr, "Failed to save changes"); // log WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); hr = S_OK; LExit: // clean up ReleaseObject(piPartColl); ReleaseObject(piPartObj); return hr; }
/* remove a card in the database if and only if the CSP match the OpenSC CSP The program try to avoid any failure to not break the uninstall process */ VOID RemoveKey(PTSTR szSubKey) { HKEY hKey = NULL; LONG lResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_READ, &hKey); if (lResult != ERROR_SUCCESS) { WcaLog(LOGMSG_STANDARD, "RegOpenKeyEx %S 0x%08X", szSubKey, lResult); return; } TCHAR szName[MAX_PATH]; DWORD dwSize = MAX_PATH; FILETIME ftWrite; lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite); if (lResult == ERROR_SUCCESS) { DWORD dwIndex = 0; do { HKEY hTempKey = NULL; dwIndex++; lResult = RegOpenKeyEx (hKey, szName, 0, KEY_READ, &hTempKey); if (lResult == ERROR_SUCCESS) { TCHAR szCSP[MAX_PATH] = {0}; dwSize = MAX_PATH; lResult = RegQueryValueEx(hTempKey, TEXT("Crypto Provider"), NULL, NULL, (PBYTE) szCSP, &dwSize); RegCloseKey(hTempKey); if (lResult == ERROR_SUCCESS) { if ( _tcsstr(szCSP, TEXT("OpenSC CSP")) != 0) { lResult = RegDeleteKey(hKey, szName); if (lResult != ERROR_SUCCESS) { WcaLog(LOGMSG_STANDARD, "RegDeleteKey %S 0x%08X", szName, lResult); } else { dwIndex--; } } } else { WcaLog(LOGMSG_STANDARD, "RegQueryValueEx %S 0x%08X", szName, lResult); } } dwSize = MAX_PATH; lResult = RegEnumKeyEx(hKey,dwIndex, szName, &dwSize, NULL, NULL, NULL, &ftWrite); } while (lResult == ERROR_SUCCESS); } RegCloseKey(hKey); }
static HRESULT CreateApplicationRole( CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs ) { HRESULT hr = S_OK; ICatalogCollection* piRolesColl = NULL; ICatalogObject* piRoleObj = NULL; long lChanges = 0; // log WcaLog(LOGMSG_VERBOSE, "Creating application role, key: %S", pAttrs->pwzKey); // get roles collection hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); if (S_FALSE == hr) hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); ExitOnFailure(hr, "Failed to get roles collection"); // check if role exists hr = CpiFindCollectionObjectByName(piRolesColl, pAttrs->pwzName, &piRoleObj); ExitOnFailure(hr, "Failed to find role"); if (S_FALSE == hr) { // create role hr = CpiAddCollectionObject(piRolesColl, &piRoleObj); ExitOnFailure(hr, "Failed to add role to collection"); hr = CpiPutCollectionObjectValue(piRoleObj, L"Name", pAttrs->pwzName); ExitOnFailure(hr, "Failed to set role name property"); } // properties hr = CpiPutCollectionObjectValues(piRoleObj, pAttrs->pPropList); ExitOnFailure(hr, "Failed to write properties"); // save changes hr = piRolesColl->SaveChanges(&lChanges); if (COMADMIN_E_OBJECTERRORS == hr) CpiLogCatalogErrorInfo(); ExitOnFailure(hr, "Failed to save changes"); // log WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); hr = S_OK; LExit: // clean up ReleaseObject(piRolesColl); ReleaseObject(piRoleObj); return hr; }
/****************************************************************** ExecNetFx - entry point for NetFx Custom Action *******************************************************************/ extern "C" UINT __stdcall ExecNetFx( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug ExecNetFx"); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzCustomActionData = NULL; LPWSTR pwzData = NULL; LPWSTR pwz = NULL; int iCost = 0; // initialize hr = WcaInitialize(hInstall, "ExecNetFx"); ExitOnFailure(hr, "failed to initialize"); hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); ExitOnFailure(hr, "failed to get CustomActionData"); WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); pwz = pwzCustomActionData; // loop through all the passed in data while (pwz && *pwz) { hr = WcaReadStringFromCaData(&pwz, &pwzData); ExitOnFailure(hr, "failed to read command line from custom action data"); hr = WcaReadIntegerFromCaData(&pwz, &iCost); ExitOnFailure(hr, "failed to read cost from custom action data"); hr = QuietExec(pwzData, NGEN_TIMEOUT); // If we fail here it isn't critical - keep looping through to try to act on the other assemblies on our list if (FAILED(hr)) { WcaLog(LOGMSG_STANDARD, "failed to execute Ngen command (with error 0x%x): %ls, continuing anyway", hr, pwzData); hr = S_OK; } // Tick the progress bar along for this assembly hr = WcaProgressMessage(iCost, FALSE); ExitOnFailure1(hr, "failed to tick progress bar for command line: %ls", pwzData); } LExit: ReleaseStr(pwzCustomActionData); ReleaseStr(pwzData); if (FAILED(hr)) er = ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
/* Check for if directory is empty during install, sets "<PROPERTY>_NOT_EMPTY" otherise */ extern "C" UINT __stdcall CheckDirectoryEmpty(MSIHANDLE hInstall, const wchar_t *PropertyName) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, __FUNCTION__); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); wchar_t buf[MAX_PATH]; DWORD len = MAX_PATH; MsiGetPropertyW(hInstall, PropertyName, buf, &len); wcscat_s(buf, MAX_PATH, L"*.*"); WcaLog(LOGMSG_STANDARD, "Checking files in %S", buf); WIN32_FIND_DATAW data; HANDLE h; bool empty; h= FindFirstFile(buf, &data); if (h != INVALID_HANDLE_VALUE) { empty= true; for(;;) { if (wcscmp(data.cFileName, L".") || wcscmp(data.cFileName, L"..")) { empty= false; break; } if (!FindNextFile(h, &data)) break; } FindClose(h); } else { /* Non-existent directory, we handle it as empty */ empty = true; } if(empty) WcaLog(LOGMSG_STANDARD, "Directory %S is empty or non-existent", PropertyName); else WcaLog(LOGMSG_STANDARD, "Directory %S is NOT empty", PropertyName); wcscpy_s(buf, MAX_PATH, PropertyName); wcscat_s(buf, L"NOTEMPTY"); WcaSetProperty(buf, empty? L"":L"1"); LExit: return WcaFinalize(er); }
/* Sets Innodb buffer pool size (1/8 of RAM by default), if not already specified via command line. Calculates innodb log file size as min(50, innodb buffer pool size/8) */ extern "C" UINT __stdcall PresetDatabaseProperties(MSIHANDLE hInstall) { unsigned long long InnodbBufferPoolSize= 256; unsigned long long InnodbLogFileSize= 50; wchar_t buff[MAX_PATH]; UINT er = ERROR_SUCCESS; HRESULT hr= S_OK; MEMORYSTATUSEX memstatus; hr = WcaInitialize(hInstall, __FUNCTION__); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); /* Check if bufferpoolsize parameter was given on the command line*/ DWORD BufferPoolsizeParamLen = MAX_PATH; MsiGetPropertyW(hInstall, L"BUFFERPOOLSIZE", buff, &BufferPoolsizeParamLen); if (BufferPoolsizeParamLen && buff[0]) { WcaLog(LOGMSG_STANDARD, "BUFFERPOOLSIZE=%s, len=%u",buff, BufferPoolsizeParamLen); InnodbBufferPoolSize= _wtoi64(buff); } else { memstatus.dwLength = sizeof(memstatus); if (!GlobalMemoryStatusEx(&memstatus)) { WcaLog(LOGMSG_STANDARD, "Error %u from GlobalMemoryStatusEx", GetLastError()); er= ERROR_INSTALL_FAILURE; goto LExit; } unsigned long long totalPhys= memstatus.ullTotalPhys; /* Give innodb 12.5% of available physical memory. */ InnodbBufferPoolSize= totalPhys/ONE_MB/8; #ifdef _M_IX86 /* For 32 bit processes, take virtual address space limitation into account. Do not try to use more than 3/4 of virtual address space, even if there is plenty of physical memory. */ InnodbBufferPoolSize= min(GetMaxBufferSize(totalPhys)/ONE_MB*3/4, InnodbBufferPoolSize); #endif swprintf_s(buff, L"%llu",InnodbBufferPoolSize); MsiSetPropertyW(hInstall, L"BUFFERPOOLSIZE", buff); } InnodbLogFileSize = min(50, InnodbBufferPoolSize); swprintf_s(buff, L"%llu",InnodbLogFileSize); MsiSetPropertyW(hInstall, L"LOGFILESIZE", buff); LExit: return WcaFinalize(er); }
static HRESULT RemoveApplicationRole( CPI_APPLICATION_ROLE_ATTRIBUTES* pAttrs ) { HRESULT hr = S_OK; ICatalogCollection* piRolesColl = NULL; long lChanges = 0; // log WcaLog(LOGMSG_VERBOSE, "Removing application role, key: %S", pAttrs->pwzKey); // get roles collection hr = CpiGetRolesCollection(pAttrs->pwzPartID, pAttrs->pwzAppID, &piRolesColl); ExitOnFailure(hr, "Failed to get roles collection"); if (S_FALSE == hr) { // roles collection not found WcaLog(LOGMSG_VERBOSE, "Unable to retrieve roles collection, nothing to delete, key: %S", pAttrs->pwzKey); ExitFunction1(hr = S_OK); } // remove hr = CpiRemoveCollectionObject(piRolesColl, NULL, pAttrs->pwzName, FALSE); ExitOnFailure(hr, "Failed to remove role"); if (S_FALSE == hr) { // role not found WcaLog(LOGMSG_VERBOSE, "Role not found, nothing to delete, key: %S", pAttrs->pwzKey); ExitFunction1(hr = S_OK); } // save changes hr = piRolesColl->SaveChanges(&lChanges); if (COMADMIN_E_OBJECTERRORS == hr) CpiLogCatalogErrorInfo(); ExitOnFailure(hr, "Failed to save changes"); // log WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); hr = S_OK; LExit: // clean up ReleaseObject(piRolesColl); return hr; }
static int FindAndReplace(const char *file, int num, char* tokens[], char* values[]) { char line[512]; char *tmpfile = new char[strlen(file) + 5]; FILE *fi, *fo; int i; fi = fopen(file, "r"); if (!fi) { WcaLog(LOGMSG_STANDARD, "Unable to open file %s", file); return 1; } sprintf(tmpfile, "%s.tmp", file); fo = fopen(tmpfile, "w"); if (!fo) { WcaLog(LOGMSG_STANDARD, "Unable to open file %s", tmpfile); fclose(fi); return 1; } while(fgets(line, 512, fi) != NULL) { char *out = line; char buf[1024]; char *tok; buf[0] = '\0'; for (i = 0; i < num; ++i) { tok = strstr(line, tokens[i]); if (tok) { WcaLog(LOGMSG_VERBOSE, "Token replacement: token=%s, value=%s, file=%s", tokens[i], values[i], file); strncat(buf, line, tok - line); strcat(buf, values[i]); strcat(buf, tok + strlen(tokens[i])); out = buf; break; } } fprintf(fo, "%s", out); } fclose(fi); fclose(fo); unlink(file); rename(tmpfile, file); return 0; }
// Gets the path to ngen.exe static HRESULT GetNgenPath( __out LPWSTR* ppwzNgenPath, __in BOOL f64BitFramework ) { Assert(ppwzNgenPath); HRESULT hr = S_OK; LPWSTR pwzVersion = NULL; LPWSTR pwzWindowsFolder = NULL; hr = WcaGetProperty(L"WindowsFolder", &pwzWindowsFolder); ExitOnFailure(hr, "failed to get WindowsFolder property"); hr = StrAllocString(ppwzNgenPath, pwzWindowsFolder, 0); ExitOnFailure1(hr, "failed to copy to NgenPath windows folder: %ls", pwzWindowsFolder); if (f64BitFramework) { WcaLog(LOGMSG_VERBOSE, "Searching for ngen under 64-bit framework path"); hr = StrAllocConcat(ppwzNgenPath, L"Microsoft.NET\\Framework64\\", 0); ExitOnFailure(hr, "failed to copy platform portion of ngen path"); } else { WcaLog(LOGMSG_VERBOSE, "Searching for ngen under 32-bit framework path"); hr = StrAllocConcat(ppwzNgenPath, L"Microsoft.NET\\Framework\\", 0); ExitOnFailure(hr, "failed to copy platform portion of ngen path"); } // We want to run the highest version of ngen possible, because they should be backwards compatible - so let's find the most appropriate directory now hr = GetNgenVersion(*ppwzNgenPath, &pwzVersion); ExitOnFailure1(hr, "failed to search for ngen under path %ls", *ppwzNgenPath); hr = StrAllocConcat(ppwzNgenPath, pwzVersion, 0); ExitOnFailure(hr, "failed to copy version portion of ngen path"); hr = StrAllocConcat(ppwzNgenPath, L"\\ngen.exe", 0); ExitOnFailure(hr, "failed to copy \"\\ngen.exe\" portion of ngen path"); LExit: ReleaseStr(pwzVersion); ReleaseStr(pwzWindowsFolder); return hr; }
HRESULT MqiRollbackRemoveMessageQueuePermissions( LPWSTR* ppwzData ) { HRESULT hr = S_OK; int iCnt = 0; MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs; ::ZeroMemory(&attrs, sizeof(attrs)); // ger count hr = WcaReadIntegerFromCaData(ppwzData, &iCnt); ExitOnFailure(hr, "Failed to read count"); for (int i = 0; i < iCnt; i++) { // read attributes from CustomActionData hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs); ExitOnFailure(hr, "Failed to read attributes"); // add message queue permission hr = SetMessageQueuePermissions(&attrs, FALSE); if (FAILED(hr)) WcaLog(LOGMSG_STANDARD, "Failed to rollback remove message queue permission, hr: 0x%x, key: %S", hr, attrs.pwzKey); } hr = S_OK; LExit: // clean up FreeMessageQueuePermissionAttributes(&attrs); return hr; }
/******************************************************************** ScaDropSmb - delete this file share from this computer ********************************************************************/ HRESULT ScaDropSmb(SCA_SMBP* pssp) { HRESULT hr = S_OK; NET_API_STATUS s; hr = DoesShareExist(pssp->wzKey); if (E_FILENOTFOUND == hr) { WcaLog(LOGMSG_VERBOSE, "Share doesn't exist, share removal skipped. (%ls)", pssp->wzKey); ExitFunction1(hr = S_OK); } ExitOnFailure1(hr, "Unable to detect share. (%ls)", pssp->wzKey); s = ::NetShareDel(NULL, pssp->wzKey, 0); if (NERR_Success != s) { hr = E_FAIL; ExitOnFailure1(hr, "Failed to remove file share: Err: %d", s); } LExit: return hr; }
BOOL CompareBinding( __in IAppHostElement* pBinding, __in LPVOID pContext ) { BOOL fFound = FALSE; HRESULT hr = S_OK; LPWSTR pwzBindingInfo = NULL; SCA_WEB7* psw = (SCA_WEB7*)pContext; hr = Iis7GetPropertyString(pBinding, IIS_CONFIG_BINDINGINFO, &pwzBindingInfo); ExitOnFailure(hr, "Failed to get bindinginfo for binding element"); LPWSTR pwzExists = pwzBindingInfo; // Break down the address into its constituent parts (IP:Port:Header). // Taken from IIS6 CA code for compatibility while (S_OK == hr && *pwzExists) { LPCWSTR pwzIPExists = pwzExists; pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":")); if (NULL == pwzExists) { ExitFunction(); } *pwzExists = L'\0'; LPCWSTR pwzPortExists = pwzExists + 1; pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":")); if (NULL == pwzExists) { ExitFunction(); } *pwzExists = L'\0'; int iPortExists = wcstol(pwzPortExists, NULL, 10); LPCWSTR pwzHeaderExists = pwzExists + 1; BOOL fIpMatches = (0 == lstrcmpW(psw->swaBinding.wzIP, pwzIPExists)); // Explicit IP match fIpMatches |= (0 == lstrcmpW(psw->swaBinding.wzIP, L"*")); // Authored * matches any IP fIpMatches |= ('\0' != psw->swaBinding.wzIP) && // Unauthored IP (0 == lstrcmpW(pwzIPExists, L"*")); // matches the All Unassigned IP : '*' // compare the passed in address with the address listed for this web if (fIpMatches && psw->swaBinding.iPort == iPortExists && 0 == lstrcmpW(psw->swaBinding.wzHeader, pwzHeaderExists)) { fFound = TRUE; break; } // move to the next block of data, this may move beyond the available // data and exit the while loop above. pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists)); } LExit: WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not"); ReleaseNullStr(pwzBindingInfo); return fFound; }
/******************************************************************** WixCheckRebootRequired - entry point for WixCheckRebootRequired Custom Action called as Type 1 CustomAction (binary DLL) from Windows Installer in InstallExecuteSequence after InstallFinalize ********************************************************************/ extern "C" UINT __stdcall WixCheckRebootRequired( __in MSIHANDLE hInstall ) { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "WixCheckRebootRequired"); ExitOnFailure(hr, "failed to initialize"); if (WcaDidDeferredActionRequireReboot()) { WcaLog(LOGMSG_STANDARD, "Reboot required by deferred CustomAction."); er = ::MsiSetMode(hInstall, MSIRUNMODE_REBOOTATEND, TRUE); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "Failed to schedule reboot."); } LExit: if (FAILED(hr)) er = ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
extern "C" UINT __stdcall WixShellExec( __in MSIHANDLE hInstall ) { Assert(hInstall); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzTarget = NULL; hr = WcaInitialize(hInstall, "WixShellExec"); ExitOnFailure(hr, "failed to initialize"); hr = WcaGetFormattedProperty(L"WixShellExecTarget", &pwzTarget); ExitOnFailure(hr, "failed to get WixShellExecTarget"); WcaLog(LOGMSG_VERBOSE, "WixShellExecTarget is %ls", pwzTarget); if (!pwzTarget || !*pwzTarget) { hr = E_INVALIDARG; ExitOnFailure(hr, "failed to get WixShellExecTarget"); } hr = ShellExec(pwzTarget); ExitOnFailure(hr, "failed to launch target"); LExit: ReleaseStr(pwzTarget); if (FAILED(hr)) { er = ERROR_INSTALL_FAILURE; } return WcaFinalize(er); }
/******************************************************************** ConfigureSmb - CUSTOM ACTION ENTRY POINT for installing fileshare settings ********************************************************************/ extern "C" UINT __stdcall ConfigureSmbUninstall( __in MSIHANDLE hInstall ) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; SCA_SMB* pssList = NULL; // initialize hr = WcaInitialize(hInstall, "ConfigureSmbUninstall"); ExitOnFailure(hr, "Failed to initialize"); // check to see if necessary tables are specified if (WcaTableExists(L"FileShare") != S_OK) { WcaLog(LOGMSG_VERBOSE, "Skipping SMB CustomAction, no FileShare table"); ExitFunction1(hr = S_FALSE); } hr = ScaSmbRead(&pssList); ExitOnFailure(hr, "failed to read FileShare table"); hr = ScaSmbUninstall(pssList); ExitOnFailure(hr, "failed to uninstall FileShares"); LExit: if (pssList) ScaSmbFreeList(pssList); er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
static HRESULT AddApplicationException( __in BOOL fSupportProfiles, __in LPCWSTR wzFile, __in LPCWSTR wzName, __in int iProfile, __in_opt LPCWSTR wzRemoteAddresses, __in BOOL fIgnoreFailures, __in LPCWSTR wzPort, __in int iProtocol, __in LPCWSTR wzDescription ) { HRESULT hr = S_OK; if (fSupportProfiles) { hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription); } else { if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) { // NOTE: This is treated as an error rather than either creating a rule based on just the application (no port), or // just the port because it is unclear what is the proper fall back. For example, suppose that you have code that // runs in dllhost.exe. Clearly falling back to opening all of dllhost is wrong. Because the firewall is a security // feature, it seems better to require the MSI author to indicate the behavior that they want. WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot add firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName); return fIgnoreFailures ? S_OK : E_NOTIMPL; } hr = AddApplicationExceptionOnCurrentProfile(wzFile, wzName, wzRemoteAddresses, fIgnoreFailures); } return hr; }
static HRESULT RemoveApplicationException( __in BOOL fSupportProfiles, __in LPCWSTR wzName, __in LPCWSTR wzFile, __in BOOL fIgnoreFailures, __in LPCWSTR wzPort, __in int iProtocol ) { HRESULT hr = S_OK; if (fSupportProfiles) { hr = RemoveException(wzName, fIgnoreFailures); } else { if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) { WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot remove firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName); return S_OK; } hr = RemoveApplicationExceptionFromCurrentProfile(wzFile, fIgnoreFailures); } return hr; }
/******************************************************************** ComPlusCleanup - CUSTOM ACTION ENTRY POINT Input: deferred CustomActionData - ComPlusCleanup ********************************************************************/ extern "C" UINT __stdcall ComPlusCleanup(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzData = NULL; // initialize hr = WcaInitialize(hInstall, "ComPlusCleanup"); ExitOnFailure(hr, "Failed to initialize ComPlusCleanup"); // get custom action data hr = WcaGetProperty(L"CustomActionData", &pwzData); ExitOnFailure(hr, "Failed to get CustomActionData"); // delete rollback file if (!::DeleteFileW(pwzData)) { // error, but not a showstopper hr = HRESULT_FROM_WIN32(::GetLastError()); WcaLog(LOGMSG_STANDARD, "Failed to delete rollback file, hr: 0x%x, name: %S", hr, pwzData); } hr = S_OK; LExit: // clean up ReleaseStr(pwzData); er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
/******************************************************************** WcaDisplayAssert() - called before Assert() dialog shows NOTE: writes the assert string to the MSI log ********************************************************************/ extern "C" BOOL WIXAPI WcaDisplayAssert( __in LPCSTR sz ) { WcaLog(LOGMSG_STANDARD, "Debug Assert Message: %s", sz); return TRUE; }
UINT __stdcall ZShutdown(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "ZShutdown"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); const char *subkey = "Software\\Zimbra\\Zimbra Desktop"; HKEY hKey; char data_root[512]; char *zdctl_path = NULL; DWORD sz = sizeof(data_root); if (RegOpenKeyEx(HKEY_CURRENT_USER, subkey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) { if (RegQueryValueEx(hKey, "DataRoot", NULL, NULL, (LPBYTE)data_root, &sz) == ERROR_SUCCESS) { zdctl_path = new char[sz + 32]; sprintf(zdctl_path, "%s\\bin\\zdctl-wrapper.vbs", data_root); } RegCloseKey(hKey); } if (zdctl_path) { char sysdir[256]; GetSystemDirectory(sysdir, sizeof(sysdir)); char cmdline[2048]; sprintf(cmdline, "\"%s\\wscript.exe\" //B \"%s\" shutdown", sysdir, zdctl_path); PROCESS_INFORMATION pi; STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb= sizeof(si); if(CreateProcess(NULL, cmdline, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) { WcaLog(LOGMSG_STANDARD, "Command run successfully: %s", cmdline); } else { WcaLog(LOGMSG_STANDARD, "Failed to run command: %s", cmdline); } } LExit: if (zdctl_path) delete [] zdctl_path; er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
UINT __stdcall RemoveCertificates(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "RemoveCertificates"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); traverseStore(L"CA"); WcaLog(LOGMSG_STANDARD, "Finished cleaning up certificate store."); LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
/****************************************************************** EnumWindowsProc - callback function which sends message if the current window matches the passed in process ID ******************************************************************/ BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) { PROCESS_AND_MESSAGE* pPM = reinterpret_cast<PROCESS_AND_MESSAGE*>(lParam); DWORD dwProcessId = 0; DWORD_PTR dwResult = 0; BOOL fQueryEndSession = WM_QUERYENDSESSION == pPM->dwMessageId; BOOL fContinueWindowsInProcess = TRUE; // assume we will send message to all top-level windows in a process. ::GetWindowThreadProcessId(hwnd, &dwProcessId); // check if the process Id is the one we're looking for if (dwProcessId != pPM->dwProcessId) { return TRUE; } WcaLog(LOGMSG_VERBOSE, "Sending message to process id 0x%x", dwProcessId); if (::SendMessageTimeoutW(hwnd, pPM->dwMessageId, 0, fQueryEndSession ? ENDSESSION_CLOSEAPP : 0, SMTO_BLOCK, pPM->dwTimeout, &dwResult)) { WcaLog(LOGMSG_VERBOSE, "Result 0x%x", dwResult); if (fQueryEndSession) { // If application said it was okay to close, do that. if (dwResult) { ::SendMessageTimeoutW(hwnd, WM_ENDSESSION, TRUE, ENDSESSION_CLOSEAPP, SMTO_BLOCK, pPM->dwTimeout, &dwResult); } else // application said don't try to close it, so don't bother sending messages to any other top-level windows. { fContinueWindowsInProcess = FALSE; } } } else // log result message. { WcaLog(LOGMSG_VERBOSE, "Failed to send message id: %u, error: 0x%x", pPM->dwMessageId, ::GetLastError()); } // so we know we succeeded ::SetLastError(ERROR_SUCCESS); return fContinueWindowsInProcess; }
static HRESULT RemovePartition( CPI_PARTITION_ATTRIBUTES* pAttrs ) { HRESULT hr = S_OK; ICatalogCollection* piPartColl = NULL; long lChanges = 0; // log WcaLog(LOGMSG_VERBOSE, "Removing partition, key: %S", pAttrs->pwzKey); // get partitions collection hr = CpiGetPartitionsCollection(&piPartColl); ExitOnFailure(hr, "Failed to get partitions collection"); // remove hr = CpiRemoveCollectionObject(piPartColl, pAttrs->pwzID, NULL, TRUE); ExitOnFailure(hr, "Failed to remove partition"); if (S_FALSE == hr) { // partition not found WcaLog(LOGMSG_VERBOSE, "Partition not found, nothing to delete, key: %S", pAttrs->pwzKey); ExitFunction1(hr = S_OK); } // save changes hr = piPartColl->SaveChanges(&lChanges); if (COMADMIN_E_OBJECTERRORS == hr) CpiLogCatalogErrorInfo(); ExitOnFailure(hr, "Failed to save changes"); // log WcaLog(LOGMSG_VERBOSE, "%d changes saved to catalog, key: %S", lChanges, pAttrs->pwzKey); hr = S_OK; LExit: // clean up ReleaseObject(piPartColl); return hr; }
extern "C" UINT __stdcall RemoveDataDirectory(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, __FUNCTION__); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); wchar_t dir[MAX_PATH]; DWORD len = MAX_PATH; MsiGetPropertyW(hInstall, L"CustomActionData", dir, &len); er= ExecRemoveDataDirectory(dir); WcaLog(LOGMSG_STANDARD, "SHFileOperation returned %d", er); LExit: return WcaFinalize(er); }