diff options
Diffstat (limited to 'src/ext/Iis/ca/scawebsvcext.cpp')
-rw-r--r-- | src/ext/Iis/ca/scawebsvcext.cpp | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/src/ext/Iis/ca/scawebsvcext.cpp b/src/ext/Iis/ca/scawebsvcext.cpp new file mode 100644 index 00000000..369e951b --- /dev/null +++ b/src/ext/Iis/ca/scawebsvcext.cpp | |||
@@ -0,0 +1,343 @@ | |||
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 | // sql queries | ||
6 | enum eWebSvcExtQuery { ldqComponent=1 , ldqFile, ldqDescription, ldqGroup, ldqAttributes, ldqInstalled, ldqAction }; | ||
7 | |||
8 | |||
9 | LPCWSTR vcsWebSvcExtRoot = L"/LM/W3SVC"; | ||
10 | |||
11 | // prototypes for private helper functions | ||
12 | static HRESULT AddWebSvcExtToList( | ||
13 | __in SCA_WEBSVCEXT** ppsWseList | ||
14 | ); | ||
15 | |||
16 | //static HRESULT ScaCheckWebSvcExtValue( | ||
17 | // __in IMSAdminBase* piMetabase, | ||
18 | // __in DWORD dwMDIdentifier | ||
19 | // ); | ||
20 | |||
21 | static HRESULT ScaWebSvcExtInstall( | ||
22 | __in LPWSTR *pwzWebSvcExtList, | ||
23 | __in DWORD_PTR *pcchWebSvcExtList, | ||
24 | __in SCA_WEBSVCEXT* psWseList | ||
25 | ); | ||
26 | |||
27 | static HRESULT ScaWebSvcExtUninstall( | ||
28 | __in LPWSTR *pwzWebSvcExtList, | ||
29 | __in const DWORD *pcchWebSvcExtList, | ||
30 | __in SCA_WEBSVCEXT* psWseList | ||
31 | ); | ||
32 | |||
33 | // functions | ||
34 | |||
35 | HRESULT __stdcall ScaWebSvcExtRead( | ||
36 | __in SCA_WEBSVCEXT** ppsWseList, | ||
37 | __inout LPWSTR *ppwzCustomActionData | ||
38 | ) | ||
39 | { | ||
40 | Assert(ppsWseList); | ||
41 | |||
42 | HRESULT hr = S_OK; | ||
43 | MSIHANDLE hRec; | ||
44 | LPWSTR pwzData = NULL; | ||
45 | INSTALLSTATE isInstalled = INSTALLSTATE_UNKNOWN; | ||
46 | INSTALLSTATE isAction = INSTALLSTATE_UNKNOWN; | ||
47 | SCA_WEBSVCEXT* psWebSvcExt = NULL; | ||
48 | WCA_WRAPQUERY_HANDLE hWrapQuery = NULL; | ||
49 | |||
50 | hr = WcaBeginUnwrapQuery(&hWrapQuery, ppwzCustomActionData); | ||
51 | ExitOnFailure(hr, "Failed to unwrap query for ScaWebSvcExtRead"); | ||
52 | |||
53 | if (0 == WcaGetQueryRecords(hWrapQuery)) | ||
54 | { | ||
55 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtRead() because IIsWebServiceExtension data not present"); | ||
56 | ExitFunction1(hr = S_FALSE); | ||
57 | } | ||
58 | |||
59 | // loop through all the web service extensions | ||
60 | while (S_OK == (hr = WcaFetchWrappedRecord(hWrapQuery, &hRec))) | ||
61 | { | ||
62 | // Get the Component first. If the Component is not being modified during | ||
63 | // this transaction, skip processing this whole record. | ||
64 | hr = WcaGetRecordString(hRec, ldqComponent, &pwzData); | ||
65 | ExitOnFailure(hr, "Failed to get Component for WebSvcExt"); | ||
66 | |||
67 | hr = WcaGetRecordInteger(hRec, ldqInstalled, (int *)&isInstalled); | ||
68 | ExitOnFailure(hr, "Failed to get Component installed state for WebSvcExt"); | ||
69 | |||
70 | hr = WcaGetRecordInteger(hRec, ldqAction, (int *)&isAction); | ||
71 | ExitOnFailure(hr, "Failed to get Component action state for WebSvcExt"); | ||
72 | |||
73 | if (!WcaIsInstalling(isInstalled, isAction) && | ||
74 | !WcaIsReInstalling(isInstalled, isAction) && | ||
75 | !WcaIsUninstalling(isInstalled, isAction)) | ||
76 | { | ||
77 | continue; // skip this record. | ||
78 | } | ||
79 | |||
80 | hr = AddWebSvcExtToList(ppsWseList); | ||
81 | ExitOnFailure(hr, "failed to add element to web svc ext list"); | ||
82 | |||
83 | psWebSvcExt = *ppsWseList; | ||
84 | Assert(psWebSvcExt); | ||
85 | |||
86 | psWebSvcExt->isInstalled = isInstalled; | ||
87 | psWebSvcExt->isAction = isAction; | ||
88 | |||
89 | hr = WcaGetRecordString(hRec, ldqFile, &pwzData); | ||
90 | ExitOnFailure(hr, "Failed to get File for WebSvcExt"); | ||
91 | hr = ::StringCchCopyW(psWebSvcExt->wzFile, countof(psWebSvcExt->wzFile), pwzData); | ||
92 | ExitOnFailure(hr, "Failed to copy File for WebSvcExt"); | ||
93 | |||
94 | hr = WcaGetRecordString(hRec, ldqDescription, &pwzData); | ||
95 | ExitOnFailure(hr, "Failed to get Description for WebSvcExt"); | ||
96 | hr = ::StringCchCopyW(psWebSvcExt->wzDescription, countof(psWebSvcExt->wzDescription), pwzData); | ||
97 | ExitOnFailure(hr, "Failed to copy Description for WebSvcExt"); | ||
98 | |||
99 | hr = WcaGetRecordString(hRec, ldqGroup, &pwzData); | ||
100 | ExitOnFailure(hr, "Failed to get Group for WebSvcExt"); | ||
101 | hr = ::StringCchCopyW(psWebSvcExt->wzGroup, countof(psWebSvcExt->wzGroup), pwzData); | ||
102 | ExitOnFailure(hr, "Failed to copy Group for WebSvcExt"); | ||
103 | |||
104 | hr = WcaGetRecordInteger(hRec, ldqAttributes, &psWebSvcExt->iAttributes); | ||
105 | ExitOnFailure(hr, "Failed to get Attributes for WebSvcExt"); | ||
106 | } | ||
107 | |||
108 | if (E_NOMOREITEMS == hr) | ||
109 | hr = S_OK; | ||
110 | ExitOnFailure(hr, "Failure while processing WebSvcExt"); | ||
111 | |||
112 | LExit: | ||
113 | WcaFinishUnwrapQuery(hWrapQuery); | ||
114 | |||
115 | ReleaseStr(pwzData); | ||
116 | |||
117 | return hr; | ||
118 | } | ||
119 | |||
120 | |||
121 | // Commit does both install and uninstall | ||
122 | HRESULT __stdcall ScaWebSvcExtCommit( | ||
123 | __in IMSAdminBase* piMetabase, | ||
124 | __in SCA_WEBSVCEXT* psWseList | ||
125 | ) | ||
126 | { | ||
127 | Assert(piMetabase); | ||
128 | |||
129 | HRESULT hr = S_OK; | ||
130 | METADATA_RECORD mr; | ||
131 | |||
132 | LPWSTR wzWebSvcExtList = NULL; | ||
133 | DWORD cbWebSvcExtList = 0; | ||
134 | DWORD_PTR cchWebSvcExtList = 0; | ||
135 | |||
136 | if (!psWseList) | ||
137 | { | ||
138 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because there are no web service extensions in the list"); | ||
139 | ExitFunction(); | ||
140 | } | ||
141 | |||
142 | // Get current set of web service extensions. | ||
143 | ::ZeroMemory(&mr, sizeof(mr)); | ||
144 | mr.dwMDIdentifier = MD_WEB_SVC_EXT_RESTRICTION_LIST; | ||
145 | mr.dwMDAttributes = 0; | ||
146 | mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
147 | mr.dwMDDataType = ALL_METADATA; | ||
148 | mr.pbMDData = NULL; | ||
149 | mr.dwMDDataLen = 0; | ||
150 | |||
151 | hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList); | ||
152 | if (MD_ERROR_DATA_NOT_FOUND == hr) | ||
153 | { | ||
154 | WcaLog(LOGMSG_VERBOSE, "Skipping ScaWebSvcExtCommit() because WebSvcExtRestrictionList value is not present"); | ||
155 | ExitFunction1(hr = S_FALSE); | ||
156 | } | ||
157 | else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
158 | { | ||
159 | // cchWebSvcExtList is returned in bytes. Convert to WCHAR size to call StrAlloc | ||
160 | cchWebSvcExtList = cbWebSvcExtList / sizeof(WCHAR); | ||
161 | hr = StrAlloc(&wzWebSvcExtList, cchWebSvcExtList); | ||
162 | ExitOnFailure(hr, "Failed allocating space for web service extensions"); | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | ExitOnFailure(hr, "Failed retrieving web service extensions"); | ||
167 | } | ||
168 | |||
169 | mr.pbMDData = (unsigned char*)wzWebSvcExtList; | ||
170 | mr.dwMDDataLen = cbWebSvcExtList; | ||
171 | |||
172 | hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cbWebSvcExtList); | ||
173 | ExitOnFailure(hr, "Failed retrieving web service extensions"); | ||
174 | |||
175 | // Make changes to local copy of metabase | ||
176 | while (psWseList) | ||
177 | { | ||
178 | if (WcaIsInstalling(psWseList->isInstalled, psWseList->isAction)) | ||
179 | { | ||
180 | hr = ScaWebSvcExtInstall(&wzWebSvcExtList, &cchWebSvcExtList, psWseList); | ||
181 | ExitOnFailure(hr, "Failed to install Web Service extension"); | ||
182 | } | ||
183 | else if (WcaIsUninstalling(psWseList->isInstalled, psWseList->isAction)) | ||
184 | { | ||
185 | hr = ScaWebSvcExtUninstall(&wzWebSvcExtList, (DWORD *)&cchWebSvcExtList, psWseList); | ||
186 | ExitOnFailure(hr, "Failed to uninstall Web Service extension"); | ||
187 | } | ||
188 | |||
189 | psWseList = psWseList->psWseNext; | ||
190 | } | ||
191 | |||
192 | // Write Metabase | ||
193 | hr = ScaWriteMetabaseValue(piMetabase, vcsWebSvcExtRoot, NULL, MD_WEB_SVC_EXT_RESTRICTION_LIST, METADATA_INHERIT, IIS_MD_UT_FILE, MULTISZ_METADATA, wzWebSvcExtList); | ||
194 | ExitOnFailure(hr, "Failed to write WebServiceExtensions: '%ls'", wzWebSvcExtList); | ||
195 | |||
196 | LExit: | ||
197 | ReleaseStr(wzWebSvcExtList); | ||
198 | |||
199 | return hr; | ||
200 | } | ||
201 | |||
202 | |||
203 | static HRESULT ScaWebSvcExtInstall( | ||
204 | __in LPWSTR *ppwzWebSvcExtList, | ||
205 | __in DWORD_PTR *pcchWebSvcExtList, | ||
206 | __in SCA_WEBSVCEXT* psWseList | ||
207 | ) | ||
208 | { | ||
209 | Assert( ppwzWebSvcExtList && pcchWebSvcExtList && psWseList); | ||
210 | Assert(*ppwzWebSvcExtList); | ||
211 | |||
212 | HRESULT hr = S_OK; | ||
213 | |||
214 | LPWSTR pwzWebSvcExt = NULL; | ||
215 | int iAllow; | ||
216 | int iUiDeletable; | ||
217 | |||
218 | BOOL fAlreadyExists = FALSE; | ||
219 | DWORD_PTR dwIndex = 0xFFFFFFFF; | ||
220 | LPCWSTR wzFoundString = NULL; | ||
221 | |||
222 | // Check if it's already in there | ||
223 | hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString); | ||
224 | ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile); | ||
225 | |||
226 | if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription)) | ||
227 | { | ||
228 | fAlreadyExists = TRUE; | ||
229 | } | ||
230 | |||
231 | // Construct the single string in the format required for the WebSvc Ext list in metabase | ||
232 | iAllow = (psWseList->iAttributes & 1); | ||
233 | iUiDeletable = ((psWseList->iAttributes >> 1) & 1); | ||
234 | hr = StrAllocFormatted(&pwzWebSvcExt, L"%d,%s,%d,%s,%s", iAllow, psWseList->wzFile, iUiDeletable, psWseList->wzGroup, psWseList->wzDescription); | ||
235 | ExitOnFailure(hr, "Failure allocating space for web service extensions"); | ||
236 | |||
237 | if (fAlreadyExists) | ||
238 | { | ||
239 | hr = MultiSzReplaceString(ppwzWebSvcExtList, dwIndex, pwzWebSvcExt); | ||
240 | ExitOnFailure(hr, "failed to update web service extension string: %ls", pwzWebSvcExt); | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | hr = MultiSzPrepend(ppwzWebSvcExtList, pcchWebSvcExtList, pwzWebSvcExt); | ||
245 | ExitOnFailure(hr, "failed to prepend web service extension string: %ls", pwzWebSvcExt); | ||
246 | } | ||
247 | |||
248 | LExit: | ||
249 | ReleaseStr(pwzWebSvcExt); | ||
250 | |||
251 | return hr; | ||
252 | } | ||
253 | |||
254 | |||
255 | static HRESULT ScaWebSvcExtUninstall( | ||
256 | __in LPWSTR *ppwzWebSvcExtList, | ||
257 | __in const DWORD* /*pcchWebSvcExtList*/, | ||
258 | __in SCA_WEBSVCEXT* psWseList | ||
259 | ) | ||
260 | { | ||
261 | Assert(ppwzWebSvcExtList && *ppwzWebSvcExtList && psWseList); | ||
262 | Assert(*ppwzWebSvcExtList); | ||
263 | |||
264 | HRESULT hr = S_OK; | ||
265 | DWORD_PTR dwIndex = 0xFFFFFFFF; | ||
266 | LPCWSTR wzFoundString = NULL; | ||
267 | |||
268 | // Find the string to remove | ||
269 | hr = MultiSzFindSubstring(*ppwzWebSvcExtList, psWseList->wzFile, &dwIndex, &wzFoundString); | ||
270 | ExitOnFailure(hr, "failed to search for string:%ls in web service extension MULTISZ", psWseList->wzFile); | ||
271 | |||
272 | // If we found a match (ignoring the Allow and Deletable flags) | ||
273 | if (S_FALSE != hr && NULL != wcsstr(wzFoundString, psWseList->wzGroup) && NULL != wcsstr(wzFoundString, psWseList->wzDescription)) | ||
274 | { | ||
275 | hr = MultiSzRemoveString(ppwzWebSvcExtList, dwIndex); | ||
276 | ExitOnFailure(hr, "failed to remove string: %d from web service extension MULTISZ", dwIndex); | ||
277 | } | ||
278 | |||
279 | LExit: | ||
280 | return hr; | ||
281 | } | ||
282 | |||
283 | |||
284 | //static HRESULT ScaCheckWebSvcExtValue( | ||
285 | // __in IMSAdminBase* piMetabase, | ||
286 | // __in DWORD dwMDIdentifier | ||
287 | // ) | ||
288 | //{ | ||
289 | // if (!piMetabase) | ||
290 | // { | ||
291 | // return E_INVALIDARG; | ||
292 | // } | ||
293 | // | ||
294 | // HRESULT hr = S_OK; | ||
295 | // METADATA_RECORD mr = { 0 }; | ||
296 | // DWORD cch = 0; | ||
297 | // | ||
298 | // mr.dwMDIdentifier = dwMDIdentifier; | ||
299 | // mr.dwMDUserType = IIS_MD_UT_SERVER; | ||
300 | // | ||
301 | // hr = piMetabase->GetData(METADATA_MASTER_ROOT_HANDLE, vcsWebSvcExtRoot, &mr, &cch); | ||
302 | // if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr) | ||
303 | // { | ||
304 | // hr = S_OK; | ||
305 | // } | ||
306 | // else if (MD_ERROR_DATA_NOT_FOUND == hr) | ||
307 | // { | ||
308 | // hr = S_FALSE; | ||
309 | // } | ||
310 | // | ||
311 | // return hr; | ||
312 | //} | ||
313 | |||
314 | |||
315 | void ScaWebSvcExtFreeList( | ||
316 | __in SCA_WEBSVCEXT* psWseList | ||
317 | ) | ||
318 | { | ||
319 | SCA_WEBSVCEXT* psWseDelete = psWseList; | ||
320 | while (psWseList) | ||
321 | { | ||
322 | psWseDelete = psWseList; | ||
323 | psWseList = psWseList->psWseNext; | ||
324 | MemFree(psWseDelete); | ||
325 | } | ||
326 | } | ||
327 | |||
328 | |||
329 | static HRESULT AddWebSvcExtToList( | ||
330 | __in SCA_WEBSVCEXT** ppsWseList | ||
331 | ) | ||
332 | { | ||
333 | HRESULT hr = S_OK; | ||
334 | |||
335 | SCA_WEBSVCEXT* psWse = static_cast<SCA_WEBSVCEXT*>(MemAlloc(sizeof(SCA_WEBSVCEXT), TRUE)); | ||
336 | ExitOnNull(psWse, hr, E_OUTOFMEMORY, "failed to allocate element for web svc ext list"); | ||
337 | |||
338 | psWse->psWseNext = *ppsWseList; | ||
339 | *ppsWseList = psWse; | ||
340 | |||
341 | LExit: | ||
342 | return hr; | ||
343 | } | ||