diff options
author | Rob Mensching <rob@firegiant.com> | 2021-05-04 22:48:12 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-05-04 22:48:12 -0700 |
commit | 7c8e34de56b3348c5a421cd0cced183e1394c5c7 (patch) | |
tree | c2f17867b49e33e0833eae2e1841a00b009c1a15 /src/ext/Iis/ca/scahttpheader.cpp | |
parent | c5c87377d99beefe83a3470aab326d12bdf0f8a4 (diff) | |
download | wix-7c8e34de56b3348c5a421cd0cced183e1394c5c7.tar.gz wix-7c8e34de56b3348c5a421cd0cced183e1394c5c7.tar.bz2 wix-7c8e34de56b3348c5a421cd0cced183e1394c5c7.zip |
Move Iis.wixext into ext
Diffstat (limited to 'src/ext/Iis/ca/scahttpheader.cpp')
-rw-r--r-- | src/ext/Iis/ca/scahttpheader.cpp | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/ext/Iis/ca/scahttpheader.cpp b/src/ext/Iis/ca/scahttpheader.cpp new file mode 100644 index 00000000..1e134cea --- /dev/null +++ b/src/ext/Iis/ca/scahttpheader.cpp | |||
@@ -0,0 +1,323 @@ | |||
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 | enum eHttpHeaderQuery { hhqName = 1, hhqParentType, hhqParentValue, hhqValue, hhqAttributes}; | ||
6 | |||
7 | static HRESULT AddHttpHeaderToList( | ||
8 | __in SCA_HTTP_HEADER** ppshhList | ||
9 | ); | ||
10 | |||
11 | |||
12 | void ScaHttpHeaderFreeList( | ||
13 | __in SCA_HTTP_HEADER* pshhList | ||
14 | ) | ||
15 | { | ||
16 | SCA_HTTP_HEADER* pshhDelete = pshhList; | ||
17 | while (pshhList) | ||
18 | { | ||
19 | pshhDelete = pshhList; | ||
20 | pshhList = pshhList->pshhNext; | ||
21 | |||
22 | MemFree(pshhDelete); | ||
23 | } | ||
24 | } | ||
25 | |||
26 | |||
27 | HRESULT ScaHttpHeaderRead( | ||
28 | __in SCA_HTTP_HEADER** ppshhList, | ||
29 | __inout LPWSTR *ppwzCustomActionData | ||
30 | ) | ||
31 | { | ||
32 | Assert(ppshhList); | ||
33 | |||
34 | HRESULT hr = S_OK; | ||
35 | MSIHANDLE hRec; | ||
36 | LPWSTR pwzData = NULL; | ||
37 | SCA_HTTP_HEADER* pshh = NULL; | ||
38 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
39 | |||
40 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
41 | ExitOnFailure(hr, "Failed to unwrap query for ScaAppPoolRead"); | ||
42 | |||
43 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
44 | { | ||
45 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaHttpHeaderRead() - required tables not present."); | ||
46 | ExitFunction1(hr = S_FALSE); | ||
47 | } | ||
48 | |||
49 | // loop through all the HTTP headers | ||
50 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
51 | { | ||
52 | hr = AddHttpHeaderToList(ppshhList); | ||
53 | ExitOnFailure(hr, "failed to add http header to list"); | ||
54 | |||
55 | pshh = *ppshhList; | ||
56 | |||
57 | hr = WcaGetRecordInteger(hRec, hhqParentType, &(pshh->iParentType)); | ||
58 | ExitOnFailure(hr, "failed to get IIsHttpHeader.ParentType"); | ||
59 | |||
60 | hr = WcaGetRecordString(hRec, hhqParentValue, &pwzData); | ||
61 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.ParentValue"); | ||
62 | hr = ::StringCchCopyW(pshh->wzParentValue, countof(pshh->wzParentValue), pwzData); | ||
63 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.ParentValue"); | ||
64 | |||
65 | hr = WcaGetRecordString(hRec, hhqName, &pwzData); | ||
66 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.Name"); | ||
67 | hr = ::StringCchCopyW(pshh->wzName, countof(pshh->wzName), pwzData); | ||
68 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Name"); | ||
69 | |||
70 | hr = WcaGetRecordString(hRec, hhqValue, &pwzData); | ||
71 | ExitOnFailure(hr, "Failed to get IIsHttpHeader.Value"); | ||
72 | hr = ::StringCchCopyW(pshh->wzValue, countof(pshh->wzValue), pwzData); | ||
73 | ExitOnFailure(hr, "Failed to copy IIsHttpHeader.Value"); | ||
74 | |||
75 | hr = WcaGetRecordInteger(hRec, hhqAttributes, &(pshh->iAttributes)); | ||
76 | ExitOnFailure(hr, "failed to get IIsHttpHeader.Attributes"); | ||
77 | } | ||
78 | |||
79 | if (E_NOMOREITEMS == hr) | ||
80 | { | ||
81 | hr = S_OK; | ||
82 | } | ||
83 | ExitOnFailure(hr, "Failure while processing web errors"); | ||
84 | |||
85 | LExit: | ||
86 | WcaFinishUnwrapQuery(hWrapQuery); | ||
87 | |||
88 | ReleaseStr(pwzData); | ||
89 | |||
90 | return hr; | ||
91 | } | ||
92 | |||
93 | |||
94 | HRESULT ScaGetHttpHeader( | ||
95 | __in int iParentType, | ||
96 | __in LPCWSTR wzParentValue, | ||
97 | __in SCA_HTTP_HEADER** ppshhList, | ||
98 | __out SCA_HTTP_HEADER** ppshhOut | ||
99 | ) | ||
100 | { | ||
101 | HRESULT hr = S_OK; | ||
102 | SCA_HTTP_HEADER* pshhAdd = NULL; | ||
103 | SCA_HTTP_HEADER* pshhLast = NULL; | ||
104 | |||
105 | *ppshhOut = NULL; | ||
106 | |||
107 | if (!*ppshhList) | ||
108 | { | ||
109 | return hr; | ||
110 | } | ||
111 | |||
112 | SCA_HTTP_HEADER* pshh = *ppshhList; | ||
113 | while (pshh) | ||
114 | { | ||
115 | if (iParentType == pshh->iParentType && CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, 0, wzParentValue, -1, pshh->wzParentValue, -1)) | ||
116 | { | ||
117 | // Found a match, take this one out of the list and add it to the matched out list | ||
118 | pshhAdd = pshh; | ||
119 | |||
120 | if (pshhLast) | ||
121 | { | ||
122 | // If we're not at the beginning of the list tell the last node about it's new next (since we're taking away it's current next) | ||
123 | pshhLast->pshhNext = pshhAdd->pshhNext; | ||
124 | } | ||
125 | else | ||
126 | { | ||
127 | // If we are at the beginning (no pshhLast) update the beginning (since we're taking it) | ||
128 | *ppshhList = pshh->pshhNext; | ||
129 | } | ||
130 | pshh = pshh->pshhNext; // move on | ||
131 | |||
132 | // Add the one we've removed to the beginning of the out list | ||
133 | pshhAdd->pshhNext = *ppshhOut; | ||
134 | *ppshhOut = pshhAdd; | ||
135 | } | ||
136 | else | ||
137 | { | ||
138 | pshhLast = pshh; // remember the last we that didn't match | ||
139 | pshh = pshh->pshhNext; // move on | ||
140 | } | ||
141 | } | ||
142 | |||
143 | return hr; | ||
144 | } | ||
145 | |||
146 | |||
147 | HRESULT ScaWriteHttpHeader( | ||
148 | __in IMSAdminBase* piMetabase, | ||
149 | __in LPCWSTR wzRoot, | ||
150 | __in SCA_HTTP_HEADER* pshhList | ||
151 | ) | ||
152 | { | ||
153 | Assert(piMetabase && pshhList); | ||
154 | |||
155 | HRESULT hr = S_OK; | ||
156 | METADATA_RECORD mr = { 0 }; | ||
157 | DWORD cchData = 0; | ||
158 | LPWSTR pwzSearchKey = NULL; | ||
159 | LPWSTR pwz = NULL; | ||
160 | LPWSTR pwzHeaders = NULL; | ||
161 | LPWSTR pwzNewHeader = NULL; | ||
162 | DWORD_PTR dwFoundHeaderIndex = 0; | ||
163 | LPCWSTR wzFoundHeader = NULL; | ||
164 | BOOL fOldValueFound = FALSE; | ||
165 | |||
166 | ExitOnNull(wzRoot, hr, E_INVALIDARG, "Failed to write HTTP header, because no root was provided"); | ||
167 | |||
168 | Assert(*wzRoot); | ||
169 | |||
170 | // Check if HTTP header already exist here. | ||
171 | mr.dwMDIdentifier = MD_HTTP_CUSTOM; | ||
172 | mr.dwMDAttributes = METADATA_INHERIT; | ||
173 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
174 | mr.dwMDDataType = ALL_METADATA; | ||
175 | mr.dwMDDataLen = cchData = 0; | ||
176 | mr.pbMDData = NULL; | ||
177 | |||
178 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, wzRoot, &mr); | ||
179 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
180 | { | ||
181 | // | ||
182 | // If we don't have any HTTP Headers already, move up to get the parent headers. | ||
183 | // TODO: Make it configurable to not inherit HTTP Headers | ||
184 | // | ||
185 | hr = StrAllocConcat(&pwzSearchKey, wzRoot, 0); | ||
186 | ExitOnFailure(hr, "Failed to copy root string: %ls", wzRoot); | ||
187 | |||
188 | pwz = pwzSearchKey + lstrlenW(pwzSearchKey); | ||
189 | while (NULL == pwzHeaders) | ||
190 | { | ||
191 | // find the last slash | ||
192 | while (*pwz != '/' && pwz != pwzSearchKey) | ||
193 | { | ||
194 | --pwz; | ||
195 | } | ||
196 | |||
197 | if (pwz == pwzSearchKey) | ||
198 | { | ||
199 | break; | ||
200 | } | ||
201 | |||
202 | *pwz = L'\0'; | ||
203 | |||
204 | // Try here. If it's not found, keep walking up the path | ||
205 | hr = MetaGetValue(piMetabase, METADATA_MASTER_ROOT_HANDLE, pwzSearchKey, &mr); | ||
206 | if (HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr || MD_ERROR_DATA_NOT_FOUND == hr) | ||
207 | { | ||
208 | hr = S_FALSE; | ||
209 | } | ||
210 | ExitOnFailure(hr, "Failed to find search for HTTP headers for web root: %ls while walking up the tree", wzRoot); | ||
211 | |||
212 | if (S_OK == hr) | ||
213 | { | ||
214 | hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0); | ||
215 | ExitOnFailure(hr, "Failed to allocate parent HTTP header string"); | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | } | ||
220 | else | ||
221 | { | ||
222 | hr = StrAllocString(&pwzHeaders, reinterpret_cast<LPWSTR>(mr.pbMDData), 0); | ||
223 | ExitOnFailure(hr, "Failed to allocate HTTP header string"); | ||
224 | } | ||
225 | ExitOnFailure(hr, "Failed while searching for default HTTP headers to start with for web root: %ls", wzRoot); | ||
226 | |||
227 | // Loop through the HTTP headers | ||
228 | for (SCA_HTTP_HEADER* pshh = pshhList; pshh; pshh = pshh->pshhNext) | ||
229 | { | ||
230 | fOldValueFound = FALSE; // assume a HTTP Header match will not be found | ||
231 | |||
232 | hr = StrAllocFormatted(&pwzNewHeader, L"%s: ", pshh->wzName); | ||
233 | ExitOnFailure(hr, "Failed to allocate header name"); | ||
234 | |||
235 | if (NULL != pwzHeaders && *pwzHeaders) | ||
236 | { | ||
237 | // Try to find a matching header already in the list | ||
238 | hr = MultiSzFindSubstring(pwzHeaders, pwzNewHeader, &dwFoundHeaderIndex, &wzFoundHeader); | ||
239 | ExitOnFailure(hr, "Failed while searching for existing HTTP header."); | ||
240 | |||
241 | // If there was a substring HTTP header match, make sure the match was at the beginning | ||
242 | // of the string because that is the HTTP header name. | ||
243 | if (S_OK == hr) | ||
244 | { | ||
245 | DWORD cchMatch = lstrlenW(pwzNewHeader); | ||
246 | if (CSTR_EQUAL == ::CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, pwzNewHeader, cchMatch, wzFoundHeader, cchMatch)) | ||
247 | { | ||
248 | fOldValueFound = TRUE; | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | |||
254 | // Add the value on to the header name now. | ||
255 | hr = StrAllocConcat(&pwzNewHeader, pshh->wzValue, 0); | ||
256 | ExitOnFailure(hr, "Failed to add value on to HTTP header name."); | ||
257 | |||
258 | // If we have something to replace, replace it, otherwise, put it at the beginning (order shouldn't matter) | ||
259 | if (fOldValueFound) | ||
260 | { | ||
261 | if (NULL == pwzHeaders) | ||
262 | { | ||
263 | ExitOnFailure(hr = E_INVALIDARG, "While attempting to replace old HTTP header with new HTTP header, it was discovered that the old HTTP header was NULL!"); | ||
264 | } | ||
265 | hr = MultiSzReplaceString(&pwzHeaders, dwFoundHeaderIndex, pwzNewHeader); | ||
266 | ExitOnFailure(hr, "Failed to replace old HTTP header with new HTTP header"); | ||
267 | } | ||
268 | else | ||
269 | { | ||
270 | hr = MultiSzPrepend(&pwzHeaders, NULL, pwzNewHeader); | ||
271 | ExitOnFailure(hr, "Failed to prepend new HTTP header"); | ||
272 | } | ||
273 | } | ||
274 | |||
275 | // now write the HttpCustom to the metabase | ||
276 | hr = ScaWriteMetabaseValue(piMetabase, wzRoot, NULL, MD_HTTP_CUSTOM, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, pwzHeaders); | ||
277 | ExitOnFailure(hr, "Failed to write HTTP Headers to metabase"); | ||
278 | |||
279 | LExit: | ||
280 | MetaFreeValue(&mr); | ||
281 | |||
282 | ReleaseStr(pwzNewHeader); | ||
283 | ReleaseStr(pwzHeaders); | ||
284 | ReleaseStr(pwzSearchKey); | ||
285 | |||
286 | return hr; | ||
287 | } | ||
288 | |||
289 | |||
290 | HRESULT ScaHttpHeaderCheckList( | ||
291 | __in SCA_HTTP_HEADER* pshhList | ||
292 | ) | ||
293 | { | ||
294 | if (!pshhList) | ||
295 | { | ||
296 | return S_OK; | ||
297 | } | ||
298 | |||
299 | while (pshhList) | ||
300 | { | ||
301 | WcaLog(LOGMSG_STANDARD, "Http Header: %ls for parent: %ls not used!", pshhList->wzName, pshhList->wzParentValue); | ||
302 | pshhList = pshhList->pshhNext; | ||
303 | } | ||
304 | |||
305 | return E_FAIL; | ||
306 | } | ||
307 | |||
308 | |||
309 | static HRESULT AddHttpHeaderToList( | ||
310 | __in SCA_HTTP_HEADER** ppshhList | ||
311 | ) | ||
312 | { | ||
313 | HRESULT hr = S_OK; | ||
314 | |||
315 | SCA_HTTP_HEADER* pshh = static_cast<SCA_HTTP_HEADER*>(MemAlloc(sizeof(SCA_HTTP_HEADER), TRUE)); | ||
316 | ExitOnNull(pshh, hr, E_OUTOFMEMORY, "failed to allocate memory for new http header list element"); | ||
317 | |||
318 | pshh->pshhNext = *ppshhList; | ||
319 | *ppshhList = pshh; | ||
320 | |||
321 | LExit: | ||
322 | return hr; | ||
323 | } | ||