Import code from old v4 repo
Sean Hall committed
Jan 20, 2019 at 09:19 UTC
4d30ab70573f9734d7fd3cd4d54c02173fa281db
20 files changed
+1512
src/ca/cost.h
new
+5
@@ -0,0 +1,5 @@
1
+#pragma once
2
+// 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.
3
+
4
+
5
+const UINT COST_HTTP_URL_ACL = 2000;
src/ca/dllmain.cpp
new
+26
@@ -0,0 +1,26 @@
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
+/********************************************************************
6
+DllMain - standard entry point for all WiX CustomActions
7
+
8
+********************************************************************/
9
+extern "C" BOOL WINAPI DllMain(
10
+ IN HINSTANCE hInstance,
11
+ IN ULONG ulReason,
12
+ IN LPVOID)
13
+{
14
+ switch(ulReason)
15
+ {
16
+ case DLL_PROCESS_ATTACH:
17
+ WcaGlobalInitialize(hInstance);
18
+ break;
19
+
20
+ case DLL_PROCESS_DETACH:
21
+ WcaGlobalFinalize();
22
+ break;
23
+ }
24
+
25
+ return TRUE;
26
+}
src/ca/precomp.h
new
+17
@@ -0,0 +1,17 @@
1
+#pragma once
2
+// 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.
3
+
4
+
5
+#include <http.h>
6
+#include <msiquery.h>
7
+#include <strsafe.h>
8
+
9
+#include "wcautil.h"
10
+#include "cryputil.h"
11
+#include "dutil.h"
12
+#include "memutil.h"
13
+#include "strutil.h"
14
+#include "aclutil.h"
15
+
16
+#include "CustomMsiErrors.h"
17
+#include "cost.h"
src/ca/wixhttpca.cpp
new
+525
@@ -0,0 +1,525 @@
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
+static HRESULT AppendUrlAce(
6
+ __in LPWSTR wzSecurityPrincipal,
7
+ __in int iRights,
8
+ __in LPWSTR* psczSDDL
9
+ );
10
+static HRESULT WriteHttpUrlReservation(
11
+ __in WCA_TODO action,
12
+ __in LPWSTR wzUrl,
13
+ __in LPWSTR wzSDDL,
14
+ __in int iHandleExisting,
15
+ __in LPWSTR* psczCustomActionData
16
+ );
17
+static HRESULT AddUrlReservation(
18
+ __in LPWSTR wzUrl,
19
+ __in LPWSTR wzSddl
20
+ );
21
+static HRESULT GetUrlReservation(
22
+ __in LPWSTR wzUrl,
23
+ __deref_out_z LPWSTR* psczSddl
24
+ );
25
+static HRESULT RemoveUrlReservation(
26
+ __in LPWSTR wzUrl
27
+ );
28
+
29
+HTTPAPI_VERSION vcHttpVersion = HTTPAPI_VERSION_1;
30
+ULONG vcHttpFlags = HTTP_INITIALIZE_CONFIG;
31
+
32
+LPCWSTR vcsHttpUrlReservationQuery =
33
+ L"SELECT `WixHttpUrlReservation`.`WixHttpUrlReservation`, `WixHttpUrlReservation`.`HandleExisting`, `WixHttpUrlReservation`.`Sddl`, `WixHttpUrlReservation`.`Url`, `WixHttpUrlReservation`.`Component_` "
34
+ L"FROM `WixHttpUrlReservation`";
35
+enum eHttpUrlReservationQuery { hurqId = 1, hurqHandleExisting, hurqSDDL, hurqUrl, hurqComponent };
36
+
37
+LPCWSTR vcsHttpUrlAceQuery =
38
+ L"SELECT `WixHttpUrlAce`.`SecurityPrincipal`, `WixHttpUrlAce`.`Rights` "
39
+ L"FROM `WixHttpUrlAce` "
40
+ L"WHERE `WixHttpUrlAce`.`WixHttpUrlReservation_`=?";
41
+enum eHttpUrlAceQuery { huaqSecurityPrincipal = 1, huaqRights };
42
+
43
+enum eHandleExisting { heReplace = 0, heIgnore = 1, heFail = 2 };
44
+
45
+/******************************************************************
46
+ SchedHttpUrlReservations - immediate custom action worker to
47
+ prepare configuring URL reservations.
48
+
49
+********************************************************************/
50
+static UINT SchedHttpUrlReservations(
51
+ __in MSIHANDLE hInstall,
52
+ __in WCA_TODO todoSched
53
+ )
54
+{
55
+ HRESULT hr = S_OK;
56
+ UINT er = ERROR_SUCCESS;
57
+ BOOL fAceTableExists = FALSE;
58
+ BOOL fHttpInitialized = FALSE;
59
+ DWORD cUrlReservations = 0;
60
+
61
+ PMSIHANDLE hView = NULL;
62
+ PMSIHANDLE hRec = NULL;
63
+ PMSIHANDLE hQueryReq = NULL;
64
+ PMSIHANDLE hAceView = NULL;
65
+
66
+ LPWSTR sczCustomActionData = NULL;
67
+ LPWSTR sczRollbackCustomActionData = NULL;
68
+
69
+ LPWSTR sczId = NULL;
70
+ LPWSTR sczComponent = NULL;
71
+ WCA_TODO todoComponent = WCA_TODO_UNKNOWN;
72
+ LPWSTR sczUrl = NULL;
73
+ LPWSTR sczSecurityPrincipal = NULL;
74
+ int iRights = 0;
75
+ int iHandleExisting = 0;
76
+
77
+ LPWSTR sczExistingSDDL = NULL;
78
+ LPWSTR sczSDDL = NULL;
79
+
80
+ // Initialize.
81
+ hr = WcaInitialize(hInstall, "SchedHttpUrlReservations");
82
+ ExitOnFailure(hr, "Failed to initialize.");
83
+
84
+ // Anything to do?
85
+ hr = WcaTableExists(L"WixHttpUrlReservation");
86
+ ExitOnFailure(hr, "Failed to check if the WixHttpUrlReservation table exists.");
87
+ if (S_FALSE == hr)
88
+ {
89
+ WcaLog(LOGMSG_STANDARD, "WixHttpUrlReservation table doesn't exist, so there are no URL reservations to configure.");
90
+ ExitFunction();
91
+ }
92
+
93
+ hr = WcaTableExists(L"WixHttpUrlAce");
94
+ ExitOnFailure(hr, "Failed to check if the WixHttpUrlAce table exists.");
95
+ fAceTableExists = S_OK == hr;
96
+
97
+ // Query and loop through all the URL reservations.
98
+ hr = WcaOpenExecuteView(vcsHttpUrlReservationQuery, &hView);
99
+ ExitOnFailure(hr, "Failed to open view on the WixHttpUrlReservation table.");
100
+
101
+ hr = HRESULT_FROM_WIN32(::HttpInitialize(vcHttpVersion, vcHttpFlags, NULL));
102
+ ExitOnFailure(hr, "Failed to initialize HTTP Server configuration.");
103
+
104
+ fHttpInitialized = TRUE;
105
+
106
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
107
+ {
108
+ hr = WcaGetRecordString(hRec, hurqId, &sczId);
109
+ ExitOnFailure(hr, "Failed to get WixHttpUrlReservation.WixHttpUrlReservation");
110
+
111
+ hr = WcaGetRecordString(hRec, hurqComponent, &sczComponent);
112
+ ExitOnFailure(hr, "Failed to get WixHttpUrlReservation.Component_");
113
+
114
+ // Figure out what we're doing for this reservation, treating reinstall the same as install.
115
+ todoComponent = WcaGetComponentToDo(sczComponent);
116
+ if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
117
+ {
118
+ WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d) for UrlReservation '%ls'.", sczComponent, todoComponent, todoSched, sczId);
119
+ continue;
120
+ }
121
+
122
+ hr = WcaGetRecordFormattedString(hRec, hurqUrl, &sczUrl);
123
+ ExitOnFailure(hr, "Failed to get WixHttpUrlReservation.Url");
124
+
125
+ hr = WcaGetRecordInteger(hRec, hurqHandleExisting, &iHandleExisting);
126
+ ExitOnFailure(hr, "Failed to get WixHttpUrlReservation.HandleExisting");
127
+
128
+ if (::MsiRecordIsNull(hRec, hurqSDDL))
129
+ {
130
+ hr = StrAllocString(&sczSDDL, L"D:", 2);
131
+ ExitOnFailure(hr, "Failed to allocate SDDL string.");
132
+
133
+ // Skip creating the SDDL on uninstall, since it's never used and the lookup(s) could fail.
134
+ if (fAceTableExists && WCA_TODO_UNINSTALL != todoComponent)
135
+ {
136
+ hQueryReq = ::MsiCreateRecord(1);
137
+ hr = WcaSetRecordString(hQueryReq, 1, sczId);
138
+ ExitOnFailure(hr, "Failed to create record for querying WixHttpUrlAce table for reservation %ls", sczId);
139
+
140
+ hr = WcaOpenView(vcsHttpUrlAceQuery, &hAceView);
141
+ ExitOnFailure(hr, "Failed to open view on WixHttpUrlAce table for reservation %ls", sczId);
142
+ hr = WcaExecuteView(hAceView, hQueryReq);
143
+ ExitOnFailure(hr, "Failed to execute view on WixHttpUrlAce table for reservation %ls", sczId);
144
+
145
+ while (S_OK == (hr = WcaFetchRecord(hAceView, &hRec)))
146
+ {
147
+ hr = WcaGetRecordFormattedString(hRec, huaqSecurityPrincipal, &sczSecurityPrincipal);
148
+ ExitOnFailure(hr, "Failed to get WixHttpUrlAce.SecurityPrincipal");
149
+
150
+ hr = WcaGetRecordInteger(hRec, huaqRights, &iRights);
151
+ ExitOnFailure(hr, "Failed to get WixHttpUrlAce.Rights");
152
+
153
+ hr = AppendUrlAce(sczSecurityPrincipal, iRights, &sczSDDL);
154
+ ExitOnFailure(hr, "Failed to append URL ACE.");
155
+ }
156
+
157
+ if (E_NOMOREITEMS == hr)
158
+ {
159
+ hr = S_OK;
160
+ }
161
+ ExitOnFailure(hr, "Failed to enumerate selected rows from WixHttpUrlAce table.");
162
+ }
163
+ }
164
+ else
165
+ {
166
+ hr = WcaGetRecordFormattedString(hRec, hurqSDDL, &sczSDDL);
167
+ ExitOnFailure(hr, "Failed to get WixHttpUrlReservation.SDDL");
168
+ }
169
+
170
+ hr = GetUrlReservation(sczUrl, &sczExistingSDDL);
171
+ ExitOnFailure(hr, "Failed to get the existing SDDL for %ls", sczUrl);
172
+
173
+ hr = WriteHttpUrlReservation(todoComponent, sczUrl, sczExistingSDDL ? sczExistingSDDL : L"", iHandleExisting, &sczRollbackCustomActionData);
174
+ ExitOnFailure(hr, "Failed to write URL Reservation to rollback custom action data.");
175
+
176
+ hr = WriteHttpUrlReservation(todoComponent, sczUrl, sczSDDL, iHandleExisting, &sczCustomActionData);
177
+ ExitOnFailure(hr, "Failed to write URL reservation to custom action data.");
178
+ ++cUrlReservations;
179
+ }
180
+
181
+ // Reaching the end of the list is not an error.
182
+ if (E_NOMOREITEMS == hr)
183
+ {
184
+ hr = S_OK;
185
+ }
186
+ ExitOnFailure(hr, "Failure occurred while processing WixHttpUrlReservation table.");
187
+
188
+ // Schedule ExecHttpUrlReservations if there's anything to do.
189
+ if (cUrlReservations)
190
+ {
191
+ WcaLog(LOGMSG_STANDARD, "Scheduling URL reservations (%ls)", sczCustomActionData);
192
+ WcaLog(LOGMSG_STANDARD, "Scheduling rollback URL reservations (%ls)", sczRollbackCustomActionData);
193
+
194
+ if (WCA_TODO_INSTALL == todoSched)
195
+ {
196
+ hr = WcaDoDeferredAction(L"WixRollbackHttpUrlReservationsInstall", sczRollbackCustomActionData, cUrlReservations * COST_HTTP_URL_ACL);
197
+ ExitOnFailure(hr, "Failed to schedule install URL reservations rollback.");
198
+ hr = WcaDoDeferredAction(L"WixExecHttpUrlReservationsInstall", sczCustomActionData, cUrlReservations * COST_HTTP_URL_ACL);
199
+ ExitOnFailure(hr, "Failed to schedule install URL reservations execution.");
200
+ }
201
+ else
202
+ {
203
+ hr = WcaDoDeferredAction(L"WixRollbackHttpUrlReservationsUninstall", sczRollbackCustomActionData, cUrlReservations * COST_HTTP_URL_ACL);
204
+ ExitOnFailure(hr, "Failed to schedule uninstall URL reservations rollback.");
205
+ hr = WcaDoDeferredAction(L"WixExecHttpUrlReservationsUninstall", sczCustomActionData, cUrlReservations * COST_HTTP_URL_ACL);
206
+ ExitOnFailure(hr, "Failed to schedule uninstall URL reservations execution.");
207
+ }
208
+ }
209
+ else
210
+ {
211
+ WcaLog(LOGMSG_STANDARD, "No URL reservations scheduled.");
212
+ }
213
+LExit:
214
+ ReleaseStr(sczSDDL);
215
+ ReleaseStr(sczExistingSDDL);
216
+ ReleaseStr(sczSecurityPrincipal);
217
+ ReleaseStr(sczUrl)
218
+ ReleaseStr(sczComponent);
219
+ ReleaseStr(sczId);
220
+ ReleaseStr(sczRollbackCustomActionData);
221
+ ReleaseStr(sczCustomActionData);
222
+
223
+ if (fHttpInitialized)
224
+ {
225
+ ::HttpTerminate(vcHttpFlags, NULL);
226
+ }
227
+
228
+ return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
229
+}
230
+
231
+static HRESULT AppendUrlAce(
232
+ __in LPWSTR wzSecurityPrincipal,
233
+ __in int iRights,
234
+ __in LPWSTR* psczSDDL
235
+ )
236
+{
237
+ HRESULT hr = S_OK;
238
+ LPCWSTR wzSid = NULL;
239
+ LPWSTR sczSid = NULL;
240
+
241
+ Assert(wzSecurityPrincipal && *wzSecurityPrincipal);
242
+ Assert(psczSDDL && *psczSDDL);
243
+
244
+ // As documented in the xsd, if the first char is '*', then the rest of the string is a SID string, e.g. *S-1-5-18.
245
+ if (L'*' == wzSecurityPrincipal[0])
246
+ {
247
+ wzSid = &wzSecurityPrincipal[1];
248
+ }
249
+ else
250
+ {
251
+ hr = AclGetAccountSidStringEx(NULL, wzSecurityPrincipal, &sczSid);
252
+ ExitOnFailure(hr, "Failed to lookup the SID for account %ls", wzSecurityPrincipal);
253
+
254
+ wzSid = sczSid;
255
+ }
256
+
257
+ hr = StrAllocFormatted(psczSDDL, L"%ls(A;;%#x;;;%ls)", *psczSDDL, iRights, wzSid);
258
+
259
+LExit:
260
+ ReleaseStr(sczSid);
261
+
262
+ return hr;
263
+}
264
+
265
+static HRESULT WriteHttpUrlReservation(
266
+ __in WCA_TODO action,
267
+ __in LPWSTR wzUrl,
268
+ __in LPWSTR wzSDDL,
269
+ __in int iHandleExisting,
270
+ __in LPWSTR* psczCustomActionData
271
+ )
272
+{
273
+ HRESULT hr = S_OK;
274
+
275
+ hr = WcaWriteIntegerToCaData(action, psczCustomActionData);
276
+ ExitOnFailure(hr, "Failed to write action to custom action data.");
277
+
278
+ hr = WcaWriteStringToCaData(wzUrl, psczCustomActionData);
279
+ ExitOnFailure(hr, "Failed to write URL to custom action data.");
280
+
281
+ hr = WcaWriteStringToCaData(wzSDDL, psczCustomActionData);
282
+ ExitOnFailure(hr, "Failed to write SDDL to custom action data.");
283
+
284
+ hr = WcaWriteIntegerToCaData(iHandleExisting, psczCustomActionData);
285
+ ExitOnFailure(hr, "Failed to write HandleExisting to custom action data.")
286
+
287
+LExit:
288
+ return hr;
289
+}
290
+
291
+/******************************************************************
292
+ SchedHttpUrlReservationsInstall - immediate custom action entry
293
+ point to prepare adding URL reservations.
294
+
295
+********************************************************************/
296
+extern "C" UINT __stdcall SchedHttpUrlReservationsInstall(
297
+ __in MSIHANDLE hInstall
298
+ )
299
+{
300
+ return SchedHttpUrlReservations(hInstall, WCA_TODO_INSTALL);
301
+}
302
+
303
+/******************************************************************
304
+ SchedHttpUrlReservationsUninstall - immediate custom action entry
305
+ point to prepare removing URL reservations.
306
+
307
+********************************************************************/
308
+extern "C" UINT __stdcall SchedHttpUrlReservationsUninstall(
309
+ __in MSIHANDLE hInstall
310
+ )
311
+{
312
+ return SchedHttpUrlReservations(hInstall, WCA_TODO_UNINSTALL);
313
+}
314
+
315
+/******************************************************************
316
+ ExecHttpUrlReservations - deferred custom action entry point to
317
+ register and remove URL reservations.
318
+
319
+********************************************************************/
320
+extern "C" UINT __stdcall ExecHttpUrlReservations(
321
+ __in MSIHANDLE hInstall
322
+ )
323
+{
324
+ HRESULT hr = S_OK;
325
+ BOOL fHttpInitialized = FALSE;
326
+ LPWSTR sczCustomActionData = NULL;
327
+ LPWSTR wz = NULL;
328
+ int iTodo = WCA_TODO_UNKNOWN;
329
+ LPWSTR sczUrl = NULL;
330
+ LPWSTR sczSDDL = NULL;
331
+ eHandleExisting handleExisting = heIgnore;
332
+ BOOL fRollback = ::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK);
333
+ BOOL fRemove = FALSE;
334
+ BOOL fAdd = FALSE;
335
+ BOOL fFailOnExisting = FALSE;
336
+
337
+ // Initialize.
338
+ hr = WcaInitialize(hInstall, "ExecHttpUrlReservations");
339
+ ExitOnFailure(hr, "Failed to initialize.");
340
+
341
+ hr = HRESULT_FROM_WIN32(::HttpInitialize(vcHttpVersion, vcHttpFlags, NULL));
342
+ ExitOnFailure(hr, "Failed to initialize HTTP Server configuration.");
343
+
344
+ fHttpInitialized = TRUE;
345
+
346
+ hr = WcaGetProperty(L"CustomActionData", &sczCustomActionData);
347
+ ExitOnFailure(hr, "Failed to get CustomActionData.");
348
+ WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", sczCustomActionData);
349
+
350
+ wz = sczCustomActionData;
351
+ while (wz && *wz)
352
+ {
353
+ // Extract the custom action data and if rolling back, swap INSTALL and UNINSTALL.
354
+ hr = WcaReadIntegerFromCaData(&wz, &iTodo);
355
+ ExitOnFailure(hr, "Failed to read todo from custom action data.");
356
+
357
+ hr = WcaReadStringFromCaData(&wz, &sczUrl);
358
+ ExitOnFailure(hr, "Failed to read Url from custom action data.");
359
+
360
+ hr = WcaReadStringFromCaData(&wz, &sczSDDL);
361
+ ExitOnFailure(hr, "Failed to read SDDL from custom action data.");
362
+
363
+ hr = WcaReadIntegerFromCaData(&wz, reinterpret_cast<int*>(&handleExisting));
364
+ ExitOnFailure(hr, "Failed to read HandleExisting from custom action data.");
365
+
366
+ switch (iTodo)
367
+ {
368
+ case WCA_TODO_INSTALL:
369
+ case WCA_TODO_REINSTALL:
370
+ fRemove = heReplace == handleExisting || fRollback;
371
+ fAdd = !fRollback || *sczSDDL;
372
+ fFailOnExisting = heFail == handleExisting && !fRollback;
373
+ break;
374
+
375
+ case WCA_TODO_UNINSTALL:
376
+ fRemove = !fRollback;
377
+ fAdd = fRollback && *sczSDDL;
378
+ fFailOnExisting = FALSE;
379
+ break;
380
+ }
381
+
382
+ if (fRemove)
383
+ {
384
+ WcaLog(LOGMSG_STANDARD, "Removing reservation for URL '%ls'", sczUrl);
385
+ hr = RemoveUrlReservation(sczUrl);
386
+ if (FAILED(hr))
387
+ {
388
+ if (fRollback)
389
+ {
390
+ WcaLogError(hr, "Failed to remove reservation for URL '%ls'", sczUrl);
391
+ }
392
+ else
393
+ {
394
+ ExitOnFailure(hr, "Failed to remove reservation for URL '%ls'", sczUrl);
395
+ }
396
+ }
397
+ }
398
+ if (fAdd)
399
+ {
400
+ WcaLog(LOGMSG_STANDARD, "Adding reservation for URL '%ls' with SDDL '%ls'", sczUrl, sczSDDL);
401
+ hr = AddUrlReservation(sczUrl, sczSDDL);
402
+ if (S_FALSE == hr && fFailOnExisting)
403
+ {
404
+ hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
405
+ }
406
+ if (FAILED(hr))
407
+ {
408
+ if (fRollback)
409
+ {
410
+ WcaLogError(hr, "Failed to add reservation for URL '%ls' with SDDL '%ls'", sczUrl, sczSDDL);
411
+ }
412
+ else
413
+ {
414
+ ExitOnFailure(hr, "Failed to add reservation for URL '%ls' with SDDL '%ls'", sczUrl, sczSDDL);
415
+ }
416
+ }
417
+ }
418
+ }
419
+
420
+LExit:
421
+ ReleaseStr(sczSDDL);
422
+ ReleaseStr(sczUrl);
423
+ ReleaseStr(sczCustomActionData);
424
+
425
+ if (fHttpInitialized)
426
+ {
427
+ ::HttpTerminate(vcHttpFlags, NULL);
428
+ }
429
+
430
+ return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
431
+}
432
+
433
+static HRESULT AddUrlReservation(
434
+ __in LPWSTR wzUrl,
435
+ __in LPWSTR wzSddl
436
+ )
437
+{
438
+ HRESULT hr = S_OK;
439
+ DWORD er = ERROR_SUCCESS;
440
+ HTTP_SERVICE_CONFIG_URLACL_SET set = { };
441
+
442
+ set.KeyDesc.pUrlPrefix = wzUrl;
443
+ set.ParamDesc.pStringSecurityDescriptor = wzSddl;
444
+
445
+ er = ::HttpSetServiceConfiguration(NULL, HttpServiceConfigUrlAclInfo, &set, sizeof(set), NULL);
446
+ if (ERROR_ALREADY_EXISTS == er)
447
+ {
448
+ hr = S_FALSE;
449
+ }
450
+ else
451
+ {
452
+ hr = HRESULT_FROM_WIN32(er);
453
+ }
454
+ ExitOnFailure(hr, "Failed to add URL reservation: %ls, ACL: %ls", wzUrl, wzSddl);
455
+
456
+LExit:
457
+ return hr;
458
+}
459
+
460
+static HRESULT GetUrlReservation(
461
+ __in LPWSTR wzUrl,
462
+ __deref_out_z LPWSTR* psczSddl
463
+ )
464
+{
465
+ HRESULT hr = S_OK;
466
+ DWORD er = ERROR_SUCCESS;
467
+ HTTP_SERVICE_CONFIG_URLACL_QUERY query = { };
468
+ HTTP_SERVICE_CONFIG_URLACL_SET* pSet = NULL;
469
+ ULONG cbSet = 0;
470
+
471
+ query.QueryDesc = HttpServiceConfigQueryExact;
472
+ query.KeyDesc.pUrlPrefix = wzUrl;
473
+
474
+ er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigUrlAclInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
475
+ if (ERROR_INSUFFICIENT_BUFFER == er)
476
+ {
477
+ pSet = reinterpret_cast<HTTP_SERVICE_CONFIG_URLACL_SET*>(MemAlloc(cbSet, TRUE));
478
+ ExitOnNull(pSet, hr, E_OUTOFMEMORY, "Failed to allocate query URLACL buffer.");
479
+
480
+ er = ::HttpQueryServiceConfiguration(NULL, HttpServiceConfigUrlAclInfo, &query, sizeof(query), pSet, cbSet, &cbSet, NULL);
481
+ }
482
+
483
+ if (ERROR_SUCCESS == er)
484
+ {
485
+ hr = StrAllocString(psczSddl, pSet->ParamDesc.pStringSecurityDescriptor, 0);
486
+ }
487
+ else if (ERROR_FILE_NOT_FOUND == er)
488
+ {
489
+ hr = S_FALSE;
490
+ }
491
+ else
492
+ {
493
+ hr = HRESULT_FROM_WIN32(er);
494
+ }
495
+
496
+LExit:
497
+ ReleaseMem(pSet);
498
+
499
+ return hr;
500
+}
501
+
502
+static HRESULT RemoveUrlReservation(
503
+ __in LPWSTR wzUrl
504
+ )
505
+{
506
+ HRESULT hr = S_OK;
507
+ DWORD er = ERROR_SUCCESS;
508
+ HTTP_SERVICE_CONFIG_URLACL_SET set = { };
509
+
510
+ set.KeyDesc.pUrlPrefix = wzUrl;
511
+
512
+ er = ::HttpDeleteServiceConfiguration(NULL, HttpServiceConfigUrlAclInfo, &set, sizeof(set), NULL);
513
+ if (ERROR_FILE_NOT_FOUND == er)
514
+ {
515
+ hr = S_FALSE;
516
+ }
517
+ else
518
+ {
519
+ hr = HRESULT_FROM_WIN32(er);
520
+ }
521
+ ExitOnFailure(hr, "Failed to remove URL reservation: %ls", wzUrl);
522
+
523
+LExit:
524
+ return hr;
525
+}
src/ca/wixhttpca.def
new
+9
@@ -0,0 +1,9 @@
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
+
4
+LIBRARY "wixhttpca"
5
+
6
+EXPORTS
7
+ SchedHttpUrlReservationsInstall
8
+ SchedHttpUrlReservationsUninstall
9
+ ExecHttpUrlReservations
src/ca/wixhttpca.vcxproj
new
+58
@@ -0,0 +1,58 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
6
+ <ItemGroup Label="ProjectConfigurations">
7
+ <ProjectConfiguration Include="Debug|Win32">
8
+ <Configuration>Debug</Configuration>
9
+ <Platform>Win32</Platform>
10
+ </ProjectConfiguration>
11
+ <ProjectConfiguration Include="Release|Win32">
12
+ <Configuration>Release</Configuration>
13
+ <Platform>Win32</Platform>
14
+ </ProjectConfiguration>
15
+ </ItemGroup>
16
+ <ItemGroup Label="ProjectConfigurations">
17
+ <ProjectConfiguration Include="Debug|ARM">
18
+ <Configuration>Debug</Configuration>
19
+ <Platform>ARM</Platform>
20
+ </ProjectConfiguration>
21
+ <ProjectConfiguration Include="Release|ARM">
22
+ <Configuration>Release</Configuration>
23
+ <Platform>ARM</Platform>
24
+ </ProjectConfiguration>
25
+ </ItemGroup>
26
+
27
+ <PropertyGroup Label="Globals">
28
+ <ProjectGuid>{90743805-C043-47C7-B5FF-8F5EE5C8A2DE}</ProjectGuid>
29
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
30
+ <CharacterSet>Unicode</CharacterSet>
31
+ <TargetName>wixhttpca</TargetName>
32
+ <ProjectModuleDefinitionFile>wixhttpca.def</ProjectModuleDefinitionFile>
33
+ </PropertyGroup>
34
+
35
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.props" />
36
+
37
+ <PropertyGroup>
38
+ <ProjectAdditionalIncludeDirectories>$(WixRoot)src\libs\dutil\inc;$(WixRoot)src\libs\wcautil</ProjectAdditionalIncludeDirectories>
39
+ <ProjectAdditionalLinkLibraries>crypt32.lib;httpapi.lib;msi.lib;dutil.lib;wcautil.lib</ProjectAdditionalLinkLibraries>
40
+ </PropertyGroup>
41
+
42
+ <ItemGroup>
43
+ <ClCompile Include="dllmain.cpp" />
44
+ <ClCompile Include="wixhttpca.cpp" />
45
+ </ItemGroup>
46
+ <ItemGroup>
47
+ <ClInclude Include="cost.h" />
48
+ <ClInclude Include="precomp.h" />
49
+ </ItemGroup>
50
+ <ItemGroup>
51
+ <None Include="wixhttpca.def" />
52
+ </ItemGroup>
53
+ <ItemGroup>
54
+ <ResourceCompile Include="wixhttpca.rc" />
55
+ </ItemGroup>
56
+
57
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
58
+</Project>
src/ca/wixhttpca.vcxproj.filters
new
+40
@@ -0,0 +1,40 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+ <ItemGroup>
4
+ <Filter Include="Source Files">
5
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
6
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
7
+ </Filter>
8
+ <Filter Include="Header Files">
9
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
10
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
11
+ </Filter>
12
+ <Filter Include="Resource Files">
13
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
14
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
15
+ </Filter>
16
+ </ItemGroup>
17
+ <ItemGroup>
18
+ <ClCompile Include="wixhttpca.cpp">
19
+ <Filter>Source Files</Filter>
20
+ </ClCompile>
21
+ <ClCompile Include="dllmain.cpp">
22
+ <Filter>Source Files</Filter>
23
+ </ClCompile>
24
+ </ItemGroup>
25
+ <ItemGroup>
26
+ <ClInclude Include="precomp.h">
27
+ <Filter>Header Files</Filter>
28
+ </ClInclude>
29
+ </ItemGroup>
30
+ <ItemGroup>
31
+ <ResourceCompile Include="wixhttpca.rc">
32
+ <Filter>Resource Files</Filter>
33
+ </ResourceCompile>
34
+ </ItemGroup>
35
+ <ItemGroup>
36
+ <None Include="wixhttpca.def">
37
+ <Filter>Source Files</Filter>
38
+ </None>
39
+ </ItemGroup>
40
+</Project>
\ No newline at end of file
src/wixext/HttpCompiler.cs
new
+280
@@ -0,0 +1,280 @@
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
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Globalization;
8
+ using System.Xml.Linq;
9
+ using WixToolset.Data;
10
+ using WixToolset.Extensibility;
11
+
12
+ /// <summary>
13
+ /// The compiler for the WiX Toolset Http Extension.
14
+ /// </summary>
15
+ public sealed class HttpCompiler : CompilerExtension
16
+ {
17
+ /// <summary>
18
+ /// Instantiate a new HttpCompiler.
19
+ /// </summary>
20
+ public HttpCompiler()
21
+ {
22
+ this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/http";
23
+ }
24
+
25
+ /// <summary>
26
+ /// Processes an element for the Compiler.
27
+ /// </summary>
28
+ /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
29
+ /// <param name="parentElement">Parent element of element to process.</param>
30
+ /// <param name="element">Element to process.</param>
31
+ /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
32
+ public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context)
33
+ {
34
+ switch (parentElement.Name.LocalName)
35
+ {
36
+ case "ServiceInstall":
37
+ string serviceInstallName = context["ServiceInstallName"];
38
+ string serviceUser = String.IsNullOrEmpty(serviceInstallName) ? null : String.Concat("NT SERVICE\\", serviceInstallName);
39
+ string serviceComponentId = context["ServiceInstallComponentId"];
40
+
41
+ switch (element.Name.LocalName)
42
+ {
43
+ case "UrlReservation":
44
+ this.ParseUrlReservationElement(element, serviceComponentId, serviceUser);
45
+ break;
46
+ default:
47
+ this.Core.UnexpectedElement(parentElement, element);
48
+ break;
49
+ }
50
+ break;
51
+ case "Component":
52
+ string componentId = context["ComponentId"];
53
+
54
+ switch (element.Name.LocalName)
55
+ {
56
+ case "UrlReservation":
57
+ this.ParseUrlReservationElement(element, componentId, null);
58
+ break;
59
+ default:
60
+ this.Core.UnexpectedElement(parentElement, element);
61
+ break;
62
+ }
63
+ break;
64
+ default:
65
+ this.Core.UnexpectedElement(parentElement, element);
66
+ break;
67
+ }
68
+ }
69
+
70
+ /// <summary>
71
+ /// Parses a UrlReservation element.
72
+ /// </summary>
73
+ /// <param name="node">The element to parse.</param>
74
+ /// <param name="componentId">Identifier of the component that owns this URL reservation.</param>
75
+ /// <param name="securityPrincipal">The security principal of the parent element (null if nested under Component).</param>
76
+ private void ParseUrlReservationElement(XElement node, string componentId, string securityPrincipal)
77
+ {
78
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
79
+ Identifier id = null;
80
+ int handleExisting = HttpConstants.heReplace;
81
+ string handleExistingValue = null;
82
+ string sddl = null;
83
+ string url = null;
84
+ bool foundACE = false;
85
+
86
+ foreach (XAttribute attrib in node.Attributes())
87
+ {
88
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
89
+ {
90
+ switch (attrib.Name.LocalName)
91
+ {
92
+ case "Id":
93
+ id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
94
+ break;
95
+ case "HandleExisting":
96
+ handleExistingValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
97
+ switch (handleExistingValue)
98
+ {
99
+ case "replace":
100
+ handleExisting = HttpConstants.heReplace;
101
+ break;
102
+ case "ignore":
103
+ handleExisting = HttpConstants.heIgnore;
104
+ break;
105
+ case "fail":
106
+ handleExisting = HttpConstants.heFail;
107
+ break;
108
+ default:
109
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, "HandleExisting", handleExistingValue, "replace", "ignore", "fail"));
110
+ break;
111
+ }
112
+ break;
113
+ case "Sddl":
114
+ sddl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
115
+ break;
116
+ case "Url":
117
+ url = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
118
+ break;
119
+ default:
120
+ this.Core.UnexpectedAttribute(node, attrib);
121
+ break;
122
+ }
123
+ }
124
+ else
125
+ {
126
+ this.Core.ParseExtensionAttribute(node, attrib);
127
+ }
128
+ }
129
+
130
+ // Need the element ID for child element processing, so generate now if not authored.
131
+ if (null == id)
132
+ {
133
+ id = this.Core.CreateIdentifier("url", componentId, securityPrincipal, url);
134
+ }
135
+
136
+ // Parse UrlAce children.
137
+ foreach (XElement child in node.Elements())
138
+ {
139
+ if (this.Namespace == child.Name.Namespace)
140
+ {
141
+ switch (child.Name.LocalName)
142
+ {
143
+ case "UrlAce":
144
+ if (null != sddl)
145
+ {
146
+ this.Core.OnMessage(WixErrors.IllegalParentAttributeWhenNested(sourceLineNumbers, "UrlReservation", "Sddl", "UrlAce"));
147
+ }
148
+ else
149
+ {
150
+ foundACE = true;
151
+ this.ParseUrlAceElement(child, id.Id, securityPrincipal);
152
+ }
153
+ break;
154
+ default:
155
+ this.Core.UnexpectedElement(node, child);
156
+ break;
157
+ }
158
+ }
159
+ else
160
+ {
161
+ this.Core.ParseExtensionElement(node, child);
162
+ }
163
+ }
164
+
165
+ // Url is required.
166
+ if (null == url)
167
+ {
168
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Url"));
169
+ }
170
+
171
+ // Security is required.
172
+ if (null == sddl && !foundACE)
173
+ {
174
+ this.Core.OnMessage(HttpErrors.NoSecuritySpecified(sourceLineNumbers));
175
+ }
176
+
177
+ if (!this.Core.EncounteredError)
178
+ {
179
+ Row row = this.Core.CreateRow(sourceLineNumbers, "WixHttpUrlReservation");
180
+ row[0] = id.Id;
181
+ row[1] = handleExisting;
182
+ row[2] = sddl;
183
+ row[3] = url;
184
+ row[4] = componentId;
185
+
186
+ if (this.Core.CurrentPlatform == Platform.ARM)
187
+ {
188
+ // Ensure ARM version of the CA is referenced.
189
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "WixSchedHttpUrlReservationsInstall_ARM");
190
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "WixSchedHttpUrlReservationsUninstall_ARM");
191
+ }
192
+ else
193
+ {
194
+ // All other supported platforms use x86.
195
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "WixSchedHttpUrlReservationsInstall");
196
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "WixSchedHttpUrlReservationsUninstall");
197
+ }
198
+ }
199
+ }
200
+
201
+ /// <summary>
202
+ /// Parses a UrlAce element.
203
+ /// </summary>
204
+ /// <param name="node">The element to parse.</param>
205
+ /// <param name="urlReservationId">The URL reservation ID.</param>
206
+ /// <param name="defaultSecurityPrincipal">The default security principal.</param>
207
+ private void ParseUrlAceElement(XElement node, string urlReservationId, string defaultSecurityPrincipal)
208
+ {
209
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
210
+ Identifier id = null;
211
+ string securityPrincipal = defaultSecurityPrincipal;
212
+ int rights = HttpConstants.GENERIC_ALL;
213
+ string rightsValue = null;
214
+
215
+ foreach (XAttribute attrib in node.Attributes())
216
+ {
217
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
218
+ {
219
+ switch (attrib.Name.LocalName)
220
+ {
221
+ case "Id":
222
+ id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
223
+ break;
224
+ case "SecurityPrincipal":
225
+ securityPrincipal = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
226
+ break;
227
+ case "Rights":
228
+ rightsValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
229
+ switch (rightsValue)
230
+ {
231
+ case "all":
232
+ rights = HttpConstants.GENERIC_ALL;
233
+ break;
234
+ case "delegate":
235
+ rights = HttpConstants.GENERIC_WRITE;
236
+ break;
237
+ case "register":
238
+ rights = HttpConstants.GENERIC_EXECUTE;
239
+ break;
240
+ default:
241
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, "Rights", rightsValue, "all", "delegate", "register"));
242
+ break;
243
+ }
244
+ break;
245
+ default:
246
+ this.Core.UnexpectedAttribute(node, attrib);
247
+ break;
248
+ }
249
+ }
250
+ else
251
+ {
252
+ this.Core.ParseExtensionAttribute(node, attrib);
253
+ }
254
+ }
255
+
256
+ // Generate Id now if not authored.
257
+ if (null == id)
258
+ {
259
+ id = this.Core.CreateIdentifier("ace", urlReservationId, securityPrincipal, rightsValue);
260
+ }
261
+
262
+ this.Core.ParseForExtensionElements(node);
263
+
264
+ // SecurityPrincipal is required.
265
+ if (null == securityPrincipal)
266
+ {
267
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SecurityPrincipal"));
268
+ }
269
+
270
+ if (!this.Core.EncounteredError)
271
+ {
272
+ Row row = this.Core.CreateRow(sourceLineNumbers, "WixHttpUrlAce");
273
+ row[0] = id.Id;
274
+ row[1] = urlReservationId;
275
+ row[2] = securityPrincipal;
276
+ row[3] = rights;
277
+ }
278
+ }
279
+ }
280
+}
src/wixext/HttpConstants.cs
new
+19
@@ -0,0 +1,19 @@
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
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+
7
+ internal static class HttpConstants
8
+ {
9
+ // from winnt.h
10
+ public const int GENERIC_ALL = 0x10000000;
11
+ public const int GENERIC_EXECUTE = 0x20000000;
12
+ public const int GENERIC_WRITE = 0x40000000;
13
+
14
+ // from wixhttpca.cpp
15
+ public const int heReplace = 0;
16
+ public const int heIgnore = 1;
17
+ public const int heFail = 2;
18
+ }
19
+}
src/wixext/HttpDecompiler.cs
new
+135
@@ -0,0 +1,135 @@
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
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Collections;
7
+ using System.Diagnostics;
8
+ using System.Globalization;
9
+ using WixToolset.Data;
10
+ using WixToolset.Extensibility;
11
+ using Http = WixToolset.Extensions.Serialize.Http;
12
+ using Wix = WixToolset.Data.Serialize;
13
+
14
+ /// <summary>
15
+ /// The decompiler for the WiX Toolset Http Extension.
16
+ /// </summary>
17
+ public sealed class HttpDecompiler : DecompilerExtension
18
+ {
19
+ /// <summary>
20
+ /// Creates a decompiler for Http Extension.
21
+ /// </summary>
22
+ public HttpDecompiler()
23
+ {
24
+ this.TableDefinitions = HttpExtensionData.GetExtensionTableDefinitions();
25
+ }
26
+
27
+ /// <summary>
28
+ /// Get the extensions library to be removed.
29
+ /// </summary>
30
+ /// <param name="tableDefinitions">Table definitions for library.</param>
31
+ /// <returns>Library to remove from decompiled output.</returns>
32
+ public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
33
+ {
34
+ return HttpExtensionData.GetExtensionLibrary(tableDefinitions);
35
+ }
36
+
37
+ /// <summary>
38
+ /// Decompiles an extension table.
39
+ /// </summary>
40
+ /// <param name="table">The table to decompile.</param>
41
+ public override void DecompileTable(Table table)
42
+ {
43
+ switch (table.Name)
44
+ {
45
+ case "WixHttpUrlReservation":
46
+ this.DecompileWixHttpUrlReservationTable(table);
47
+ break;
48
+ case "WixHttpUrlAce":
49
+ this.DecompileWixHttpUrlAceTable(table);
50
+ break;
51
+ default:
52
+ base.DecompileTable(table);
53
+ break;
54
+ }
55
+ }
56
+
57
+ /// <summary>
58
+ /// Decompile the WixHttpUrlReservation table.
59
+ /// </summary>
60
+ /// <param name="table">The table to decompile.</param>
61
+ private void DecompileWixHttpUrlReservationTable(Table table)
62
+ {
63
+ foreach (Row row in table.Rows)
64
+ {
65
+ Http.UrlReservation urlReservation = new Http.UrlReservation();
66
+ urlReservation.Id = (string)row[0];
67
+ switch((int)row[1])
68
+ {
69
+ case HttpConstants.heReplace:
70
+ default:
71
+ urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.replace;
72
+ break;
73
+ case HttpConstants.heIgnore:
74
+ urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.ignore;
75
+ break;
76
+ case HttpConstants.heFail:
77
+ urlReservation.HandleExisting = Http.UrlReservation.HandleExistingType.fail;
78
+ break;
79
+ }
80
+ urlReservation.Sddl = (string)row[2];
81
+ urlReservation.Url = (string)row[3];
82
+
83
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[4]);
84
+ if (null != component)
85
+ {
86
+ component.AddChild(urlReservation);
87
+ }
88
+ else
89
+ {
90
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
91
+ }
92
+ this.Core.IndexElement(row, urlReservation);
93
+ }
94
+ }
95
+
96
+
97
+ /// <summary>
98
+ /// Decompile the WixHttpUrlAce table.
99
+ /// </summary>
100
+ /// <param name="table">The table to decompile.</param>
101
+ private void DecompileWixHttpUrlAceTable(Table table)
102
+ {
103
+ foreach (Row row in table.Rows)
104
+ {
105
+ Http.UrlAce urlace = new Http.UrlAce();
106
+ urlace.Id = (string)row[0];
107
+ urlace.SecurityPrincipal = (string)row[2];
108
+ switch (Convert.ToInt32(row[3]))
109
+ {
110
+ case HttpConstants.GENERIC_ALL:
111
+ default:
112
+ urlace.Rights = Http.UrlAce.RightsType.all;
113
+ break;
114
+ case HttpConstants.GENERIC_EXECUTE:
115
+ urlace.Rights = Http.UrlAce.RightsType.register;
116
+ break;
117
+ case HttpConstants.GENERIC_WRITE:
118
+ urlace.Rights = Http.UrlAce.RightsType.@delegate;
119
+ break;
120
+ }
121
+
122
+ string reservationId = (string)row[1];
123
+ Http.UrlReservation urlReservation = (Http.UrlReservation)this.Core.GetIndexedElement("WixHttpUrlReservation", reservationId);
124
+ if (null != urlReservation)
125
+ {
126
+ urlReservation.AddChild(urlace);
127
+ }
128
+ else
129
+ {
130
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, urlace.Id, "WixHttpUrlReservation_", reservationId, "WixHttpUrlReservation"));
131
+ }
132
+ }
133
+ }
134
+ }
135
+}
src/wixext/HttpExtensionData.cs
new
+64
@@ -0,0 +1,64 @@
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
+namespace WixToolset.Extensions
4
+{
5
+ using System;
6
+ using System.Reflection;
7
+ using WixToolset.Data;
8
+ using WixToolset.Extensibility;
9
+
10
+ /// <summary>
11
+ /// The WiX Toolset Http Extension.
12
+ /// </summary>
13
+ public sealed class HttpExtensionData : ExtensionData
14
+ {
15
+ /// <summary>
16
+ /// Gets the default culture.
17
+ /// </summary>
18
+ /// <value>The default culture.</value>
19
+ public override string DefaultCulture
20
+ {
21
+ get { return "en-us"; }
22
+ }
23
+
24
+ /// <summary>
25
+ /// Gets the optional table definitions for this extension.
26
+ /// </summary>
27
+ /// <value>The optional table definitions for this extension.</value>
28
+ public override TableDefinitionCollection TableDefinitions
29
+ {
30
+ get
31
+ {
32
+ return HttpExtensionData.GetExtensionTableDefinitions();
33
+ }
34
+ }
35
+
36
+ /// <summary>
37
+ /// Gets the library associated with this extension.
38
+ /// </summary>
39
+ /// <param name="tableDefinitions">The table definitions to use while loading the library.</param>
40
+ /// <returns>The loaded library.</returns>
41
+ public override Library GetLibrary(TableDefinitionCollection tableDefinitions)
42
+ {
43
+ return HttpExtensionData.GetExtensionLibrary(tableDefinitions);
44
+ }
45
+
46
+ /// <summary>
47
+ /// Internal mechanism to access the extension's table definitions.
48
+ /// </summary>
49
+ /// <returns>Extension's table definitions.</returns>
50
+ internal static TableDefinitionCollection GetExtensionTableDefinitions()
51
+ {
52
+ return ExtensionData.LoadTableDefinitionHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.tables.xml");
53
+ }
54
+
55
+ /// <summary>
56
+ /// Internal mechanism to access the extension's library.
57
+ /// </summary>
58
+ /// <returns>Extension's library.</returns>
59
+ internal static Library GetExtensionLibrary(TableDefinitionCollection tableDefinitions)
60
+ {
61
+ return ExtensionData.LoadLibraryHelper(Assembly.GetExecutingAssembly(), "WixToolset.Extensions.Data.http.wixlib", tableDefinitions);
62
+ }
63
+ }
64
+}
src/wixext/WixHttpExtension.csproj
new
+48
@@ -0,0 +1,48 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
6
+ <PropertyGroup>
7
+ <ProjectGuid>{AAFC3C7F-D818-4B1D-AF3F-A331EA917F3F}</ProjectGuid>
8
+ <AssemblyName>WixHttpExtension</AssemblyName>
9
+ <OutputType>Library</OutputType>
10
+ <RootNamespace>WixToolset.Extensions</RootNamespace>
11
+ </PropertyGroup>
12
+ <ItemGroup>
13
+ <Compile Include="AssemblyInfo.cs" />
14
+ <Compile Include="HttpCompiler.cs" />
15
+ <Compile Include="HttpConstants.cs" />
16
+ <Compile Include="HttpDecompiler.cs" />
17
+ <Compile Include="HttpExtensionData.cs" />
18
+ <MsgGenSource Include="Data\messages.xml">
19
+ <ResourcesLogicalName>$(RootNamespace).Data.Messages.resources</ResourcesLogicalName>
20
+ </MsgGenSource>
21
+ <EmbeddedFlattenedResource Include="Data\tables.xml">
22
+ <LogicalName>$(RootNamespace).Data.tables.xml</LogicalName>
23
+ </EmbeddedFlattenedResource>
24
+ <EmbeddedFlattenedResource Include="Xsd\http.xsd">
25
+ <LogicalName>$(RootNamespace).Xsd.http.xsd</LogicalName>
26
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
27
+ </EmbeddedFlattenedResource>
28
+ <XsdGenSource Include="Xsd\http.xsd">
29
+ <CommonNamespace>WixToolset.Data.Serialize</CommonNamespace>
30
+ <Namespace>WixToolset.Extensions.Serialize.Http</Namespace>
31
+ </XsdGenSource>
32
+ <EmbeddedResource Include="$(OutputPath)\http.wixlib">
33
+ <Link>Data\http.wixlib</Link>
34
+ </EmbeddedResource>
35
+ </ItemGroup>
36
+ <ItemGroup>
37
+ <Reference Include="System" />
38
+ <Reference Include="System.Xml" />
39
+ <Reference Include="System.Xml.Linq" />
40
+ <ProjectReference Include="..\..\..\libs\WixToolset.Data\WixToolset.Data.csproj" />
41
+ <ProjectReference Include="..\..\..\libs\WixToolset.Extensibility\WixToolset.Extensibility.csproj" />
42
+ <ProjectReference Include="..\..\..\tools\wix\Wix.csproj" />
43
+ <ProjectReference Include="..\wixlib\HttpExtension.wixproj">
44
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
45
+ </ProjectReference>
46
+ </ItemGroup>
47
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
48
+</Project>
src/wixext/http.xsd
new
+148
@@ -0,0 +1,148 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
6
+ xmlns:xse="http://wixtoolset.org/schemas/XmlSchemaExtension"
7
+ xmlns:html="http://www.w3.org/1999/xhtml"
8
+ targetNamespace="http://wixtoolset.org/schemas/v4/wxs/http"
9
+ xmlns="http://wixtoolset.org/schemas/v4/wxs/http">
10
+ <xs:annotation>
11
+ <xs:documentation>
12
+ The source code schema for the Windows Installer XML Toolset Http Extension.
13
+ </xs:documentation>
14
+ </xs:annotation>
15
+
16
+ <xs:import namespace="http://wixtoolset.org/schemas/v4/wxs" />
17
+
18
+ <xs:element name="UrlReservation">
19
+ <xs:annotation>
20
+ <xs:documentation>
21
+ Makes a reservation record for the HTTP Server API configuration store on Windows XP SP2,
22
+ Windows Server 2003, and later. For more information about the HTTP Server API, see
23
+ <html:a href="http://msdn.microsoft.com/library/windows/desktop/aa364510.aspx">
24
+ HTTP Server API
25
+ </html:a>.
26
+ </xs:documentation>
27
+ <xs:appinfo>
28
+ <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" />
29
+ <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="ServiceInstall" />
30
+ </xs:appinfo>
31
+ </xs:annotation>
32
+
33
+ <xs:complexType>
34
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
35
+ <xs:annotation>
36
+ <xs:documentation>
37
+ The access control entries for the access control list.
38
+ </xs:documentation>
39
+ </xs:annotation>
40
+ <xs:element ref="UrlAce" />
41
+ </xs:choice>
42
+
43
+ <xs:attribute name="HandleExisting">
44
+ <xs:annotation>
45
+ <xs:documentation>
46
+ Specifies the behavior when trying to install a URL reservation and it already exists.
47
+ </xs:documentation>
48
+ </xs:annotation>
49
+ <xs:simpleType>
50
+ <xs:restriction base="xs:NMTOKEN">
51
+ <xs:enumeration value="replace">
52
+ <xs:annotation>
53
+ <xs:documentation>
54
+ Replaces the existing URL reservation (the default).
55
+ </xs:documentation>
56
+ </xs:annotation>
57
+ </xs:enumeration>
58
+ <xs:enumeration value="ignore">
59
+ <xs:annotation>
60
+ <xs:documentation>
61
+ Keeps the existing URL reservation.
62
+ </xs:documentation>
63
+ </xs:annotation>
64
+ </xs:enumeration>
65
+ <xs:enumeration value="fail">
66
+ <xs:annotation>
67
+ <xs:documentation>
68
+ The installation fails.
69
+ </xs:documentation>
70
+ </xs:annotation>
71
+ </xs:enumeration>
72
+ </xs:restriction>
73
+ </xs:simpleType>
74
+ </xs:attribute>
75
+
76
+ <xs:attribute name="Id" type="xs:string">
77
+ <xs:annotation>
78
+ <xs:documentation>
79
+ Unique ID of this URL reservation.
80
+ If this attribute is not specified, an identifier will be generated automatically.
81
+ </xs:documentation>
82
+ </xs:annotation>
83
+ </xs:attribute>
84
+
85
+ <xs:attribute name="Sddl" type="xs:string">
86
+ <xs:annotation>
87
+ <xs:documentation>
88
+ Security descriptor to apply to the URL reservation.
89
+ Can't be specified when using children UrlAce elements.
90
+ </xs:documentation>
91
+ </xs:annotation>
92
+ </xs:attribute>
93
+
94
+ <xs:attribute name="Url" type="xs:string" use="required">
95
+ <xs:annotation>
96
+ <xs:documentation>
97
+ The <html:a href="http://msdn.microsoft.com/library/windows/desktop/aa364698.aspx">UrlPrefix</html:a>
98
+ string that defines the portion of the URL namespace to which this reservation pertains.
99
+ </xs:documentation>
100
+ </xs:annotation>
101
+ </xs:attribute>
102
+ </xs:complexType>
103
+ </xs:element>
104
+
105
+ <xs:element name="UrlAce">
106
+ <xs:annotation>
107
+ <xs:documentation>
108
+ The security principal and which rights to assign to them for the URL reservation.
109
+ </xs:documentation>
110
+ </xs:annotation>
111
+ <xs:complexType>
112
+ <xs:attribute name="Id" type="xs:string">
113
+ <xs:annotation>
114
+ <xs:documentation>
115
+ Unique ID of this URL ACE.
116
+ If this attribute is not specified, an identifier will be generated automatically.
117
+ </xs:documentation>
118
+ </xs:annotation>
119
+ </xs:attribute>
120
+
121
+ <xs:attribute name="SecurityPrincipal" type="xs:string">
122
+ <xs:annotation>
123
+ <xs:documentation>
124
+ The security principal for this ACE. When the UrlReservation is under a ServiceInstall element, this defaults to
125
+ "NT SERVICE\ServiceInstallName". This may be either a SID or an account name in a format that
126
+ <html:a href="http://msdn.microsoft.com/library/windows/desktop/aa379159.aspx">LookupAccountName</html:a>
127
+ supports. When using a SID, an asterisk must be prepended. For example, "*S-1-5-18".
128
+ </xs:documentation>
129
+ </xs:annotation>
130
+ </xs:attribute>
131
+
132
+ <xs:attribute name="Rights">
133
+ <xs:annotation>
134
+ <xs:documentation>
135
+ Rights for this ACE. Default is "all".
136
+ </xs:documentation>
137
+ </xs:annotation>
138
+ <xs:simpleType>
139
+ <xs:restriction base="xs:NMTOKEN">
140
+ <xs:enumeration value="register" />
141
+ <xs:enumeration value="delegate" />
142
+ <xs:enumeration value="all" />
143
+ </xs:restriction>
144
+ </xs:simpleType>
145
+ </xs:attribute>
146
+ </xs:complexType>
147
+ </xs:element>
148
+</xs:schema>
src/wixext/messages.xml
new
+13
@@ -0,0 +1,13 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Messages Namespace="WixToolset.Extensions" Resources="Data.Messages" xmlns="http://schemas.microsoft.com/genmsgs/2004/07/messages">
6
+ <Class Name="HttpErrors" ContainerName="HttpErrorEventArgs" BaseContainerName="MessageEventArgs" Level="Error">
7
+ <Message Id="NoSecuritySpecified" Number="6701">
8
+ <Instance>
9
+ The UrlReservation element doesn't identify the security for the reservation. You must either specify the Sddl attribute, or provide child UrlAce elements.
10
+ </Instance>
11
+ </Message>
12
+ </Class>
13
+</Messages>
src/wixext/tables.xml
new
+28
@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<tableDefinitions xmlns="http://wixtoolset.org/schemas/v4/wi/tables">
6
+ <tableDefinition name="WixHttpUrlReservation">
7
+ <columnDefinition name="WixHttpUrlReservation" type="string" length="72" primaryKey="yes" modularize="column"
8
+ category="identifier" description="The non-localized primary key for the table." />
9
+ <columnDefinition name="HandleExisting" type="number" length="4" nullable="no"
10
+ minValue="0" maxValue="2" description="The behavior when trying to install a URL reservation and it already exists." />
11
+ <columnDefinition name="Sddl" type="string" length="0" modularize="property" nullable="yes"
12
+ category="formatted" description="Security descriptor for the URL reservation." />
13
+ <columnDefinition name="Url" type="string" length="0" modularize="property" nullable="no"
14
+ category="formatted" description="URL to be reserved." />
15
+ <columnDefinition name="Component_" type="string" length="72" modularize="column"
16
+ keyTable="Component" keyColumn="1" category="identifier" description="Foreign key into the Component table referencing the component that controls the URL reservation." />
17
+ </tableDefinition>
18
+ <tableDefinition name="WixHttpUrlAce">
19
+ <columnDefinition name="WixHttpUrlAce" type="string" length="72" primaryKey="yes" modularize="column"
20
+ category="identifier" description="The non-localized primary key for the table." />
21
+ <columnDefinition name="WixHttpUrlReservation_" type="string" length="72" keyTable="WixHttpUrlReservation" keyColumn="1" modularize="column"
22
+ category="identifier" description="Foreign key into the WixHttpUrlReservation table." />
23
+ <columnDefinition name="SecurityPrincipal" type="string" length="0" modularize="property"
24
+ category="formatted" description="The security principal for this ACE." />
25
+ <columnDefinition name="Rights" type="number" length="4" nullable="no"
26
+ minValue="0" maxValue="1073741824" description="The rights for this ACE." />
27
+ </tableDefinition>
28
+</tableDefinitions>
src/wixlib/HttpExtension.wixproj
new
+26
@@ -0,0 +1,26 @@
1
+<?xml version="1.0" encoding="utf-8" ?>
2
+<!-- 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. -->
3
+
4
+
5
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
6
+ <PropertyGroup>
7
+ <ProjectGuid>{055C1517-4CED-4199-BCDE-A383E5C4EF78}</ProjectGuid>
8
+ <OutputName>http</OutputName>
9
+ <OutputType>Library</OutputType>
10
+ <BindFiles>true</BindFiles>
11
+ <Pedantic>true</Pedantic>
12
+ <Cultures>en-us</Cultures>
13
+ </PropertyGroup>
14
+
15
+ <ItemGroup>
16
+ <Compile Include="HttpExtension.wxs" />
17
+ <Compile Include="HttpExtension_x86.wxs" />
18
+ <EmbeddedResource Include="en-us.wxl" />
19
+ </ItemGroup>
20
+
21
+ <ItemGroup>
22
+ <ProjectReference Include="..\ca\wixhttpca.vcxproj" />
23
+ </ItemGroup>
24
+
25
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
26
+</Project>
src/wixlib/HttpExtension.wxs
new
+11
@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
6
+ <?include caerr.wxi ?>
7
+ <Fragment>
8
+ <UI Id="WixHttpErrors">
9
+ </UI>
10
+ </Fragment>
11
+</Wix>
src/wixlib/HttpExtension_Platform.wxi
new
+40
@@ -0,0 +1,40 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
6
+ <?include caSuffix.wxi ?>
7
+ <Fragment>
8
+ <UIRef Id="WixHttpErrors" />
9
+ <UI>
10
+ <ProgressText Action="WixSchedHttpUrlReservationsInstall$(var.Suffix)">!(loc.WixSchedHttpUrlReservationsInstall)</ProgressText>
11
+ <ProgressText Action="WixSchedHttpUrlReservationsUninstall$(var.Suffix)">!(loc.WixSchedHttpUrlReservationsUninstall)</ProgressText>
12
+ <ProgressText Action="WixRollbackHttpUrlReservationsInstall$(var.DeferredSuffix)">!(loc.WixRollbackHttpUrlReservationsInstall)</ProgressText>
13
+ <ProgressText Action="WixExecHttpUrlReservationsInstall$(var.DeferredSuffix)">!(loc.WixExecHttpUrlReservationsInstall)</ProgressText>
14
+ <ProgressText Action="WixRollbackHttpUrlReservationsUninstall$(var.DeferredSuffix)">!(loc.WixRollbackHttpUrlReservationsUninstall)</ProgressText>
15
+ <ProgressText Action="WixExecHttpUrlReservationsUninstall$(var.DeferredSuffix)">!(loc.WixExecHttpUrlReservationsUninstall)</ProgressText>
16
+ </UI>
17
+
18
+ <CustomAction Id="WixSchedHttpUrlReservationsInstall$(var.Suffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="SchedHttpUrlReservationsInstall" Execute="immediate" Return="check" SuppressModularization="yes" />
19
+ <CustomAction Id="WixSchedHttpUrlReservationsUninstall$(var.Suffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="SchedHttpUrlReservationsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" />
20
+ <CustomAction Id="WixRollbackHttpUrlReservationsInstall$(var.DeferredSuffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="ExecHttpUrlReservations" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" />
21
+ <CustomAction Id="WixExecHttpUrlReservationsInstall$(var.DeferredSuffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="ExecHttpUrlReservations" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" />
22
+ <CustomAction Id="WixRollbackHttpUrlReservationsUninstall$(var.DeferredSuffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="ExecHttpUrlReservations" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" />
23
+ <CustomAction Id="WixExecHttpUrlReservationsUninstall$(var.DeferredSuffix)" BinaryKey="WixHttpCA$(var.Suffix)" DllEntry="ExecHttpUrlReservations" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" />
24
+
25
+ <!--
26
+ We need the HTTP server on Windows XP SP2 or later.
27
+ -->
28
+ <InstallExecuteSequence>
29
+ <Custom Action="WixSchedHttpUrlReservationsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes">
30
+ <![CDATA[ VersionNT >= 600 OR (VersionNT >= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel >= 2) OR (MsiNTProductType > 1))) ]]>
31
+ </Custom>
32
+ <Custom Action="WixSchedHttpUrlReservationsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes">
33
+ <![CDATA[ VersionNT >= 600 OR (VersionNT >= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel >= 2) OR (MsiNTProductType > 1))) ]]>
34
+ </Custom>
35
+ </InstallExecuteSequence>
36
+ </Fragment>
37
+ <Fragment>
38
+ <Binary Id="WixHttpCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))wixhttpca.dll" />
39
+ </Fragment>
40
+</Include>
src/wixlib/HttpExtension_x86.wxs
new
+8
@@ -0,0 +1,8 @@
1
+<?xml version="1.0"?>
2
+<!-- 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. -->
3
+
4
+
5
+<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
6
+ <?define platform=x86 ?>
7
+ <?include HttpExtension_Platform.wxi ?>
8
+</Wix>
src/wixlib/en-us.wxl
new
+12
@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!-- 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. -->
3
+
4
+
5
+<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
6
+ <String Id="WixSchedHttpUrlReservationsInstall" Overridable="yes">Preparing to configure Windows HTTP Server</String>
7
+ <String Id="WixSchedHttpUrlReservationsUninstall" Overridable="yes">Preparing to configure Windows HTTP Server</String>
8
+ <String Id="WixRollbackHttpUrlReservationsInstall" Overridable="yes">Rolling back Windows HTTP Server configuration</String>
9
+ <String Id="WixExecHttpUrlReservationsInstall" Overridable="yes">Configuring Windows HTTP Server</String>
10
+ <String Id="WixRollbackHttpUrlReservationsUninstall" Overridable="yes">Rolling back Windows HTTP Server configuration</String>
11
+ <String Id="WixExecHttpUrlReservationsUninstall" Overridable="yes">Configuring Windows HTTP Server</String>
12
+</WixLocalization>