HRESULT ScaVirtualDirGetComponent( __in LPCWSTR wzVirtualDir, __out LPWSTR* ppwzData ) { Assert(wzVirtualDir && *wzVirtualDir); HRESULT hr = S_OK; PMSIHANDLE hView, hRec; hr = WcaTableExists(L"IIsWebVirtualDir"); if (S_FALSE == hr) hr = E_ABORT; ExitOnFailure(hr, "IIsWebVirtualDir table does not exist or error"); hRec = ::MsiCreateRecord(1); if (!hRec) { hr = E_OUTOFMEMORY; ExitOnFailure(hr, "Failed to create record for lookup."); } hr = WcaSetRecordString(hRec, 1, wzVirtualDir); ExitOnFailure(hr, "Failed to look up VirtualDir Component"); hr = WcaOpenView(vcsVDirPropertiesQuery, &hView); ExitOnFailure(hr, "Failed to open view on VirtualDir"); hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "Failed to exectue view on VirtualDir"); hr = WcaFetchSingleRecord(hView, &hRec); if (S_OK == hr) { #if DEBUG // check that vdir matches hr = WcaGetRecordString(hRec, vdqVDir, ppwzData); ExitOnFailure(hr, "Failed to get IIsWebVirtualDir.VirtualDir"); Assert(0 == lstrcmpW(*ppwzData, wzVirtualDir)); #endif hr = WcaGetRecordString(hRec, vdqComponent, ppwzData); ExitOnFailure(hr, "Failed to get Component for VirtualDir"); } else if (E_NOMOREITEMS == hr) { WcaLog(LOGMSG_STANDARD, "Error: Cannot locate IIsWebVirtualDir.VirtualDir='%S'", wzVirtualDir); hr = E_FAIL; } else { ExitOnFailure(hr, "Error or found multiple matching VirtualDir rows"); } LExit: return hr; }
static HRESULT GetUserAccountName( LPCWSTR pwzKey, LPWSTR* ppwzAccount ) { HRESULT hr = S_OK; PMSIHANDLE hView, hRecKey, hRec; LPWSTR pwzDomain = NULL; LPWSTR pwzName = NULL; // create parameter record hRecKey = ::MsiCreateRecord(1); ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); hr = WcaSetRecordString(hRecKey, 1, pwzKey); ExitOnFailure(hr, "Failed to set record string"); // open view hr = WcaOpenView(vcsUserQuery, &hView); ExitOnFailure(hr, "Failed to open view on User table"); hr = WcaExecuteView(hView, hRecKey); ExitOnFailure(hr, "Failed to execute view on User table"); // fetch record hr = WcaFetchSingleRecord(hView, &hRec); if (S_FALSE == hr) ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "User not found, key: %S", pwzKey); ExitOnFailure(hr, "Failed to fetch user record"); // get user domain hr = WcaGetRecordFormattedString(hRec, uqDomain, &pwzDomain); ExitOnFailure(hr, "Failed to get domain"); // get user name hr = WcaGetRecordFormattedString(hRec, uqName, &pwzName); ExitOnFailure(hr, "Failed to get name"); // build account name hr = CpiBuildAccountName(pwzDomain, pwzName, ppwzAccount); ExitOnFailure(hr, "Failed to build account name"); hr = S_OK; LExit: // clean up ReleaseStr(pwzDomain); ReleaseStr(pwzName); return hr; }
HRESULT CpiVerifyComponentArchitecure( LPCWSTR pwzComponent, BOOL* pfMatchingArchitecture ) { HRESULT hr = S_OK; PMSIHANDLE hView, hRecKey, hRec; int iAttributes = 0; if (S_OK == WcaTableExists(L"Component")) { // create parameter record hRecKey = ::MsiCreateRecord(1); ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); hr = WcaSetRecordString(hRecKey, 1, pwzComponent); ExitOnFailure(hr, "Failed to set record string"); // open view hr = WcaOpenView(vcsComponentAttributesQuery, &hView); ExitOnFailure(hr, "Failed to open view on ActionText table"); hr = WcaExecuteView(hView, hRecKey); ExitOnFailure(hr, "Failed to execute view on ActionText table"); // fetch record hr = WcaFetchSingleRecord(hView, &hRec); if (S_FALSE != hr) { ExitOnFailure(hr, "Failed to fetch component record"); hr = WcaGetRecordInteger(hRec, caqAttributes, &iAttributes); ExitOnFailure(hr, "Failed to get component attributes"); } } // return values #ifdef _WIN64 *pfMatchingArchitecture = 256 == (iAttributes & 256); #else *pfMatchingArchitecture = 256 != (iAttributes & 256); #endif hr = S_OK; LExit: return hr; }
/****************************************************************** FileIdExists - checks if the file ID is found in the File table returns S_OK if the file exists; S_FALSE if not; otherwise, error ********************************************************************/ static HRESULT FileIdExists( __in_opt LPCWSTR wzFile ) { HRESULT hr = S_OK; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; if (!wzFile) { hr = S_FALSE; ExitFunction(); } hRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hRec, fiFile, wzFile); ExitOnFailure1(hr, "failed to create a record with the file: %ls", wzFile); hr = WcaTableExists(L"File"); if (S_OK == hr) { hr = WcaOpenView(vcsFileId, &hView); ExitOnFailure(hr, "failed to open view on File table"); hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "failed to execute view on File table"); // Reuse the same record; the handle will be released. hr = WcaFetchSingleRecord(hView, &hRec); ExitOnFailure(hr, "failed to fetch File from File table"); } LExit: return hr; }
HRESULT __stdcall ScaGetGroup( __in LPCWSTR wzGroup, __out SCA_GROUP* pscag ) { if (!wzGroup || !pscag) { return E_INVALIDARG; } HRESULT hr = S_OK; PMSIHANDLE hView, hRec; LPWSTR pwzData = NULL; hRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hRec, 1, wzGroup); ExitOnFailure(hr, "Failed to look up Group"); hr = WcaOpenView(vcsGroupQuery, &hView); ExitOnFailure(hr, "Failed to open view on Group table"); hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "Failed to execute view on Group table"); hr = WcaFetchSingleRecord(hView, &hRec); if (S_OK == hr) { hr = WcaGetRecordString(hRec, vgqGroup, &pwzData); ExitOnFailure(hr, "Failed to get Group.Group"); hr = ::StringCchCopyW(pscag->wzKey, countof(pscag->wzKey), pwzData); ExitOnFailure(hr, "Failed to copy Group.Group."); hr = WcaGetRecordString(hRec, vgqComponent, &pwzData); ExitOnFailure(hr, "Failed to get Group.Component_"); hr = ::StringCchCopyW(pscag->wzComponent, countof(pscag->wzComponent), pwzData); ExitOnFailure(hr, "Failed to copy Group.Component_."); hr = WcaGetRecordFormattedString(hRec, vgqName, &pwzData); ExitOnFailure(hr, "Failed to get Group.Name"); hr = ::StringCchCopyW(pscag->wzName, countof(pscag->wzName), pwzData); ExitOnFailure(hr, "Failed to copy Group.Name."); hr = WcaGetRecordFormattedString(hRec, vgqDomain, &pwzData); ExitOnFailure(hr, "Failed to get Group.Domain"); hr = ::StringCchCopyW(pscag->wzDomain, countof(pscag->wzDomain), pwzData); ExitOnFailure(hr, "Failed to copy Group.Domain."); } else if (E_NOMOREITEMS == hr) { WcaLog(LOGMSG_STANDARD, "Error: Cannot locate Group.Group='%ls'", wzGroup); hr = E_FAIL; } else { ExitOnFailure(hr, "Error or found multiple matching Group rows"); } LExit: ReleaseStr(pwzData); return hr; }
/****************************************************************** CaSchedSecureObjects - entry point for CaReadSecureObjects Custom Action called as Type 1 CustomAction (binary DLL) from Windows Installer in InstallExecuteSequence before CaSecureObjects ******************************************************************/ extern "C" UINT __stdcall SchedSecureObjects( __in MSIHANDLE hInstall ) { // AssertSz(FALSE, "debug SchedSecureObjects"); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; LPWSTR pwzData = NULL; LPWSTR pwzTable = NULL; LPWSTR pwzTargetPath = NULL; LPWSTR pwzFormattedString = NULL; int iRoot = 0; int iAllUsers = 0; LPWSTR pwzKey = NULL; PMSIHANDLE hView = NULL; PMSIHANDLE hRec = NULL; MSIHANDLE hViewObject = NULL; // Don't free this since it's always a copy of either hViewService or hViewCreateFolder PMSIHANDLE hViewService = NULL; PMSIHANDLE hViewCreateFolder = NULL; PMSIHANDLE hViewFile = NULL; PMSIHANDLE hViewRegistry = NULL; PMSIHANDLE hRecObject = NULL; INSTALLSTATE isInstalled; INSTALLSTATE isAction; LPWSTR pwzCustomActionData = NULL; DWORD cchCustomActionData = 0; DWORD cObjects = 0; eOBJECTTYPE eType = OT_UNKNOWN; // // initialize // hr = WcaInitialize(hInstall, "SchedSecureObjects"); ExitOnFailure(hr, "failed to initialize"); // // loop through all the objects to be secured // hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView); ExitOnFailure(hr, "failed to open view on SecureObjects table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hViewObject = NULL; eType = OT_UNKNOWN; hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable); ExitOnFailure(hr, "failed to get object table"); // ensure we're looking at a known table if (0 == lstrcmpW(L"ServiceInstall", pwzTable)) { eType = OT_SERVICE; } else if (0 == lstrcmpW(L"CreateFolder", pwzTable)) { eType = OT_FOLDER; } else if (0 == lstrcmpW(L"File", pwzTable)) { eType = OT_FILE; } else if (0 == lstrcmpW(L"Registry", pwzTable)) { eType = OT_REGISTRY; } else { ExitOnFailure1(hr = E_INVALIDARG, "unknown SecureObject.Table: %S", pwzTable); } // if we haven't opened a view on the ServiceInstall/CreateFolder table, do that now if (OT_SERVICE == eType) { if (!hViewService) { hr = WcaTableExists(pwzTable); if (S_FALSE == hr) hr = E_UNEXPECTED; ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable); hr = WcaOpenView(wzQUERY_SERVICECOMPONENT, &hViewService); ExitOnFailure(hr, "failed to open view on ServiceInstall table"); } hViewObject = hViewService; } else if (OT_FOLDER == eType) { if (!hViewCreateFolder) { hr = WcaTableExists(pwzTable); if (S_FALSE == hr) hr = E_UNEXPECTED; ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable); hr = WcaOpenView(wzQUERY_CREATEFOLDERCOMPONENT, &hViewCreateFolder); ExitOnFailure(hr, "failed to open view on CreateFolder table"); } hViewObject = hViewCreateFolder; } else if (OT_FILE== eType) { if (!hViewFile) { hr = WcaTableExists(pwzTable); if (S_FALSE == hr) hr = E_UNEXPECTED; ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable); hr = WcaOpenView(wzQUERY_FILECOMPONENT, &hViewFile); ExitOnFailure(hr, "failed to open view on CreateFolder table"); } hViewObject = hViewFile; } else if (OT_REGISTRY== eType) { if (!hViewRegistry) { hr = WcaTableExists(pwzTable); if (S_FALSE == hr) hr = E_UNEXPECTED; ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable); hr = WcaOpenView(wzQUERY_REGISTRYCOMPONENT, &hViewRegistry); ExitOnFailure(hr, "failed to open view on CreateFolder table"); } hViewObject = hViewRegistry; } Assert(hViewObject); // execute a view looking for the object's Component_ hr = WcaExecuteView(hViewObject, hRec); ExitOnFailure1(hr, "failed to execute view on %S table", pwzData); hr = WcaFetchSingleRecord(hViewObject, &hRecObject); ExitOnFailure(hr, "failed to fetch Component for secure object"); hr = WcaGetRecordString(hRecObject, QSOC_COMPONENT, &pwzData); ExitOnFailure(hr, "failed to get Component name for secure object"); // // if we are installing this Component // er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction); ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %S", pwzData); if (WcaIsInstalling(isInstalled, isAction)) { // add the data to the CustomActionData hr = WcaGetRecordString(hRecObject, QSOC_OBJECTNAME, &pwzData); ExitOnFailure(hr, "failed to get name of object"); if (OT_SERVICE == eType) { hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); } else if (OT_FOLDER == eType) { hr = WcaGetTargetPath(pwzData, &pwzTargetPath); ExitOnFailure1(hr, "failed to get target path for directory id: %S", pwzData); hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); } else if (OT_FILE == eType) { hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzData); ExitOnFailure1(hr, "failed to create formatted string for securing file object: %S", pwzData); hr = WcaGetFormattedString(pwzFormattedString, &pwzTargetPath); ExitOnFailure2(hr, "failed to get file path from formatted string: %S for secure object: %S", pwzFormattedString, pwzData); hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); } else if (OT_REGISTRY == eType) { hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot); ExitOnFailure1(hr, "Failed to get reg key root for secure object: %S", pwzData); hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey); ExitOnFailure1(hr, "Failed to get reg key for secure object: %S", pwzData); // Decode the root value if (-1 == iRoot) { // They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers); ExitOnFailure(hr, "failed to get value of ALLUSERS property"); if (1 == iAllUsers) { hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); } else { hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); } } else if (/*msidbRegistryRootClassesRoot*/ 0 == iRoot) { hr = StrAllocString(&pwzTargetPath, L"CLASSES_ROOT\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCR root"); } else if (/*msidbRegistryRootCurrentUser*/ 1 == iRoot) { hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); } else if (/*msidbRegistryRootLocalMachine*/ 2 == iRoot) { hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); } else if (/*msidbRegistryRootUsers*/ 3 == iRoot) { hr = StrAllocString(&pwzTargetPath, L"USERS\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKU root"); } else { ExitOnFailure2(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%S' root: %d", pwzData, iRoot); } hr = StrAllocConcat(&pwzTargetPath, pwzKey, 0); ExitOnFailure2(hr, "Failed to concat key: %S for secure object: %S", pwzKey, pwzData); hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); } else { AssertSz(FALSE, "How did you get here?"); } hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData); ExitOnFailure(hr, "failed to get domain for user to configure object"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData); ExitOnFailure(hr, "failed to get user to configure object"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData); ExitOnFailure(hr, "failed to get domain for user to configure object"); hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData); ExitOnFailure(hr, "failed to add data to CustomActionData"); cObjects++; } } // 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 < cObjects); hr = WcaDoDeferredAction(L"ExecSecureObjects", pwzCustomActionData, cObjects * COST_SECUREOBJECT); ExitOnFailure(hr, "failed to schedule ExecSecureObjects action"); } LExit: ReleaseStr(pwzCustomActionData); ReleaseStr(pwzData); ReleaseStr(pwzTable); ReleaseStr(pwzTargetPath); ReleaseStr(pwzFormattedString); ReleaseStr(pwzKey); if (FAILED(hr)) er = ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
HRESULT ScaWebAppExtensionsRead( LPCWSTR wzApplication, SCA_WEB_APPLICATION_EXTENSION** ppswappextList ) { HRESULT hr = S_OK; PMSIHANDLE hView, hRec; SCA_WEB_APPLICATION_EXTENSION* pswappext = NULL; LPWSTR pwzData = NULL; // check pre-requisites hr = WcaTableExists(L"IIsWebApplicationExtension"); if (S_FALSE == hr) ExitFunction(); // convert the string into a msi record hRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hRec, 1, wzApplication); ExitOnFailure(hr, "Failed to set record to look up Web Application"); // open and execute the view on the applicatoin extension table hr = WcaOpenView(vcsWebAppExtensionQuery, &hView); ExitOnFailure(hr, "Failed to open view on IIsWebApplicationExtension table"); hr = WcaExecuteView(hView, hRec); ExitOnFailure1(hr, "Failed to execute view on IIsWebApplicationExtension table looking Application: %S", wzApplication); // get the application extention information while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hr = NewAppExt(&pswappext); ExitOnFailure(hr, "failed to create new web app extension"); // get the extension hr = WcaGetRecordString(hRec, wappextqExtension, &pwzData); ExitOnFailure(hr, "Failed to get Web Application Extension"); StringCchCopyW(pswappext->wzExtension, countof(pswappext->wzExtension), pwzData); // application extension verbs hr = WcaGetRecordString(hRec, wappextqVerbs, &pwzData); ExitOnFailure1(hr, "Failed to get Verbs for Application: '%S'", wzApplication); StringCchCopyW(pswappext->wzVerbs, countof(pswappext->wzVerbs), pwzData); // extension executeable hr = WcaGetRecordFormattedString(hRec, wappextqExecutable, &pwzData); ExitOnFailure1(hr, "Failed to get Executable for Application: '%S'", wzApplication); StringCchCopyW(pswappext->wzExecutable, countof(pswappext->wzExecutable), pwzData); hr = WcaGetRecordInteger(hRec, wappextqAttributes, &pswappext->iAttributes); if (S_FALSE == hr) { pswappext->iAttributes = 0; hr = S_OK; } ExitOnFailure(hr, "Failed to get App isolation"); *ppswappextList = AddAppExtToList(*ppswappextList, pswappext); pswappext = NULL; // set the appext 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 if (pswappext) ScaWebAppExtensionsFreeList(pswappext); ReleaseStr(pwzData); return hr; }
HRESULT CpiPropertiesRead( LPCWSTR pwzQuery, LPCWSTR pwzKey, CPI_PROPERTY_DEFINITION* pPropDefList, CPI_PROPERTY** ppPropList, int* piCount ) { HRESULT hr = S_OK; PMSIHANDLE hView, hRecKey, hRec; CPI_PROPERTY* pItm = NULL; LPWSTR pwzData = NULL; int iVersionNT = 0; CPI_PROPERTY_DEFINITION* pPropDef; *piCount = 0; // get NT version hr = WcaGetIntProperty(L"VersionNT", &iVersionNT); ExitOnFailure(hr, "Failed to set record string"); // create parameter record hRecKey = ::MsiCreateRecord(1); ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); hr = WcaSetRecordString(hRecKey, 1, pwzKey); ExitOnFailure(hr, "Failed to set record string"); // open view hr = WcaOpenView(pwzQuery, &hView); ExitOnFailure(hr, "Failed to open view on property table"); hr = WcaExecuteView(hView, hRecKey); ExitOnFailure(hr, "Failed to execute view on property table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { // create entry pItm = (CPI_PROPERTY*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CPI_PROPERTY)); if (!pItm) ExitFunction1(hr = E_OUTOFMEMORY); // get name hr = WcaGetRecordString(hRec, pqName, &pwzData); ExitOnFailure(hr, "Failed to get name"); StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData); // get value hr = WcaGetRecordFormattedString(hRec, pqValue, &pItm->pwzValue); ExitOnFailure(hr, "Failed to get value"); // find property definition hr = FindPropertyDefinition(pPropDefList, pItm->wzName, &pPropDef); ExitOnFailure(hr, "Failed to find property definition"); if (S_FALSE == hr) ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "Unknown property, key: %S, property: %S", pwzKey, pItm->wzName); // check version, ignore if catalog version is too low if (iVersionNT < pPropDef->iMinVersionNT) { WcaLog(LOGMSG_VERBOSE, "Skipping property since NT version is too low, key: %S, property: %S", pwzKey, pItm->wzName); CpiPropertiesFreeList(pItm); pItm = NULL; continue; } // if the property is a user, replace the User table key with a user account name if (cpptUser == pPropDef->iType) { hr = GetUserAccountName(pItm->pwzValue, &pItm->pwzValue); ExitOnFailure(hr, "Failed to get user account name"); } // add entry ++*piCount; if (*ppPropList) pItm->pNext = *ppPropList; *ppPropList = pItm; pItm = NULL; } if (E_NOMOREITEMS == hr) hr = S_OK; LExit: // clean up if (pItm) CpiPropertiesFreeList(pItm); ReleaseStr(pwzData); return hr; }
HRESULT ScaWebsRead( __in IMSAdminBase* piMetabase, __in SCA_WEB** ppswList, __in SCA_HTTP_HEADER** ppshhList, __in SCA_WEB_ERROR** ppsweList ) { Assert(piMetabase && ppswList); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; BOOL fIIsWebSiteTable = FALSE; BOOL fIIsWebAddressTable = FALSE; BOOL fIIsWebApplicationTable = FALSE; PMSIHANDLE hView, hRec; PMSIHANDLE hViewAddresses, hRecAddresses; PMSIHANDLE hViewApplications, hRecApplications; SCA_WEB* psw = NULL; LPWSTR pwzData = NULL; DWORD dwLen = 0; // check to see what tables are available fIIsWebSiteTable = (S_OK == WcaTableExists(L"IIsWebSite")); fIIsWebAddressTable = (S_OK == WcaTableExists(L"IIsWebAddress")); fIIsWebApplicationTable = (S_OK == WcaTableExists(L"IIsWebApplication")); if (!fIIsWebSiteTable || !fIIsWebAddressTable) { WcaLog(LOGMSG_VERBOSE, "Required tables not present"); hr = S_FALSE; goto LExit; } // open the view on webs' addresses hr = WcaOpenView(vcsWebAddressQuery, &hViewAddresses); ExitOnFailure(hr, "Failed to open view on IIsWebAddress table"); // open the view on webs' applications if (fIIsWebApplicationTable) { hr = WcaOpenView(vcsWebApplicationQuery, &hViewApplications); ExitOnFailure(hr, "Failed to open view on IIsWebApplication table"); } // loop through all the webs hr = WcaOpenExecuteView(vcsWebQuery, &hView); ExitOnFailure(hr, "Failed to execute view on IIsWebSite table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { psw = NewWeb(); if (!psw) { hr = E_OUTOFMEMORY; break; } // get the darwin information hr = WcaGetRecordString(hRec, wqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web"); StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData); // get component install state hr = WcaGetRecordString(hRec, wqComponent, &pwzData); ExitOnFailure(hr, "Failed to get Component for Web"); StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData); if (*(psw->wzComponent)) { psw->fHasComponent = TRUE; er = ::MsiGetComponentStateW(WcaGetInstallHandle(), psw->wzComponent, &psw->isInstalled, &psw->isAction); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "Failed to get web Component state"); } // get the web's key address hr = WcaGetRecordString(hRec, wqAddress, &pwzData); ExitOnFailure(hr, "Failed to get Address for Web"); StringCchCopyW(psw->swaKey.wzKey, countof(psw->swaKey.wzKey), pwzData); hr = WcaGetRecordFormattedString(hRec, wqIP, &pwzData); ExitOnFailure(hr, "Failed to get IP for Web"); StringCchCopyW(psw->swaKey.wzIP, countof(psw->swaKey.wzIP), pwzData); hr = WcaGetRecordFormattedString(hRec, wqPort, &pwzData); ExitOnFailure(hr, "Failed to get Web Address port"); psw->swaKey.iPort = wcstol(pwzData, NULL, 10); if (0 == psw->swaKey.iPort) ExitOnFailure1(hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA), "invalid port provided for web site: %S", psw->wzDescription); hr = WcaGetRecordFormattedString(hRec, wqHeader, &pwzData); ExitOnFailure(hr, "Failed to get Header for Web"); StringCchCopyW(psw->swaKey.wzHeader, countof(psw->swaKey.wzHeader), pwzData); hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaKey.fSecure); ExitOnFailure(hr, "Failed to get if Web is secure"); if (S_FALSE == hr) psw->swaKey.fSecure = FALSE; // TODO: fix this to look for the description as well (or is address enough)? // find the web root dwLen = METADATA_MAX_NAME_LEN; hr = ScaWebFindBase(piMetabase, *ppswList, psw->wzKey, psw->swaKey.wzIP, psw->swaKey.iPort, psw->swaKey.wzHeader, psw->swaKey.fSecure, psw->wzWebBase, &dwLen); if (S_OK == hr) { psw->fBaseExists = TRUE; } else if (S_FALSE == hr && FALSE == psw->fHasComponent) // if we're not installing it, fail if it wasn't found { ExitOnFailure1(hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND), "failed to find web site: '%S'", psw->wzKey); } else if (S_FALSE == hr) { dwLen = METADATA_MAX_NAME_LEN; hr = ScaWebFindFreeBase(piMetabase, *ppswList, psw->wzWebBase, dwLen); psw->fBaseExists = FALSE; } ExitOnFailure(hr, "Failed to find web root"); // get any extra web addresses hr = WcaExecuteView(hViewAddresses, hRec); ExitOnFailure(hr, "Failed to execute view on extra IIsWebAddress table"); while (S_OK == (hr = WcaFetchRecord(hViewAddresses, &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)) { StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData); hr = WcaGetRecordFormattedString(hRecAddresses, waqIP, &pwzData); ExitOnFailure(hr, "Failed to get extra web IP"); StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData); hr = WcaGetRecordFormattedString(hRecAddresses, waqPort, &pwzData); ExitOnFailure(hr, "Failed to get port for extra web IP"); psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10); hr = WcaGetRecordFormattedString(hRecAddresses, waqHeader, &pwzData); ExitOnFailure(hr, "Failed to get header for extra web IP"); StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData); 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"); // get the web's description hr = WcaGetRecordFormattedString(hRec, wqDescription, &pwzData); ExitOnFailure(hr, "Failed to get Description for Web"); StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData); 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 hr = WcaGetRecordString(hRec, wqDirectory, &pwzData); ExitOnFailure(hr, "Failed to get Directory for Web"); WCHAR wzPath[MAX_PATH]; dwLen = countof(wzPath); if (INSTALLSTATE_SOURCE == psw->isAction) er = ::MsiGetSourcePathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); else er = ::MsiGetTargetPathW(WcaGetInstallHandle(), pwzData, wzPath, &dwLen); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); if (dwLen > countof(wzPath)) { hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); ExitOnFailure(hr, "Failed because Source/TargetPath for Directory was greater than MAX_PATH."); } // remove traling backslash if (dwLen > 0 && wzPath[dwLen-1] == L'\\') wzPath[dwLen-1] = 0; StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), wzPath); } 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 properties for Web"); if (*pwzData) { hr = ScaGetWebDirProperties(pwzData, &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, &psw->swapp); ExitOnFailure(hr, "Failed to get application for Web"); psw->fHasApplication = TRUE; } // get the SSL certificates hr = ScaSslCertificateRead(psw->wzKey, &(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, &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 if (psw) ScaWebsFreeList(psw); ReleaseStr(pwzData); return hr; }
HRESULT ScaSqlStrsReadScripts( __inout SCA_SQLSTR** ppsssList, __in SCA_ACTION saAction ) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; PMSIHANDLE hView, hRec; PMSIHANDLE hViewBinary, hRecBinary; PMSIHANDLE hViewUser, hRecUser; LPWSTR pwzComponent = NULL; LPWSTR pwzData = NULL; BYTE* pbScript = NULL; DWORD cbRead = 0; DWORD cbScript = 0; DWORD cchScript = 0; LPWSTR pwzScriptBuffer = NULL; WCHAR* pwzScript = NULL; WCHAR* pwz; DWORD cch = 0; SCA_SQLSTR sss; SCA_SQLSTR* psss = NULL; if (S_OK != WcaTableExists(L"SqlScript") || S_OK != WcaTableExists(L"SqlDatabase") || S_OK != WcaTableExists(L"Binary")) { WcaLog(LOGMSG_VERBOSE, "Skipping ScaSqlStrsReadScripts() - SqlScripts and/or SqlDatabase table not present"); ExitFunction1(hr = S_FALSE); } // open a view on the binary table hr = WcaOpenView(vcsSqlBinaryScriptQuery, &hViewBinary); ExitOnFailure(hr, "Failed to open view on Binary table for SqlScripts"); // loop through all the sql scripts hr = WcaOpenExecuteView(vcsSqlScriptQuery, &hView); ExitOnFailure(hr, "Failed to open view on SqlScript table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; hr = WcaGetRecordString(hRec, sscrqComponent, &pwzComponent); ExitOnFailure(hr, "Failed to get Component for SQL Script."); er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzComponent, &isInstalled, &isAction); hr = HRESULT_FROM_WIN32(er); ExitOnFailure1(hr, "Failed to get state for component: %ls", pwzComponent); // If we're doing install but the Component is not being installed or we're doing // uninstall but the Component is not being uninstalled, skip it. if ((WcaIsInstalling(isInstalled, isAction) && SCA_ACTION_INSTALL != saAction) || (WcaIsUninstalling(isInstalled, isAction) && SCA_ACTION_UNINSTALL != saAction)) { continue; } ::ZeroMemory(&sss, sizeof(sss)); sss.isInstalled = isInstalled; sss.isAction = isAction; hr = WcaGetRecordString(hRec, sscrqSqlScript, &pwzData); ExitOnFailure(hr, "Failed to get SqlScript.Script"); hr = ::StringCchCopyW(sss.wzKey, countof(sss.wzKey), pwzData); ExitOnFailure1(hr, "Failed to copy SqlScript.Script: %ls", pwzData); // find the database information for this string hr = WcaGetRecordString(hRec, sscrqSqlDb, &pwzData); ExitOnFailure1(hr, "Failed to get SqlScript.SqlDb_ for SqlScript '%ls'", sss.wzKey); hr = ::StringCchCopyW(sss.wzSqlDb, countof(sss.wzSqlDb), pwzData); ExitOnFailure1(hr, "Failed to copy SqlScritp.SqlDbb: %ls", pwzData); hr = WcaGetRecordInteger(hRec, sscrqAttributes, &sss.iAttributes); ExitOnFailure1(hr, "Failed to get SqlScript.Attributes for SqlScript '%ls'", sss.wzKey); hr = WcaGetRecordInteger(hRec, sscrqSequence, &sss.iSequence); ExitOnFailure1(hr, "Failed to get SqlScript.Sequence for SqlScript '%ls'", sss.wzKey); // get the sql script out of the binary stream hr = WcaExecuteView(hViewBinary, hRec); ExitOnFailure1(hr, "Failed to open SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); hr = WcaFetchSingleRecord(hViewBinary, &hRecBinary); ExitOnFailure1(hr, "Failed to fetch SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); // Note: We need to allocate an extra character on the stream to NULL terminate the SQL script. // The WcaGetRecordStream() function won't let us add extra space on the end of the stream // so we'll read the stream "the old fashioned way". //hr = WcaGetRecordStream(hRecBinary, ssbsqData, (BYTE**)&pbScript, &cbScript); //ExitOnFailure1(hr, "Failed to read SqlScript.BinaryScript_ for SqlScript '%ls'", sss.wzKey); er = ::MsiRecordReadStream(hRecBinary, ssbsqData, NULL, &cbRead); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "failed to get size of stream"); cbScript = cbRead + sizeof(WCHAR); // we may have an ANSI SQL script but leave enough to even NULL terminate a WCHAR string hr = WcaAllocStream(&pbScript, cbScript); // this will allocate a fully zeroed out buffer so our string will be NULL terminated ExitOnFailure(hr, "failed to allocate data for stream"); er = ::MsiRecordReadStream(hRecBinary, ssbsqData, reinterpret_cast<char*>(pbScript), &cbRead); //read the buffer but leave the space for the NULL terminator hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "failed to read from stream"); Assert(cbRead + sizeof(WCHAR) == cbScript); // Check for the UNICODE BOM file marker. if ((0xFF == *pbScript) && (0xFE == *(pbScript + 1))) { // Copy the UNICODE string after the BOM marker (subtract one because we'll skip the BOM marker). cchScript = (cbScript / sizeof(WCHAR)) - 1; hr = StrAllocString(&pwzScriptBuffer, reinterpret_cast<LPWSTR>(pbScript) + 1, 0); ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript); } else { // We have an ANSI string so convert it to UNICODE. cchScript = cbScript; hr = StrAllocStringAnsi(&pwzScriptBuffer, reinterpret_cast<LPCSTR>(pbScript), 0, CP_ACP); ExitOnFailure1(hr, "Failed to allocate WCHAR string of size '%d'", cchScript); } // Free the byte buffer since it has been converted to a new UNICODE string, one way or another. if (pbScript) { WcaFreeStream(pbScript); pbScript = NULL; } // Process the SQL script stripping out unnecessary stuff (like comments) and looking for "GO" statements. pwzScript = pwzScriptBuffer; while (cchScript && pwzScript && *pwzScript) { // strip off leading whitespace while (cchScript && *pwzScript && iswspace(*pwzScript)) { ++pwzScript; --cchScript; } Assert(0 <= cchScript); // if there is a SQL comment remove it while (cchScript && L'/' == *pwzScript && L'*' == *(pwzScript + 1)) { // go until end of comment while (cchScript && *pwzScript && *(pwzScript + 1) && !(L'*' == *pwzScript && L'/' == *(pwzScript + 1))) { ++pwzScript; --cchScript; } Assert(2 <= cchScript); if (2 <= cchScript) { // to account for */ at end pwzScript+=2; cchScript-=2; } Assert(0 <= cchScript); // strip off any new leading whitespace while (cchScript && *pwzScript && iswspace(*pwzScript)) { ++pwzScript; --cchScript; } } while (cchScript && L'-' == *pwzScript && L'-' == *(pwzScript + 1)) { // go past the new line character while (cchScript && *pwzScript && L'\n' != *pwzScript) { ++pwzScript; --cchScript; } Assert(0 <= cchScript); if (cchScript && L'\n' == *pwzScript) { ++pwzScript; --cchScript; } Assert(0 <= cchScript); // strip off any new leading whitespace while (cchScript && *pwzScript && iswspace(*pwzScript)) { ++pwzScript; --cchScript; } } Assert(0 <= cchScript); // try to isolate a "GO" keyword and count the characters in the SQL string pwz = pwzScript; cch = 0; while (cchScript && *pwz) { //skip past comment lines that might have "go" in them //note that these comments are "in the middle" of our function, //or possibly at the end of a line if (cchScript && L'-' == *pwz && L'-' == *(pwz + 1)) { // skip past chars until the new line character while (cchScript && *pwz && (L'\n' != *pwz)) { ++pwz; ++cch; --cchScript; } } //skip past comment lines of form /* to */ that might have "go" in them //note that these comments are "in the middle" of our function, //or possibly at the end of a line if (cchScript && L'/' == *pwz && L'*' == *(pwz + 1)) { // skip past chars until the new line character while (cchScript && *pwz && *(pwz + 1) && !((L'*' == *pwz) && (L'/' == *(pwz + 1)))) { ++pwz; ++cch; --cchScript; } if (2 <= cchScript) { // to account for */ at end pwz+=2; cch+=2; cchScript-=2; } } // Skip past strings that may be part of the SQL statement that might have a "go" in them if ( cchScript && L'\'' == *pwz ) { ++pwz; ++cch; --cchScript; // Skip past chars until the end of the string while ( cchScript && *pwz && !(L'\'' == *pwz) ) { ++pwz; ++cch; --cchScript; } } // Skip past strings that may be part of the SQL statement that might have a "go" in them if ( cchScript && L'\"' == *pwz ) { ++pwz; ++cch; --cchScript; // Skip past chars until the end of the string while ( cchScript && *pwz && !(L'\"' == *pwz) ) { ++pwz; ++cch; --cchScript; } } // if "GO" is isolated if ((pwzScript == pwz || iswspace(*(pwz - 1))) && (L'G' == *pwz || L'g' == *pwz) && (L'O' == *(pwz + 1) || L'o' == *(pwz + 1)) && (0 == *(pwz + 2) || iswspace(*(pwz + 2)))) { *pwz = 0; // null terminate the SQL string on the "G" pwz += 2; cchScript -= 2; break; // found "GO" now add SQL string to list } ++pwz; ++cch; --cchScript; } Assert(0 <= cchScript); if (0 < cch) //don't process if there's nothing to process { // replace tabs with spaces for (LPWSTR pwzTab = wcsstr(pwzScript, L"\t"); pwzTab; pwzTab = wcsstr(pwzTab, L"\t")) *pwzTab = ' '; // strip off whitespace at the end of the script string for (LPWSTR pwzErase = pwzScript + cch - 1; pwzScript < pwzErase && iswspace(*pwzErase); pwzErase--) { *(pwzErase) = 0; cch--; } } if (0 < cch) { hr = NewSqlStr(&psss); ExitOnFailure(hr, "failed to allocate new sql string element"); // copy everything over hr = ::StringCchCopyW(psss->wzKey, countof(psss->wzKey), sss.wzKey); ExitOnFailure(hr, "Failed to copy key string to sqlstr object"); hr = ::StringCchCopyW(psss->wzSqlDb, countof(psss->wzSqlDb), sss.wzSqlDb); ExitOnFailure(hr, "Failed to copy DB string to sqlstr object"); hr = ::StringCchCopyW(psss->wzComponent, countof(psss->wzComponent), sss.wzComponent); ExitOnFailure(hr, "Failed to copy component string to sqlstr object"); psss->isInstalled = sss.isInstalled; psss->isAction = sss.isAction; psss->iAttributes = sss.iAttributes; psss->iSequence = sss.iSequence; // cchRequired includes the NULL terminating char hr = StrAllocString(&psss->pwzSql, pwzScript, 0); ExitOnFailure1(hr, "Failed to allocate string for SQL script: '%ls'", psss->wzKey); *ppsssList = AddSqlStrToList(*ppsssList, psss); psss = NULL; // set the db NULL so it doesn't accidentally get freed below } pwzScript = pwz; } } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "Failure occured while reading SqlString table"); LExit: // if anything was left over after an error clean it all up if (psss) { ScaSqlStrsFreeList(psss); } if (pbScript) { WcaFreeStream(pbScript); } ReleaseStr(pwzScriptBuffer); ReleaseStr(pwzData); ReleaseStr(pwzComponent); return hr; }
static HRESULT GetTargetPath( __in eOBJECTTYPE eType, __in LPCWSTR pwzSecureObject, __out LPWSTR* ppwzTargetPath ) { HRESULT hr = S_OK; PMSIHANDLE hView = NULL; PMSIHANDLE hRecObject = NULL; PMSIHANDLE hRec = NULL; int iRoot = 0; int iAllUsers = 0; LPWSTR pwzKey = NULL; LPWSTR pwzFormattedString = NULL; if (OT_SERVICE == eType) { hr = WcaTableExists(L"ServiceInstall"); if (S_FALSE == hr) { hr = E_UNEXPECTED; } ExitOnFailure(hr, "failed to open ServiceInstall table to secure object"); hr = WcaOpenView(wzQUERY_SERVICEINSTALL, &hView); ExitOnFailure(hr, "failed to open view on ServiceInstall table"); // create a record that stores the object to secure hRec = MsiCreateRecord(1); MsiRecordSetStringW(hRec, 1, pwzSecureObject); // execute a view looking for the object's ServiceInstall.ServiceInstall row. hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "failed to execute view on ServiceInstall table"); hr = WcaFetchSingleRecord(hView, &hRecObject); ExitOnFailure(hr, "failed to fetch ServiceInstall row for secure object"); hr = WcaGetRecordFormattedString(hRecObject, QSSI_NAME, ppwzTargetPath); ExitOnFailure1(hr, "failed to get service name for secure object: %ls", pwzSecureObject); } else if (OT_FOLDER == eType) { hr = WcaGetTargetPath(pwzSecureObject, ppwzTargetPath); ExitOnFailure1(hr, "failed to get target path for directory id: %ls", pwzSecureObject); } else if (OT_FILE == eType) { hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzSecureObject); ExitOnFailure1(hr, "failed to create formatted string for securing file object: %ls", pwzSecureObject); hr = WcaGetFormattedString(pwzFormattedString, ppwzTargetPath); ExitOnFailure2(hr, "failed to get file path from formatted string: %ls for secure object: %ls", pwzFormattedString, pwzSecureObject); } else if (OT_REGISTRY == eType) { hr = WcaTableExists(L"Registry"); if (S_FALSE == hr) { hr = E_UNEXPECTED; } ExitOnFailure(hr, "failed to open Registry table to secure object"); hr = WcaOpenView(wzQUERY_REGISTRY, &hView); ExitOnFailure(hr, "failed to open view on Registry table"); // create a record that stores the object to secure hRec = MsiCreateRecord(1); MsiRecordSetStringW(hRec, 1, pwzSecureObject); // execute a view looking for the object's Registry row hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "failed to execute view on Registry table"); hr = WcaFetchSingleRecord(hView, &hRecObject); ExitOnFailure(hr, "failed to fetch Registry row for secure object"); hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot); ExitOnFailure1(hr, "Failed to get reg key root for secure object: %ls", pwzSecureObject); hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey); ExitOnFailure1(hr, "Failed to get reg key for secure object: %ls", pwzSecureObject); // Decode the root value if (-1 == iRoot) { // They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers); ExitOnFailure(hr, "failed to get value of ALLUSERS property"); if (1 == iAllUsers) { hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); } else { hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); } } else if (msidbRegistryRootClassesRoot == iRoot) { hr = StrAllocString(ppwzTargetPath, L"CLASSES_ROOT\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCR root"); } else if (msidbRegistryRootCurrentUser == iRoot) { hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKCU root"); } else if (msidbRegistryRootLocalMachine == iRoot) { hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKLM root"); } else if (msidbRegistryRootUsers == iRoot) { hr = StrAllocString(ppwzTargetPath, L"USERS\\", 0); ExitOnFailure(hr, "failed to allocate target registry string with HKU root"); } else { ExitOnFailure2(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%ls' root: %d", pwzSecureObject, iRoot); } hr = StrAllocConcat(ppwzTargetPath, pwzKey, 0); ExitOnFailure2(hr, "Failed to concat key: %ls for secure object: %ls", pwzKey, pwzSecureObject); } else { AssertSz(FALSE, "How did you get here?"); ExitOnFailure1(hr = E_UNEXPECTED, "Unknown secure object type: %d", eType); } LExit: ReleaseStr(pwzFormattedString); ReleaseStr(pwzKey); 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 GetStrongName( __out LPWSTR* ppwzStrongName, __in LPCWSTR pwzComponent ) { Assert(ppwzStrongName); HRESULT hr = S_OK; PMSIHANDLE hView = NULL; PMSIHANDLE hComponentRec = NULL; PMSIHANDLE hRec = NULL; LPWSTR pwzData = NULL; LPWSTR pwzName = NULL; LPWSTR pwzVersion = NULL; LPWSTR pwzCulture = NULL; LPWSTR pwzPublicKeyToken = NULL; hComponentRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hComponentRec, 1, pwzComponent); ExitOnFailure1(hr, "failed to set component value in record to: %ls", pwzComponent); // get the name value records for this component hr = WcaOpenView(vcsNgenStrongName, &hView); ExitOnFailure(hr, "failed to open view on NetFxNativeImage table"); hr = WcaExecuteView(hView, hComponentRec); ExitOnFailure(hr, "failed to execute strong name view"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hr = WcaGetRecordString(hRec, ngsnName, &pwzData); ExitOnFailure1(hr, "failed to get MsiAssemblyName.Name for component: %ls", pwzComponent); if (0 == lstrcmpW(L"name", pwzData)) { hr = WcaGetRecordString(hRec, ngsnValue, &pwzName); ExitOnFailure2(hr, "failed to get MsiAssemblyName.Value for component: %ls Name: %ls", pwzComponent, pwzData); } else if (0 == lstrcmpW(L"version", pwzData)) { hr = WcaGetRecordString(hRec, ngsnValue, &pwzVersion); ExitOnFailure2(hr, "failed to get MsiAssemblyName.Value for component: %ls Name: %ls", pwzComponent, pwzData); } else if (0 == lstrcmpW(L"culture", pwzData)) { hr = WcaGetRecordString(hRec, ngsnValue, &pwzCulture); ExitOnFailure2(hr, "failed to get MsiAssemblyName.Value for component: %ls Name: %ls", pwzComponent, pwzData); } else if (0 == lstrcmpW(L"publicKeyToken", pwzData)) { hr = WcaGetRecordString(hRec, ngsnValue, &pwzPublicKeyToken); ExitOnFailure2(hr, "failed to get MsiAssemblyName.Value for component: %ls Name: %ls", pwzComponent, pwzData); } } if (E_NOMOREITEMS == hr) hr = S_OK; ExitOnFailure1(hr, "failed while looping through all names and values in MsiAssemblyName table for component: %ls", pwzComponent); hr = StrAllocFormatted(ppwzStrongName, L"\"%s, Version=%s, Culture=%s, PublicKeyToken=%s\"", pwzName, pwzVersion, pwzCulture, pwzPublicKeyToken); ExitOnFailure1(hr, "failed to format strong name for component: %ls", pwzComponent); LExit: ReleaseStr(pwzData); ReleaseStr(pwzName); ReleaseStr(pwzVersion); ReleaseStr(pwzCulture); ReleaseStr(pwzPublicKeyToken); return hr; }
HRESULT GetFileSpec( __in MSIHANDLE hViewFileSpec, __in LPCWSTR wzKey, __in SQL_FILESPEC* psf ) { HRESULT hr = S_OK; PMSIHANDLE hRecFileSpec, hRec; LPWSTR pwzData = NULL; // create a record to do the fetch hRecFileSpec = ::MsiCreateRecord(1); if (!hRecFileSpec) { ExitOnFailure1(hr = E_UNEXPECTED, "failed to create record for filespec: %ls", wzKey); } hr = WcaSetRecordString(hRecFileSpec, 1, wzKey); ExitOnFailure1(hr, "failed to set record string for filespec: %ls", wzKey); // get the FileSpec record hr = WcaExecuteView(hViewFileSpec, hRecFileSpec); ExitOnFailure1(hr, "failed to execute view on SqlFileSpec table for filespec: %ls", wzKey); hr = WcaFetchSingleRecord(hViewFileSpec, &hRec); ExitOnFailure1(hr, "failed to get record for filespec: %ls", wzKey); // read the data out of the filespec record hr = WcaGetRecordFormattedString(hRec, sfsqName, &pwzData); ExitOnFailure1(hr, "Failed to get SqlFileSpec.Name for filespec: %ls", wzKey); hr = ::StringCchCopyW(psf->wzName, countof(psf->wzName), pwzData); ExitOnFailure1(hr, "Failed to copy SqlFileSpec.Name string: %ls", pwzData); hr = WcaGetRecordFormattedString(hRec, sfsqFilename, &pwzData); ExitOnFailure1(hr, "Failed to get SqlFileSpec.Filename for filespec: %ls", wzKey); if (*pwzData) { hr = ::StringCchCopyW(psf->wzFilename, countof(psf->wzFilename), pwzData); ExitOnFailure1(hr, "Failed to copy filename to filespec object: %ls", pwzData); } else // if there is no file, skip this FILESPEC { WcaLog(LOGMSG_VERBOSE, "No filename specified, skipping FileSpec: %ls", psf->wzName); ExitFunction1(hr = S_FALSE); } hr = WcaGetRecordFormattedString(hRec, sfsqSize, &pwzData); ExitOnFailure1(hr, "Failed to get SqlFileSpec.Size for filespec: %ls", wzKey); if (*pwzData) { hr = ::StringCchCopyW(psf->wzSize, countof(psf->wzSize), pwzData); ExitOnFailure1(hr, "Failed to copy size to filespec object: %ls", pwzData); } else { psf->wzSize[0] = 0; } hr = WcaGetRecordFormattedString(hRec, sfsqMaxSize, &pwzData); ExitOnFailure1(hr, "Failed to get SqlFileSpec.MaxSize for filespec: %ls", wzKey); if (*pwzData) { hr = ::StringCchCopyW(psf->wzMaxSize, countof(psf->wzMaxSize), pwzData); ExitOnFailure1(hr, "Failed to copy max size to filespec object: %ls", pwzData); } else { psf->wzMaxSize[0] = 0; } hr = WcaGetRecordFormattedString(hRec, sfsqGrowth, &pwzData); ExitOnFailure1(hr, "Failed to get SqlFileSpec.GrowthSize for filespec: %ls", wzKey); if (*pwzData) { hr = ::StringCchCopyW(psf->wzGrow, countof(psf->wzGrow), pwzData); ExitOnFailure1(hr, "Failed to copy growth size to filespec object: %ls", pwzData); } else { psf->wzGrow[0] = 0; } hr = S_OK; LExit: ReleaseStr(pwzData); return hr; }
HRESULT __stdcall ScaGetUser( __in LPCWSTR wzUser, __out SCA_USER* pscau ) { if (!wzUser || !pscau) { return E_INVALIDARG; } HRESULT hr = S_OK; PMSIHANDLE hView, hRec; LPWSTR pwzData = NULL; // clear struct and bail right away if no user key was passed to search for ::ZeroMemory(pscau, sizeof(*pscau)); if (!*wzUser) { ExitFunction1(hr = S_OK); } hRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hRec, 1, wzUser); ExitOnFailure(hr, "Failed to look up User"); hr = WcaOpenView(vcsUserQuery, &hView); ExitOnFailure(hr, "Failed to open view on User table"); hr = WcaExecuteView(hView, hRec); ExitOnFailure(hr, "Failed to execute view on User table"); hr = WcaFetchSingleRecord(hView, &hRec); if (S_OK == hr) { hr = WcaGetRecordString(hRec, vuqUser, &pwzData); ExitOnFailure(hr, "Failed to get User.User"); hr = ::StringCchCopyW(pscau->wzKey, countof(pscau->wzKey), pwzData); ExitOnFailure(hr, "Failed to copy key string to user object"); hr = WcaGetRecordString(hRec, vuqComponent, &pwzData); ExitOnFailure(hr, "Failed to get User.Component_"); hr = ::StringCchCopyW(pscau->wzComponent, countof(pscau->wzComponent), pwzData); ExitOnFailure(hr, "Failed to copy component string to user object"); hr = WcaGetRecordFormattedString(hRec, vuqName, &pwzData); ExitOnFailure(hr, "Failed to get User.Name"); hr = ::StringCchCopyW(pscau->wzName, countof(pscau->wzName), pwzData); ExitOnFailure(hr, "Failed to copy name string to user object"); hr = WcaGetRecordFormattedString(hRec, vuqDomain, &pwzData); ExitOnFailure(hr, "Failed to get User.Domain"); hr = ::StringCchCopyW(pscau->wzDomain, countof(pscau->wzDomain), pwzData); ExitOnFailure(hr, "Failed to copy domain string to user object"); hr = WcaGetRecordFormattedString(hRec, vuqPassword, &pwzData); ExitOnFailure(hr, "Failed to get User.Password"); hr = ::StringCchCopyW(pscau->wzPassword, countof(pscau->wzPassword), pwzData); ExitOnFailure(hr, "Failed to copy password string to user object"); } else if (E_NOMOREITEMS == hr) { WcaLog(LOGMSG_STANDARD, "Error: Cannot locate User.User='******'", wzUser); hr = E_FAIL; } else { ExitOnFailure(hr, "Error or found multiple matching User rows"); } LExit: ReleaseStr(pwzData); return hr; }
HRESULT ScaUserRead( __out SCA_USER** ppsuList ) { //Assert(FALSE); Assert(ppsuList); HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; PMSIHANDLE hView, hRec, hUserRec, hUserGroupView; LPWSTR pwzData = NULL; BOOL fUserGroupExists = FALSE; SCA_USER *psu = NULL; INSTALLSTATE isInstalled, isAction; if (S_OK != WcaTableExists(L"User")) { WcaLog(LOGMSG_VERBOSE, "User Table does not exist, exiting"); ExitFunction1(hr = S_FALSE); } if (S_OK == WcaTableExists(L"UserGroup")) { fUserGroupExists = TRUE; } // // loop through all the users // hr = WcaOpenExecuteView(vActionableQuery, &hView); ExitOnFailure(hr, "failed to open view on User table"); while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) { hr = WcaGetRecordString(hRec, vaqComponent, &pwzData); ExitOnFailure(hr, "failed to get User.Component"); er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &isInstalled, &isAction); hr = HRESULT_FROM_WIN32(er); ExitOnFailure(hr, "failed to get Component state for User"); // don't bother if we aren't installing or uninstalling this component if (WcaIsInstalling(isInstalled, isAction) || WcaIsUninstalling(isInstalled, isAction)) { // // Add the user to the list and populate it's values // hr = AddUserToList(ppsuList); ExitOnFailure(hr, "failed to add user to list"); psu = *ppsuList; psu->isInstalled = isInstalled; psu->isAction = isAction; hr = ::StringCchCopyW(psu->wzComponent, countof(psu->wzComponent), pwzData); ExitOnFailure1(hr, "failed to copy component name: %ls", pwzData); hr = WcaGetRecordString(hRec, vaqUser, &pwzData); ExitOnFailure(hr, "failed to get User.User"); hr = ::StringCchCopyW(psu->wzKey, countof(psu->wzKey), pwzData); ExitOnFailure1(hr, "failed to copy user key: %ls", pwzData); hr = WcaGetRecordFormattedString(hRec, vaqName, &pwzData); ExitOnFailure(hr, "failed to get User.Name"); hr = ::StringCchCopyW(psu->wzName, countof(psu->wzName), pwzData); ExitOnFailure1(hr, "failed to copy user name: %ls", pwzData); hr = WcaGetRecordFormattedString(hRec, vaqDomain, &pwzData); ExitOnFailure(hr, "failed to get User.Domain"); hr = ::StringCchCopyW(psu->wzDomain, countof(psu->wzDomain), pwzData); ExitOnFailure1(hr, "failed to copy user domain: %ls", pwzData); hr = WcaGetRecordFormattedString(hRec, vaqPassword, &pwzData); ExitOnFailure(hr, "failed to get User.Password"); hr = ::StringCchCopyW(psu->wzPassword, countof(psu->wzPassword), pwzData); ExitOnFailure(hr, "failed to copy user password"); hr = WcaGetRecordInteger(hRec, vaqAttributes, &psu->iAttributes); ExitOnFailure(hr, "failed to get User.Attributes"); // Check if this user is to be added to any groups if (fUserGroupExists) { hUserRec = ::MsiCreateRecord(1); hr = WcaSetRecordString(hUserRec, 1, psu->wzKey); ExitOnFailure(hr, "Failed to create user record for querying UserGroup table"); hr = WcaOpenView(vcsUserGroupQuery, &hUserGroupView); ExitOnFailure1(hr, "Failed to open view on UserGroup table for user %ls", psu->wzKey); hr = WcaExecuteView(hUserGroupView, hUserRec); ExitOnFailure1(hr, "Failed to execute view on UserGroup table for user: %ls", psu->wzKey); while (S_OK == (hr = WcaFetchRecord(hUserGroupView, &hRec))) { hr = WcaGetRecordString(hRec, vugqGroup, &pwzData); ExitOnFailure(hr, "failed to get UserGroup.Group"); hr = AddGroupToList(&(psu->psgGroups)); ExitOnFailure(hr, "failed to add group to list"); hr = ScaGetGroup(pwzData, psu->psgGroups); ExitOnFailure1(hr, "failed to get information for group: %ls", pwzData); } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "failed to enumerate selected rows from UserGroup table"); } } } if (E_NOMOREITEMS == hr) { hr = S_OK; } ExitOnFailure(hr, "failed to enumerate selected rows from User table"); LExit: ReleaseStr(pwzData); return hr; }
HRESULT CpiAddActionTextToActionData( LPCWSTR pwzAction, LPWSTR* ppwzActionData ) { HRESULT hr = S_OK; PMSIHANDLE hView, hRecKey, hRec; LPWSTR pwzDescription = NULL; LPWSTR pwzTemplate = NULL; if (S_OK == WcaTableExists(L"ActionText")) { // create parameter record hRecKey = ::MsiCreateRecord(1); ExitOnNull(hRecKey, hr, E_OUTOFMEMORY, "Failed to create record"); hr = WcaSetRecordString(hRecKey, 1, pwzAction); ExitOnFailure(hr, "Failed to set record string"); // open view hr = WcaOpenView(vcsActionTextQuery, &hView); ExitOnFailure(hr, "Failed to open view on ActionText table"); hr = WcaExecuteView(hView, hRecKey); ExitOnFailure(hr, "Failed to execute view on ActionText table"); // fetch record hr = WcaFetchSingleRecord(hView, &hRec); if (S_FALSE != hr) { ExitOnFailure(hr, "Failed to fetch action text record"); // get description hr = WcaGetRecordString(hRec, atqDescription, &pwzDescription); ExitOnFailure(hr, "Failed to get description"); // get template hr = WcaGetRecordString(hRec, atqTemplate, &pwzTemplate); ExitOnFailure(hr, "Failed to get template"); } } // add action name to action data hr = WcaWriteStringToCaData(pwzAction, ppwzActionData); ExitOnFailure(hr, "Failed to add action name to custom action data"); // add description to action data hr = WcaWriteStringToCaData(pwzDescription ? pwzDescription : L"", ppwzActionData); ExitOnFailure(hr, "Failed to add description to custom action data"); // add template to action data hr = WcaWriteStringToCaData(pwzTemplate ? pwzTemplate : L"", ppwzActionData); ExitOnFailure(hr, "Failed to add template to custom action data"); hr = S_OK; LExit: // clean up ReleaseStr(pwzDescription); ReleaseStr(pwzTemplate); return hr; }