HRESULT ScaDbsInstall( __in SCA_DB* psdList ) { HRESULT hr = S_FALSE; // assume nothing will be done SCA_DB* psd = NULL; for (psd = psdList; psd; psd = psd->psdNext) { if (psd->fHasComponent) { // if we need to drop, do that first if (((psd->iAttributes & SCADB_DROP_ON_INSTALL) && WcaIsInstalling(psd->isInstalled, psd->isAction) && !WcaIsReInstalling(psd->isInstalled, psd->isAction)) || ((psd->iAttributes & SCADB_DROP_ON_REINSTALL) && WcaIsReInstalling(psd->isInstalled, psd->isAction))) { hr = SchedDropDatabase(psd->wzKey, psd->wzServer, psd->wzInstance, psd->wzDatabase, psd->iAttributes, psd->fUseIntegratedAuth, psd->scau.wzName, psd->scau.wzPassword); ExitOnFailure1(hr, "Failed to drop database %ls", psd->wzKey); } // if installing this component if (((psd->iAttributes & SCADB_CREATE_ON_INSTALL) && WcaIsInstalling(psd->isInstalled, psd->isAction) && !WcaIsReInstalling(psd->isInstalled, psd->isAction)) || ((psd->iAttributes & SCADB_CREATE_ON_REINSTALL) && WcaIsReInstalling(psd->isInstalled, psd->isAction))) { hr = SchedCreateDatabase(psd); ExitOnFailure1(hr, "Failed to ensure database %ls exists", psd->wzKey); } } } LExit: return hr; }
/******************************************************************** WcaGetComponentToDo() - gets a component's install states and determines if they mean install, uninstall, or reinstall. ********************************************************************/ extern "C" WCA_TODO WIXAPI WcaGetComponentToDo( __in_z LPCWSTR wzComponentId ) { INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; if (ERROR_SUCCESS != ::MsiGetComponentStateW(WcaGetInstallHandle(), wzComponentId, &isInstalled, &isAction)) { return WCA_TODO_UNKNOWN; } if (WcaIsReInstalling(isInstalled, isAction)) { return WCA_TODO_REINSTALL; } else if (WcaIsUninstalling(isInstalled, isAction)) { return WCA_TODO_UNINSTALL; } else if (WcaIsInstalling(isInstalled, isAction)) { return WCA_TODO_INSTALL; } else { return WCA_TODO_UNKNOWN; } }
HRESULT ScaWebDirsInstall(IMSAdminBase* piMetabase, SCA_WEBDIR* pswdList, SCA_APPPOOL * psapList) { HRESULT hr = S_OK; SCA_WEBDIR* pswd = pswdList; int i; while (pswd) { // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created if (WcaIsReInstalling(pswd->isInstalled, pswd->isAction)) { if (pswd->fHasApplication) { hr = ScaDeleteApp(piMetabase, pswd->wzWebDirRoot); ExitOnFailure(hr, "Failed to remove application for WebDir as part of a reinstall"); } } // if we are installing the web site if (WcaIsInstalling(pswd->isInstalled, pswd->isAction)) { hr = ScaCreateMetabaseKey(piMetabase, pswd->wzWebDirRoot, L""); ExitOnFailure(hr, "Failed to create key for WebDir"); hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebDirectory"); ExitOnFailure(hr, "Failed to write key type for for WebDir"); i = 0x4000003e; // 1073741886: default directory browsing rights hr = ScaWriteMetabaseValue(piMetabase, pswd->wzWebDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i)); ExitOnFailure(hr, "Failed to set directory browsing for WebDir"); // get the security information for this web if (pswd->fHasProperties) { ScaWriteWebDirProperties(piMetabase, pswd->wzWebDirRoot, &pswd->swp); ExitOnFailure(hr, "Failed to write properties for WebDir"); } // get the application information for this web directory if (pswd->fHasApplication) { hr = ScaWriteWebApplication(piMetabase, pswd->wzWebDirRoot, &pswd->swapp, psapList); ExitOnFailure(hr, "Failed to write application for WebDir"); } } pswd = pswd->pswdNext; } LExit: return hr; }
/* **************************************************************** 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; }
HRESULT ScaWebsRead( __in IMSAdminBase* piMetabase, __in SCA_MIMEMAP** ppsmmList, __in SCA_WEB** ppswList, __in SCA_HTTP_HEADER** ppshhList, __in SCA_WEB_ERROR** ppsweList, __in WCA_WRAPQUERY_HANDLE hUserQuery, __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, __in WCA_WRAPQUERY_HANDLE hSslCertQuery, __in WCA_WRAPQUERY_HANDLE hWebLogQuery, __in WCA_WRAPQUERY_HANDLE hWebAppQuery, __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, __inout LPWSTR *ppwzCustomActionData ) { Assert(piMetabase && ppswList); HRESULT hr = S_OK; MSIHANDLE hRec; MSIHANDLE hRecAddresses; SCA_WEB* psw = NULL; LPWSTR pwzData = NULL; int iSiteId; DWORD dwLen = 0; WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL; WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL; hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData); ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData); ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); if (0 == WcaGetQueryRecords(hQueryWebSite)) { WcaLog(LOGMSG_VERBOSE, "Required tables not present"); ExitFunction1(hr = S_FALSE); } // loop through all the webs while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec))) { psw = NewWeb(); ExitOnNull(psw, hr, E_OUTOFMEMORY, "Failed to allocate memory for web object in memory"); // get the darwin information hr = WcaGetRecordString(hRec, wqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web"); hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData); ExitOnFailure(hr, "Failed to copy key string to web object"); if (*pwzData && *ppsmmList) { hr = ScaGetMimeMap(mmptWeb, pwzData, ppsmmList, &psw->psmm); ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); } // get component install state hr = WcaGetRecordString(hRec, wqComponent, &pwzData); ExitOnFailure(hr, "Failed to get Component for Web"); hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData); ExitOnFailure(hr, "Failed to copy component string to web object"); if (*(psw->wzComponent)) { psw->fHasComponent = TRUE; hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled); ExitOnFailure(hr, "Failed to get web Component's installed state"); WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction); ExitOnFailure(hr, "Failed to get web Component's action state"); if (!WcaIsInstalling(psw->isInstalled, psw->isAction) && !WcaIsUninstalling(psw->isInstalled, psw->isAction) && !WcaIsReInstalling(psw->isInstalled, psw->isAction)) { FreeWeb(psw); psw = NULL; continue; // If we aren't acting on this component, skip it } } hr = WcaGetRecordInteger(hRec, wqId, &iSiteId); ExitOnFailure(hr, "Failed to get SiteId for Web"); // Get the web's key address. hr = WcaGetRecordString(hRec, wqAddress, &pwzData); ExitOnFailure(hr, "Failed to get Address for Web"); hr = ::StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData); ExitOnFailure(hr, "Failed to copy key string to web object"); hr = WcaGetRecordString(hRec, wqIP, &pwzData); ExitOnFailure(hr, "Failed to get IP for Web"); hr = ::StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData); ExitOnFailure(hr, "Failed to copy IP string to web object"); hr = WcaGetRecordString(hRec, wqPort, &pwzData); ExitOnFailure(hr, "Failed to get Web Address port"); psw->swaKey.iPort = wcstol(pwzData, NULL, 10); hr = WcaGetRecordString(hRec, wqHeader, &pwzData); ExitOnFailure(hr, "Failed to get Header for Web"); hr = ::StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData); ExitOnFailure(hr, "Failed to copy header string to web object"); hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure); ExitOnFailure(hr, "Failed to get if Web is secure"); if (S_FALSE == hr) { psw->swaKey.fSecure = FALSE; } // Get the web's description. hr = WcaGetRecordString(hRec, wqDescription, &pwzData); ExitOnFailure(hr, "Failed to get Description for Web"); hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData); ExitOnFailure(hr, "Failed to copy description string to web object"); // Try to find the web root in case it already exists. dwLen = METADATA_MAX_NAME_LEN; hr = ScaWebFindBase(piMetabase, *ppswList, psw->wzKey, iSiteId, psw->swaKey.wzIP, psw->swaKey.iPort, psw->swaKey.wzHeader, psw->swaKey.fSecure, psw->wzDescription, psw->wzWebBase, dwLen); if (S_OK == hr) { psw->fBaseExists = TRUE; } else if (S_FALSE == hr) // didn't find the web site. { psw->fBaseExists = FALSE; // If we're actually configuring the web site. if (psw->fHasComponent) { if (WcaIsInstalling(psw->isInstalled, psw->isAction)) { hr = ScaWebFindFreeBase(piMetabase, *ppswList, iSiteId, psw->wzDescription, psw->wzWebBase, countof(psw->wzWebBase)); ExitOnFailure(hr, "Failed to find free web root."); } else if (WcaIsUninstalling(psw->isInstalled, psw->isAction)) { WcaLog(LOGMSG_VERBOSE, "Web site: '%ls' was already removed, skipping.", psw->wzKey); hr = S_OK; continue; } } } ExitOnFailure(hr, "Failed to find web root"); // get any extra web addresses WcaFetchWrappedReset(hQueryWebAddress); while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses))) { if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses) { hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded."); } hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData); ExitOnFailure(hr, "Failed to get extra web Address"); // if this isn't the key address add it if (0 != lstrcmpW(pwzData, psw->swaKey.wzKey)) { hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData); ExitOnFailure(hr, "Failed to copy extra addresses key string to web object"); hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData); ExitOnFailure(hr, "Failed to get extra web IP"); hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData); ExitOnFailure(hr, "Failed to copy extra addresses IP string to web object"); hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData); ExitOnFailure(hr, "Failed to get port for extra web IP"); psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10); hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData); ExitOnFailure(hr, "Failed to get header for extra web IP"); hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData); ExitOnFailure(hr, "Failed to copy extra addresses header string to web object"); hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure); ExitOnFailure(hr, "Failed to get if secure extra web IP"); if (S_FALSE == hr) psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE; ++psw->cExtraAddresses; } } if (E_NOMOREITEMS == hr) hr = S_OK; ExitOnFailure(hr, "Failure occured while getting extra web addresses"); hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout); ExitOnFailure(hr, "Failed to get connection timeout for Web"); if (psw->fHasComponent) // If we're installing it, it needs a dir { // get the web's directory if (INSTALLSTATE_SOURCE == psw->isAction) { hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData); } else { hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData); } ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); // remove trailing backslashes while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') { pwzData[lstrlenW(pwzData)-1] = 0; } hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData); ExitOnFailure(hr, "Failed to copy directory string to web object"); } hr = WcaGetRecordInteger(hRec, wqState, &psw->iState); ExitOnFailure(hr, "Failed to get state for Web"); hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes); ExitOnFailure(hr, "Failed to get attributes for Web"); // get the dir properties for this web hr = WcaGetRecordString(hRec, wqProperties, &pwzData); ExitOnFailure(hr, "Failed to get directory property record for Web"); if (*pwzData) { hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp); ExitOnFailure(hr, "Failed to get directory properties for Web"); psw->fHasProperties = TRUE; } // get the application information for this web hr = WcaGetRecordString(hRec, wqApplication, &pwzData); ExitOnFailure(hr, "Failed to get application identifier for Web"); if (*pwzData) { hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp); ExitOnFailure(hr, "Failed to get application for Web"); psw->fHasApplication = TRUE; } // get the SSL certificates hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList)); ExitOnFailure(hr, "Failed to get SSL Certificates."); // get the custom headers if (*ppshhList) { hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList)); ExitOnFailure(hr, "Failed to get Custom HTTP Headers"); } // get the errors if (*ppsweList) { hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList)); ExitOnFailure(hr, "Failed to get Custom Errors"); } // get the log information for this web hr = WcaGetRecordString(hRec, wqLog, &pwzData); ExitOnFailure(hr, "Failed to get log identifier for Web"); if (*pwzData) { hr = ScaGetWebLog(piMetabase, pwzData, hWebLogQuery, &psw->swl); ExitOnFailure(hr, "Failed to get Log for Web."); psw->fHasLog = TRUE; } *ppswList = AddWebToList(*ppswList, psw); psw = NULL; // set the web NULL so it doesn't accidentally get freed below } if (E_NOMOREITEMS == hr) { hr = S_OK; } LExit: // if anything was left over after an error clean it all up WcaFinishUnwrapQuery(hQueryWebSite); WcaFinishUnwrapQuery(hQueryWebAddress); if (psw) { ScaWebsFreeList(psw); } ReleaseStr(pwzData); return hr; }
HRESULT ScaVirtualDirsInstall( __in IMSAdminBase* piMetabase, __in SCA_VDIR* psvdList, __in SCA_APPPOOL * psapList ) { Assert(piMetabase); HRESULT hr = S_OK; SCA_VDIR* psvd = psvdList; int i; while (psvd) { // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created if (WcaIsReInstalling(psvd->isInstalled, psvd->isAction)) { if (psvd->fHasApplication) { hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot); ExitOnFailure(hr, "Failed to remove application for WebVDir as part of a reinstall"); } } if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) { hr = ScaCreateMetabaseKey(piMetabase, psvd->wzVDirRoot, L""); ExitOnFailure(hr, "Failed to create key for VirtualDir"); hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir"); ExitOnFailure(hr, "Failed to write key type for for VirtualDir"); i = 0x4000003e; // 1073741886; // default directory browsing rights hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i)); ExitOnFailure(hr, "Failed to set directory browsing for VirtualDir"); hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psvd->wzDirectory); ExitOnFailure(hr, "Failed to write Directory for VirtualDir"); if (psvd->fHasProperties) { ScaWriteWebDirProperties(piMetabase, psvd->wzVDirRoot, &psvd->swp); ExitOnFailure(hr, "Failed to write directory properties for VirtualDir"); } if (psvd->fHasApplication) { hr = ScaWriteWebApplication(piMetabase, psvd->wzVDirRoot, &psvd->swapp, psapList); ExitOnFailure(hr, "Failed to write application for VirtualDir"); } if (psvd->psmm) { hr = ScaWriteMimeMap(piMetabase, psvd->wzVDirRoot, psvd->psmm); ExitOnFailure(hr, "Failed to write mimemap for VirtualDir"); } if (psvd->pshh) { hr = ScaWriteHttpHeader(piMetabase, psvd->wzVDirRoot, psvd->pshh); ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir"); } if (psvd->pswe) { hr = ScaWriteWebError(piMetabase, weptVDir, psvd->wzVDirRoot, psvd->pswe); ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir"); } } psvd = psvd->psvdNext; } LExit: return hr; }
HRESULT __stdcall ScaVirtualDirsRead( __in IMSAdminBase* piMetabase, __in SCA_WEB* pswList, __in SCA_VDIR** ppsvdList, __in SCA_MIMEMAP** ppsmmList, __in SCA_HTTP_HEADER** ppshhList, __in SCA_WEB_ERROR** ppsweList, __in WCA_WRAPQUERY_HANDLE hUserQuery, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, __in WCA_WRAPQUERY_HANDLE hWebAppQuery, __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, __inout LPWSTR *ppwzCustomActionData ) { Assert(piMetabase && ppsvdList); HRESULT hr = S_OK; MSIHANDLE hRec; INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; SCA_VDIR* pvdir = NULL; LPWSTR pwzData = NULL; WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); if (0 == WcaGetQueryRecords(hWrapQuery)) { WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present"); ExitFunction1(hr = S_FALSE); } // loop through all the vdirs while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) { // Get the Component first. If there is a Component and it is not being modified during // this transaction, skip processing this whole record. hr = WcaGetRecordString(hRec, vdqComponent, &pwzData); ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component"); hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&isInstalled); ExitOnFailure(hr, "Failed to get Component installed state for virtual dir"); hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&isAction); ExitOnFailure(hr, "Failed to get Component action state for virtual dir"); if (!WcaIsInstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction) && !WcaIsUninstalling(isInstalled, isAction)) { continue; // skip this record. } hr = AddVirtualDirToList(ppsvdList); ExitOnFailure(hr, "failed to add virtual dir to list"); pvdir = *ppsvdList; hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData); ExitOnFailure1(hr, "failed to copy component name: %ls", pwzData); pvdir->isInstalled = isInstalled; pvdir->isAction = isAction; // get the web key hr = WcaGetRecordString(hRec, vdqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web for VirtualDir"); hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, countof(pvdir->wzWebBase), hWebBaseQuery); if (WcaIsUninstalling(isInstalled, isAction)) { // If we're uninstalling, ignore any failure to find the existing web hr = S_OK; } ExitOnFailure1(hr, "Failed to get base of web: %ls for VirtualDir", pwzData); hr = WcaGetRecordString(hRec, vdqAlias, &pwzData); ExitOnFailure(hr, "Failed to get Alias for VirtualDir"); if (0 != lstrlenW(pvdir->wzWebBase)) { hr = ::StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData); ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir"); } // get the vdir's directory hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData); ExitOnFailure(hr, "Failed to get Directory for VirtualDir"); // get the web's directory if (INSTALLSTATE_SOURCE == pvdir->isAction) { hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData); } else { hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData); } ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); // remove trailing backslash(es) while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') { pwzData[lstrlenW(pwzData)-1] = 0; } hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData); ExitOnFailure(hr, "Failed to copy directory string to vdir object"); // get the security information for this web hr = WcaGetRecordString(hRec, vdqProperties, &pwzData); ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir"); if (*pwzData) { hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp); ExitOnFailure(hr, "Failed to get web directory for VirtualDir"); pvdir->fHasProperties = TRUE; } // get the application information for this web hr = WcaGetRecordString(hRec, vdqApplication, &pwzData); ExitOnFailure(hr, "Failed to get application identifier for VirtualDir"); if (*pwzData) { hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp); ExitOnFailure(hr, "Failed to get application for VirtualDir"); pvdir->fHasApplication = TRUE; } hr = WcaGetRecordString(hRec, vdqVDir, &pwzData); ExitOnFailure(hr, "Failed to get VDir for VirtualDir"); if (*pwzData && *ppsmmList) { hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm); ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); } if (*pwzData && *ppshhList) { hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh); ExitOnFailure1(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData); } if (*pwzData && *ppsweList) { hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe); ExitOnFailure1(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData); } } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "Failure while processing VirtualDirs"); LExit: WcaFinishUnwrapQuery(hWrapQuery); ReleaseStr(pwzData); return hr; }
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; }
/****************************************************************** 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); }
UINT __stdcall ScaWebDirsRead( __in IMSAdminBase* piMetabase, __in SCA_WEB* pswList, __in WCA_WRAPQUERY_HANDLE hUserQuery, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, __in WCA_WRAPQUERY_HANDLE hWebAppQuery, __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, __inout LPWSTR *ppwzCustomActionData, __out SCA_WEBDIR** ppswdList ) { Assert(piMetabase && ppswdList); HRESULT hr = S_OK; MSIHANDLE hRec; LPWSTR pwzData = NULL; SCA_WEBDIR* pswd; WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); ExitOnFailure(hr, "Failed to unwrap query for ScaWebDirsRead"); if (0 == WcaGetQueryRecords(hWrapQuery)) { WcaLog(LOGMSG_VERBOSE, "Skipping ScaInstallWebDirs() because IIsWebDir table not present"); ExitFunction1(hr = S_FALSE); } // loop through all the web directories while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) { pswd = NewWebDir(); ExitOnNull(pswd, hr, E_OUTOFMEMORY, "Failed to allocate memory for web dir object in memory"); // get component install state hr = WcaGetRecordString(hRec, wdqComponent, &pwzData); ExitOnFailure(hr, "Failed to get Component for WebDirs"); hr = ::StringCchCopyW(pswd->wzComponent, countof(pswd->wzComponent), pwzData); ExitOnFailure(hr, "Failed to copy component string to webdir object"); hr = WcaGetRecordInteger(hRec, wdqInstalled, (int *)&pswd->isInstalled); ExitOnFailure(hr, "Failed to get Component installed state for webdir"); hr = WcaGetRecordInteger(hRec, wdqAction, (int *)&pswd->isAction); ExitOnFailure(hr, "Failed to get Component action state for webdir"); // If this record has a component and no action is being taken for it, skip processing it entirely if (0 < lstrlenW(pswd->wzComponent) && !WcaIsInstalling(pswd->isInstalled, pswd->isAction) && !WcaIsUninstalling(pswd->isInstalled, pswd->isAction) && !WcaIsReInstalling(pswd->isInstalled, pswd->isAction)) { FreeWebDir(pswd); pswd = NULL; continue; } hr = WcaGetRecordString(hRec, wdqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web for WebDir"); hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pswd->wzWebBase, countof(pswd->wzWebBase), hWebBaseQuery); if (WcaIsUninstalling(pswd->isInstalled, pswd->isAction)) { // If we're uninstalling, ignore any failure to find the existing web hr = S_OK; } ExitOnFailure(hr, "Failed to get base of web for WebDir"); hr = WcaGetRecordString(hRec, wdqPath, &pwzData); ExitOnFailure(hr, "Failed to get Path for WebDir"); hr = ::StringCchPrintfW(pswd->wzWebDirRoot, countof(pswd->wzWebDirRoot), L"%s/Root/%s", pswd->wzWebBase, pwzData); ExitOnFailure(hr, "Failed to format webdir root string"); // get the directory properties for this web hr = WcaGetRecordString(hRec, wdqProperties, &pwzData); ExitOnFailure(hr, "Failed to get security identifier for WebDir"); if (*pwzData) { hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pswd->swp); ExitOnFailure(hr, "Failed to get properties for WebDir"); pswd->fHasProperties = TRUE; } // get the application information for this web directory hr = WcaGetRecordString(hRec, wdqApplication, &pwzData); ExitOnFailure(hr, "Failed to get application identifier for WebDir"); if (*pwzData) { hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pswd->swapp); ExitOnFailure(hr, "Failed to get application for WebDir"); pswd->fHasApplication = TRUE; } AddWebDirToList(ppswdList, pswd); } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "Failure while processing WebDirs"); LExit: WcaFinishUnwrapQuery(hWrapQuery); ReleaseStr(pwzData); return hr; }
UINT __stdcall ScaFiltersRead7( __in SCA_WEB7* pswList, __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, __inout SCA_FILTER** ppsfList, __inout LPWSTR *ppwzCustomActionData ) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; MSIHANDLE hRec; INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; SCA_FILTER* psf; LPWSTR pwzData = NULL; WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); if (0 == WcaGetQueryRecords(hWrapQuery)) { WcaLog(LOGMSG_VERBOSE, "Skipping ScaFiltersRead() - no IIsFilter table"); ExitFunction1(hr = S_FALSE); } // loop through all the filters while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) { // Get the Component first. If the component is not being modified during // this transaction, skip processing this whole record. // get the darwin information hr = WcaGetRecordString(hRec, fqComponent, &pwzData); ExitOnFailure(hr, "failed to get IIsFilter.Component"); hr = WcaGetRecordInteger(hRec, fqInstalled, (int *)&isInstalled); ExitOnFailure(hr, "Failed to get Component installed state for IIs filter"); hr = WcaGetRecordInteger(hRec, fqAction, (int *)&isAction); ExitOnFailure(hr, "Failed to get Component action state for IIs filter"); if (!WcaIsInstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction) && !WcaIsUninstalling(isInstalled, isAction)) { continue; // skip this record. } hr = AddFilterToList(ppsfList); ExitOnFailure(hr, "failed to add filter to list"); psf = *ppsfList; hr = ::StringCchCopyW(psf->wzComponent, countof(psf->wzComponent), pwzData); ExitOnFailure1(hr, "failed to copy component name: %ls", pwzData); psf->isInstalled = isInstalled; psf->isAction = isAction; hr = WcaGetRecordString(hRec, fqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web for VirtualDir"); if (*pwzData) { hr = ScaWebsGetBase7(pswList, pwzData, psf->wzFilterRoot, countof(psf->wzFilterRoot)); if (FAILED(hr)) { WcaLog(LOGMSG_VERBOSE, "Could not find site for filter: %ls. Result 0x%x ", psf->wzFilterRoot, hr); hr = S_OK; } } else { hr = ::StringCchCopyW(psf->wzFilterRoot, countof(psf->wzFilterRoot), L"/"); ExitOnFailure(hr, "Failed to allocate global filter base string"); } // filter Name key hr = WcaGetRecordString(hRec, fqFilter, &pwzData); ExitOnFailure(hr, "Failed to get Filter.Filter"); hr = ::StringCchCopyW(psf->wzKey, countof(psf->wzKey), pwzData); ExitOnFailure(hr, "Failed to copy key string to filter object"); // filter path hr = WcaGetRecordString(hRec, fqPath, &pwzData); ExitOnFailure(hr, "Failed to get Filter.Path"); hr = ::StringCchCopyW(psf->wzPath, countof(psf->wzPath), pwzData); ExitOnFailure(hr, "Failed to copy path string to filter object"); // filter description -- not supported in iis 7 hr = WcaGetRecordString(hRec, fqDescription, &pwzData); ExitOnFailure(hr, "Failed to get Filter.Description"); hr = ::StringCchCopyW(psf->wzDescription, countof(psf->wzDescription), pwzData); ExitOnFailure(hr, "Failed to copy description string to filter object"); // filter flags //What are these hr = WcaGetRecordInteger(hRec, fqFlags, &psf->iFlags); ExitOnFailure(hr, "Failed to get Filter.Flags"); // filter load order hr = WcaGetRecordInteger(hRec, fqLoadOrder, &psf->iLoadOrder); ExitOnFailure(hr, "Failed to get Filter.LoadOrder"); } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "Failure while processing filters"); LExit: WcaFinishUnwrapQuery(hWrapQuery); ReleaseStr(pwzData); 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); }
/******************************************************************** ConfigureEventManifestRegister - CUSTOM ACTION ENTRY POINT for scheduling Event manifest registering ********************************************************************/ extern "C" UINT __stdcall ConfigureEventManifestUnregister( __in MSIHANDLE hInstall ) { HRESULT hr; UINT er = ERROR_SUCCESS; PMSIHANDLE hView, hRec; LPWSTR pwzData = NULL, pwzFile = NULL, pwzCommand = NULL; INSTALLSTATE isInstalled, isAction; hr = WcaInitialize(hInstall, "ConfigureEventManifestUnreg"); ExitOnFailure(hr, "Failed to initialize"); if (!IsVistaOrAbove()) { WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because the target system does not support event manifest"); ExitFunction1(hr = S_FALSE); } // check to see if necessary tables are specified if (S_OK != WcaTableExists(L"EventManifest")) { WcaLog(LOGMSG_VERBOSE, "Skipping ConfigureEventManifestUnregister() because EventManifest table not present"); ExitFunction1(hr = S_FALSE); } hr = WcaOpenExecuteView(vcsEventManifestQuery, &hView); ExitOnFailure(hr, "failed to open view on EventManifest table"); while ((hr = WcaFetchRecord(hView, &hRec)) == S_OK) { // get component install state hr = WcaGetRecordString(hRec, emComponent, &pwzData); ExitOnFailure(hr, "failed to get Component for EventManifest"); er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "failed to get Component state for EventManifest"); // nothing to do on an install // schedule the rollback action when reinstalling to re-register pre-patch manifest if (!WcaIsUninstalling(isInstalled, isAction) && !WcaIsReInstalling(isInstalled, isAction)) { continue; } hr = WcaGetRecordFormattedString(hRec, emFile, &pwzFile); ExitOnFailure(hr, "failed to get File for EventManifest"); hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" im \"%s\"", pwzFile); ExitOnFailure(hr, "failed to copy string in EventManifest"); hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"RollbackUnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_REGISTER); ExitOnFailure(hr, "failed to schedule RollbackUnregisterEventManifest action"); // no need to uninstall on a repair/patch. Register action will re-register and update the manifest. if (!WcaIsReInstalling(isInstalled, isAction)) { hr = StrAllocFormatted(&pwzCommand, L"\"wevtutil.exe\" um \"%s\"", pwzFile); ExitOnFailure(hr, "failed to copy string in EventManifest"); WcaLog(LOGMSG_VERBOSE, "UnregisterEventManifest's CustomActionData: '%ls'", pwzCommand); hr = WcaDoDeferredAction(PLATFORM_DECORATION(L"UnregisterEventManifest"), pwzCommand, COST_PERFMONMANIFEST_UNREGISTER); ExitOnFailure(hr, "failed to schedule UnregisterEventManifest action"); } } if (hr == E_NOMOREITEMS) { hr = S_OK; } ExitOnFailure(hr, "Failure while processing EventManifest"); hr = S_OK; LExit: ReleaseStr(pwzData); ReleaseStr(pwzFile); ReleaseStr(pwzCommand); er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }