diff options
Diffstat (limited to 'src/ext/Iis/ca/scaweb7.cpp')
-rw-r--r-- | src/ext/Iis/ca/scaweb7.cpp | 953 |
1 files changed, 953 insertions, 0 deletions
diff --git a/src/ext/Iis/ca/scaweb7.cpp b/src/ext/Iis/ca/scaweb7.cpp new file mode 100644 index 00000000..3ee781f2 --- /dev/null +++ b/src/ext/Iis/ca/scaweb7.cpp | |||
@@ -0,0 +1,953 @@ | |||
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 | //Adding this because delivery doesn't have the updated specstrings.h that windows build does | ||
6 | #ifndef __in_xcount | ||
7 | #define __in_xcount(size) | ||
8 | #endif | ||
9 | |||
10 | // prototypes for private helper functions | ||
11 | static SCA_WEB7* NewWeb7(); | ||
12 | static SCA_WEB7* AddWebToList7( | ||
13 | __in SCA_WEB7* pswList, | ||
14 | __in SCA_WEB7* psw | ||
15 | ); | ||
16 | |||
17 | static HRESULT ScaWebFindBase7( | ||
18 | __in SCA_WEB7* pswList, | ||
19 | LPCWSTR wzDescription | ||
20 | ); | ||
21 | |||
22 | static HRESULT ScaWebWrite7( | ||
23 | __in SCA_WEB7* psw, | ||
24 | __in SCA_APPPOOL * psapList | ||
25 | ); | ||
26 | |||
27 | static HRESULT ScaWebRemove7(__in const SCA_WEB7* psw); | ||
28 | |||
29 | |||
30 | HRESULT ScaWebsRead7( | ||
31 | __in SCA_WEB7** ppswList, | ||
32 | __in SCA_HTTP_HEADER** ppshhList, | ||
33 | __in SCA_WEB_ERROR** ppsweList, | ||
34 | __in WCA_WRAPQUERY_HANDLE hUserQuery, | ||
35 | __in WCA_WRAPQUERY_HANDLE hWebDirPropQuery, | ||
36 | __in WCA_WRAPQUERY_HANDLE hSslCertQuery, | ||
37 | __in WCA_WRAPQUERY_HANDLE hWebLogQuery, | ||
38 | __in WCA_WRAPQUERY_HANDLE hWebAppQuery, | ||
39 | __in WCA_WRAPQUERY_HANDLE hWebAppExtQuery, | ||
40 | __inout LPWSTR *ppwzCustomActionData | ||
41 | ) | ||
42 | { | ||
43 | Assert(ppswList); | ||
44 | WcaLog(LOGMSG_VERBOSE, "Entering ScaWebsRead7()"); | ||
45 | |||
46 | HRESULT hr = S_OK; | ||
47 | |||
48 | MSIHANDLE hRec; | ||
49 | MSIHANDLE hRecAddresses; | ||
50 | |||
51 | WCA_WRAPQUERY_HANDLE hQueryWebSite = NULL; | ||
52 | WCA_WRAPQUERY_HANDLE hQueryWebAddress = NULL; | ||
53 | |||
54 | SCA_WEB7* psw = NULL; | ||
55 | LPWSTR pwzData = NULL; | ||
56 | |||
57 | DWORD dwLen = 0; | ||
58 | errno_t error = EINVAL; | ||
59 | |||
60 | // check to see what tables are available | ||
61 | hr = WcaBeginUnwrapQuery(&hQueryWebSite, ppwzCustomActionData); | ||
62 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
63 | |||
64 | hr = WcaBeginUnwrapQuery(&hQueryWebAddress, ppwzCustomActionData); | ||
65 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebsRead"); | ||
66 | |||
67 | |||
68 | if (0 == WcaGetQueryRecords(hQueryWebSite) || 0 == WcaGetQueryRecords(hQueryWebAddress)) | ||
69 | { | ||
70 | WcaLog(LOGMSG_VERBOSE, "Required tables not present"); | ||
71 | ExitFunction1(hr = S_FALSE); | ||
72 | } | ||
73 | |||
74 | // loop through all the webs | ||
75 | while (S_OK == (hr = WcaFetchWrappedRecord(hQueryWebSite, &hRec))) | ||
76 | { | ||
77 | psw = NewWeb7(); | ||
78 | if (!psw) | ||
79 | { | ||
80 | hr = E_OUTOFMEMORY; | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | // get the darwin information | ||
85 | hr = WcaGetRecordString(hRec, wqWeb, &pwzData); | ||
86 | ExitOnFailure(hr, "Failed to get Web"); | ||
87 | hr = ::StringCchCopyW(psw->wzKey, countof(psw->wzKey), pwzData); | ||
88 | ExitOnFailure(hr, "Failed to copy key string to web object"); | ||
89 | |||
90 | // get component install state | ||
91 | hr = WcaGetRecordString(hRec, wqComponent, &pwzData); | ||
92 | ExitOnFailure(hr, "Failed to get Component for Web"); | ||
93 | hr = ::StringCchCopyW(psw->wzComponent, countof(psw->wzComponent), pwzData); | ||
94 | ExitOnFailure(hr, "Failed to copy component string to web object"); | ||
95 | if (*(psw->wzComponent)) | ||
96 | { | ||
97 | psw->fHasComponent = TRUE; | ||
98 | |||
99 | hr = WcaGetRecordInteger(hRec, wqInstalled, (int *)&psw->isInstalled); | ||
100 | ExitOnFailure(hr, "Failed to get web Component's installed state"); | ||
101 | |||
102 | WcaGetRecordInteger(hRec, wqAction, (int *)&psw->isAction); | ||
103 | ExitOnFailure(hr, "Failed to get web Component's action state"); | ||
104 | } | ||
105 | |||
106 | // Get the web's description. | ||
107 | hr = WcaGetRecordString(hRec, wqDescription, &pwzData); | ||
108 | ExitOnFailure(hr, "Failed to get Description for Web"); | ||
109 | hr = ::StringCchCopyW(psw->wzDescription, countof(psw->wzDescription), pwzData); | ||
110 | ExitOnFailure(hr, "Failed to copy description string to web object"); | ||
111 | |||
112 | //get web's site Id | ||
113 | hr = WcaGetRecordInteger(hRec, wqId, &psw->iSiteId); | ||
114 | ExitOnFailure(hr, "Failed to get SiteId for Web"); | ||
115 | |||
116 | // get the web's key address (Bindings) | ||
117 | hr = WcaGetRecordString(hRec, wqAddress, &pwzData); | ||
118 | ExitOnFailure(hr, "Failed to get Address for Web"); | ||
119 | hr = ::StringCchCopyW(psw->swaBinding.wzKey, countof(psw->swaBinding.wzKey), pwzData); | ||
120 | ExitOnFailure(hr, "Failed to copy web binding key"); | ||
121 | |||
122 | hr = WcaGetRecordString(hRec, wqIP, &pwzData); | ||
123 | ExitOnFailure(hr, "Failed to get IP for Web"); | ||
124 | hr = ::StringCchCopyW(psw->swaBinding.wzIP, countof(psw->swaBinding.wzIP), pwzData); | ||
125 | ExitOnFailure(hr, "Failed to copy web IP"); | ||
126 | |||
127 | hr = WcaGetRecordString(hRec, wqPort, &pwzData); | ||
128 | ExitOnFailure(hr, "Failed to get Web Address port"); | ||
129 | psw->swaBinding.iPort = wcstol(pwzData, NULL, 10); | ||
130 | |||
131 | hr = WcaGetRecordString(hRec, wqHeader, &pwzData); | ||
132 | ExitOnFailure(hr, "Failed to get Header for Web"); | ||
133 | hr = ::StringCchCopyW(psw->swaBinding.wzHeader, countof(psw->swaBinding.wzHeader), pwzData); | ||
134 | ExitOnFailure(hr, "Failed to copy web header"); | ||
135 | |||
136 | hr = WcaGetRecordInteger(hRec, wqSecure, &psw->swaBinding.fSecure); | ||
137 | ExitOnFailure(hr, "Failed to get if Web is secure"); | ||
138 | if (S_FALSE == hr) | ||
139 | { | ||
140 | psw->swaBinding.fSecure = FALSE; | ||
141 | } | ||
142 | |||
143 | // look to see if site exists | ||
144 | dwLen = METADATA_MAX_NAME_LEN; | ||
145 | hr = ScaWebFindBase7(*ppswList, psw->wzDescription); | ||
146 | |||
147 | // If we didn't find a web in memory, ignore it - during execute CA | ||
148 | // if the site truly does not exist then there will be an error. | ||
149 | if (S_OK == hr) | ||
150 | { | ||
151 | // site exists in config | ||
152 | psw->fBaseExists = TRUE; | ||
153 | } | ||
154 | else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) | ||
155 | { | ||
156 | hr = S_OK; | ||
157 | |||
158 | // site does not exists in config | ||
159 | psw->fBaseExists = FALSE; | ||
160 | } | ||
161 | ExitOnFailure(hr, "Failed to find web site"); | ||
162 | |||
163 | // get any extra web addresses | ||
164 | WcaFetchWrappedReset(hQueryWebAddress); | ||
165 | |||
166 | while (S_OK == (hr = WcaFetchWrappedRecordWhereString(hQueryWebAddress, 2, psw->wzKey, &hRecAddresses))) | ||
167 | { | ||
168 | if (MAX_ADDRESSES_PER_WEB <= psw->cExtraAddresses) | ||
169 | { | ||
170 | hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); | ||
171 | ExitOnFailure(hr, "Failure to get more extra web addresses, max exceeded."); | ||
172 | } | ||
173 | |||
174 | hr = WcaGetRecordString(hRecAddresses, waqAddress, &pwzData); | ||
175 | ExitOnFailure(hr, "Failed to get extra web Address"); | ||
176 | |||
177 | // if this isn't the key address add it | ||
178 | if (0 != lstrcmpW(pwzData, psw->swaBinding.wzKey)) | ||
179 | { | ||
180 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey, | ||
181 | countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzKey), pwzData); | ||
182 | ExitOnFailure(hr, "Failed to copy web binding key"); | ||
183 | |||
184 | hr = WcaGetRecordString(hRecAddresses, waqIP, &pwzData); | ||
185 | ExitOnFailure(hr, "Failed to get extra web IP"); | ||
186 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzIP), pwzData); | ||
187 | ExitOnFailure(hr, "Failed to copy web binding IP"); | ||
188 | |||
189 | hr = WcaGetRecordString(hRecAddresses, waqPort, &pwzData); | ||
190 | ExitOnFailure(hr, "Failed to get port for extra web IP"); | ||
191 | psw->swaExtraAddresses[psw->cExtraAddresses].iPort= wcstol(pwzData, NULL, 10); | ||
192 | |||
193 | // errno is set to ERANGE if overflow or underflow occurs | ||
194 | _get_errno(&error); | ||
195 | |||
196 | if (ERANGE == error) | ||
197 | { | ||
198 | hr = E_INVALIDARG; | ||
199 | ExitOnFailure(hr, "Failed to convert web Port address"); | ||
200 | } | ||
201 | |||
202 | hr = WcaGetRecordString(hRecAddresses, waqHeader, &pwzData); | ||
203 | ExitOnFailure(hr, "Failed to get header for extra web IP"); | ||
204 | hr = ::StringCchCopyW(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader, countof(psw->swaExtraAddresses[psw->cExtraAddresses].wzHeader), pwzData); | ||
205 | ExitOnFailure(hr, "Failed to copy web binding header"); | ||
206 | |||
207 | hr = WcaGetRecordInteger(hRecAddresses, waqSecure, &psw->swaExtraAddresses[psw->cExtraAddresses].fSecure); | ||
208 | ExitOnFailure(hr, "Failed to get if secure extra web IP"); | ||
209 | if (S_FALSE == hr) | ||
210 | { | ||
211 | psw->swaExtraAddresses[psw->cExtraAddresses].fSecure = FALSE; | ||
212 | } | ||
213 | |||
214 | ++psw->cExtraAddresses; | ||
215 | } | ||
216 | } | ||
217 | |||
218 | if (E_NOMOREITEMS == hr) | ||
219 | { | ||
220 | hr = S_OK; | ||
221 | } | ||
222 | ExitOnFailure(hr, "Failure occured while getting extra web addresses"); | ||
223 | |||
224 | // | ||
225 | // Connection time out | ||
226 | // | ||
227 | hr = WcaGetRecordInteger(hRec, wqConnectionTimeout, &psw->iConnectionTimeout); | ||
228 | ExitOnFailure(hr, "Failed to get connection timeout for Web"); | ||
229 | |||
230 | if (psw->fHasComponent) // If we're installing it, it needs a dir | ||
231 | { | ||
232 | // get the web's directory | ||
233 | if (INSTALLSTATE_SOURCE == psw->isAction) | ||
234 | { | ||
235 | hr = WcaGetRecordString(hRec, wqSourcePath, &pwzData); | ||
236 | } | ||
237 | else | ||
238 | { | ||
239 | hr = WcaGetRecordString(hRec, wqTargetPath, &pwzData); | ||
240 | } | ||
241 | ExitOnFailure(hr, "Failed to get Source/TargetPath for Directory"); | ||
242 | |||
243 | dwLen = lstrlenW(pwzData); | ||
244 | // remove trailing backslash | ||
245 | if (dwLen > 0 && pwzData[dwLen-1] == L'\\') | ||
246 | { | ||
247 | pwzData[dwLen-1] = 0; | ||
248 | } | ||
249 | hr = ::StringCchCopyW(psw->wzDirectory, countof(psw->wzDirectory), pwzData); | ||
250 | ExitOnFailure(hr, "Failed to copy web dir: '%ls'", pwzData); | ||
251 | |||
252 | } | ||
253 | |||
254 | hr = WcaGetRecordInteger(hRec, wqState, &psw->iState); | ||
255 | ExitOnFailure(hr, "Failed to get state for Web"); | ||
256 | |||
257 | hr = WcaGetRecordInteger(hRec, wqAttributes, &psw->iAttributes); | ||
258 | ExitOnFailure(hr, "Failed to get attributes for Web"); | ||
259 | |||
260 | // get the dir properties for this web | ||
261 | hr = WcaGetRecordString(hRec, wqProperties, &pwzData); | ||
262 | ExitOnFailure(hr, "Failed to get directory properties for Web"); | ||
263 | if (*pwzData) | ||
264 | { | ||
265 | hr = ScaGetWebDirProperties(pwzData, hUserQuery, hWebDirPropQuery, &psw->swp); | ||
266 | ExitOnFailure(hr, "Failed to get directory properties for Web"); | ||
267 | |||
268 | psw->fHasProperties = TRUE; | ||
269 | } | ||
270 | |||
271 | // get the application information for this web | ||
272 | hr = WcaGetRecordString(hRec, wqApplication, &pwzData); | ||
273 | ExitOnFailure(hr, "Failed to get application identifier for Web"); | ||
274 | if (*pwzData) | ||
275 | { | ||
276 | hr = ScaGetWebApplication(NULL, pwzData, hWebAppQuery, hWebAppExtQuery, &psw->swapp); | ||
277 | ExitOnFailure(hr, "Failed to get application for Web"); | ||
278 | |||
279 | psw->fHasApplication = TRUE; | ||
280 | } | ||
281 | |||
282 | // get the SSL certificates | ||
283 | hr = ScaSslCertificateRead(psw->wzKey, hSslCertQuery, &(psw->pswscList)); | ||
284 | ExitOnFailure(hr, "Failed to get SSL Certificates."); | ||
285 | |||
286 | // get the custom headers | ||
287 | if (*ppshhList) | ||
288 | { | ||
289 | hr = ScaGetHttpHeader(hhptWeb, psw->wzKey, ppshhList, &(psw->pshhList)); | ||
290 | ExitOnFailure(hr, "Failed to get Custom HTTP Headers"); | ||
291 | } | ||
292 | |||
293 | // get the errors | ||
294 | if (*ppsweList) | ||
295 | { | ||
296 | hr = ScaGetWebError(weptWeb, psw->wzKey, ppsweList, &(psw->psweList)); | ||
297 | ExitOnFailure(hr, "Failed to get Custom Errors"); | ||
298 | } | ||
299 | |||
300 | // get the log information for this web | ||
301 | hr = WcaGetRecordString(hRec, wqLog, &pwzData); | ||
302 | ExitOnFailure(hr, "Failed to get log identifier for Web"); | ||
303 | if (*pwzData) | ||
304 | { | ||
305 | hr = ScaGetWebLog7(pwzData, hWebLogQuery, &psw->swl); | ||
306 | ExitOnFailure(hr, "Failed to get Log for Web."); | ||
307 | psw->fHasLog = TRUE; | ||
308 | } | ||
309 | |||
310 | *ppswList = AddWebToList7(*ppswList, psw); | ||
311 | psw = NULL; // set the web NULL so it doesn't accidentally get freed below | ||
312 | } | ||
313 | |||
314 | if (E_NOMOREITEMS == hr) | ||
315 | { | ||
316 | hr = S_OK; | ||
317 | } | ||
318 | |||
319 | LExit: | ||
320 | // if anything was left over after an error clean it all up | ||
321 | WcaFinishUnwrapQuery(hQueryWebSite); | ||
322 | WcaFinishUnwrapQuery(hQueryWebAddress); | ||
323 | |||
324 | ScaWebsFreeList7(psw); | ||
325 | |||
326 | ReleaseStr(pwzData); | ||
327 | WcaLog(LOGMSG_VERBOSE, "Exiting ScaWebsRead7()"); | ||
328 | |||
329 | return hr; | ||
330 | } | ||
331 | |||
332 | BOOL CompareBinding( | ||
333 | __in IAppHostElement* pBinding, | ||
334 | __in LPVOID pContext | ||
335 | ) | ||
336 | { | ||
337 | BOOL fFound = FALSE; | ||
338 | HRESULT hr = S_OK; | ||
339 | LPWSTR pwzBindingInfo = NULL; | ||
340 | SCA_WEB7* psw = (SCA_WEB7*)pContext; | ||
341 | |||
342 | hr = Iis7GetPropertyString(pBinding, IIS_CONFIG_BINDINGINFO, &pwzBindingInfo); | ||
343 | ExitOnFailure(hr, "Failed to get bindinginfo for binding element"); | ||
344 | |||
345 | LPWSTR pwzExists = pwzBindingInfo; | ||
346 | // Break down the address into its constituent parts (IP:Port:Header). | ||
347 | // Taken from IIS6 CA code for compatibility | ||
348 | while (S_OK == hr && *pwzExists) | ||
349 | { | ||
350 | LPCWSTR pwzIPExists = pwzExists; | ||
351 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzIPExists, L":")); | ||
352 | if (NULL == pwzExists) | ||
353 | { | ||
354 | ExitFunction(); | ||
355 | } | ||
356 | *pwzExists = L'\0'; | ||
357 | |||
358 | LPCWSTR pwzPortExists = pwzExists + 1; | ||
359 | pwzExists = const_cast<LPWSTR>(wcsstr(pwzPortExists, L":")); | ||
360 | if (NULL == pwzExists) | ||
361 | { | ||
362 | ExitFunction(); | ||
363 | } | ||
364 | *pwzExists = L'\0'; | ||
365 | int iPortExists = wcstol(pwzPortExists, NULL, 10); | ||
366 | |||
367 | LPCWSTR pwzHeaderExists = pwzExists + 1; | ||
368 | |||
369 | BOOL fIpMatches = (0 == lstrcmpW(psw->swaBinding.wzIP, pwzIPExists)); // Explicit IP match | ||
370 | fIpMatches |= (0 == lstrcmpW(psw->swaBinding.wzIP, L"*")); // Authored * matches any IP | ||
371 | fIpMatches |= ('\0' != psw->swaBinding.wzIP) && // Unauthored IP | ||
372 | (0 == lstrcmpW(pwzIPExists, L"*")); // matches the All Unassigned IP : '*' | ||
373 | |||
374 | // compare the passed in address with the address listed for this web | ||
375 | if (fIpMatches && psw->swaBinding.iPort == iPortExists && | ||
376 | 0 == lstrcmpW(psw->swaBinding.wzHeader, pwzHeaderExists)) | ||
377 | { | ||
378 | fFound = TRUE; | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | // move to the next block of data, this may move beyond the available | ||
383 | // data and exit the while loop above. | ||
384 | pwzExists = const_cast<LPWSTR>(pwzHeaderExists + lstrlenW(pwzHeaderExists)); | ||
385 | } | ||
386 | |||
387 | LExit: | ||
388 | WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not"); | ||
389 | ReleaseNullStr(pwzBindingInfo); | ||
390 | return fFound; | ||
391 | } | ||
392 | |||
393 | BOOL EnumSiteCompareBinding( | ||
394 | __in IAppHostElement* pSite, | ||
395 | __in LPVOID pContext | ||
396 | ) | ||
397 | { | ||
398 | BOOL fFound = FALSE; | ||
399 | HRESULT hr = S_OK; | ||
400 | SCA_WEB7* psw = (SCA_WEB7*)pContext; | ||
401 | IAppHostChildElementCollection *pSiteChildren = NULL; | ||
402 | IAppHostElement *pBindings = NULL; | ||
403 | IAppHostElementCollection *pBindingsCollection = NULL; | ||
404 | IAppHostElement *pBinding = NULL; | ||
405 | VARIANT vtProp; | ||
406 | VariantInit(&vtProp); | ||
407 | |||
408 | hr = pSite->get_ChildElements(&pSiteChildren); | ||
409 | ExitOnFailure(hr, "Failed get site child elements collection"); | ||
410 | |||
411 | vtProp.vt = VT_BSTR; | ||
412 | vtProp.bstrVal = ::SysAllocString(IIS_CONFIG_BINDINGS); | ||
413 | hr = pSiteChildren->get_Item(vtProp, &pBindings); | ||
414 | ExitOnFailure(hr, "Failed get bindings element"); | ||
415 | |||
416 | hr = pBindings->get_Collection(&pBindingsCollection); | ||
417 | ExitOnFailure(hr, "Failed get bindings collection"); | ||
418 | |||
419 | WcaLog(LOGMSG_VERBOSE, "Searching for site with binding %ls:%d:%ls", psw->swaBinding.wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader); | ||
420 | |||
421 | hr = Iis7EnumAppHostElements(pBindingsCollection, CompareBinding, psw, &pBinding, NULL); | ||
422 | ExitOnFailure(hr, "Failed search bindings collection"); | ||
423 | |||
424 | fFound = NULL != pBinding; | ||
425 | LExit: | ||
426 | VariantClear(&vtProp); | ||
427 | ReleaseNullObject(pSiteChildren); | ||
428 | ReleaseNullObject(pBindings); | ||
429 | ReleaseNullObject(pBindingsCollection); | ||
430 | ReleaseNullObject(pBinding); | ||
431 | return fFound; | ||
432 | } | ||
433 | |||
434 | HRESULT ScaWebSearch7( | ||
435 | __in SCA_WEB7* psw, | ||
436 | __deref_out_z_opt LPWSTR* pswWeb, | ||
437 | __out_opt BOOL* pfFound | ||
438 | ) | ||
439 | { | ||
440 | HRESULT hr = S_OK; | ||
441 | BOOL fInitializedCom = FALSE; | ||
442 | BSTR bstrSites = NULL; | ||
443 | BSTR bstrAppHostRoot = NULL; | ||
444 | IAppHostAdminManager *pAdminMgr = NULL; | ||
445 | IAppHostElement *pSites = NULL; | ||
446 | IAppHostElementCollection *pCollection = NULL; | ||
447 | IAppHostElement *pSite = NULL; | ||
448 | |||
449 | if (NULL != pswWeb) | ||
450 | { | ||
451 | ReleaseNullStr(*pswWeb); | ||
452 | } | ||
453 | |||
454 | if (NULL != pfFound) | ||
455 | { | ||
456 | *pfFound = FALSE; | ||
457 | } | ||
458 | |||
459 | hr = ::CoInitialize(NULL); | ||
460 | ExitOnFailure(hr, "Failed to initialize COM"); | ||
461 | fInitializedCom = TRUE; | ||
462 | |||
463 | hr = CoCreateInstance(__uuidof(AppHostAdminManager), NULL, CLSCTX_INPROC_SERVER, __uuidof(IAppHostAdminManager), reinterpret_cast<void**> (&pAdminMgr)); | ||
464 | if (REGDB_E_CLASSNOTREG == hr) | ||
465 | { | ||
466 | WcaLog(LOGMSG_VERBOSE, "AppHostAdminManager was not registered, cannot find site."); | ||
467 | hr = S_OK; | ||
468 | ExitFunction(); | ||
469 | } | ||
470 | ExitOnFailure(hr, "Failed to CoCreate IAppHostAdminManager"); | ||
471 | |||
472 | bstrSites = ::SysAllocString(IIS_CONFIG_SITES_SECTION); | ||
473 | ExitOnNull(bstrSites, hr, E_OUTOFMEMORY, "Failed to allocate sites string."); | ||
474 | |||
475 | bstrAppHostRoot = ::SysAllocString(IIS_CONFIG_APPHOST_ROOT); | ||
476 | ExitOnNull(bstrAppHostRoot, hr, E_OUTOFMEMORY, "Failed to allocate host root string."); | ||
477 | |||
478 | hr = pAdminMgr->GetAdminSection(bstrSites, bstrAppHostRoot, &pSites); | ||
479 | ExitOnFailure(hr, "Failed get sites section"); | ||
480 | ExitOnNull(pSites, hr, ERROR_FILE_NOT_FOUND, "Failed get sites section object"); | ||
481 | |||
482 | hr = pSites->get_Collection(&pCollection); | ||
483 | ExitOnFailure(hr, "Failed get sites collection"); | ||
484 | |||
485 | // not explicitly doing a Description search | ||
486 | if (-1 != psw->iSiteId) | ||
487 | { | ||
488 | if (MSI_NULL_INTEGER == psw->iSiteId) | ||
489 | { | ||
490 | // Enumerate sites & determine if the binding matches | ||
491 | hr = Iis7EnumAppHostElements(pCollection, EnumSiteCompareBinding, psw, &pSite, NULL); | ||
492 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
493 | } | ||
494 | else | ||
495 | { | ||
496 | // Find a site with ID matches | ||
497 | hr = Iis7FindAppHostElementInteger(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_ID, psw->iSiteId, &pSite, NULL); | ||
498 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | if (NULL == pSite) | ||
503 | { | ||
504 | // Find a site with Name that matches | ||
505 | hr = Iis7FindAppHostElementString(pCollection, IIS_CONFIG_SITE, IIS_CONFIG_NAME, psw->wzDescription, &pSite, NULL); | ||
506 | ExitOnFailure(hr, "Failed locate site by ID"); | ||
507 | } | ||
508 | |||
509 | if (NULL != pSite) | ||
510 | { | ||
511 | if (NULL != pfFound) | ||
512 | { | ||
513 | *pfFound = TRUE; | ||
514 | } | ||
515 | |||
516 | if (NULL != pswWeb) | ||
517 | { | ||
518 | // We found a site, return its description | ||
519 | hr = Iis7GetPropertyString(pSite, IIS_CONFIG_NAME, pswWeb); | ||
520 | ExitOnFailure(hr, "Failed get site name"); | ||
521 | } | ||
522 | } | ||
523 | LExit: | ||
524 | ReleaseNullObject(pAdminMgr); | ||
525 | ReleaseNullObject(pSites); | ||
526 | ReleaseNullObject(pCollection); | ||
527 | ReleaseNullObject(pSite); | ||
528 | ReleaseBSTR(bstrAppHostRoot); | ||
529 | ReleaseBSTR(bstrSites); | ||
530 | |||
531 | if (fInitializedCom) | ||
532 | { | ||
533 | ::CoUninitialize(); | ||
534 | } | ||
535 | return hr; | ||
536 | } | ||
537 | |||
538 | |||
539 | HRESULT ScaWebsGetBase7( | ||
540 | __in SCA_WEB7* pswList, | ||
541 | __in LPCWSTR pswWebKey, | ||
542 | __out_ecount(cchDest) LPWSTR pswWeb, | ||
543 | __in DWORD_PTR cchDest | ||
544 | ) | ||
545 | { | ||
546 | HRESULT hr = S_OK; | ||
547 | BOOL fFound = FALSE; | ||
548 | SCA_WEB7* psw = pswList; | ||
549 | LPWSTR wzSiteName = NULL; | ||
550 | |||
551 | *pswWeb = '/0'; | ||
552 | |||
553 | //looking for psw->wzKey == pswWebKey | ||
554 | while(psw) | ||
555 | { | ||
556 | if (0 == wcscmp(pswWebKey, psw->wzKey)) | ||
557 | { | ||
558 | fFound = TRUE; | ||
559 | break; | ||
560 | } | ||
561 | psw = psw->pswNext; | ||
562 | } | ||
563 | |||
564 | if (!fFound) | ||
565 | { | ||
566 | ExitFunction1(hr = S_FALSE); | ||
567 | } | ||
568 | |||
569 | // Search if we're not installing the site | ||
570 | if (!psw->fHasComponent || (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS)) | ||
571 | { | ||
572 | // We are not installing this website. Search for it in IIS config | ||
573 | hr = ScaWebSearch7(psw, &wzSiteName, NULL); | ||
574 | ExitOnFailure(hr, "Failed to search for Website"); | ||
575 | |||
576 | if (NULL != wzSiteName) | ||
577 | { | ||
578 | hr = ::StringCchCopyW(pswWeb, cchDest, wzSiteName); | ||
579 | ExitOnFailure(hr, "Failed to set Website description for located Website"); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | if ('/0' == *pswWeb) | ||
584 | { | ||
585 | WcaLog(LOGMSG_VERBOSE, "Could not find Web: %ls, defaulting to %ls", psw->wzKey, psw->wzDescription); | ||
586 | // Default to the provided description, the Exec CA will locate by description | ||
587 | hr = ::StringCchCopyW(pswWeb, cchDest, psw->wzDescription); | ||
588 | ExitOnFailure(hr, "Failed to set Website description to default"); | ||
589 | } | ||
590 | LExit: | ||
591 | ReleaseNullStr(wzSiteName); | ||
592 | return hr; | ||
593 | } | ||
594 | |||
595 | HRESULT ScaWebsInstall7( | ||
596 | __in SCA_WEB7* pswList, | ||
597 | __in SCA_APPPOOL * psapList | ||
598 | ) | ||
599 | { | ||
600 | HRESULT hr = S_OK; | ||
601 | SCA_WEB7* psw = pswList; | ||
602 | |||
603 | while (psw) | ||
604 | { | ||
605 | // if we are installing the web site | ||
606 | if (psw->fHasComponent && WcaIsInstalling(psw->isInstalled, psw->isAction)) | ||
607 | { | ||
608 | hr = ScaWebWrite7(psw, psapList); | ||
609 | ExitOnFailure(hr, "failed to write web '%ls' to metabase", psw->wzKey); | ||
610 | } | ||
611 | |||
612 | psw = psw->pswNext; | ||
613 | } | ||
614 | |||
615 | LExit: | ||
616 | return hr; | ||
617 | } | ||
618 | |||
619 | |||
620 | HRESULT ScaWebsUninstall7( | ||
621 | __in SCA_WEB7* pswList | ||
622 | ) | ||
623 | { | ||
624 | HRESULT hr = S_OK; | ||
625 | SCA_WEB7* psw = pswList; | ||
626 | |||
627 | while (psw) | ||
628 | { | ||
629 | if (psw->fHasComponent && WcaIsUninstalling(psw->isInstalled, psw->isAction)) | ||
630 | { | ||
631 | // If someone | ||
632 | hr = ScaWebRemove7(psw); | ||
633 | ExitOnFailure(hr, "Failed to remove web '%ls' ", psw->wzKey); | ||
634 | } | ||
635 | |||
636 | psw = psw->pswNext; | ||
637 | } | ||
638 | |||
639 | LExit: | ||
640 | return hr; | ||
641 | } | ||
642 | |||
643 | |||
644 | void ScaWebsFreeList7(__in SCA_WEB7* pswList) | ||
645 | { | ||
646 | SCA_WEB7* pswDelete = pswList; | ||
647 | while (pswList) | ||
648 | { | ||
649 | pswDelete = pswList; | ||
650 | pswList = pswList->pswNext; | ||
651 | |||
652 | // Free the SSL, headers and errors list first | ||
653 | ScaSslCertificateFreeList(pswDelete->pswscList); | ||
654 | ScaHttpHeaderFreeList(pswDelete->pshhList); | ||
655 | ScaWebErrorFreeList(pswDelete->psweList); | ||
656 | |||
657 | MemFree(pswDelete); | ||
658 | } | ||
659 | } | ||
660 | |||
661 | |||
662 | // private helper functions | ||
663 | |||
664 | static SCA_WEB7* NewWeb7() | ||
665 | { | ||
666 | SCA_WEB7* psw = (SCA_WEB7*)MemAlloc(sizeof(SCA_WEB7), TRUE); | ||
667 | Assert(psw); | ||
668 | return psw; | ||
669 | } | ||
670 | |||
671 | |||
672 | static SCA_WEB7* AddWebToList7( | ||
673 | __in SCA_WEB7* pswList, | ||
674 | __in SCA_WEB7* psw | ||
675 | ) | ||
676 | { | ||
677 | if (pswList) | ||
678 | { | ||
679 | SCA_WEB7* pswTemp = pswList; | ||
680 | while (pswTemp->pswNext) | ||
681 | { | ||
682 | pswTemp = pswTemp->pswNext; | ||
683 | } | ||
684 | |||
685 | pswTemp->pswNext = psw; | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | pswList = psw; | ||
690 | } | ||
691 | |||
692 | return pswList; | ||
693 | } | ||
694 | |||
695 | |||
696 | static HRESULT ScaWebFindBase7( | ||
697 | __in SCA_WEB7* pswList, | ||
698 | __in_z LPCWSTR wzDescription | ||
699 | ) | ||
700 | { | ||
701 | HRESULT hr = S_OK; | ||
702 | BOOL fFound = FALSE; | ||
703 | |||
704 | // try to find the web in memory first | ||
705 | for (SCA_WEB7* psw = pswList; psw; psw = psw->pswNext) | ||
706 | { | ||
707 | if (0 == wcscmp(wzDescription, psw->wzDescription)) | ||
708 | { | ||
709 | fFound = TRUE; | ||
710 | break; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | if (!fFound) | ||
715 | { | ||
716 | hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); | ||
717 | } | ||
718 | |||
719 | return hr; | ||
720 | } | ||
721 | |||
722 | |||
723 | static HRESULT ScaWebWrite7( | ||
724 | __in SCA_WEB7* psw, | ||
725 | __in SCA_APPPOOL * psapList | ||
726 | ) | ||
727 | { | ||
728 | HRESULT hr = S_OK; | ||
729 | |||
730 | BOOL fExists = FALSE; | ||
731 | UINT ui = 0; | ||
732 | WCHAR wzIP[64]; | ||
733 | WCHAR wzBinding[1024]; | ||
734 | WCHAR wzAppPoolName[MAX_PATH]; | ||
735 | |||
736 | // | ||
737 | // determine if site must be new | ||
738 | // | ||
739 | if (psw->iAttributes & SWATTRIB_NOCONFIGUREIFEXISTS) | ||
740 | { | ||
741 | // Check if site already exists. | ||
742 | hr = ScaWebSearch7(psw, NULL, &fExists); | ||
743 | ExitOnFailure(hr, "Failed to search for web: %ls", psw->wzKey); | ||
744 | |||
745 | if (fExists) | ||
746 | { | ||
747 | hr = S_FALSE; | ||
748 | WcaLog(LOGMSG_VERBOSE, "Skipping configuration of existing web: %ls", psw->wzKey); | ||
749 | ExitFunction(); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | //create a site | ||
754 | hr = ScaWriteConfigID(IIS_SITE); | ||
755 | ExitOnFailure(hr, "Failed write site ID"); | ||
756 | |||
757 | hr = ScaWriteConfigID(IIS_CREATE); | ||
758 | ExitOnFailure(hr, "Failed write site ID create action"); | ||
759 | |||
760 | //Site Name | ||
761 | hr = ScaWriteConfigString(psw->wzDescription); //Site Name | ||
762 | ExitOnFailure(hr, "Failed write site desc"); | ||
763 | |||
764 | //Site Id -- value is MSI_NULL_INTEGER if not set in WIX | ||
765 | hr = ScaWriteConfigInteger(psw->iSiteId); //SiteID | ||
766 | ExitOnFailure(hr, "Failed write site id value"); | ||
767 | |||
768 | //Site Auto Start -- value is MSI_NULL_INTEGER if not set in WIX | ||
769 | hr = ScaWriteConfigInteger(psw->iState); // serverAutoStart | ||
770 | ExitOnFailure(hr, "Failed write site autostart"); | ||
771 | |||
772 | hr = ScaWriteConfigInteger(psw->iConnectionTimeout); //limits/connectionTimeout | ||
773 | ExitOnFailure(hr, "Failed write site timeout"); | ||
774 | |||
775 | //create default application | ||
776 | hr = ScaWriteConfigID(IIS_APPLICATION); | ||
777 | ExitOnFailure(hr, "Failed write app ID"); | ||
778 | hr = ScaWriteConfigID(IIS_CREATE); | ||
779 | ExitOnFailure(hr, "Failed write app action ID"); | ||
780 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
781 | ExitOnFailure(hr, "Failed write app desc"); | ||
782 | hr = ScaWriteConfigString(L"/"); // App Path (default) | ||
783 | ExitOnFailure(hr, "Failed write app def path /"); | ||
784 | |||
785 | if (psw->fHasApplication && *psw->swapp.wzAppPool) | ||
786 | { | ||
787 | hr = ScaFindAppPool7(psw->swapp.wzAppPool, wzAppPoolName, countof(wzAppPoolName), psapList); | ||
788 | ExitOnFailure(hr, "Failed to read app pool from application"); | ||
789 | |||
790 | hr = ScaWriteConfigString(wzAppPoolName); | ||
791 | ExitOnFailure(hr, "Failed write app appPool"); | ||
792 | } | ||
793 | else | ||
794 | { | ||
795 | hr = ScaWriteConfigString(L""); | ||
796 | ExitOnFailure(hr, "Failed write app appPool"); | ||
797 | } | ||
798 | |||
799 | //create vdir for default application | ||
800 | hr = ScaWriteConfigID(IIS_VDIR); | ||
801 | ExitOnFailure(hr, "Failed write vdir ID"); | ||
802 | hr = ScaWriteConfigID(IIS_CREATE); | ||
803 | ExitOnFailure(hr, "Failed write vdir action"); | ||
804 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
805 | ExitOnFailure(hr, "Failed write vdir desc"); | ||
806 | hr = ScaWriteConfigString(L"/"); //vdir path (default) | ||
807 | ExitOnFailure(hr, "Failed write vdir app"); | ||
808 | hr = ScaWriteConfigString(psw->wzDirectory); //physical dir | ||
809 | ExitOnFailure(hr, "Failed write vdir dir"); | ||
810 | |||
811 | //create bindings for site | ||
812 | hr = ScaWriteConfigID(IIS_BINDING); | ||
813 | ExitOnFailure(hr, "Failed write binding ID"); | ||
814 | hr = ScaWriteConfigID(IIS_CREATE); | ||
815 | ExitOnFailure(hr, "Failed write binding action ID"); | ||
816 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
817 | ExitOnFailure(hr, "Failed write binding site key"); | ||
818 | |||
819 | if (psw->swaBinding.fSecure) | ||
820 | { | ||
821 | hr = ScaWriteConfigString(L"https"); // binding protocol | ||
822 | ExitOnFailure(hr, "Failed write binding https"); | ||
823 | } | ||
824 | else | ||
825 | { | ||
826 | hr = ScaWriteConfigString(L"http"); // binding protocol | ||
827 | ExitOnFailure(hr, "Failed write binding http"); | ||
828 | } | ||
829 | |||
830 | // set the IP address appropriately | ||
831 | if (0 == wcscmp(psw->swaBinding.wzIP, L"")) | ||
832 | { | ||
833 | hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add * | ||
834 | } | ||
835 | else | ||
836 | { | ||
837 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
838 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaBinding.wzIP); // else leave untouched | ||
839 | } | ||
840 | ExitOnFailure(hr, "Failed to copy IP string"); | ||
841 | |||
842 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaBinding.iPort, psw->swaBinding.wzHeader); | ||
843 | ExitOnFailure(hr, "Failed to format IP:Port:Header binding string"); | ||
844 | |||
845 | // write bindings CAData | ||
846 | hr = ScaWriteConfigString(wzBinding) ; //binding info | ||
847 | ExitOnFailure(hr, "Failed to create web bindings"); | ||
848 | |||
849 | for (ui = 0; (ui < MAX_ADDRESSES_PER_WEB) && (ui < psw->cExtraAddresses); ++ui) | ||
850 | { | ||
851 | // set the IP address appropriately | ||
852 | if (0 == wcscmp(psw->swaExtraAddresses[ui].wzIP, L"")) | ||
853 | { | ||
854 | hr = ::StringCchCopyW(wzIP, countof(wzIP), L"*"); // if no IP specified = add * | ||
855 | } | ||
856 | else | ||
857 | { | ||
858 | #pragma prefast(suppress:26037, "Source string is null terminated - it is populated as target of ::StringCchCopyW") | ||
859 | hr = ::StringCchCopyW(wzIP, countof(wzIP), psw->swaExtraAddresses[ui].wzIP); //else leave untouched | ||
860 | } | ||
861 | ExitOnFailure(hr, "Failed to copy web IP string"); | ||
862 | |||
863 | hr = ::StringCchPrintfW(wzBinding, countof(wzBinding), L"%s:%d:%s", wzIP, psw->swaExtraAddresses[ui].iPort, psw->swaExtraAddresses[ui].wzHeader); | ||
864 | ExitOnFailure(hr, "Failed to copy web IP"); | ||
865 | |||
866 | //create bindings for site | ||
867 | hr = ScaWriteConfigID(IIS_BINDING); | ||
868 | ExitOnFailure(hr, "Failed write binding ID"); | ||
869 | hr = ScaWriteConfigID(IIS_CREATE); | ||
870 | ExitOnFailure(hr, "Failed write binding action"); | ||
871 | hr = ScaWriteConfigString(psw->wzDescription); //site name key | ||
872 | ExitOnFailure(hr, "Failed write binding web name"); | ||
873 | |||
874 | if (psw->swaExtraAddresses[ui].fSecure) | ||
875 | { | ||
876 | hr = ScaWriteConfigString(L"https"); // binding protocol | ||
877 | } | ||
878 | else | ||
879 | { | ||
880 | hr = ScaWriteConfigString(L"http"); // binding protocol | ||
881 | } | ||
882 | ExitOnFailure(hr, "Failed write binding http(s)"); | ||
883 | |||
884 | // write bindings CAData | ||
885 | hr = ScaWriteConfigString(wzBinding) ; //binding info | ||
886 | ExitOnFailure(hr, "Failed write binding info"); | ||
887 | } | ||
888 | |||
889 | // write the web dirproperties information | ||
890 | if (psw->fHasProperties) | ||
891 | { | ||
892 | // dir properties are for the default application of the web | ||
893 | // with location '/' | ||
894 | hr = ScaWriteWebDirProperties7(psw->wzDescription, L"/", &psw->swp); | ||
895 | ExitOnFailure(hr, "Failed to write web security information to metabase"); | ||
896 | } | ||
897 | |||
898 | //// write the application information | ||
899 | if (psw->fHasApplication) | ||
900 | { | ||
901 | hr = ScaWriteWebApplication7(psw->wzDescription, L"/", &psw->swapp, psapList); | ||
902 | ExitOnFailure(hr, "Failed to write web application information to metabase"); | ||
903 | } | ||
904 | |||
905 | // write the SSL certificate information | ||
906 | if (psw->pswscList) | ||
907 | { | ||
908 | hr = ScaSslCertificateWrite7(psw->wzDescription, psw->pswscList); | ||
909 | ExitOnFailure(hr, "Failed to write SSL certificates for Web site: %ls", psw->wzKey); | ||
910 | } | ||
911 | |||
912 | // write the headers | ||
913 | if (psw->pshhList) | ||
914 | { | ||
915 | hr = ScaWriteHttpHeader7(psw->wzDescription, L"/", psw->pshhList); | ||
916 | ExitOnFailure(hr, "Failed to write custom HTTP headers for Web site: %ls", psw->wzKey); | ||
917 | } | ||
918 | |||
919 | // write the errors | ||
920 | if (psw->psweList) | ||
921 | { | ||
922 | hr = ScaWriteWebError7(psw->wzDescription, L"/", psw->psweList); | ||
923 | ExitOnFailure(hr, "Failed to write custom web errors for Web site: %ls", psw->wzKey); | ||
924 | } | ||
925 | |||
926 | // write the log information to the metabase | ||
927 | if (psw->fHasLog) | ||
928 | { | ||
929 | hr = ScaWriteWebLog7(psw->wzDescription, &psw->swl); | ||
930 | ExitOnFailure(hr, "Failed to write web log information to metabase"); | ||
931 | } | ||
932 | |||
933 | LExit: | ||
934 | return hr; | ||
935 | } | ||
936 | |||
937 | |||
938 | static HRESULT ScaWebRemove7( | ||
939 | __in const SCA_WEB7* psw | ||
940 | ) | ||
941 | { | ||
942 | HRESULT hr = S_OK; | ||
943 | |||
944 | hr = ScaWriteConfigID(IIS_SITE); | ||
945 | ExitOnFailure(hr, "Failed write site ID"); | ||
946 | hr = ScaWriteConfigID(IIS_DELETE); | ||
947 | ExitOnFailure(hr, "Failed write site action"); | ||
948 | hr = ScaWriteConfigString(psw->wzDescription); //Site Name | ||
949 | ExitOnFailure(hr, "Failed write site name"); | ||
950 | |||
951 | LExit: | ||
952 | return hr; | ||
953 | } | ||