aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Iis/ca/scaiis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Iis/ca/scaiis.cpp')
-rw-r--r--src/ext/Iis/ca/scaiis.cpp481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/ext/Iis/ca/scaiis.cpp b/src/ext/Iis/ca/scaiis.cpp
new file mode 100644
index 00000000..958051ed
--- /dev/null
+++ b/src/ext/Iis/ca/scaiis.cpp
@@ -0,0 +1,481 @@
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// globals
6LPWSTR vpwzCustomActionData = NULL;
7DWORD vdwCustomActionCost = 0;
8
9HRESULT ScaMetabaseTransaction(__in_z LPCWSTR wzBackup)
10{
11 HRESULT hr = S_OK;
12
13 // TODO: These functions have been reported to hang IIS (O11:51709). They may have been fixed in IIS6, but if not, need to be re-written the hard way
14
15 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"StartMetabaseTransaction"), wzBackup, COST_IIS_TRANSACTIONS);
16 ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
17
18 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackMetabaseTransaction"), wzBackup, 0); // rollback cost is irrelevant
19 ExitOnFailure(hr, "Failed to schedule RollbackMetabaseTransaction");
20
21 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"CommitMetabaseTransaction"), wzBackup, 0); // commit is free
22 ExitOnFailure(hr, "Failed to schedule StartMetabaseTransaction");
23
24LExit:
25 return hr;
26}
27
28
29HRESULT ScaCreateWeb(IMSAdminBase* piMetabase, LPCWSTR /*wzWeb*/, LPCWSTR wzWebBase)
30{
31 Assert(piMetabase);
32
33 HRESULT hr = S_OK;
34 UINT ui = 0;
35
36 hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"");
37 ExitOnFailure(hr, "Failed to create web");
38
39 hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebServer");
40 ExitOnFailure(hr, "Failed to set key type for web");
41
42 hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Root");
43 ExitOnFailure(hr, "Failed to create web root");
44
45 hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsWebVirtualDir");
46 ExitOnFailure(hr, "Failed to set key type for web root");
47
48 ui = 0x4000003e; // 1073741886; // default directory browsing rights
49 hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Root", MD_DIRECTORY_BROWSING, METADATA_INHERIT, IIS_MD_UT_FILE, DWORD_METADATA, (LPVOID)((DWORD_PTR)ui));
50 ExitOnFailure(hr, "Failed to set directory browsing for web");
51
52 hr = ScaCreateMetabaseKey(piMetabase, wzWebBase, L"Filters");
53 ExitOnFailure(hr, "Failed to create web filters root");
54
55 hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_KEY_TYPE, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"IIsFilters");
56 ExitOnFailure(hr, "Failed to set key for web filters root");
57
58 hr = ScaWriteMetabaseValue(piMetabase, wzWebBase, L"Filters", MD_FILTER_LOAD_ORDER, METADATA_NO_ATTRIBUTES, IIS_MD_UT_SERVER, STRING_METADATA, (LPVOID)L"");
59 ExitOnFailure(hr, "Failed to set empty load order for web");
60
61LExit:
62 return hr;
63}
64
65
66HRESULT ScaDeleteApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot)
67{
68 Assert(piMetabase);
69 Unused(piMetabase);
70
71 HRESULT hr = S_OK;
72 WCHAR wzKey[METADATA_MAX_NAME_LEN];
73
74 WCHAR* pwzCustomActionData = NULL;
75
76 hr = WcaWriteIntegerToCaData(MBA_DELETEAPP, &pwzCustomActionData);
77 ExitOnFailure(hr, "Failed to add metabase delete app directive to CustomActionData");
78
79 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
80 ExitOnFailure(hr, "Failed to copy webroot string to key");
81 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
82 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
83
84 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEAPP);
85 ExitOnFailure(hr, "Failed to add ScaDeleteApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEAPP);
86
87LExit:
88 ReleaseStr(pwzCustomActionData);
89
90 return hr;
91}
92
93
94HRESULT ScaCreateApp(IMSAdminBase* piMetabase, LPCWSTR wzWebRoot,
95 DWORD dwIsolation)
96{
97 Assert(piMetabase);
98 Unused(piMetabase);
99
100 HRESULT hr = S_OK;
101 WCHAR wzKey[METADATA_MAX_NAME_LEN];
102 BOOL fInProc = FALSE;
103
104 WCHAR* pwzCustomActionData = NULL;
105
106 hr = WcaWriteIntegerToCaData(MBA_CREATEAPP, &pwzCustomActionData);
107 ExitOnFailure(hr, "Failed to add metabase create app directive to CustomActionData");
108
109 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzWebRoot);
110 ExitOnFailure(hr, "Failed to copy webroot string to key");
111 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
112 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
113
114 if (0 == dwIsolation)
115 fInProc = TRUE;
116 else
117 fInProc = FALSE;
118
119 hr = WcaWriteIntegerToCaData(fInProc, &pwzCustomActionData);
120 ExitOnFailure(hr, "Failed to add isolation value to CustomActionData");
121
122 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEAPP);
123 ExitOnFailure(hr, "Failed to add ScaCreateApp action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEAPP);
124
125LExit:
126 ReleaseStr(pwzCustomActionData);
127
128 return hr;
129}
130
131
132HRESULT ScaCreateMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
133 LPCWSTR wzSubKey)
134{
135 Assert(piMetabase);
136 Unused(piMetabase);
137
138 HRESULT hr = S_OK;
139 WCHAR wzKey[METADATA_MAX_NAME_LEN];
140 WCHAR* pwzCustomActionData = NULL;
141
142 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
143 ExitOnFailure(hr, "Failed to copy root key string to key");
144 if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
145 {
146 hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
147 ExitOnFailure(hr, "Failed to concatenate / to key string");
148 }
149 if (wzSubKey && *wzSubKey)
150 {
151 if (L'/' == *wzSubKey)
152 {
153 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
154 ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
155 }
156 else
157 {
158 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
159 ExitOnFailure(hr, "Failed to concatenate subkey to key string");
160 }
161 }
162
163 hr = WcaWriteIntegerToCaData(MBA_CREATEKEY, &pwzCustomActionData);
164 ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
165
166 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
167 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
168
169 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_CREATEKEY);
170 ExitOnFailure(hr, "Failed to add ScaCreateMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_CREATEKEY);
171
172LExit:
173 ReleaseStr(pwzCustomActionData);
174
175 return hr;
176}
177
178
179HRESULT ScaDeleteMetabaseKey(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
180 LPCWSTR wzSubKey)
181{
182 Assert(piMetabase);
183 Unused(piMetabase);
184
185 HRESULT hr = S_OK;
186 WCHAR wzKey[METADATA_MAX_NAME_LEN];
187 WCHAR* pwzCustomActionData = NULL;
188
189 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
190 ExitOnFailure(hr, "Failed to copy root key string to key");
191 if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
192 {
193 hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
194 ExitOnFailure(hr, "Failed to concatenate / to key string");
195 }
196 if (*wzSubKey)
197 {
198 if (L'/' == *wzSubKey)
199 {
200 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
201 ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
202 }
203 else
204 {
205 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
206 ExitOnFailure(hr, "Failed to concatenate subkey to key string");
207 }
208 }
209
210 hr = WcaWriteIntegerToCaData(MBA_DELETEKEY, &pwzCustomActionData);
211 ExitOnFailure(hr, "Failed to add metabase delete key directive to CustomActionData");
212
213 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
214 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
215
216 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEKEY);
217 ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseKey action data: %ls cost: %d", pwzCustomActionData, COST_IIS_DELETEKEY);
218
219LExit:
220 ReleaseStr(pwzCustomActionData);
221
222 return hr;
223}
224
225
226HRESULT ScaDeleteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
227 LPCWSTR wzSubKey, DWORD dwIdentifier,
228 DWORD dwDataType)
229{
230 Assert(piMetabase);
231 Unused(piMetabase);
232
233 HRESULT hr = S_OK;
234 WCHAR wzKey[METADATA_MAX_NAME_LEN];
235 WCHAR* pwzCustomActionData = NULL;
236
237 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
238 ExitOnFailure(hr, "Failed to copy root key string to key");
239 if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
240 {
241 hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
242 ExitOnFailure(hr, "Failed to concatenate / to key string");
243 }
244
245 if (wzSubKey && *wzSubKey)
246 {
247 if (L'/' == *wzSubKey)
248 {
249 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
250 ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
251 }
252 else
253 {
254 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
255 ExitOnFailure(hr, "Failed to concatenate subkey to key string");
256 }
257 }
258
259 hr = WcaWriteIntegerToCaData(MBA_DELETEVALUE, &pwzCustomActionData);
260 ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
261
262 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
263 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
264
265 hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
266 ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
267
268 hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
269 ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
270
271 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_DELETEVALUE);
272 ExitOnFailure(hr, "Failed to add ScaDeleteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_DELETEVALUE);
273
274LExit:
275 ReleaseStr(pwzCustomActionData);
276
277 return hr;
278}
279
280
281#pragma prefast(push)
282#pragma prefast(disable:25120) // Disable "requires count parameter" warning - we do have a way to distinguish buffer sizes in all situations,
283 // it just depends on the dwDataType, and there's no way to annotate the situation in SAL
284HRESULT ScaWriteMetabaseValue(IMSAdminBase* piMetabase, LPCWSTR wzRootKey,
285 LPCWSTR wzSubKey, DWORD dwIdentifier,
286 DWORD dwAttributes, DWORD dwUserType,
287 DWORD dwDataType, LPVOID pvData)
288#pragma prefast(pop)
289{
290 Assert(piMetabase && (pvData || (DWORD_METADATA == dwDataType))); // pvData may be 0 if it is DWORD data
291 Unused(piMetabase);
292
293 HRESULT hr = S_OK;
294 WCHAR wzKey[METADATA_MAX_NAME_LEN];
295 WCHAR* pwzCustomActionData = NULL;
296
297 if (BINARY_METADATA == dwDataType)
298 {
299 ExitOnNull(pvData, hr, E_INVALIDARG, "Failed to write binary metadata - no data available to write");
300 }
301
302 hr = ::StringCchCopyW(wzKey, countof(wzKey), wzRootKey);
303 ExitOnFailure(hr, "Failed to copy root key string to key");
304 if (L'/' != *(wzKey + lstrlenW(wzRootKey)))
305 {
306 hr = ::StringCchCatW(wzKey, countof(wzKey), L"/");
307 ExitOnFailure(hr, "Failed to concatenate / to key string");
308 }
309 if (wzSubKey && *wzSubKey)
310 {
311 if (L'/' == *wzSubKey)
312 {
313 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey + 1);
314 ExitOnFailure(hr, "Failed to concatenate subkey (minus slash) to key string");
315 }
316 else
317 {
318 hr = ::StringCchCatW(wzKey, countof(wzKey), wzSubKey);
319 ExitOnFailure(hr, "Failed to concatenate subkey to key string");
320 }
321 }
322
323 hr = WcaWriteIntegerToCaData(MBA_WRITEVALUE, &pwzCustomActionData);
324 ExitOnFailure(hr, "Failed to add metabase write value directive to CustomActionData");
325
326 hr = WcaWriteStringToCaData(wzKey, &pwzCustomActionData);
327 ExitOnFailure(hr, "Failed to add metabase key to CustomActionData");
328
329 hr = WcaWriteIntegerToCaData(dwIdentifier, &pwzCustomActionData);
330 ExitOnFailure(hr, "Failed to add metabase identifier to CustomActionData");
331
332 hr = WcaWriteIntegerToCaData(dwAttributes, &pwzCustomActionData);
333 ExitOnFailure(hr, "Failed to add metabase attributes to CustomActionData");
334
335 hr = WcaWriteIntegerToCaData(dwUserType, &pwzCustomActionData);
336 ExitOnFailure(hr, "Failed to add metabase user type to CustomActionData");
337
338 hr = WcaWriteIntegerToCaData(dwDataType, &pwzCustomActionData);
339 ExitOnFailure(hr, "Failed to add metabase data type to CustomActionData");
340
341 switch (dwDataType)
342 {
343 case DWORD_METADATA:
344 hr = WcaWriteIntegerToCaData((DWORD)((DWORD_PTR)pvData), &pwzCustomActionData);
345 break;
346 case STRING_METADATA:
347 hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
348 break;
349 case MULTISZ_METADATA:
350 {
351 // change NULLs to unprintable character to create a 'safe' MULTISZ string
352 LPWSTR pwz = (LPWSTR)pvData;
353 for (;;)
354 {
355 if ('\0' == *pwz)
356 {
357 *pwz = MAGIC_MULTISZ_CHAR;
358 if ('\0' == *(pwz + 1)) // second null back to back means end of string
359 break;
360 }
361
362 ++pwz;
363 }
364
365 hr = WcaWriteStringToCaData((LPCWSTR)pvData, &pwzCustomActionData);
366 }
367 break;
368 case BINARY_METADATA:
369 hr = WcaWriteStreamToCaData(((BLOB*) pvData)->pBlobData, ((BLOB*) pvData)->cbSize, &pwzCustomActionData);
370 break;
371 default:
372 hr = E_UNEXPECTED;
373 }
374 ExitOnFailure(hr, "Failed to add metabase data to CustomActionData");
375
376 // TODO: maybe look the key up and make sure we're not just writing the same value that already there
377
378 hr = ScaAddToIisConfiguration(pwzCustomActionData, COST_IIS_WRITEVALUE);
379 ExitOnFailure(hr, "Failed to add ScaWriteMetabaseValue action data: %ls, cost: %d", pwzCustomActionData, COST_IIS_WRITEVALUE);
380
381LExit:
382 ReleaseStr(pwzCustomActionData);
383
384 return hr;
385}
386
387
388HRESULT ScaAddToIisConfiguration(LPCWSTR pwzData, DWORD dwCost)
389{
390 HRESULT hr = S_OK;
391
392 hr = WcaWriteStringToCaData(pwzData, &vpwzCustomActionData);
393 ExitOnFailure(hr, "failed to add to metabase configuration data string: %ls", pwzData);
394
395 vdwCustomActionCost += dwCost;
396
397LExit:
398 return hr;
399}
400
401
402HRESULT ScaWriteConfigurationScript(__in LPCWSTR pwzCaScriptKey)
403{
404 HRESULT hr = S_OK;
405 WCA_CASCRIPT_HANDLE hScript = NULL;
406 LPWSTR pwzHashString = NULL;
407 BYTE rgbActualHash[SHA1_HASH_LEN] = { };
408 DWORD dwHashedBytes = SHA1_HASH_LEN;
409
410 // Create CaScript for communication with WriteMetabaseChanges
411 hr = WcaCaScriptCreate(WCA_ACTION_INSTALL, WCA_CASCRIPT_SCHEDULED, FALSE, pwzCaScriptKey, FALSE, &hScript);
412 ExitOnFailure(hr, "Failed to write ca script for WriteMetabaseChanges script.");
413
414 if (vpwzCustomActionData && *vpwzCustomActionData)
415 {
416 // Write the actual custom action data to the ca script
417 WcaCaScriptWriteString(hScript, vpwzCustomActionData);
418
419 hr = CrypHashBuffer((BYTE*)vpwzCustomActionData, sizeof(vpwzCustomActionData) * sizeof(WCHAR), PROV_RSA_AES, CALG_SHA1, rgbActualHash, dwHashedBytes);
420 ExitOnFailure(hr, "Failed to calculate hash of CustomAction data.");
421
422 hr = StrAlloc(&pwzHashString, ((dwHashedBytes * 2) + 1));
423 ExitOnFailure(hr, "Failed to allocate string for script hash");
424
425 hr = StrHexEncode(rgbActualHash, dwHashedBytes, pwzHashString, ((dwHashedBytes * 2) + 1));
426 ExitOnFailure(hr, "Failed to convert hash bytes to string.");
427
428 WcaLog(LOGMSG_VERBOSE, "Custom action data hash: %ls", pwzHashString);
429 WcaLog(LOGMSG_TRACEONLY, "Custom action data being written to ca script: %ls", vpwzCustomActionData);
430 }
431 else
432 hr = S_FALSE;
433
434LExit:
435 // Release the string
436 ReleaseStr(vpwzCustomActionData);
437 ReleaseStr(pwzHashString);
438
439 // Flush the ca script to disk as best we can
440 WcaCaScriptFlush(hScript);
441
442 WcaCaScriptClose(hScript, WCA_CASCRIPT_CLOSE_PRESERVE);
443
444 return hr;
445}
446
447
448HRESULT ScaLoadMetabase(IMSAdminBase** ppiMetabase)
449{
450 HRESULT hr = S_OK;
451 UINT er = ERROR_SUCCESS;
452
453 // if IIS was uninstalled (thus no IID_IMSAdminBase) allow the
454 // user to still uninstall this package by clicking "Ignore"
455 do
456 {
457 hr = ::CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, IID_IMSAdminBase, (void**)ppiMetabase);
458 if (FAILED(hr))
459 {
460 WcaLog(LOGMSG_STANDARD, "failed to get IID_IMSAdminBase Object");
461 er = WcaErrorMessage(msierrIISCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
462 switch (er)
463 {
464 case IDABORT:
465 ExitFunction(); // bail with the error result from the CoCreate to kick off a rollback
466 case IDRETRY:
467 hr = S_FALSE; // hit me, baby, one more time
468 break;
469 case IDIGNORE:
470 hr = S_OK; // pretend everything is okay and bail
471 break;
472 default: // For failure on uninstall continue
473 hr = S_OK;
474 break;
475 }
476 }
477 } while (S_FALSE == hr);
478
479LExit:
480 return hr;
481}