// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. #include "precomp.h" // prototypes static HRESULT AddVirtualDirToList7( __in SCA_VDIR7** psvdList ); HRESULT __stdcall ScaVirtualDirsRead7( __in SCA_WEB7* pswList, __in SCA_VDIR7** 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(ppsvdList); HRESULT hr = S_OK; MSIHANDLE hRec; SCA_VDIR7* 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))) { // Add this record's information into the list of things to process. hr = AddVirtualDirToList7(ppsvdList); ExitOnFailure(hr, "failed to add vdir to vdir list"); pvdir = *ppsvdList; // get the darwin information hr = WcaGetRecordString(hRec, vdqComponent, &pwzData); ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component"); hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&pvdir->isInstalled); ExitOnFailure(hr, "Failed to get Component installed state for virtual dir"); hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&pvdir->isAction); ExitOnFailure(hr, "Failed to get Component action state for virtual dir"); // get vdir properties hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData); ExitOnFailure(hr, "failed to copy vdir component name: %ls", pwzData); hr = WcaGetRecordString(hRec, vdqWeb, &pwzData); ExitOnFailure(hr, "Failed to get Web for VirtualDir"); hr = ScaWebsGetBase7(pswList, pwzData, pvdir->wzWebName , countof(pvdir->wzWebName)); if (S_FALSE == hr) { hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); ExitOnFailure(hr, "Failed to get Web Base for VirtualDir"); } if (WcaIsUninstalling(pvdir->isInstalled, pvdir->isAction)) { // If we're uninstalling, ignore any failure to find the existing web hr = S_OK; } hr = WcaGetRecordString(hRec, vdqAlias, &pwzData); ExitOnFailure(hr, "Failed to get Alias for VirtualDir"); hr = ::StringCchCopyW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), 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); ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData); } if (*pwzData && *ppsweList) { hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe); ExitOnFailure(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; } HRESULT ScaVirtualDirsInstall7( __in SCA_VDIR7* psvdList, __in SCA_APPPOOL * psapList ) { HRESULT hr = S_OK; SCA_VDIR7* psvd = psvdList; LPWSTR wzPath = NULL; WCHAR wzAppPoolName[MAX_PATH]; while (psvd) { if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) { // First write all applications, this is necessary since vdirs must be nested under the applications. if (psvd->fHasApplication) { //create the application for this vdir application hr = ScaWriteConfigID(IIS_APPLICATION); ExitOnFailure(hr, "Failed to write app ID"); hr = ScaWriteConfigID(IIS_CREATE); ExitOnFailure(hr, "Failed to write app action"); #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(psvd->wzWebName); //site name key ExitOnFailure(hr, "Failed to write app web key"); hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); ExitOnFailure(hr, "Failed to create app path"); hr = ScaWriteConfigString(wzPath); // App Path ExitOnFailure(hr, "Failed to write app path root "); if (!*psvd->swapp.wzAppPool) { //This Application goes in default appPool hr = ScaWriteConfigString(L""); // App Pool } else { //get apppool from WebApplication #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaFindAppPool7(psvd->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList); ExitOnFailure(hr, "Failed to read app pool from application"); hr = ScaWriteConfigString(wzAppPoolName); // App Pool ExitOnFailure(hr, "Failed to write appPool for vdir"); } } } psvd = psvd->psvdNext; } // Reset our linked list and write all the VDirs psvd = psvdList; while (psvd) { if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) { //create the Vdir hr = ScaWriteConfigID(IIS_VDIR); ExitOnFailure(hr, "Failed write VirDir ID") hr = ScaWriteConfigID(IIS_CREATE); ExitOnFailure(hr, "Failed write VirDir action") #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(psvd->wzWebName); //site name key ExitOnFailure(hr, "Failed write VirDir web name"); hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); ExitOnFailure(hr, "Failed to create vdir path"); hr = ScaWriteConfigString(wzPath); //vdir path ExitOnFailure(hr, "Failed write VirDir path") #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(psvd->wzDirectory); //physical dir ExitOnFailure(hr, "Failed write VirDir dir"); if (psvd->fHasProperties) { ScaWriteWebDirProperties7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swp); ExitOnFailure(hr, "Failed to write directory properties for VirtualDir"); } if (psvd->fHasApplication) { hr = ScaWriteWebApplication7(psvd->wzWebName, psvd->wzVDirRoot, &psvd->swapp, psapList); ExitOnFailure(hr, "Failed to write application for VirtualDir"); } if (psvd->psmm) { hr = ScaWriteMimeMap7(psvd->wzWebName, psvd->wzVDirRoot, psvd->psmm); ExitOnFailure(hr, "Failed to write mimemap for VirtualDir"); } if (psvd->pshh) { hr = ScaWriteHttpHeader7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pshh); ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir"); } if (psvd->pswe) { hr = ScaWriteWebError7(psvd->wzWebName, psvd->wzVDirRoot, psvd->pswe); ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir"); } } psvd = psvd->psvdNext; } LExit: ReleaseStr(wzPath); return hr; } HRESULT ScaVirtualDirsUninstall7( __in SCA_VDIR7* psvdList ) { HRESULT hr = S_OK; SCA_VDIR7* psvd = psvdList; LPWSTR wzPath = NULL; while (psvd) { if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction)) { //init path hr = StrAllocFormatted(&wzPath, L"/%s", psvd->wzVDirRoot); ExitOnFailure(hr, "Failed to create vdir path"); if (psvd->fHasApplication) { //delete Application hr = ScaWriteConfigID(IIS_APPLICATION); ExitOnFailure(hr, "Failed to write app ID "); hr = ScaWriteConfigID(IIS_DELETE); ExitOnFailure(hr, "Failed to write delete app ID "); #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(psvd->wzWebName); //site name key ExitOnFailure(hr, "Failed to write App site Name"); #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(wzPath); // App Path ExitOnFailure(hr, "Failed to write app path root "); hr = ScaWriteConfigString(L"NOP"); // App pool ExitOnFailure(hr, "Failed to write app path app pool "); } else { //delete VDir hr = ScaWriteConfigID(IIS_VDIR); ExitOnFailure(hr, "Failed to write vDir ID "); hr = ScaWriteConfigID(IIS_DELETE); #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") hr = ScaWriteConfigString(psvd->wzWebName); //site name key ExitOnFailure(hr, "Failed to write App site Name"); hr = ScaWriteConfigString(wzPath); // Vdir Path ExitOnFailure(hr, "Failed to write app vdir "); hr = ScaWriteConfigString(L"NOP"); // Phy Path ExitOnFailure(hr, "Failed to write vdir path"); } ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from config", psvd->wzKey); } psvd = psvd->psvdNext; } LExit: ReleaseStr(wzPath); return hr; } void ScaVirtualDirsFreeList7( __in SCA_VDIR7* psvdList ) { SCA_VDIR7* psvdDelete = psvdList; while (psvdList) { psvdDelete = psvdList; psvdList = psvdList->psvdNext; if (psvdDelete->psmm) { ScaMimeMapFreeList(psvdDelete->psmm); } if (psvdDelete->pswe) { ScaWebErrorFreeList(psvdDelete->pswe); } MemFree(psvdDelete); } } static HRESULT AddVirtualDirToList7( __in SCA_VDIR7** ppsvdList ) { HRESULT hr = S_OK; SCA_VDIR7* psvd = static_cast(MemAlloc(sizeof(SCA_VDIR7), TRUE)); ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element"); psvd->psvdNext= *ppsvdList; *ppsvdList = psvd; LExit: return hr; }