static HRESULT AddPartitionToActionData( CPI_PARTITION* pItm, int iActionType, int iActionCost, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add action information to custom action data hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); ExitOnFailure(hr, "Failed to add action type to custom action data"); hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); ExitOnFailure(hr, "Failed to add action cost to custom action data"); // add partition information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add partition key to custom action data"); hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); ExitOnFailure(hr, "Failed to add partition id to custom action data"); hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); ExitOnFailure(hr, "Failed to add partition name to custom action data"); // add properties to custom action data hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); ExitOnFailure(hr, "Failed to add properties to custom action data"); hr = S_OK; LExit: return hr; }
static HRESULT AddPartitionUserToActionData( CPI_PARTITION_USER* pItm, int iActionType, int iActionCost, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add action information to custom action data hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); ExitOnFailure(hr, "Failed to add action type to custom action data"); hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); ExitOnFailure(hr, "Failed to add action cost to custom action data"); // add partition user information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add partition user key to custom action data"); hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); ExitOnFailure(hr, "Failed to add user account to custom action data"); // add partition information to custom action data hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->pPartition->wzID : L"", ppwzActionData); ExitOnFailure(hr, "Failed to add partition id to custom action data"); hr = S_OK; LExit: return hr; }
static HRESULT AddMessageQueueToActionData( MQI_MESSAGE_QUEUE* pItm, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add message queue information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add key to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iBasePriority, ppwzActionData); ExitOnFailure(hr, "Failed to add base priority to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iJournalQuota, ppwzActionData); ExitOnFailure(hr, "Failed to add journal quota to custom action data"); hr = WcaWriteStringToCaData(pItm->wzLabel, ppwzActionData); ExitOnFailure(hr, "Failed to add label to custom action data"); hr = WcaWriteStringToCaData(pItm->wzMulticastAddress, ppwzActionData); ExitOnFailure(hr, "Failed to add multicast address to custom action data"); hr = WcaWriteStringToCaData(pItm->wzPathName, ppwzActionData); ExitOnFailure(hr, "Failed to add path name to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iPrivLevel, ppwzActionData); ExitOnFailure(hr, "Failed to add privacy level to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iQuota, ppwzActionData); ExitOnFailure(hr, "Failed to add quota to custom action data"); hr = WcaWriteStringToCaData(pItm->wzServiceTypeGuid, ppwzActionData); ExitOnFailure(hr, "Failed to add service type guid to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData); ExitOnFailure(hr, "Failed to add attributes to custom action data"); hr = S_OK; LExit: return hr; }
static HRESULT AddUserInPartitionRoleToActionData( CPI_USER_IN_PARTITION_ROLE* pItm, int iActionType, int iActionCost, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add action information to custom action data hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); ExitOnFailure(hr, "Failed to add action type to custom action data"); hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); ExitOnFailure(hr, "Failed to add action cost to custom action data"); // add application role information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add key to custom action data"); hr = WcaWriteStringToCaData(pItm->pPartitionRole->wzName, ppwzActionData); ExitOnFailure(hr, "Failed to add role name to custom action data"); hr = WcaWriteStringToCaData(pItm->pwzAccount, ppwzActionData); ExitOnFailure(hr, "Failed to add user account to custom action data"); // add partition information to custom action data hr = WcaWriteStringToCaData(pItm->pPartitionRole->pPartition->wzID, ppwzActionData); ExitOnFailure(hr, "Failed to add partition id to custom action data"); hr = S_OK; LExit: return hr; }
static HRESULT BeginChangeFile( __in LPCWSTR pwzFile, __in int iCompAttributes, __inout LPWSTR* ppwzCustomActionData ) { Assert(pwzFile && *pwzFile && ppwzCustomActionData); HRESULT hr = S_OK; BOOL fIs64Bit = iCompAttributes & msidbComponentAttributes64bit; LPBYTE pbData = NULL; DWORD cbData = 0; LPWSTR pwzRollbackCustomActionData = NULL; if (fIs64Bit) { hr = WcaWriteIntegerToCaData((int)xaOpenFilex64, ppwzCustomActionData); ExitOnFailure(hr, "failed to write 64-bit file indicator to custom action data"); } else { hr = WcaWriteIntegerToCaData((int)xaOpenFile, ppwzCustomActionData); ExitOnFailure(hr, "failed to write file indicator to custom action data"); } hr = WcaWriteStringToCaData(pwzFile, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write file to custom action data: %ls", pwzFile); // If the file already exits, then we have to put it back the way it was on failure if (FileExistsEx(pwzFile, NULL)) { hr = FileRead(&pbData, &cbData, pwzFile); ExitOnFailure1(hr, "failed to read file: %ls", pwzFile); // Set up the rollback for this file hr = WcaWriteIntegerToCaData((int)fIs64Bit, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to write component bitness to rollback custom action data"); hr = WcaWriteStringToCaData(pwzFile, &pwzRollbackCustomActionData); ExitOnFailure1(hr, "failed to write file name to rollback custom action data: %ls", pwzFile); hr = WcaWriteStreamToCaData(pbData, cbData, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to write file contents to rollback custom action data."); hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"ExecXmlConfigRollback"), pwzRollbackCustomActionData, COST_XMLFILE); ExitOnFailure1(hr, "failed to schedule ExecXmlConfigRollback for file: %ls", pwzFile); ReleaseStr(pwzRollbackCustomActionData); } LExit: ReleaseMem(pbData); return hr; }
static HRESULT WriteChangeData( __in XML_CONFIG_CHANGE* pxfc, __in eXmlAction action, __inout LPWSTR* ppwzCustomActionData ) { Assert(pxfc && ppwzCustomActionData); HRESULT hr = S_OK; XML_CONFIG_CHANGE* pxfcAdditionalChanges = NULL; hr = WcaWriteStringToCaData(pxfc->pwzElementPath, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write ElementPath to custom action data: %ls", pxfc->pwzElementPath); hr = WcaWriteStringToCaData(pxfc->pwzVerifyPath, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write VerifyPath to custom action data: %ls", pxfc->pwzVerifyPath); hr = WcaWriteStringToCaData(pxfc->wzName, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); hr = WcaWriteStringToCaData(pxfc->pwzValue, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); if (pxfc->iXmlFlags & XMLCONFIG_CREATE && pxfc->iXmlFlags & XMLCONFIG_ELEMENT && xaCreateElement == action && pxfc->pxfcAdditionalChanges) { hr = WcaWriteIntegerToCaData(pxfc->cAdditionalChanges, ppwzCustomActionData); ExitOnFailure(hr, "failed to write additional changes value to custom action data"); pxfcAdditionalChanges = pxfc->pxfcAdditionalChanges; while (pxfcAdditionalChanges) { Assert((0 == lstrcmpW(pxfcAdditionalChanges->wzComponent, pxfc->wzComponent)) && 0 == pxfcAdditionalChanges->iXmlFlags && (0 == lstrcmpW(pxfcAdditionalChanges->wzFile, pxfc->wzFile))); hr = WcaWriteStringToCaData(pxfcAdditionalChanges->wzName, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write Name to custom action data: %ls", pxfc->wzName); hr = WcaWriteStringToCaData(pxfcAdditionalChanges->pwzValue, ppwzCustomActionData); ExitOnFailure1(hr, "failed to write Value to custom action data: %ls", pxfc->pwzValue); pxfcAdditionalChanges = pxfcAdditionalChanges->pxfcNext; } } else { hr = WcaWriteIntegerToCaData(0, ppwzCustomActionData); ExitOnFailure(hr, "failed to write additional changes value to custom action data"); } LExit: return hr; }
static HRESULT AddSubscriptionToActionData( CPI_SUBSCRIPTION* pItm, int iActionType, int iActionCost, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add action information to custom action data hr = WcaWriteIntegerToCaData(iActionType, ppwzActionData); ExitOnFailure(hr, "Failed to add action type to custom action data"); hr = WcaWriteIntegerToCaData(iActionCost, ppwzActionData); ExitOnFailure(hr, "Failed to add action cost to custom action data"); // add application role information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add subscription key to custom action data"); hr = WcaWriteStringToCaData(pItm->wzID, ppwzActionData); ExitOnFailure(hr, "Failed to add subscription id to custom action data"); hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); ExitOnFailure(hr, "Failed to add subscription name to custom action data"); hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzEventCLSID : L"", ppwzActionData); ExitOnFailure(hr, "Failed to add assembly tlb path to custom action data"); hr = WcaWriteStringToCaData(atCreate == iActionType ? pItm->wzPublisherID : L"", ppwzActionData); ExitOnFailure(hr, "Failed to add assembly proxy-stub dll path to custom action data"); // add component information to custom action data hr = WcaWriteStringToCaData(pItm->pComponent->wzCLSID, ppwzActionData); ExitOnFailure(hr, "Failed to add application id to custom action data"); // add application information to custom action data hr = WcaWriteStringToCaData(pItm->pAssembly->pApplication->wzID, ppwzActionData); ExitOnFailure(hr, "Failed to add application id to custom action data"); // add partition information to custom action data LPCWSTR pwzPartID = pItm->pAssembly->pApplication->pPartition ? pItm->pAssembly->pApplication->pPartition->wzID : L""; hr = WcaWriteStringToCaData(pwzPartID, ppwzActionData); ExitOnFailure(hr, "Failed to add partition id to custom action data"); // add properties to custom action data hr = CpiAddPropertiesToActionData(atCreate == iActionType ? pItm->iPropertyCount : 0, pItm->pProperties, ppwzActionData); ExitOnFailure(hr, "Failed to add properties to custom action data"); hr = S_OK; LExit: return hr; }
HRESULT MqiMessageQueueUninstall( MQI_MESSAGE_QUEUE_LIST* pList, BOOL fRollback, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add count to action data hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); for (MQI_MESSAGE_QUEUE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // queues that are being uninstalled only if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) continue; // if we did not create the queue we should not try to delete it if (pItm->fExists && fRollback) { continue; } // add message queue to action data hr = AddMessageQueueToActionData(pItm, ppwzActionData); ExitOnFailure(hr, "Failed to add message queue to action data"); } hr = S_OK; LExit: return hr; }
HRESULT MqiMessageQueuePermissionUninstall( MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add count to action data hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); for (MQI_MESSAGE_QUEUE_PERMISSION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // queue permissions that are being uninstalled only if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) continue; // add message queue permission to action data hr = AddMessageQueuePermissionToActionData(pItm, ppwzActionData); ExitOnFailure(hr, "Failed to add message queue permission to action data"); } hr = S_OK; LExit: return hr; }
HRESULT CpiAddPropertiesToActionData( int iPropCount, CPI_PROPERTY* pPropList, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; hr = WcaWriteIntegerToCaData(iPropCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); if (iPropCount) // count might be 0 event thought there are elements in the list { for (CPI_PROPERTY* pProp = pPropList; pProp; pProp = pProp->pNext) { hr = WcaWriteStringToCaData(pProp->wzName, ppwzActionData); ExitOnFailure(hr, "Failed to add property name to custom action data, name: %S", pProp->wzName); hr = WcaWriteStringToCaData(pProp->pwzValue, ppwzActionData); ExitOnFailure(hr, "Failed to add property value to custom action data, name: %S", pProp->wzName); } } hr = S_OK; LExit: return hr; }
HRESULT CpiPartitionUsersInstall( CPI_PARTITION_USER_LIST* pList, int iRunMode, LPWSTR* ppwzActionData, int* piProgress ) { HRESULT hr = S_OK; int iActionType; // add action text hr = CpiAddActionTextToActionData(L"AddComPlusPartitionUsers", ppwzActionData); ExitOnFailure(hr, "Failed to add action text to custom action data"); // add partition count to action data hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); // add applications to custom action data for (CPI_PARTITION_USER* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // partitions that are being installed only if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction)) continue; // action type if (rmRollback == iRunMode) { if (CpiIsInstalled(pItm->isInstalled)) iActionType = atNoOp; else iActionType = atRemove; } else iActionType = atCreate; // add to action data hr = AddPartitionUserToActionData(pItm, iActionType, COST_PARTITION_USER_CREATE, ppwzActionData); ExitOnFailure(hr, "Failed to add partition user to custom action data, key: %S", pItm->wzKey); } // add progress tics if (piProgress) *piProgress += COST_PARTITION_USER_CREATE * pList->iInstallCount; hr = S_OK; LExit: return hr; }
HRESULT CpiUsersInApplicationRolesUninstall( CPI_USER_IN_APPLICATION_ROLE_LIST* pList, int iRunMode, LPWSTR* ppwzActionData, int* piProgress ) { HRESULT hr = S_OK; int iActionType; // add action text hr = CpiAddActionTextToActionData(L"RemoveUsersFromComPlusAppRoles", ppwzActionData); ExitOnFailure(hr, "Failed to add action text to custom action data"); // add count to action data hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); // add roles to custom action data for (CPI_USER_IN_APPLICATION_ROLE* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // roles that are being uninstalled only if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) continue; // action type if (rmRollback == iRunMode) iActionType = atCreate; else iActionType = atRemove; // add to action data hr = AddUserInApplicationRoleToActionData(pItm, iActionType, COST_USER_IN_APPLICATION_ROLE_DELETE, ppwzActionData); ExitOnFailure1(hr, "Failed to add user in application role to custom action data, key: %S", pItm->wzKey); } // add progress tics if (piProgress) *piProgress += COST_USER_IN_APPLICATION_ROLE_DELETE * pList->iUninstallCount; hr = S_OK; LExit: return hr; }
HRESULT CpiPartitionsUninstall( CPI_PARTITION_LIST* pList, int iRunMode, LPWSTR* ppwzActionData, int* piProgress ) { HRESULT hr = S_OK; int iActionType; // add action text hr = CpiAddActionTextToActionData(L"RemoveComPlusPartitions", ppwzActionData); ExitOnFailure(hr, "Failed to add action text to custom action data"); // add partition count to action data hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); // add partitions to custom action data for (CPI_PARTITION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // partitions that are being uninstalled only if (!pItm->fHasComponent || pItm->fObjectNotFound || !WcaIsUninstalling(pItm->isInstalled, pItm->isAction)) continue; // action type if (rmRollback == iRunMode) iActionType = atCreate; else iActionType = atRemove; // add to action data hr = AddPartitionToActionData(pItm, iActionType, COST_PARTITION_DELETE, ppwzActionData); ExitOnFailure(hr, "Failed to add partition to custom action data, key:", pItm->wzKey); } // add progress tics if (piProgress) *piProgress += COST_PARTITION_DELETE * pList->iUninstallCount; hr = S_OK; LExit: return hr; }
HRESULT SchedDropDatabase( __in LPCWSTR wzKey, __in LPCWSTR wzServer, __in LPCWSTR wzInstance, __in LPCWSTR wzDatabase, __in int iAttributes, __in BOOL fIntegratedAuth, __in LPCWSTR wzUser, __in LPCWSTR wzPassword ) { HRESULT hr = S_OK; WCHAR* pwzCustomActionData = NULL; hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData); ExitOnFailure(hr, "failed to add DBKey to CustomActionData"); hr = WcaWriteStringToCaData(wzServer, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server name to CustomActionData"); hr = WcaWriteStringToCaData(wzInstance, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server instance to CustomActionData"); hr = WcaWriteStringToCaData(wzDatabase, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add database name to CustomActionData"); hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server name to CustomActionData"); hr = WcaWriteStringToCaData(fIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server name to CustomActionData"); hr = WcaWriteStringToCaData(wzUser, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server user to CustomActionData"); hr = WcaWriteStringToCaData(wzPassword, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add user password to CustomActionData"); hr = WcaDoDeferredAction(L"DropDatabase", pwzCustomActionData, COST_SQL_DROPDB); ExitOnFailure(hr, "Failed to schedule DropDatabase action"); LExit: ReleaseStr(pwzCustomActionData); return hr; }
static HRESULT AddMessageQueuePermissionToActionData( MQI_MESSAGE_QUEUE_PERMISSION* pItm, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; // add message queue information to custom action data hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData); ExitOnFailure(hr, "Failed to add key to custom action data"); hr = WcaWriteStringToCaData(pItm->pMessageQueue->wzPathName, ppwzActionData); ExitOnFailure(hr, "Failed to add path name to custom action data"); hr = WcaWriteStringToCaData(pItm->wzDomain, ppwzActionData); ExitOnFailure(hr, "Failed to add domain to custom action data"); hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData); ExitOnFailure(hr, "Failed to add name to custom action data"); hr = WcaWriteIntegerToCaData(pItm->iPermissions, ppwzActionData); ExitOnFailure(hr, "Failed to add permissions to custom action data"); hr = S_OK; LExit: return hr; }
/****************************************************************** SchedNetFx - entry point for NetFx Custom Action ********************************************************************/ extern "C" UINT __stdcall SchedNetFx( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug SchedNetFx"); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzInstallCustomActionData = NULL; LPWSTR pwzUninstallCustomActionData = NULL; UINT uiCost = 0; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; PMSIHANDLE hViewGac = NULL; PMSIHANDLE hRecGac = NULL; LPWSTR pwzId = NULL; LPWSTR pwzData = NULL; LPWSTR pwzTemp = NULL; LPWSTR pwzFile = NULL; int iPriority = 0; int iAssemblyCost = 0; int iAttributes = 0; LPWSTR pwzFileApp = NULL; LPWSTR pwzDirAppBase = NULL; LPWSTR pwzComponent = NULL; INSTALLSTATE isInstalled; INSTALLSTATE isAction; LPWSTR pwz32Ngen = NULL; LPWSTR pwz64Ngen = NULL; BOOL f32NgenExeExists = FALSE; BOOL f64NgenExeExists = FALSE; BOOL fNeedInstallUpdate32 = FALSE; BOOL fNeedUninstallUpdate32 = FALSE; BOOL fNeedInstallUpdate64 = FALSE; BOOL fNeedUninstallUpdate64 = FALSE; // initialize hr = WcaInitialize(hInstall, "SchedNetFx"); ExitOnFailure(hr, "failed to initialize"); hr = GetNgenPath(&pwz32Ngen, FALSE); f32NgenExeExists = SUCCEEDED(hr); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) { hr = ERROR_SUCCESS; WcaLog(LOGMSG_STANDARD, "Failed to find 32bit ngen. No actions will be scheduled to create native images for 32bit."); } ExitOnFailure(hr, "failed to get 32bit ngen.exe path"); hr = GetNgenPath(&pwz64Ngen, TRUE); f64NgenExeExists = SUCCEEDED(hr); if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr || HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) { hr = ERROR_SUCCESS; WcaLog(LOGMSG_STANDARD, "Failed to find 64bit ngen. No actions will be scheduled to create native images for 64bit."); } ExitOnFailure(hr, "failed to get 64bit ngen.exe path"); // loop through all the NetFx records hr = WcaOpenExecuteView(vcsNgenQuery, &hView); ExitOnFailure(hr, "failed to open view on NetFxNativeImage table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { // Get Id hr = WcaGetRecordString(hRec, ngqId, &pwzId); ExitOnFailure(hr, "failed to get NetFxNativeImage.NetFxNativeImage"); // Get File hr = WcaGetRecordString(hRec, ngqFile, &pwzData); ExitOnFailure1(hr, "failed to get NetFxNativeImage.File_ for record: %ls", pwzId); hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedFile, pwzData); ExitOnFailure1(hr, "failed to format file string for file: %ls", pwzData); hr = WcaGetFormattedString(pwzTemp, &pwzFile); ExitOnFailure1(hr, "failed to get formatted string for file: %ls", pwzData); // Get Priority hr = WcaGetRecordInteger(hRec, ngqPriority, &iPriority); ExitOnFailure1(hr, "failed to get NetFxNativeImage.Priority for record: %ls", pwzId); if (0 == iPriority) iAssemblyCost = COST_NGEN_BLOCKING; else iAssemblyCost = COST_NGEN_NONBLOCKING; // Get Attributes hr = WcaGetRecordInteger(hRec, ngqAttributes, &iAttributes); ExitOnFailure1(hr, "failed to get NetFxNativeImage.Attributes for record: %ls", pwzId); // Get File_Application or leave pwzFileApp NULL. hr = WcaGetRecordFormattedString(hRec, ngqFileApp, &pwzData); ExitOnFailure1(hr, "failed to get NetFxNativeImage.File_Application for record: %ls", pwzId); // Check if the value resolves to a valid file ID. if (S_OK == FileIdExists(pwzData)) { // Resolve the file ID to a path. hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedFile, pwzData); ExitOnFailure1(hr, "failed to format file application string for file: %ls", pwzData); hr = WcaGetFormattedString(pwzTemp, &pwzFileApp); ExitOnFailure1(hr, "failed to get formatted string for file application: %ls", pwzData); } else { // Assume record formatted to a path already. hr = StrAllocString(&pwzFileApp, pwzData, 0); ExitOnFailure1(hr, "failed to allocate string for file path: %ls", pwzData); hr = PathEnsureQuoted(&pwzFileApp, FALSE); ExitOnFailure1(hr, "failed to quote file path: %ls", pwzData); } // Get Directory_ApplicationBase or leave pwzDirAppBase NULL. hr = WcaGetRecordFormattedString(hRec, ngqDirAppBase, &pwzData); ExitOnFailure1(hr, "failed to get NetFxNativeImage.Directory_ApplicationBase for record: %ls", pwzId); if (WcaIsUnicodePropertySet(pwzData)) { // Resolve the directory ID to a path. hr = StrAllocFormatted(&pwzTemp, vpwzUnformattedQuotedDirectory, pwzData); ExitOnFailure1(hr, "failed to format directory application base string for property: %ls", pwzData); hr = WcaGetFormattedString(pwzTemp, &pwzDirAppBase); ExitOnFailure1(hr, "failed to get formatted string for directory application base: %ls", pwzData); } else { // Assume record formatted to a path already. hr = StrAllocString(&pwzDirAppBase, pwzData, 0); ExitOnFailure1(hr, "failed to allocate string for directory path: %ls", pwzData); hr = PathEnsureQuoted(&pwzDirAppBase, TRUE); ExitOnFailure1(hr, "failed to quote and backslashify directory: %ls", pwzData); } // Get Component hr = WcaGetRecordString(hRec, ngqComponent, &pwzComponent); ExitOnFailure1(hr, "failed to get NetFxNativeImage.Directory_ApplicationBase for record: %ls", pwzId); er = ::MsiGetComponentStateW(hInstall, pwzComponent, &isInstalled, &isAction); ExitOnWin32Error1(er, hr, "failed to get install state for Component: %ls", pwzComponent); // // Figure out if it's going to be GAC'd. The possibility exists that no assemblies are going to be GAC'd // so we have to check for the MsiAssembly table first. // if (S_OK == WcaTableExists(L"MsiAssembly")) { hr = WcaOpenView(vcsNgenGac, &hViewGac); ExitOnFailure(hr, "failed to open view on File/MsiAssembly table"); hr = WcaExecuteView(hViewGac, hRec); ExitOnFailure(hr, "failed to execute view on File/MsiAssembly table"); hr = WcaFetchSingleRecord(hViewGac, &hRecGac); ExitOnFailure(hr, "failed to fetch File_Assembly from File/MsiAssembly table"); if (S_FALSE != hr) { hr = WcaGetRecordString(hRecGac, nggApplication, &pwzData); ExitOnFailure(hr, "failed to get MsiAssembly.File_Application"); // If it's in the GAC replace the file name with the strong name if (L'\0' == pwzData[0]) { hr = GetStrongName(&pwzFile, pwzComponent); ExitOnFailure1(hr, "failed to get strong name for component: %ls", pwzData); } } } // // Schedule the work // if (!(iAttributes & NGEN_32BIT) && !(iAttributes & NGEN_64BIT)) ExitOnFailure1(hr = E_INVALIDARG, "Neither 32bit nor 64bit is specified for NGEN of file: %ls", pwzFile); if (WcaIsInstalling(isInstalled, isAction) || WcaIsReInstalling(isInstalled, isAction)) { if (iAttributes & NGEN_32BIT && f32NgenExeExists) { // Assemble the install command line hr = CreateInstallCommand(&pwzData, pwz32Ngen, pwzFile, iPriority, iAttributes, pwzFileApp, pwzDirAppBase); ExitOnFailure(hr, "failed to create install command line"); hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(iAssemblyCost, &pwzInstallCustomActionData); ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData); uiCost += iAssemblyCost; fNeedInstallUpdate32 = TRUE; } if (iAttributes & NGEN_64BIT && f64NgenExeExists) { // Assemble the install command line hr = CreateInstallCommand(&pwzData, pwz64Ngen, pwzFile, iPriority, iAttributes, pwzFileApp, pwzDirAppBase); ExitOnFailure(hr, "failed to create install command line"); hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(iAssemblyCost, &pwzInstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData); uiCost += iAssemblyCost; fNeedInstallUpdate64 = TRUE; } } else if (WcaIsUninstalling(isInstalled, isAction)) { if (iAttributes & NGEN_32BIT && f32NgenExeExists) { hr = StrAllocFormatted(&pwzData, L"%s uninstall %s", pwz32Ngen, pwzFile); ExitOnFailure(hr, "failed to create update 32 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; fNeedUninstallUpdate32 = TRUE; } if (iAttributes & NGEN_64BIT && f64NgenExeExists) { hr = StrAllocFormatted(&pwzData, L"%s uninstall %s", pwz64Ngen, pwzFile); ExitOnFailure(hr, "failed to create update 64 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; fNeedUninstallUpdate64 = TRUE; } } } if (E_NOMOREITEMS == hr) hr = S_OK; ExitOnFailure(hr, "failed while looping through all files to create native images for"); // If we need 32 bit install update if (fNeedInstallUpdate32) { hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz32Ngen); ExitOnFailure(hr, "failed to create install update 32 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to install custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzInstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to install custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; } // If we need 32 bit uninstall update if (fNeedUninstallUpdate32) { hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz32Ngen); ExitOnFailure(hr, "failed to create uninstall update 32 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to uninstall custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to uninstall custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; } // If we need 64 bit install update if (fNeedInstallUpdate64) { hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz64Ngen); ExitOnFailure(hr, "failed to create install update 64 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzInstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to install custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzInstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to install custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; } // If we need 64 bit install update if (fNeedUninstallUpdate64) { hr = StrAllocFormatted(&pwzData, L"%s update /queue", pwz64Ngen); ExitOnFailure(hr, "failed to create uninstall update 64 command line"); hr = WcaWriteStringToCaData(pwzData, &pwzUninstallCustomActionData); // command ExitOnFailure1(hr, "failed to add install command to uninstall custom action data: %ls", pwzData); hr = WcaWriteIntegerToCaData(COST_NGEN_NONBLOCKING, &pwzUninstallCustomActionData); // cost ExitOnFailure1(hr, "failed to add cost to uninstall custom action data: %ls", pwzData); uiCost += COST_NGEN_NONBLOCKING; } // Add to progress bar if ((pwzInstallCustomActionData && *pwzInstallCustomActionData) || (pwzUninstallCustomActionData && *pwzUninstallCustomActionData)) { hr = WcaProgressMessage(uiCost, TRUE); ExitOnFailure(hr, "failed to extend progress bar for NetFxExecuteNativeImage"); } // Schedule the install custom action if (pwzInstallCustomActionData && *pwzInstallCustomActionData) { hr = WcaSetProperty(L"NetFxExecuteNativeImageInstall", pwzInstallCustomActionData); ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageInstall action"); hr = WcaSetProperty(L"NetFxExecuteNativeImageCommitInstall", pwzInstallCustomActionData); ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageCommitInstall action"); } // Schedule the uninstall custom action if (pwzUninstallCustomActionData && *pwzUninstallCustomActionData) { hr = WcaSetProperty(L"NetFxExecuteNativeImageUninstall", pwzUninstallCustomActionData); ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageUninstall action"); hr = WcaSetProperty(L"NetFxExecuteNativeImageCommitUninstall", pwzUninstallCustomActionData); ExitOnFailure(hr, "failed to schedule NetFxExecuteNativeImageCommitUninstall action"); } LExit: ReleaseStr(pwzInstallCustomActionData); ReleaseStr(pwzUninstallCustomActionData); ReleaseStr(pwzId); ReleaseStr(pwzData); ReleaseStr(pwzTemp); ReleaseStr(pwzFile); ReleaseStr(pwzFileApp); ReleaseStr(pwzDirAppBase); ReleaseStr(pwzComponent); ReleaseStr(pwz32Ngen); ReleaseStr(pwz64Ngen); if (FAILED(hr)) er = ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
static HRESULT StoreACLRollbackInfo( __in LPWSTR pwzObject, __in LPCWSTR pwzTable ) { HRESULT hr = S_OK; DWORD er = ERROR_SUCCESS; PSECURITY_DESCRIPTOR psd = NULL; SECURITY_DESCRIPTOR_CONTROL sdc = {0}; DWORD dwRevision = 0; LPWSTR pwzCustomActionData = NULL; LPWSTR pwzSecurityInfo = NULL; Assert(pwzObject && pwzTable); SE_OBJECT_TYPE objectType = SEObjectTypeFromString(const_cast<LPCWSTR> (pwzTable)); if (SE_UNKNOWN_OBJECT_TYPE != objectType) { er = ::GetNamedSecurityInfoW(pwzObject, objectType, DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd); if (ERROR_FILE_NOT_FOUND == er || ERROR_PATH_NOT_FOUND == er || ERROR_SERVICE_DOES_NOT_EXIST == HRESULT_CODE(er)) { // If the file, path or service doesn't exist yet, skip rollback without a message hr = HRESULT_FROM_WIN32(er); ExitFunction(); } ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "Unable to schedule rollback for object: %ls", pwzObject); //Need to see if DACL is protected so getting Descriptor information if (!::GetSecurityDescriptorControl(psd, &sdc, &dwRevision)) { ExitOnLastError1(hr, "Unable to schedule rollback for object (failed to get security descriptor control): %ls", pwzObject); } // Convert the security information to a string, and write this to the custom action data if (!::ConvertSecurityDescriptorToStringSecurityDescriptorW(psd,SDDL_REVISION_1,DACL_SECURITY_INFORMATION,&pwzSecurityInfo,NULL)) { hr = E_UNEXPECTED; ExitOnFailure1(hr, "Unable to schedule rollback for object (failed to convert security descriptor to a valid security descriptor string): %ls", pwzObject); } hr = WcaWriteStringToCaData(pwzObject, &pwzCustomActionData); ExitOnFailure(hr, "failed to add object data to rollback CustomActionData"); hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); ExitOnFailure(hr, "failed to add table name to rollback CustomActionData"); hr = WcaWriteStringToCaData(pwzSecurityInfo, &pwzCustomActionData); ExitOnFailure(hr, "failed to add security info data to rollback CustomActionData"); // Write a 1 if DACL is protected, 0 otherwise if (sdc & SE_DACL_PROTECTED) { hr = WcaWriteIntegerToCaData(1,&pwzCustomActionData); ExitOnFailure(hr, "failed to add data to rollbackCustomActionData"); } else { hr = WcaWriteIntegerToCaData(0,&pwzCustomActionData); ExitOnFailure(hr, "failed to add data to rollback CustomActionData"); } hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"ExecSecureObjectsRollback"), pwzCustomActionData, COST_SECUREOBJECT); ExitOnFailure2(hr, "failed to schedule ExecSecureObjectsRollback for item: %ls of type: %ls", pwzObject, pwzTable); ReleaseStr(pwzCustomActionData); pwzCustomActionData = NULL; } else { MessageExitOnFailure1(hr = E_UNEXPECTED, msierrSecureObjectsUnknownType, "unknown object type: %ls", pwzTable); } LExit: ReleaseStr(pwzCustomActionData); if (psd) { ::LocalFree(psd); } return hr; }
/****************************************************************** SchedServiceConfig - entry point for SchedServiceConfig Custom Action called as Type 1 CustomAction (binary DLL) from Windows Installer in InstallExecuteSequence before CaExecServiceConfig ********************************************************************/ extern "C" UINT __stdcall SchedServiceConfig( __in MSIHANDLE hInstall ) { //AssertSz(FALSE, "debug SchedServiceConfig"); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzScriptKey = NULL; LPWSTR pwzCustomActionData = NULL; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; LPWSTR pwzData = NULL; int iData = 0; DWORD cServices = 0; // initialize hr = WcaInitialize(hInstall, "SchedServiceConfig"); ExitOnFailure(hr, "Failed to initialize."); // Get the script key for this CustomAction and put it on the front of the // CustomActionData of the install action. hr = WcaCaScriptCreateKey(&pwzScriptKey); ExitOnFailure(hr, "Failed to get encoding key."); hr = WcaWriteStringToCaData(pwzScriptKey, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add encoding key to CustomActionData."); // Loop through all the services to be configured. hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView); ExitOnFailure(hr, "Failed to open view on ServiceConfig table."); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; // Get component name to check if we are installing it. If so // then add the table data to the CustomActionData, otherwise // skip it. hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData); ExitOnFailure(hr, "Failed to get component name"); hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); ExitOnFailure1(hr = HRESULT_FROM_WIN32(hr), "Failed to get install state for Component: %ls", pwzData); if (WcaIsInstalling(isInstalled, isAction)) { // Add the data to the CustomActionData (for install). hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData); ExitOnFailure(hr, "Failed to get name of service."); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add name to CustomActionData."); hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData); ExitOnFailure(hr, "Failed to get ServiceConfig.NewService."); hr = WcaWriteIntegerToCaData(0 != iData, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add NewService data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get first failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get second failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get third failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData); if (S_FALSE == hr) // deal w/ possible null value { iData = 0; } ExitOnFailure(hr, "failed to get reset period in days between service restart attempts."); hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData); if (S_FALSE == hr) // deal w/ possible null value { iData = 0; } ExitOnFailure(hr, "failed to get server restart delay value."); hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordFormattedString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly ExitOnFailure(hr, "failed to get command line to run on service failure."); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure."); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); ++cServices; } } // if we looped through all records all is well if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "failed while looping through all objects to secure"); // setup CustomActionData and add to progress bar for download if (0 < cServices) { hr = WcaDoDeferredAction(L"RollbackServiceConfig", pwzScriptKey, cServices * COST_SERVICECONFIG); ExitOnFailure(hr, "failed to schedule RollbackServiceConfig action"); hr = WcaDoDeferredAction(L"ExecServiceConfig", pwzCustomActionData, cServices * COST_SERVICECONFIG); ExitOnFailure(hr, "failed to schedule ExecServiceConfig action"); } LExit: ReleaseStr(pwzData); ReleaseStr(pwzCustomActionData); ReleaseStr(pwzScriptKey); er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
HRESULT CpiSubscriptionsInstall( CPI_SUBSCRIPTION_LIST* pList, int iRunMode, LPWSTR* ppwzActionData, int* piProgress ) { HRESULT hr = S_OK; int iActionType; int iCount = 0; // add action text hr = CpiAddActionTextToActionData(L"CreateSubscrComPlusComponents", ppwzActionData); ExitOnFailure(hr, "Failed to add action text to custom action data"); // subscription count switch (iRunMode) { case rmDeferred: iCount = pList->iInstallCount - pList->iCommitCount; break; case rmCommit: iCount = pList->iCommitCount; break; case rmRollback: iCount = pList->iInstallCount; break; } // add subscription count to action data hr = WcaWriteIntegerToCaData(iCount, ppwzActionData); ExitOnFailure(hr, "Failed to add count to custom action data"); // add assemblies to custom action data in forward order for (CPI_SUBSCRIPTION* pItm = pList->pFirst; pItm; pItm = pItm->pNext) { // roles that are being installed only if ((rmCommit == iRunMode && !(pItm->pAssembly->iAttributes & aaRunInCommit)) || (rmDeferred == iRunMode && (pItm->pAssembly->iAttributes & aaRunInCommit)) || !WcaIsInstalling(pItm->isInstalled, pItm->isAction)) continue; // action type if (rmRollback == iRunMode) { if (CpiIsInstalled(pItm->isInstalled)) iActionType = atNoOp; else iActionType = atRemove; } else iActionType = atCreate; // add to action data hr = AddSubscriptionToActionData(pItm, iActionType, COST_SUBSCRIPTION_CREATE, ppwzActionData); ExitOnFailure1(hr, "Failed to add subscription to custom action data, key: %S", pItm->wzKey); } // add progress tics if (piProgress) *piProgress += COST_SUBSCRIPTION_CREATE * pList->iInstallCount; hr = S_OK; LExit: return hr; }
/****************************************************************** SchedXmlConfig - entry point for XmlConfig Custom Action ********************************************************************/ extern "C" UINT __stdcall SchedXmlConfig( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug SchedXmlConfig"); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzCurrentFile = NULL; BOOL fCurrentFileChanged = FALSE; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; XML_CONFIG_CHANGE* pxfcHead = NULL; XML_CONFIG_CHANGE* pxfcTail = NULL; // TODO: do we need this any more? XML_CONFIG_CHANGE* pxfc = NULL; eXmlAction xa = xaUnknown; eXmlPreserveDate xd; LPWSTR pwzCustomActionData = NULL; DWORD cFiles = 0; // initialize hr = WcaInitialize(hInstall, "SchedXmlConfig"); ExitOnFailure(hr, "failed to initialize"); hr = ReadXmlConfigTable(&pxfcHead, &pxfcTail); MessageExitOnFailure(hr, msierrXmlConfigFailedRead, "failed to read XmlConfig table"); hr = ProcessChanges(&pxfcHead); ExitOnFailure(hr, "failed to process XmlConfig changes"); // loop through all the xml configurations for (pxfc = pxfcHead; pxfc; pxfc = pxfc->pxfcNext) { // If this is a different file, or the first file... if (NULL == pwzCurrentFile || 0 != lstrcmpW(pwzCurrentFile, pxfc->wzFile)) { // Remember the file we're currently working on hr = StrAllocString(&pwzCurrentFile, pxfc->wzFile, 0); ExitOnFailure(hr, "failed to copy file name"); fCurrentFileChanged = TRUE; } // // Figure out what action to take // xa = xaUnknown; // If it's being installed or reinstalled or uninstalled and that matches // what we are doing then calculate the right action. if ((XMLCONFIG_INSTALL & pxfc->iXmlFlags && (WcaIsInstalling(pxfc->isInstalled, pxfc->isAction) || WcaIsReInstalling(pxfc->isInstalled, pxfc->isAction))) || (XMLCONFIG_UNINSTALL & pxfc->iXmlFlags && WcaIsUninstalling(pxfc->isInstalled, pxfc->isAction))) { if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) { xa = xaCreateElement; } else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_ELEMENT & pxfc->iXmlFlags) { xa = xaDeleteElement; } else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) { xa = xaDeleteValue; } else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_VALUE & pxfc->iXmlFlags) { xa = xaWriteValue; } else if (XMLCONFIG_CREATE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) { xa = xaWriteDocument; } else if (XMLCONFIG_DELETE & pxfc->iXmlFlags && XMLCONFIG_DOCUMENT & pxfc->iXmlFlags) { hr = E_INVALIDARG; ExitOnFailure(hr, "Invalid flag configuration. Cannot delete a fragment node."); } } if (XMLCONFIG_PRESERVE_MODIFIED & pxfc->iXmlFlags) { xd = xdPreserve; } else { xd= xdDontPreserve; } if (xaUnknown != xa) { if (fCurrentFileChanged) { hr = BeginChangeFile(pwzCurrentFile, pxfc->iCompAttributes, &pwzCustomActionData); ExitOnFailure1(hr, "failed to begin file change for file: %ls", pwzCurrentFile); fCurrentFileChanged = FALSE; ++cFiles; } hr = WcaWriteIntegerToCaData((int)xa, &pwzCustomActionData); ExitOnFailure(hr, "failed to write action indicator custom action data"); hr = WcaWriteIntegerToCaData((int)xd, &pwzCustomActionData); ExitOnFailure(hr, "failed to write Preserve Date indicator to custom action data"); hr = WriteChangeData(pxfc, xa, &pwzCustomActionData); ExitOnFailure(hr, "failed to write change data"); } } // If we looped through all records all is well if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "failed while looping through all objects to secure"); // Schedule the custom action and add to progress bar if (pwzCustomActionData && *pwzCustomActionData) { Assert(0 < cFiles); hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"ExecXmlConfig"), pwzCustomActionData, cFiles * COST_XMLFILE); ExitOnFailure(hr, "failed to schedule ExecXmlConfig action"); } LExit: ReleaseStr(pwzCurrentFile); ReleaseStr(pwzCustomActionData); FreeXmlConfigChangeList(pxfcHead); if (FAILED(hr)) { er = ERROR_INSTALL_FAILURE; } return WcaFinalize(er); }
static HRESULT ExecuteStrings( __in SCA_DB* psdList, __in SCA_SQLSTR* psssList, __in BOOL fInstall ) { HRESULT hr = S_FALSE; // assume nothing will be done int iRollback = -1; int iOldRollback = iRollback; LPCWSTR wzOldDb = NULL; UINT uiCost = 0; WCHAR* pwzCustomActionData = NULL; WCHAR wzNumber[64]; // loop through all sql strings for (SCA_SQLSTR* psss = psssList; psss; psss = psss->psssNext) { // if installing this component if ((fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_INSTALL) && WcaIsInstalling(psss->isInstalled, psss->isAction) && !WcaIsReInstalling(psss->isInstalled, psss->isAction)) || (fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_REINSTALL) && WcaIsReInstalling(psss->isInstalled, psss->isAction)) || (!fInstall && (psss->iAttributes & SCASQL_EXECUTE_ON_UNINSTALL) && WcaIsUninstalling(psss->isInstalled, psss->isAction))) { // determine if this is a rollback scheduling or normal deferred scheduling if (psss->iAttributes & SCASQL_ROLLBACK) { iRollback = 1; } else { iRollback = 0; } // if we need to create a connection to a new server\database if (!wzOldDb || 0 != lstrcmpW(wzOldDb, psss->wzSqlDb) || iOldRollback != iRollback) { const SCA_DB* psd = ScaDbsFindDatabase(psss->wzSqlDb, psdList); if (!psd) { ExitOnFailure1(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "failed to find data for Database: %ls", psss->wzSqlDb); } if (-1 == iOldRollback) { iOldRollback = iRollback; } Assert(0 == iOldRollback || 1 == iOldRollback); // if there was custom action data before, schedule the action to write it if (pwzCustomActionData && *pwzCustomActionData) { Assert(pwzCustomActionData && *pwzCustomActionData && uiCost); hr = WcaDoDeferredAction(1 == iOldRollback ? L"RollbackExecuteSqlStrings" : L"ExecuteSqlStrings", pwzCustomActionData, uiCost); ExitOnFailure1(hr, "failed to schedule ExecuteSqlStrings action, rollback: %d", iOldRollback); iOldRollback = iRollback; *pwzCustomActionData = L'\0'; uiCost = 0; } Assert(!pwzCustomActionData || (pwzCustomActionData && 0 == *pwzCustomActionData) && 0 == uiCost); hr = WcaWriteStringToCaData(psd->wzKey, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Server Database String to CustomActionData for Database String: %ls", psd->wzKey); hr = WcaWriteStringToCaData(psd->wzServer, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Server to CustomActionData for Database String: %ls", psd->wzKey); hr = WcaWriteStringToCaData(psd->wzInstance, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Instance to CustomActionData for Database String: %ls", psd->wzKey); hr = WcaWriteStringToCaData(psd->wzDatabase, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Database to CustomActionData for Database String: %ls", psd->wzKey); hr = ::StringCchPrintfW(wzNumber, countof(wzNumber), L"%d", psd->iAttributes); ExitOnFailure(hr, "Failed to format attributes integer value to string"); hr = WcaWriteStringToCaData(wzNumber, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Attributes to CustomActionData for Database String: %ls", psd->wzKey); hr = ::StringCchPrintfW(wzNumber, countof(wzNumber), L"%d", psd->fUseIntegratedAuth); ExitOnFailure(hr, "Failed to format UseIntegratedAuth integer value to string"); hr = WcaWriteStringToCaData(wzNumber, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL IntegratedAuth flag to CustomActionData for Database String: %ls", psd->wzKey); hr = WcaWriteStringToCaData(psd->scau.wzName, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL UserName to CustomActionData for Database String: %ls", psd->wzKey); hr = WcaWriteStringToCaData(psd->scau.wzPassword, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Password to CustomActionData for Database String: %ls", psd->wzKey); uiCost += COST_SQL_CONNECTDB; wzOldDb = psss->wzSqlDb; } WcaLog(LOGMSG_VERBOSE, "Scheduling SQL string: %ls", psss->pwzSql); hr = WcaWriteStringToCaData(psss->wzKey, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to add SQL Key to CustomActionData for SQL string: %ls", psss->wzKey); hr = WcaWriteIntegerToCaData(psss->iAttributes, &pwzCustomActionData); ExitOnFailure1(hr, "failed to add attributes to CustomActionData for SQL string: %ls", psss->wzKey); hr = WcaWriteStringToCaData(psss->pwzSql, &pwzCustomActionData); ExitOnFailure1(hr, "Failed to to add SQL Query to CustomActionData for SQL string: %ls", psss->wzKey); uiCost += COST_SQL_STRING; } } if (pwzCustomActionData && *pwzCustomActionData) { Assert(pwzCustomActionData && *pwzCustomActionData && uiCost); hr = WcaDoDeferredAction(1 == iRollback ? L"RollbackExecuteSqlStrings" : L"ExecuteSqlStrings", pwzCustomActionData, uiCost); ExitOnFailure(hr, "Failed to schedule ExecuteSqlStrings action"); *pwzCustomActionData = L'\0'; uiCost = 0; } LExit: ReleaseStr(pwzCustomActionData); return hr; }
/****************************************************************** SchedAddinRegistration - entry point for AddinRegistration Custom Action ********************************************************************/ HRESULT SchedAddinRegistration(MSIHANDLE hInstall, BOOL fInstall) { // AssertSz(FALSE, "debug SchedRegisterAddins"); HRESULT hr = S_OK; LPWSTR pwzCustomActionData = NULL; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; LPWSTR pwzData = NULL; LPWSTR pwzTemp = NULL; LPWSTR pwzComponent = NULL; LPWSTR pwzId = NULL; LPWSTR pwzFile = NULL; LPWSTR pwzFriendlyName = NULL; LPWSTR pwzDescription = NULL; int iBitness = 0; int iCommandLineSafe = 1; int iLoadBehavior = 0; LPWSTR pwzAllUsers = NULL; int nAddins = 0; hr = WcaGetProperty(L"ALLUSERS", &pwzAllUsers); ExitOnFailure(hr, "failed to read value of ALLUSERS property"); // loop through all the RegisterAddin records hr = WcaOpenExecuteView(vcsRegisterAddinsQuery, &hView); ExitOnFailure(hr, "failed to open view on AddinRegistration table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { ++nAddins; // Get Id hr = WcaGetRecordString(hRec, arqId, &pwzId); ExitOnFailure(hr, "failed to get AddinRegistration.AddinRegistration"); // Get File hr = WcaGetRecordString(hRec, arqFile, &pwzData); ExitOnFailure1(hr, "failed to get AddinRegistration.File_ for record: %ls", pwzId); hr = StrAllocFormatted(&pwzTemp, L"[#%ls]", pwzData); ExitOnFailure1(hr, "failed to format file string for file: %ls", pwzData); hr = WcaGetFormattedString(pwzTemp, &pwzFile); ExitOnFailure1(hr, "failed to get formatted string for file: %ls", pwzData); // Get name hr = WcaGetRecordFormattedString(hRec, arqName, &pwzFriendlyName); ExitOnFailure1(hr, "failed to get AddinRegistration.Name for record: %ls", pwzId); // Get description hr = WcaGetRecordFormattedString(hRec, arqDescription, &pwzDescription); ExitOnFailure1(hr, "failed to get AddinRegistration.Description for record: %ls", pwzId); // Get description hr = WcaGetRecordInteger(hRec, arqBitness, &iBitness); ExitOnFailure1(hr, "failed to get AddinRegistration.Bitnesss for record: %ls", pwzId); // Get description hr = WcaGetRecordInteger(hRec, arqCommandLineSafe, &iCommandLineSafe); ExitOnFailure1(hr, "failed to get AddinRegistration.CommandLineSafe for record: %ls", pwzId); // Get description hr = WcaGetRecordInteger(hRec, arqLoadBehavior, &iLoadBehavior); ExitOnFailure1(hr, "failed to get AddinRegistration.LoadBehavior for record: %ls", pwzId); // get component and its install/action states hr = WcaGetRecordString(hRec, arqComponent, &pwzComponent); ExitOnFailure(hr, "failed to get addin component id"); // we need to know if the component's being installed, uninstalled, or reinstalled WCA_TODO todo = WcaGetComponentToDo(pwzComponent); // skip this entry if this is the install CA and we are uninstalling the component if (fInstall && WCA_TODO_UNINSTALL == todo) { continue; } // skip this entry if this is an uninstall CA and we are not uninstalling the component if (!fInstall && WCA_TODO_UNINSTALL != todo) { continue; } // write custom action data: operation, instance guid, path, directory hr = WcaWriteIntegerToCaData(todo, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write operation to custom action data for instance id: %ls", pwzId); hr = WcaWriteStringToCaData(pwzId, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write id to custom action data for instance id: %ls", pwzId); hr = WcaWriteStringToCaData(pwzFile, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write custom action data for instance id: %ls", pwzId); hr = WcaWriteStringToCaData(pwzFriendlyName, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write addin name to custom action data for instance id: %ls", pwzId); hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write addin description to custom action data for instance id: %ls", pwzId); hr = WcaWriteIntegerToCaData(iBitness, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write Bitness to custom action data for instance id: %ls", pwzId); hr = WcaWriteIntegerToCaData(iCommandLineSafe, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write CommandLineSafe to custom action data for instance id: %ls", pwzId); hr = WcaWriteIntegerToCaData(iLoadBehavior, &pwzCustomActionData); ExitOnFailure1(hr, "failed to write LoadBehavior to custom action data for instance id: %ls", pwzId); hr = WcaWriteStringToCaData(pwzAllUsers, &pwzCustomActionData); ExitOnFailure(hr, "failed to write allusers property to custom action data for instance id: %ls", pwzId); } if (E_NOMOREITEMS == hr) hr = S_OK; ExitOnFailure(hr, "failed while looping through all files to create native images for"); // Schedule the install custom action if (pwzCustomActionData && *pwzCustomActionData) { WcaLog(LOGMSG_STANDARD, "Scheduling Addin Registration (%ls)", pwzCustomActionData); hr = WcaDoDeferredAction(L"RollbackAddinRegistration", pwzCustomActionData, nAddins * COST_REGISTER_ADDIN); ExitOnFailure(hr, "Failed to schedule addin registration rollback"); hr = WcaDoDeferredAction(L"ExecAddinRegistration", pwzCustomActionData, nAddins * COST_REGISTER_ADDIN); ExitOnFailure(hr, "Failed to schedule addin registration execution"); } LExit: ReleaseStr(pwzAllUsers); ReleaseStr(pwzCustomActionData); ReleaseStr(pwzId); ReleaseStr(pwzData); ReleaseStr(pwzData); ReleaseStr(pwzTemp); ReleaseStr(pwzComponent); ReleaseStr(pwzFile); ReleaseStr(pwzFriendlyName); ReleaseStr(pwzDescription); return hr; }
/****************************************************************** CaSchedServiceConfig - entry point for CaSchedServiceConfig Custom Action called as Type 1 CustomAction (binary DLL) from Windows Installer in InstallExecuteSequence before CaExecServiceConfig ********************************************************************/ extern "C" UINT __stdcall SchedServiceConfig( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug SchedServiceConfig"); HRESULT hr = S_OK; UINT uiResult = ERROR_SUCCESS; DWORD dwError = 0; LPWSTR pwzData = NULL; int iData = 0; BOOL fExistingService = FALSE; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; INSTALLSTATE isInstalled; INSTALLSTATE isAction; SC_HANDLE hSCM = NULL; SC_HANDLE hService = NULL; LPSERVICE_FAILURE_ACTIONSW psfa; LPWSTR pwzCustomActionData = NULL; LPWSTR pwzRollbackCustomActionData = NULL; DWORD cServices = 0; DWORD dwRestartDelay = 0; WCHAR wzActionName[32] = { 0 }; DWORD dwSizeNeeded = 0; // initialize hr = WcaInitialize(hInstall, "SchedServiceConfig"); ExitOnFailure(hr, "failed to initialize"); //Get a handle to the service control manager hSCM = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT); if (hSCM == NULL) ExitOnLastError(hr, "failed to get handle to SCM"); // loop through all the services to be configured hr = WcaOpenExecuteView(wzQUERY_SERVICECONFIG, &hView); ExitOnFailure(hr, "failed to open view on ServiceConfig table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hr = WcaGetRecordInteger(hRec, QSC_NEWSERVICE, &iData); ExitOnFailure(hr, "failed to get object NewService"); fExistingService = 1 != iData; // Get component name hr = WcaGetRecordString(hRec, QSC_COMPONENT, &pwzData); ExitOnFailure(hr, "failed to get component name"); // check if we are installing this Component hr = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); ExitOnFailure1(hr = HRESULT_FROM_WIN32(hr), "failed to get install state for Component: %S", pwzData); // We want to configure either a service we're installing or one already on the box if (WcaIsInstalling(isInstalled, isAction)) { // Check if we're configuring an existing service if (fExistingService) { // Confirm the service is actually on the box hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData); ExitOnFailure(hr, "failed to get object NewService"); //Get a handle to the service hService = ::OpenServiceW(hSCM, pwzData, SERVICE_QUERY_CONFIG); if (hService == NULL) { dwError = ::GetLastError(); hr = HRESULT_FROM_WIN32(dwError); if (hr == ERROR_SERVICE_DOES_NOT_EXIST) { ExitOnFailure1(hr, "Service \"%s\" does not exist on this system.", pwzData); } else { ExitOnFailure1(hr, "Failed to get handle to the service \"%S\".", pwzData); } } // Get Current Service Config info if(!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, NULL, 0, &dwSizeNeeded) && ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) { ExitOnLastError(hr, "Failed to get current service config info."); } // Alloc space we were told we needed psfa = (LPSERVICE_FAILURE_ACTIONSW) MemAlloc(dwSizeNeeded, TRUE); ExitOnNull(psfa, hr, E_OUTOFMEMORY, "failed to allocate memory for service failure actions."); // Now do the real query if (!::QueryServiceConfig2W(hService, SERVICE_CONFIG_FAILURE_ACTIONS, (LPBYTE)psfa, dwSizeNeeded, &dwSizeNeeded)) ExitOnLastError(hr, "failed to Query Service."); // Build up rollback CA data so we can restore service state if necessary hr = WcaWriteStringToCaData(pwzData, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); // If this service struct is empty, fill in defualt values if(psfa->cActions < 3) { hr = WcaWriteStringToCaData(c_wzActionTypeNone, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); hr = WcaWriteStringToCaData(c_wzActionTypeNone, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); hr = WcaWriteStringToCaData(c_wzActionTypeNone, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); } else { // psfa actually had actions defined, so use them // action 1 hr = GetSCActionTypeString(psfa->lpsaActions[0].Type, (LPWSTR)wzActionName, 32); ExitOnFailure(hr, "failed to query SFA object"); if (SC_ACTION_RESTART == psfa->lpsaActions[0].Type) dwRestartDelay = psfa->lpsaActions[0].Delay / 1000; hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); // action 2 hr = GetSCActionTypeString(psfa->lpsaActions[1].Type, (LPWSTR)wzActionName, 32); ExitOnFailure(hr, "failed to query SFA object"); if (SC_ACTION_RESTART == psfa->lpsaActions[1].Type) dwRestartDelay = psfa->lpsaActions[1].Delay / 1000; hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); // action 3 hr = GetSCActionTypeString(psfa->lpsaActions[2].Type, (LPWSTR)wzActionName, 32); ExitOnFailure(hr, "failed to query SFA object"); if (SC_ACTION_RESTART == psfa->lpsaActions[2].Type) dwRestartDelay = psfa->lpsaActions[2].Delay / 1000; hr = WcaWriteStringToCaData(wzActionName, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); } hr = WcaWriteIntegerToCaData(psfa->dwResetPeriod / (24 * 60 * 60), &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaWriteIntegerToCaData(dwRestartDelay, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); // check for value being null if(!psfa->lpCommand) psfa->lpCommand = L""; hr = WcaWriteStringToCaData(psfa->lpCommand, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); // check for value being null if(!psfa->lpRebootMsg) psfa->lpRebootMsg = L""; hr = WcaWriteStringToCaData(psfa->lpRebootMsg, &pwzRollbackCustomActionData); ExitOnFailure(hr, "failed to add data to Rollback CustomActionData"); // Clear up per-service values if(psfa) MemFree(psfa); } // add the data to the CustomActionData (for install) hr = WcaGetRecordFormattedString(hRec, QSC_SERVICENAME, &pwzData); ExitOnFailure(hr, "failed to get name of service"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_FIRSTFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get first failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_SECONDFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get second failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_THIRDFAILUREACTIONTYPE, &pwzData); ExitOnFailure(hr, "failed to get third failure action type"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordInteger(hRec, QSC_RESETPERIODINDAYS, &iData); if (hr == S_FALSE) // deal w/ possible null value iData = 0; ExitOnFailure(hr, "failed to get reset period in days between service restart attempts."); hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordInteger(hRec, QSC_RESTARTSERVICEDELAYINSECONDS, &iData); if (hr == S_FALSE) // deal w/ possible null value iData = 0; ExitOnFailure(hr, "failed to get server restart delay value."); hr = WcaWriteIntegerToCaData(iData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_PROGRAMCOMMANDLINE, &pwzData); // null value already dealt w/ properly ExitOnFailure(hr, "failed to get command line to run on service failure."); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSC_REBOOTMESSAGE, &pwzData); // null value already dealt w/ properly ExitOnFailure(hr, "failed to get message to send to users when server reboots due to service failure."); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); cServices++; ::CloseServiceHandle(hService); hService = NULL; } } // if we looped through all records all is well if (E_NOMOREITEMS == hr) hr = S_OK; ExitOnFailure(hr, "failed while looping through all objects to secure"); // setup CustomActionData and add to progress bar for download if (pwzRollbackCustomActionData && *pwzRollbackCustomActionData) { Assert(0 < cServices); hr = WcaDoDeferredAction(L"ExecServiceConfigRollback", pwzRollbackCustomActionData, cServices * COST_SERVICECONFIG); ExitOnFailure(hr, "failed to schedule ExecSecureObjects action"); } // schedule the custom action and add to progress bar if (pwzCustomActionData && *pwzCustomActionData) { Assert(0 < cServices); hr = WcaDoDeferredAction(L"ExecServiceConfig", pwzCustomActionData, cServices * COST_SERVICECONFIG); ExitOnFailure(hr, "failed to schedule ExecSecureObjects action"); } LExit: // Clean up handles if (hService != NULL) ::CloseServiceHandle(hService); if (hSCM != NULL) ::CloseServiceHandle(hSCM); ReleaseStr(pwzCustomActionData); ReleaseStr(pwzRollbackCustomActionData); ReleaseStr(pwzData); if (FAILED(hr)) uiResult = ERROR_INSTALL_FAILURE; return WcaFinalize(uiResult); }
/****************************************************************** SchedFirewallExceptions - immediate custom action worker to register and remove firewall exceptions. ********************************************************************/ static UINT SchedFirewallExceptions( __in MSIHANDLE hInstall, WCA_TODO todoSched ) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; int cFirewallExceptions = 0; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; LPWSTR pwzCustomActionData = NULL; LPWSTR pwzName = NULL; LPWSTR pwzRemoteAddresses = NULL; LPWSTR pwzPort = NULL; int iProtocol = 0; int iAttributes = 0; int iProfile = 0; LPWSTR pwzProgram = NULL; LPWSTR pwzComponent = NULL; LPWSTR pwzFormattedFile = NULL; LPWSTR pwzDescription = NULL; // initialize hr = WcaInitialize(hInstall, "SchedFirewallExceptions"); ExitOnFailure(hr, "failed to initialize"); // anything to do? if (S_OK != WcaTableExists(L"WixFirewallException")) { WcaLog(LOGMSG_STANDARD, "WixFirewallException table doesn't exist, so there are no firewall exceptions to configure."); ExitFunction(); } // query and loop through all the firewall exceptions hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView); ExitOnFailure(hr, "failed to open view on WixFirewallException table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hr = WcaGetRecordFormattedString(hRec, feqName, &pwzName); ExitOnFailure(hr, "failed to get firewall exception name"); hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &pwzRemoteAddresses); ExitOnFailure(hr, "failed to get firewall exception remote addresses"); hr = WcaGetRecordFormattedString(hRec, feqPort, &pwzPort); ExitOnFailure(hr, "failed to get firewall exception port"); hr = WcaGetRecordInteger(hRec, feqProtocol, &iProtocol); ExitOnFailure(hr, "failed to get firewall exception protocol"); hr = WcaGetRecordFormattedString(hRec, feqProgram, &pwzProgram); ExitOnFailure(hr, "failed to get firewall exception program"); hr = WcaGetRecordInteger(hRec, feqAttributes, &iAttributes); ExitOnFailure(hr, "failed to get firewall exception attributes"); hr = WcaGetRecordInteger(hRec, feqProfile, &iProfile); ExitOnFailure(hr, "failed to get firewall exception profile"); hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent); ExitOnFailure(hr, "failed to get firewall exception component"); hr = WcaGetRecordString(hRec, feqDescription, &pwzDescription); ExitOnFailure(hr, "failed to get firewall description"); // figure out what we're doing for this exception, treating reinstall the same as install WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent); if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched) { WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d)", pwzComponent, todoComponent, todoSched); continue; } // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path} ++cFirewallExceptions; hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception action to custom action data"); hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception name to custom action data"); hr = WcaWriteIntegerToCaData(iProfile, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception profile to custom action data"); hr = WcaWriteStringToCaData(pwzRemoteAddresses, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception remote addresses to custom action data"); hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception attributes to custom action data"); if (*pwzProgram) { // If program is defined, we have an application exception. hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception target (application) to custom action data"); hr = WcaWriteStringToCaData(pwzProgram, &pwzCustomActionData); ExitOnFailure(hr, "failed to write application path to custom action data"); } else { // we have a port-only exception hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception target (port) to custom action data"); } hr = WcaWriteStringToCaData(pwzPort, &pwzCustomActionData); ExitOnFailure(hr, "failed to write application path to custom action data"); hr = WcaWriteIntegerToCaData(iProtocol, &pwzCustomActionData); ExitOnFailure(hr, "failed to write exception protocol to custom action data"); hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData); ExitOnFailure(hr, "failed to write firewall rule description to custom action data"); } // reaching the end of the list is actually a good thing, not an error if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "failure occured while processing WixFirewallException table"); // schedule ExecFirewallExceptions if there's anything to do if (pwzCustomActionData && *pwzCustomActionData) { WcaLog(LOGMSG_STANDARD, "Scheduling firewall exception (%ls)", pwzCustomActionData); if (WCA_TODO_INSTALL == todoSched) { hr = WcaDoDeferredAction(L"WixRollbackFirewallExceptionsInstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback"); hr = WcaDoDeferredAction(L"WixExecFirewallExceptionsInstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); ExitOnFailure(hr, "failed to schedule firewall install exceptions execution"); } else { hr = WcaDoDeferredAction(L"WixRollbackFirewallExceptionsUninstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback"); hr = WcaDoDeferredAction(L"WixExecFirewallExceptionsUninstall", pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution"); } } else { WcaLog(LOGMSG_STANDARD, "No firewall exceptions scheduled"); } LExit: ReleaseStr(pwzCustomActionData); ReleaseStr(pwzName); ReleaseStr(pwzRemoteAddresses); ReleaseStr(pwzPort); ReleaseStr(pwzProgram); ReleaseStr(pwzComponent); ReleaseStr(pwzDescription); ReleaseStr(pwzFormattedFile); return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); }
/* **************************************************************** ScaUserExecute - Schedules user account creation or removal based on component state. ******************************************************************/ HRESULT ScaUserExecute( __in SCA_USER *psuList ) { HRESULT hr = S_OK; DWORD er = 0; PDOMAIN_CONTROLLER_INFOW pDomainControllerInfo = NULL; USER_INFO_0 *pUserInfo = NULL; LPWSTR pwzActionData = NULL; LPWSTR pwzRollbackData = NULL; for (SCA_USER *psu = psuList; psu; psu = psu->psuNext) { USER_EXISTS ueUserExists = USER_EXISTS_INDETERMINATE; // Always put the User Name and Domain plus Attributes on the front of the CustomAction // data. Sometimes we'll add more data. Assert(psu->wzName); hr = WcaWriteStringToCaData(psu->wzName, &pwzActionData); ExitOnFailure1(hr, "Failed to add user name to custom action data: %ls", psu->wzName); hr = WcaWriteStringToCaData(psu->wzDomain, &pwzActionData); ExitOnFailure1(hr, "Failed to add user domain to custom action data: %ls", psu->wzDomain); hr = WcaWriteIntegerToCaData(psu->iAttributes, &pwzActionData); ExitOnFailure1(hr, "failed to add user attributes to custom action data for user: %ls", psu->wzKey); // Check to see if the user already exists since we have to be very careful when adding // and removing users. Note: MSDN says that it is safe to call these APIs from any // user, so we should be safe calling it during immediate mode. er = ::NetApiBufferAllocate(sizeof(USER_INFO_0), reinterpret_cast<LPVOID*>(&pUserInfo)); hr = HRESULT_FROM_WIN32(er); ExitOnFailure1(hr, "Failed to allocate memory to check existence of user: %ls", psu->wzName); LPCWSTR wzDomain = psu->wzDomain; if (wzDomain && *wzDomain) { er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, NULL, &pDomainControllerInfo); if (HRESULT_FROM_WIN32(er) == RPC_S_SERVER_UNAVAILABLE) { // MSDN says, if we get the above error code, try again with the "DS_FORCE_REDISCOVERY" flag er = ::DsGetDcNameW(NULL, wzDomain, NULL, NULL, DS_FORCE_REDISCOVERY, &pDomainControllerInfo); } if (ERROR_SUCCESS == er) { wzDomain = pDomainControllerInfo->DomainControllerName + 2; //Add 2 so that we don't get the \\ prefix } } er = ::NetUserGetInfo(wzDomain, psu->wzName, 0, reinterpret_cast<LPBYTE*>(pUserInfo)); if (NERR_Success == er) { ueUserExists = USER_EXISTS_YES; } else if (NERR_UserNotFound == er) { ueUserExists = USER_EXISTS_NO; } else { ueUserExists = USER_EXISTS_INDETERMINATE; hr = HRESULT_FROM_WIN32(er); WcaLog(LOGMSG_VERBOSE, "Failed to check existence of domain: %ls, user: %ls (error code 0x%x) - continuing", wzDomain, psu->wzName, hr); } if (WcaIsInstalling(psu->isInstalled, psu->isAction)) { // If the user exists, check to see if we are supposed to fail if user the exists before // the install. if (USER_EXISTS_YES == ueUserExists) { // Reinstalls will always fail if we don't remove the check for "fail if exists". if (WcaIsReInstalling(psu->isInstalled, psu->isAction)) { psu->iAttributes &= ~SCAU_FAIL_IF_EXISTS; } if ((SCAU_FAIL_IF_EXISTS & (psu->iAttributes)) && !(SCAU_UPDATE_IF_EXISTS & (psu->iAttributes))) { hr = HRESULT_FROM_WIN32(NERR_UserExists); MessageExitOnFailure1(hr, msierrUSRFailedUserCreateExists, "Failed to create user: %ls because user already exists.", psu->wzName); } } // Rollback only if the user already exists, we couldn't determine if the user exists, or we are going to create the user if ((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists) || !(psu->iAttributes & SCAU_DONT_CREATE_USER)) { INT iRollbackUserAttributes = psu->iAttributes; // If the user already exists, ensure this is accounted for in rollback if (USER_EXISTS_YES == ueUserExists) { iRollbackUserAttributes |= SCAU_DONT_CREATE_USER; } else { iRollbackUserAttributes &= ~SCAU_DONT_CREATE_USER; } hr = WcaWriteStringToCaData(psu->wzName, &pwzRollbackData); ExitOnFailure1(hr, "Failed to add user name to rollback custom action data: %ls", psu->wzName); hr = WcaWriteStringToCaData(psu->wzDomain, &pwzRollbackData); ExitOnFailure1(hr, "Failed to add user domain to rollback custom action data: %ls", psu->wzDomain); hr = WcaWriteIntegerToCaData(iRollbackUserAttributes, &pwzRollbackData); ExitOnFailure1(hr, "failed to add user attributes to rollback custom action data for user: %ls", psu->wzKey); // If the user already exists, add relevant group information to rollback data if (USER_EXISTS_YES == ueUserExists || USER_EXISTS_INDETERMINATE == ueUserExists) { hr = WriteGroupRollbackInfo(psu->wzName, psu->wzDomain, psu->psgGroups, &pwzRollbackData); ExitOnFailure(hr, "failed to add group information to rollback custom action data"); } hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"CreateUserRollback"), pwzRollbackData, COST_USER_DELETE); ExitOnFailure(hr, "failed to schedule CreateUserRollback"); } // // Schedule the creation now. // hr = WcaWriteStringToCaData(psu->wzPassword, &pwzActionData); ExitOnFailure1(hr, "failed to add user password to custom action data for user: %ls", psu->wzKey); // Add user's group information to custom action data hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); ExitOnFailure(hr, "failed to add group information to custom action data"); hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"CreateUser"), pwzActionData, COST_USER_ADD); ExitOnFailure(hr, "failed to schedule CreateUser"); } else if (((USER_EXISTS_YES == ueUserExists) || (USER_EXISTS_INDETERMINATE == ueUserExists)) && WcaIsUninstalling(psu->isInstalled, psu->isAction) && !(psu->iAttributes & SCAU_DONT_REMOVE_ON_UNINSTALL)) { // Add user's group information - this will ensure the user can be removed from any groups they were added to, if the user isn't be deleted hr = WriteGroupInfo(psu->psgGroups, &pwzActionData); ExitOnFailure(hr, "failed to add group information to custom action data"); // // Schedule the removal because the user exists and we don't have any flags set // that say, don't remove the user on uninstall. // // Note: We can't rollback the removal of a user which is why RemoveUser is a commit // CustomAction. hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"RemoveUser"), pwzActionData, COST_USER_DELETE); ExitOnFailure(hr, "failed to schedule RemoveUser"); } ReleaseNullStr(pwzActionData); ReleaseNullStr(pwzRollbackData); if (pUserInfo) { ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); pUserInfo = NULL; } if (pDomainControllerInfo) { ::NetApiBufferFree(static_cast<LPVOID>(pDomainControllerInfo)); pDomainControllerInfo = NULL; } } LExit: ReleaseStr(pwzActionData); ReleaseStr(pwzRollbackData); if (pUserInfo) { ::NetApiBufferFree(static_cast<LPVOID>(pUserInfo)); } if (pDomainControllerInfo) { ::NetApiBufferFree(static_cast<LPVOID>(pDomainControllerInfo)); } return hr; }
/****************************************************************** WixSchedInternetShortcuts - entry point ********************************************************************/ extern "C" UINT __stdcall WixSchedInternetShortcuts( __in MSIHANDLE hInstall ) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; UINT uiCost = 0; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; MSIHANDLE hCreateFolderTable = NULL; MSIHANDLE hCreateFolderColumns = NULL; LPWSTR pwzCustomActionData = NULL; LPWSTR pwzComponent = NULL; LPWSTR pwzDirectory = NULL; LPWSTR pwzFilename = NULL; LPWSTR pwzTarget = NULL; LPWSTR pwzShortcutPath = NULL; int iAttr = 0; LPWSTR pwzIconFile = NULL; int iIconIndex = 0; IUniformResourceLocatorW* piURL = NULL; IShellLinkW* piShellLink = NULL; BOOL fInitializedCom = FALSE; hr = WcaInitialize(hInstall, "WixSchedInternetShortcuts"); ExitOnFailure(hr, "failed to initialize WixSchedInternetShortcuts."); // anything to do? if (S_OK != WcaTableExists(L"WixInternetShortcut")) { WcaLog(LOGMSG_STANDARD, "WixInternetShortcut table doesn't exist, so there are no Internet shortcuts to process"); goto LExit; } // check to see if we can create a shortcut - Server Core and others may not have a shell registered. hr = ::CoInitialize(NULL); ExitOnFailure(hr, "failed to initialize COM"); fInitializedCom = TRUE; hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL); if (S_OK != hr) { WcaLog(LOGMSG_STANDARD, "failed to create an instance of IUniformResourceLocatorW, skipping shortcut creation"); ExitFunction1(hr = S_OK); } hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink); if (S_OK != hr) { WcaLog(LOGMSG_STANDARD, "failed to create an instance of IShellLinkW, skipping shortcut creation"); ExitFunction1(hr = S_OK); } // query and loop through all the shortcuts hr = WcaOpenExecuteView(vcsShortcutsQuery, &hView); ExitOnFailure(hr, "failed to open view on WixInternetShortcut table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { // read column values hr = WcaGetRecordString(hRec, esqComponent, &pwzComponent); ExitOnFailure(hr, "failed to get shortcut component"); hr = WcaGetRecordString(hRec, esqDirectory, &pwzDirectory); ExitOnFailure(hr, "failed to get shortcut directory"); hr = WcaGetRecordString(hRec, esqFilename, &pwzFilename); ExitOnFailure(hr, "failed to get shortcut filename"); hr = WcaGetRecordFormattedString(hRec, esqTarget, &pwzTarget); ExitOnFailure(hr, "failed to get shortcut target"); hr = WcaGetRecordInteger(hRec, esqAttributes, &iAttr); ExitOnFailure(hr, "failed to get shortcut attributes"); hr = WcaGetRecordFormattedString(hRec, esqIconFile, &pwzIconFile); ExitOnFailure(hr, "failed to get shortcut icon file"); hr = WcaGetRecordInteger(hRec, esqIconIndex, &iIconIndex); ExitOnFailure(hr, "failed to get shortcut icon index"); // skip processing this WixInternetShortcut row if the component isn't being configured WCA_TODO todo = WcaGetComponentToDo(pwzComponent); if (WCA_TODO_UNKNOWN == todo) { WcaLog(LOGMSG_VERBOSE, "Skipping shortcut for null-action component '%ls'", pwzComponent); continue; } // we need to create the directory where the shortcut is supposed to live; rather // than doing so in our deferred custom action, use the CreateFolder table to have MSI // make (and remove) them on our behalf (including the correct cleanup of parent directories). MSIDBERROR dbError = MSIDBERROR_NOERROR; WcaLog(LOGMSG_STANDARD, "Adding folder '%ls', component '%ls' to the CreateFolder table", pwzDirectory, pwzComponent); hr = WcaAddTempRecord(&hCreateFolderTable, &hCreateFolderColumns, L"CreateFolder", &dbError, 0, 2, pwzDirectory, pwzComponent); if (MSIDBERROR_DUPLICATEKEY == dbError) { WcaLog(LOGMSG_STANDARD, "Folder '%ls' already exists in the CreateFolder table; the above error is harmless", pwzDirectory); hr = S_OK; } ExitOnFailure(hr, "Couldn't add temporary CreateFolder row"); // only if we're installing/reinstalling do we need to schedule the deferred CA // (uninstallation is handled via permanent RemoveFile rows and temporary CreateFolder rows) if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo) { // turn the Directory_ id into a path hr = WcaGetTargetPath(pwzDirectory, &pwzShortcutPath); ExitOnFailure(hr, "failed to allocate string for shortcut directory"); // append the shortcut filename hr = StrAllocConcat(&pwzShortcutPath, pwzFilename, 0); ExitOnFailure(hr, "failed to allocate string for shortcut filename"); // write the shortcut path and target to custom action data for deferred CAs hr = WcaWriteStringToCaData(pwzShortcutPath, &pwzCustomActionData); ExitOnFailure(hr, "failed to write shortcut path to custom action data"); hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData); ExitOnFailure(hr, "failed to write shortcut target to custom action data"); hr = WcaWriteIntegerToCaData(iAttr, &pwzCustomActionData); ExitOnFailure(hr, "failed to write shortcut attributes to custom action data"); hr = WcaWriteStringToCaData(pwzIconFile, &pwzCustomActionData); ExitOnFailure(hr, "failed to write icon file to custom action data"); hr = WcaWriteIntegerToCaData(iIconIndex, &pwzCustomActionData); ExitOnFailure(hr, "failed to write icon index to custom action data"); uiCost += COST_INTERNETSHORTCUT; } } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "Failure occured while processing WixInternetShortcut table"); // if we have any shortcuts to install if (pwzCustomActionData && *pwzCustomActionData) { // add cost to progress bar hr = WcaProgressMessage(uiCost, TRUE); ExitOnFailure(hr, "failed to extend progress bar for InternetShortcuts"); // provide custom action data to deferred and rollback CAs hr = WcaSetProperty(PLATFORM_DECORATION(L"WixRollbackInternetShortcuts"), pwzCustomActionData); ExitOnFailure(hr, "failed to set WixRollbackInternetShortcuts rollback custom action data"); hr = WcaSetProperty(PLATFORM_DECORATION(L"WixCreateInternetShortcuts"), pwzCustomActionData); ExitOnFailure(hr, "failed to set WixCreateInternetShortcuts custom action data"); } LExit: if (hCreateFolderTable) { ::MsiCloseHandle(hCreateFolderTable); } if (hCreateFolderColumns) { ::MsiCloseHandle(hCreateFolderColumns); } ReleaseStr(pwzCustomActionData); ReleaseStr(pwzComponent); ReleaseStr(pwzDirectory); ReleaseStr(pwzFilename); ReleaseStr(pwzTarget); ReleaseStr(pwzShortcutPath); ReleaseObject(piShellLink); ReleaseObject(piURL); if (fInitializedCom) { ::CoUninitialize(); } er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
static HRESULT SchedCreateDatabase( __in SCA_DB* psd ) { HRESULT hr = S_OK; WCHAR* pwzCustomActionData = NULL; hr = WcaWriteStringToCaData(psd->wzKey, &pwzCustomActionData); ExitOnFailure(hr, "failed to add DBKey to CustomActionData"); hr = WcaWriteStringToCaData(psd->wzServer, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server name to CustomActionData"); hr = WcaWriteStringToCaData(psd->wzInstance, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server instance to CustomActionData"); hr = WcaWriteStringToCaData(psd->wzDatabase, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add database name to CustomActionData"); hr = WcaWriteIntegerToCaData(psd->iAttributes, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add Sql attributes to CustomActionData"); hr = WcaWriteStringToCaData(psd->fUseIntegratedAuth ? L"1" : L"0", &pwzCustomActionData); ExitOnFailure(hr, "Failed to add if integrated connection to CustomActionData"); hr = WcaWriteStringToCaData(psd->scau.wzName, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add server user to CustomActionData"); hr = WcaWriteStringToCaData(psd->scau.wzPassword, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add user password to CustomActionData"); // Check to see if the database exists, if it does not then schedule a rollback // so we clean up after ourselves if the creation of the database fails or is // aborted. It is interesting to note that we can do this check here because the // deferred CustomActions are Impersonated. That means this scheduling action and // the execution actions all run with the same user context, so it is safe to // to do the check. hr = SqlDatabaseExists(psd->wzServer, psd->wzInstance, psd->wzDatabase, psd->fUseIntegratedAuth, psd->scau.wzName, psd->scau.wzPassword, NULL); if (S_FALSE == hr) { hr = WcaDoDeferredAction(L"RollbackCreateDatabase", pwzCustomActionData, COST_SQL_CREATEDB); ExitOnFailure(hr, "Failed to schedule RollbackCreateDatabase action"); } // database filespec if (psd->fHasDbSpec) { hr = WcaWriteStringToCaData(L"1", &pwzCustomActionData); ExitOnFailure(hr, "failed to specify that do have db.filespec to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfDb.wzName, &pwzCustomActionData); ExitOnFailure(hr, "failed to add FileSpec.Name to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfDb.wzFilename, &pwzCustomActionData); ExitOnFailure(hr, "failed to add FileSpec.Filename to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfDb.wzSize, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.Size to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfDb.wzMaxSize, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.MaxSize to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfDb.wzGrow, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.GrowthSize to CustomActionData"); } else { hr = WcaWriteStringToCaData(L"0", &pwzCustomActionData); ExitOnFailure(hr, "failed to specify that do not have db.filespec to CustomActionData"); } // log filespec if (psd->fHasLogSpec) { hr = WcaWriteStringToCaData(L"1", &pwzCustomActionData); ExitOnFailure(hr, "failed to specify that do have log.filespec to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfLog.wzName, &pwzCustomActionData); ExitOnFailure(hr, "failed to add FileSpec.Name to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfLog.wzFilename, &pwzCustomActionData); ExitOnFailure(hr, "failed to add FileSpec.Filename to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfLog.wzSize, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.Size to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfLog.wzMaxSize, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.MaxSize to CustomActionData"); hr = WcaWriteStringToCaData(psd->sfLog.wzGrow, &pwzCustomActionData); ExitOnFailure(hr, "Failed to add FileSpec.GrowthSize to CustomActionData"); } else { hr = WcaWriteStringToCaData(L"0", &pwzCustomActionData); ExitOnFailure(hr, "failed to specify that do not have log.filespec to CustomActionData"); } // schedule the CreateDatabase action hr = WcaDoDeferredAction(L"CreateDatabase", pwzCustomActionData, COST_SQL_CREATEDB); ExitOnFailure(hr, "Failed to schedule CreateDatabase action"); LExit: ReleaseStr(pwzCustomActionData); return hr; }