aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Iis/ca/scaweb7.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Iis/ca/scaweb7.cpp')
-rw-r--r--src/ext/Iis/ca/scaweb7.cpp953
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
11static SCA_WEB7* NewWeb7();
12static SCA_WEB7* AddWebToList7(
13 __in SCA_WEB7* pswList,
14 __in SCA_WEB7* psw
15 );
16
17static HRESULT ScaWebFindBase7(
18 __in SCA_WEB7* pswList,
19 LPCWSTR wzDescription
20 );
21
22static HRESULT ScaWebWrite7(
23 __in SCA_WEB7* psw,
24 __in SCA_APPPOOL * psapList
25 );
26
27static HRESULT ScaWebRemove7(__in const SCA_WEB7* psw);
28
29
30HRESULT 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
319LExit:
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
332BOOL 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
387LExit:
388 WcaLog(LOGMSG_VERBOSE, "Site with binding %ls %s a match", pwzBindingInfo, fFound ? "is" : "is not");
389 ReleaseNullStr(pwzBindingInfo);
390 return fFound;
391}
392
393BOOL 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;
425LExit:
426 VariantClear(&vtProp);
427 ReleaseNullObject(pSiteChildren);
428 ReleaseNullObject(pBindings);
429 ReleaseNullObject(pBindingsCollection);
430 ReleaseNullObject(pBinding);
431 return fFound;
432}
433
434HRESULT 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 }
523LExit:
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
539HRESULT 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 }
590LExit:
591 ReleaseNullStr(wzSiteName);
592 return hr;
593}
594
595HRESULT 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
615LExit:
616 return hr;
617}
618
619
620HRESULT 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
639LExit:
640 return hr;
641}
642
643
644void 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
664static SCA_WEB7* NewWeb7()
665{
666 SCA_WEB7* psw = (SCA_WEB7*)MemAlloc(sizeof(SCA_WEB7), TRUE);
667 Assert(psw);
668 return psw;
669}
670
671
672static 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
696static 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
723static 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
933LExit:
934 return hr;
935}
936
937
938static 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
951LExit:
952 return hr;
953}