diff options
Diffstat (limited to 'src/ca/scavdir.cpp')
| -rw-r--r-- | src/ca/scavdir.cpp | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/src/ca/scavdir.cpp b/src/ca/scavdir.cpp new file mode 100644 index 00000000..d388ce97 --- /dev/null +++ b/src/ca/scavdir.cpp | |||
| @@ -0,0 +1,331 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | #include "precomp.h" | ||
| 4 | |||
| 5 | // prototypes | ||
| 6 | static HRESULT AddVirtualDirToList( | ||
| 7 | __in SCA_VDIR** psvdList | ||
| 8 | ); | ||
| 9 | |||
| 10 | |||
| 11 | HRESULT __stdcall ScaVirtualDirsRead( | ||
| 12 | __in IMSAdminBase* piMetabase, | ||
| 13 | __in SCA_WEB* pswList, | ||
| 14 | __in SCA_VDIR** ppsvdList, | ||
| 15 | __in SCA_MIMEMAP** ppsmmList, | ||
| 16 | __in SCA_HTTP_HEADER** ppshhList, | ||
| 17 | __in SCA_WEB_ERROR** ppsweList, | ||
| 18 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
| 19 | __in WCA_WRAPQUERY_HANDLE hWebBaseQuery, | ||
| 20 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
| 21 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
| 22 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
| 23 | __inout LPWSTR *ppwzCustomActionData | ||
| 24 | ) | ||
| 25 | { | ||
| 26 | Assert(piMetabase && ppsvdList); | ||
| 27 | |||
| 28 | HRESULT hr = S_OK; | ||
| 29 | MSIHANDLE hRec; | ||
| 30 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
| 31 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
| 32 | |||
| 33 | SCA_VDIR* pvdir = NULL; | ||
| 34 | LPWSTR pwzData = NULL; | ||
| 35 | |||
| 36 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
| 37 | |||
| 38 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
| 39 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
| 40 | |||
| 41 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
| 42 | { | ||
| 43 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaVirtualDirsRead() because IIsWebVirtualDir table not present"); | ||
| 44 | ExitFunction1(hr = S_FALSE); | ||
| 45 | } | ||
| 46 | |||
| 47 | // loop through all the vdirs | ||
| 48 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
| 49 | { | ||
| 50 | // Get the Component first. If there is a Component and it is not being modified during | ||
| 51 | // this transaction, skip processing this whole record. | ||
| 52 | hr = WcaGetRecordString(hRec, vdqComponent, &pwzData); | ||
| 53 | ExitOnFailure(hr, "failed to get IIsWebVirtualDir.Component"); | ||
| 54 | |||
| 55 | hr = WcaGetRecordInteger(hRec, vdqInstalled, (int *)&isInstalled); | ||
| 56 | ExitOnFailure(hr, "Failed to get Component installed state for virtual dir"); | ||
| 57 | |||
| 58 | hr = WcaGetRecordInteger(hRec, vdqAction, (int *)&isAction); | ||
| 59 | ExitOnFailure(hr, "Failed to get Component action state for virtual dir"); | ||
| 60 | |||
| 61 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
| 62 | !WcaIsReInstalling(isInstalled, isAction) && | ||
| 63 | !WcaIsUninstalling(isInstalled, isAction)) | ||
| 64 | { | ||
| 65 | continue; // skip this record. | ||
| 66 | } | ||
| 67 | |||
| 68 | hr = AddVirtualDirToList(ppsvdList); | ||
| 69 | ExitOnFailure(hr, "failed to add virtual dir to list"); | ||
| 70 | |||
| 71 | pvdir = *ppsvdList; | ||
| 72 | |||
| 73 | hr = ::StringCchCopyW(pvdir->wzComponent, countof(pvdir->wzComponent), pwzData); | ||
| 74 | ExitOnFailure(hr, "failed to copy component name: %ls", pwzData); | ||
| 75 | |||
| 76 | pvdir->isInstalled = isInstalled; | ||
| 77 | pvdir->isAction = isAction; | ||
| 78 | |||
| 79 | // get the web key | ||
| 80 | hr = WcaGetRecordString(hRec, vdqWeb, &pwzData); | ||
| 81 | ExitOnFailure(hr, "Failed to get Web for VirtualDir"); | ||
| 82 | |||
| 83 | hr = ScaWebsGetBase(piMetabase, pswList, pwzData, pvdir->wzWebBase, countof(pvdir->wzWebBase), hWebBaseQuery); | ||
| 84 | if (WcaIsUninstalling(isInstalled, isAction)) | ||
| 85 | { | ||
| 86 | // If we're uninstalling, ignore any failure to find the existing web | ||
| 87 | hr = S_OK; | ||
| 88 | } | ||
| 89 | ExitOnFailure(hr, "Failed to get base of web: %ls for VirtualDir", pwzData); | ||
| 90 | |||
| 91 | hr = WcaGetRecordString(hRec, vdqAlias, &pwzData); | ||
| 92 | ExitOnFailure(hr, "Failed to get Alias for VirtualDir"); | ||
| 93 | |||
| 94 | if (0 != lstrlenW(pvdir->wzWebBase)) | ||
| 95 | { | ||
| 96 | hr = ::StringCchPrintfW(pvdir->wzVDirRoot, countof(pvdir->wzVDirRoot), L"%s/Root/%s", pvdir->wzWebBase, pwzData); | ||
| 97 | ExitOnFailure(hr, "Failed to set VDirRoot for VirtualDir"); | ||
| 98 | } | ||
| 99 | |||
| 100 | // get the vdir's directory | ||
| 101 | hr = WcaGetRecordString(hRec, vdqDirectory, &pwzData); | ||
| 102 | ExitOnFailure(hr, "Failed to get Directory for VirtualDir"); | ||
| 103 | |||
| 104 | // get the web's directory | ||
| 105 | if (INSTALLSTATE_SOURCE == pvdir->isAction) | ||
| 106 | { | ||
| 107 | hr = WcaGetRecordString(hRec, vdqSourcePath, &pwzData); | ||
| 108 | } | ||
| 109 | else | ||
| 110 | { | ||
| 111 | hr = WcaGetRecordString(hRec, vdqTargetPath, &pwzData); | ||
| 112 | } | ||
| 113 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
| 114 | |||
| 115 | // remove trailing backslash(es) | ||
| 116 | while (lstrlenW(pwzData) > 0 && pwzData[lstrlenW(pwzData)-1] == L'\\') | ||
| 117 | { | ||
| 118 | pwzData[lstrlenW(pwzData)-1] = 0; | ||
| 119 | } | ||
| 120 | hr = ::StringCchCopyW(pvdir->wzDirectory, countof(pvdir->wzDirectory), pwzData); | ||
| 121 | ExitOnFailure(hr, "Failed to copy directory string to vdir object"); | ||
| 122 | |||
| 123 | // get the security information for this web | ||
| 124 | hr = WcaGetRecordString(hRec, vdqProperties, &pwzData); | ||
| 125 | ExitOnFailure(hr, "Failed to get web directory identifier for VirtualDir"); | ||
| 126 | if (*pwzData) | ||
| 127 | { | ||
| 128 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &pvdir->swp); | ||
| 129 | ExitOnFailure(hr, "Failed to get web directory for VirtualDir"); | ||
| 130 | |||
| 131 | pvdir->fHasProperties = TRUE; | ||
| 132 | } | ||
| 133 | |||
| 134 | // get the application information for this web | ||
| 135 | hr = WcaGetRecordString(hRec, vdqApplication, &pwzData); | ||
| 136 | ExitOnFailure(hr, "Failed to get application identifier for VirtualDir"); | ||
| 137 | if (*pwzData) | ||
| 138 | { | ||
| 139 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &pvdir->swapp); | ||
| 140 | ExitOnFailure(hr, "Failed to get application for VirtualDir"); | ||
| 141 | |||
| 142 | pvdir->fHasApplication = TRUE; | ||
| 143 | } | ||
| 144 | |||
| 145 | hr = WcaGetRecordString(hRec, vdqVDir, &pwzData); | ||
| 146 | ExitOnFailure(hr, "Failed to get VDir for VirtualDir"); | ||
| 147 | |||
| 148 | if (*pwzData && *ppsmmList) | ||
| 149 | { | ||
| 150 | hr = ScaGetMimeMap(mmptVDir, pwzData, ppsmmList, &pvdir->psmm); | ||
| 151 | ExitOnFailure(hr, "Failed to get mimemap for VirtualDir"); | ||
| 152 | } | ||
| 153 | |||
| 154 | if (*pwzData && *ppshhList) | ||
| 155 | { | ||
| 156 | hr = ScaGetHttpHeader(hhptVDir, pwzData, ppshhList, &pvdir->pshh); | ||
| 157 | ExitOnFailure(hr, "Failed to get custom HTTP headers for VirtualDir: %ls", pwzData); | ||
| 158 | } | ||
| 159 | |||
| 160 | if (*pwzData && *ppsweList) | ||
| 161 | { | ||
| 162 | hr = ScaGetWebError(weptVDir, pwzData, ppsweList, &pvdir->pswe); | ||
| 163 | ExitOnFailure(hr, "Failed to get custom web errors for VirtualDir: %ls", pwzData); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | if (E_NOMOREITEMS == hr) | ||
| 168 | { | ||
| 169 | hr = S_OK; | ||
| 170 | } | ||
| 171 | ExitOnFailure(hr, "Failure while processing VirtualDirs"); | ||
| 172 | |||
| 173 | LExit: | ||
| 174 | WcaFinishUnwrapQuery(hWrapQuery); | ||
| 175 | |||
| 176 | ReleaseStr(pwzData); | ||
| 177 | return hr; | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | HRESULT ScaVirtualDirsInstall( | ||
| 182 | __in IMSAdminBase* piMetabase, | ||
| 183 | __in SCA_VDIR* psvdList, | ||
| 184 | __in SCA_APPPOOL * psapList | ||
| 185 | ) | ||
| 186 | { | ||
| 187 | Assert(piMetabase); | ||
| 188 | |||
| 189 | HRESULT hr = S_OK; | ||
| 190 | SCA_VDIR* psvd = psvdList; | ||
| 191 | int i; | ||
| 192 | |||
| 193 | while (psvd) | ||
| 194 | { | ||
| 195 | // On reinstall, we have to uninstall the old application, otherwise a duplicate will be created | ||
| 196 | if (WcaIsReInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 197 | { | ||
| 198 | if (psvd->fHasApplication) | ||
| 199 | { | ||
| 200 | hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot); | ||
| 201 | ExitOnFailure(hr, "Failed to remove application for WebVDir as part of a reinstall"); | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | if (WcaIsInstalling(psvd->isInstalled, psvd->isAction)) | ||
| 206 | { | ||
| 207 | hr = ScaCreateMetabaseKey(piMetabase, psvd->wzVDirRoot, L""); | ||
| 208 | ExitOnFailure(hr, "Failed to create key for VirtualDir"); | ||
| 209 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir"); | ||
| 210 | ExitOnFailure(hr, "Failed to write key type for for VirtualDir"); | ||
| 211 | i = 0x4000003e; // 1073741886; // default directory browsing rights | ||
| 212 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)i)); | ||
| 213 | ExitOnFailure(hr, "Failed to set directory browsing for VirtualDir"); | ||
| 214 | |||
| 215 | hr = ScaWriteMetabaseValue(piMetabase, psvd->wzVDirRoot, L"", MD_VR_PATH, METADATA_INHERIT, IIS_MD_UT_FILE, STRING_METADATA, (LPVOID)psvd->wzDirectory); | ||
| 216 | ExitOnFailure(hr, "Failed to write Directory for VirtualDir"); | ||
| 217 | |||
| 218 | if (psvd->fHasProperties) | ||
| 219 | { | ||
| 220 | ScaWriteWebDirProperties(piMetabase, psvd->wzVDirRoot, &psvd->swp); | ||
| 221 | ExitOnFailure(hr, "Failed to write directory properties for VirtualDir"); | ||
| 222 | } | ||
| 223 | |||
| 224 | if (psvd->fHasApplication) | ||
| 225 | { | ||
| 226 | hr = ScaWriteWebApplication(piMetabase, psvd->wzVDirRoot, &psvd->swapp, psapList); | ||
| 227 | ExitOnFailure(hr, "Failed to write application for VirtualDir"); | ||
| 228 | } | ||
| 229 | |||
| 230 | if (psvd->psmm) | ||
| 231 | { | ||
| 232 | hr = ScaWriteMimeMap(piMetabase, psvd->wzVDirRoot, psvd->psmm); | ||
| 233 | ExitOnFailure(hr, "Failed to write mimemap for VirtualDir"); | ||
| 234 | } | ||
| 235 | |||
| 236 | if (psvd->pshh) | ||
| 237 | { | ||
| 238 | hr = ScaWriteHttpHeader(piMetabase, psvd->wzVDirRoot, psvd->pshh); | ||
| 239 | ExitOnFailure(hr, "Failed to write custom HTTP headers for VirtualDir"); | ||
| 240 | } | ||
| 241 | |||
| 242 | if (psvd->pswe) | ||
| 243 | { | ||
| 244 | hr = ScaWriteWebError(piMetabase, weptVDir, psvd->wzVDirRoot, psvd->pswe); | ||
| 245 | ExitOnFailure(hr, "Failed to write custom web errors for VirtualDir"); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | psvd = psvd->psvdNext; | ||
| 250 | } | ||
| 251 | |||
| 252 | LExit: | ||
| 253 | return hr; | ||
| 254 | } | ||
| 255 | |||
| 256 | |||
| 257 | HRESULT ScaVirtualDirsUninstall( | ||
| 258 | __in IMSAdminBase* piMetabase, | ||
| 259 | __in SCA_VDIR* psvdList | ||
| 260 | ) | ||
| 261 | { | ||
| 262 | Assert(piMetabase); | ||
| 263 | |||
| 264 | HRESULT hr = S_OK; | ||
| 265 | SCA_VDIR* psvd = psvdList; | ||
| 266 | |||
| 267 | while (psvd) | ||
| 268 | { | ||
| 269 | if (WcaIsUninstalling(psvd->isInstalled, psvd->isAction)) | ||
| 270 | { | ||
| 271 | // delete the application for this virtual directory | ||
| 272 | if (psvd->fHasApplication) | ||
| 273 | { | ||
| 274 | hr = ScaDeleteApp(piMetabase, psvd->wzVDirRoot); | ||
| 275 | ExitOnFailure(hr, "Failed to remove application for WebVDir"); | ||
| 276 | } | ||
| 277 | |||
| 278 | if (0 != lstrlenW(psvd->wzVDirRoot)) | ||
| 279 | { | ||
| 280 | hr = ScaDeleteMetabaseKey(piMetabase, psvd->wzVDirRoot, L""); | ||
| 281 | ExitOnFailure(hr, "Failed to remove VirtualDir '%ls' from metabase", psvd->wzKey); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | psvd = psvd->psvdNext; | ||
| 286 | } | ||
| 287 | |||
| 288 | LExit: | ||
| 289 | return hr; | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | void ScaVirtualDirsFreeList( | ||
| 294 | __in SCA_VDIR* psvdList | ||
| 295 | ) | ||
| 296 | { | ||
| 297 | SCA_VDIR* psvdDelete = psvdList; | ||
| 298 | while (psvdList) | ||
| 299 | { | ||
| 300 | psvdDelete = psvdList; | ||
| 301 | psvdList = psvdList->psvdNext; | ||
| 302 | |||
| 303 | if (psvdDelete->psmm) | ||
| 304 | { | ||
| 305 | ScaMimeMapFreeList(psvdDelete->psmm); | ||
| 306 | } | ||
| 307 | |||
| 308 | if (psvdDelete->pswe) | ||
| 309 | { | ||
| 310 | ScaWebErrorFreeList(psvdDelete->pswe); | ||
| 311 | } | ||
| 312 | |||
| 313 | MemFree(psvdDelete); | ||
| 314 | } | ||
| 315 | } | ||
| 316 | |||
| 317 | |||
| 318 | static HRESULT AddVirtualDirToList( | ||
| 319 | __in SCA_VDIR** ppsvdList | ||
| 320 | ) | ||
| 321 | { | ||
| 322 | HRESULT hr = S_OK; | ||
| 323 | SCA_VDIR* psvd = static_cast<SCA_VDIR*>(MemAlloc(sizeof(SCA_VDIR), TRUE)); | ||
| 324 | ExitOnNull(psvd, hr, E_OUTOFMEMORY, "failed to allocate memory for new vdir list element"); | ||
| 325 | |||
| 326 | psvd->psvdNext= *ppsvdList; | ||
| 327 | *ppsvdList = psvd; | ||
| 328 | |||
| 329 | LExit: | ||
| 330 | return hr; | ||
| 331 | } | ||
