aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Iis/ca/scawebsvcext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Iis/ca/scawebsvcext.cpp')
-rw-r--r--src/ext/Iis/ca/scawebsvcext.cpp343
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
6enum eWebSvcExtQuery { ldqComponent=1 , ldqFile, ldqDescription, ldqGroup, ldqAttributes, ldqInstalled, ldqAction };
7
8
9LPCWSTR vcsWebSvcExtRoot = L"/LM/W3SVC";
10
11// prototypes for private helper functions
12static HRESULT AddWebSvcExtToList(
13 __in SCA_WEBSVCEXT** ppsWseList
14 );
15
16//static HRESULT ScaCheckWebSvcExtValue(
17// __in IMSAdminBase* piMetabase,
18// __in DWORD dwMDIdentifier
19// );
20
21static HRESULT ScaWebSvcExtInstall(
22 __in LPWSTR *pwzWebSvcExtList,
23 __in DWORD_PTR *pcchWebSvcExtList,
24 __in SCA_WEBSVCEXT* psWseList
25 );
26
27static HRESULT ScaWebSvcExtUninstall(
28 __in LPWSTR *pwzWebSvcExtList,
29 __in const DWORD *pcchWebSvcExtList,
30 __in SCA_WEBSVCEXT* psWseList
31 );
32
33// functions
34
35HRESULT __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
112LExit:
113 WcaFinishUnwrapQuery(hWrapQuery);
114
115 ReleaseStr(pwzData);
116
117 return hr;
118}
119
120
121// Commit does both install and uninstall
122HRESULT __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
196LExit:
197 ReleaseStr(wzWebSvcExtList);
198
199 return hr;
200}
201
202
203static 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
248LExit:
249 ReleaseStr(pwzWebSvcExt);
250
251 return hr;
252}
253
254
255static 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
279LExit:
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
315void 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
329static 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
341LExit:
342 return hr;
343}