aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Iis/ca/scahttpheader.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-04 22:48:12 -0700
committerRob Mensching <rob@firegiant.com>2021-05-04 22:48:12 -0700
commit7c8e34de56b3348c5a421cd0cced183e1394c5c7 (patch)
treec2f17867b49e33e0833eae2e1841a00b009c1a15 /src/ext/Iis/ca/scahttpheader.cpp
parentc5c87377d99beefe83a3470aab326d12bdf0f8a4 (diff)
downloadwix-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.cpp323
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
5enum eHttpHeaderQuery { hhqName = 1, hhqParentType, hhqParentValue, hhqValue, hhqAttributes};
6
7static HRESULT AddHttpHeaderToList(
8 __in SCA_HTTP_HEADER** ppshhList
9 );
10
11
12void 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
27HRESULT 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
85LExit:
86 WcaFinishUnwrapQuery(hWrapQuery);
87
88 ReleaseStr(pwzData);
89
90 return hr;
91}
92
93
94HRESULT 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
147HRESULT 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
279LExit:
280 MetaFreeValue(&mr);
281
282 ReleaseStr(pwzNewHeader);
283 ReleaseStr(pwzHeaders);
284 ReleaseStr(pwzSearchKey);
285
286 return hr;
287}
288
289
290HRESULT 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
309static 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
321LExit:
322 return hr;
323}