Import code from old v4 repo
Sean Hall committed
Jan 19, 2019 at 19:19 UTC
a12b13c36d1da707cf541595cf5f38338f37cc68
22 files changed
+3807
src/ca/mqcost.h
new
+9
@@ -0,0 +1,9 @@
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
+#define COST_MESSAGE_QUEUE_CREATE 10000
6
+#define COST_MESSAGE_QUEUE_DELETE 10000
7
+
8
+#define COST_MESSAGE_QUEUE_PERMISSION_ADD 10000
9
+#define COST_MESSAGE_QUEUE_PERMISSION_REMOVE 10000
src/ca/mqexec.cpp
new
+214
@@ -0,0 +1,214 @@
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 hInst,
11
+ IN ULONG ulReason,
12
+ IN LPVOID)
13
+{
14
+ switch(ulReason)
15
+ {
16
+ case DLL_PROCESS_ATTACH:
17
+ WcaGlobalInitialize(hInst);
18
+ break;
19
+
20
+ case DLL_PROCESS_DETACH:
21
+ WcaGlobalFinalize();
22
+ break;
23
+ }
24
+
25
+ return TRUE;
26
+}
27
+
28
+/********************************************************************
29
+ MessageQueuingExecuteInstall - CUSTOM ACTION ENTRY POINT
30
+
31
+ Input: deferred CustomActionData - MessageQueuingExecuteInstall
32
+********************************************************************/
33
+extern "C" UINT __stdcall MessageQueuingExecuteInstall(MSIHANDLE hInstall)
34
+{
35
+ HRESULT hr = S_OK;
36
+ UINT er = ERROR_SUCCESS;
37
+
38
+ LPWSTR pwzCustomActionData = NULL;
39
+ LPWSTR pwzData = NULL;
40
+
41
+ // initialize
42
+ hr = WcaInitialize(hInstall, "MessageQueuingExecuteInstall");
43
+ ExitOnFailure(hr, "Failed to initialize MessageQueuingExecuteInstall");
44
+
45
+ hr = MqiInitialize();
46
+ ExitOnFailure(hr, "Failed to initialize");
47
+
48
+ // get custom action data
49
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
50
+ ExitOnFailure(hr, "Failed to get CustomActionData");
51
+ pwzData = pwzCustomActionData;
52
+
53
+ // create message queues
54
+ hr = MqiCreateMessageQueues(&pwzData);
55
+ ExitOnFailure(hr, "Failed to create message queues");
56
+ if (S_FALSE == hr) ExitFunction();
57
+
58
+ // add message queue permissions
59
+ hr = MqiAddMessageQueuePermissions(&pwzData);
60
+ ExitOnFailure(hr, "Failed to add message queue permissions");
61
+ if (S_FALSE == hr) ExitFunction();
62
+
63
+ hr = S_OK;
64
+
65
+LExit:
66
+ // clean up
67
+ ReleaseStr(pwzCustomActionData);
68
+
69
+ // uninitialize
70
+ MqiUninitialize();
71
+
72
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
73
+ return WcaFinalize(er);
74
+}
75
+
76
+/********************************************************************
77
+ MessageQueuingRollbackInstall - CUSTOM ACTION ENTRY POINT
78
+
79
+ Input: deferred CustomActionData - MessageQueuingRollbackInstall
80
+********************************************************************/
81
+extern "C" UINT __stdcall MessageQueuingRollbackInstall(MSIHANDLE hInstall)
82
+{
83
+ HRESULT hr = S_OK;
84
+ UINT er = ERROR_SUCCESS;
85
+
86
+ LPWSTR pwzCustomActionData = NULL;
87
+ LPWSTR pwzData = NULL;
88
+
89
+ // initialize
90
+ hr = WcaInitialize(hInstall, "MessageQueuingRollbackInstall");
91
+ ExitOnFailure(hr, "Failed to initialize MessageQueuingRollbackInstall");
92
+
93
+ hr = MqiInitialize();
94
+ ExitOnFailure(hr, "Failed to initialize");
95
+
96
+ // get custom action data
97
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
98
+ ExitOnFailure(hr, "Failed to get CustomActionData");
99
+ pwzData = pwzCustomActionData;
100
+
101
+ // add message queue permissions
102
+ hr = MqiRollbackAddMessageQueuePermissions(&pwzData);
103
+ ExitOnFailure(hr, "Failed to rollback add message queue permissions");
104
+
105
+ // create message queues
106
+ hr = MqiRollbackCreateMessageQueues(&pwzData);
107
+ ExitOnFailure(hr, "Failed to rollback create message queues");
108
+
109
+ hr = S_OK;
110
+
111
+LExit:
112
+ // clean up
113
+ ReleaseStr(pwzCustomActionData);
114
+
115
+ // uninitialize
116
+ MqiUninitialize();
117
+
118
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
119
+ return WcaFinalize(er);
120
+}
121
+
122
+/********************************************************************
123
+ MessageQueuingExecuteUninstall - CUSTOM ACTION ENTRY POINT
124
+
125
+ Input: deferred CustomActionData - MessageQueuingExecuteUninstall
126
+********************************************************************/
127
+extern "C" UINT __stdcall MessageQueuingExecuteUninstall(MSIHANDLE hInstall)
128
+{
129
+ HRESULT hr = S_OK;
130
+ UINT er = ERROR_SUCCESS;
131
+
132
+ LPWSTR pwzCustomActionData = NULL;
133
+ LPWSTR pwzData = NULL;
134
+
135
+ // initialize
136
+ hr = WcaInitialize(hInstall, "MessageQueuingExecuteUninstall");
137
+ ExitOnFailure(hr, "Failed to initialize MessageQueuingExecuteUninstall");
138
+
139
+ hr = MqiInitialize();
140
+ ExitOnFailure(hr, "Failed to initialize");
141
+
142
+ // get custom action data
143
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
144
+ ExitOnFailure(hr, "Failed to get CustomActionData");
145
+ pwzData = pwzCustomActionData;
146
+
147
+ // remove message queue permissions
148
+ hr = MqiRemoveMessageQueuePermissions(&pwzData);
149
+ ExitOnFailure(hr, "Failed to remove message queue permissions");
150
+ if (S_FALSE == hr) ExitFunction();
151
+
152
+ // delete message queues
153
+ hr = MqiDeleteMessageQueues(&pwzData);
154
+ ExitOnFailure(hr, "Failed to delete message queues");
155
+ if (S_FALSE == hr) ExitFunction();
156
+
157
+ hr = S_OK;
158
+
159
+LExit:
160
+ // clean up
161
+ ReleaseStr(pwzCustomActionData);
162
+
163
+ // uninitialize
164
+ MqiUninitialize();
165
+
166
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
167
+ return WcaFinalize(er);
168
+}
169
+
170
+/********************************************************************
171
+ MessageQueuingRollbackUninstall - CUSTOM ACTION ENTRY POINT
172
+
173
+ Input: deferred CustomActionData - MessageQueuingRollbackUninstall
174
+********************************************************************/
175
+extern "C" UINT __stdcall MessageQueuingRollbackUninstall(MSIHANDLE hInstall)
176
+{
177
+ HRESULT hr = S_OK;
178
+ UINT er = ERROR_SUCCESS;
179
+
180
+ LPWSTR pwzCustomActionData = NULL;
181
+ LPWSTR pwzData = NULL;
182
+
183
+ // initialize
184
+ hr = WcaInitialize(hInstall, "MessageQueuingRollbackUninstall");
185
+ ExitOnFailure(hr, "Failed to initialize MessageQueuingRollbackUninstall");
186
+
187
+ hr = MqiInitialize();
188
+ ExitOnFailure(hr, "Failed to initialize");
189
+
190
+ // get custom action data
191
+ hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
192
+ ExitOnFailure(hr, "Failed to get CustomActionData");
193
+ pwzData = pwzCustomActionData;
194
+
195
+ // delete message queues
196
+ hr = MqiRollbackDeleteMessageQueues(&pwzData);
197
+ ExitOnFailure(hr, "Failed to delete message queues");
198
+
199
+ // remove message queue permissions
200
+ hr = MqiRollbackRemoveMessageQueuePermissions(&pwzData);
201
+ ExitOnFailure(hr, "Failed to remove message queue permissions");
202
+
203
+ hr = S_OK;
204
+
205
+LExit:
206
+ // clean up
207
+ ReleaseStr(pwzCustomActionData);
208
+
209
+ // uninitialize
210
+ MqiUninitialize();
211
+
212
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
213
+ return WcaFinalize(er);
214
+}
src/ca/mqqueueexec.cpp
new
+927
@@ -0,0 +1,927 @@
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
+// private typedefs
7
+
8
+typedef HRESULT (__stdcall *MQCreateQueueFunc)(PSECURITY_DESCRIPTOR, MQQUEUEPROPS*, LPWSTR, LPDWORD);
9
+typedef HRESULT (__stdcall *MQDeleteQueueFunc)(LPCWSTR);
10
+typedef HRESULT (__stdcall *MQPathNameToFormatNameFunc)(LPCWSTR, LPWSTR, LPDWORD);
11
+typedef HRESULT (__stdcall *MQGetQueueSecurityFunc)(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
12
+typedef HRESULT (__stdcall *MQSetQueueSecurityFunc)(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
13
+
14
+
15
+// private enums
16
+
17
+enum eMessageQueueAttributes
18
+{
19
+ mqaAuthenticate = (1 << 0),
20
+ mqaJournal = (1 << 1),
21
+ mqaTransactional = (1 << 2)
22
+};
23
+
24
+enum eMessageQueuePrivacyLevel
25
+{
26
+ mqplNone = 0,
27
+ mqplOptional = 1,
28
+ mqplBody = 2
29
+};
30
+
31
+enum eMessageQueuePermission
32
+{
33
+ mqpDeleteMessage = (1 << 0),
34
+ mqpPeekMessage = (1 << 1),
35
+ mqpWriteMessage = (1 << 2),
36
+ mqpDeleteJournalMessage = (1 << 3),
37
+ mqpSetQueueProperties = (1 << 4),
38
+ mqpGetQueueProperties = (1 << 5),
39
+ mqpDeleteQueue = (1 << 6),
40
+ mqpGetQueuePermissions = (1 << 7),
41
+ mqpChangeQueuePermissions = (1 << 8),
42
+ mqpTakeQueueOwnership = (1 << 9),
43
+ mqpReceiveMessage = (1 << 10),
44
+ mqpReceiveJournalMessage = (1 << 11),
45
+ mqpQueueGenericRead = (1 << 12),
46
+ mqpQueueGenericWrite = (1 << 13),
47
+ mqpQueueGenericExecute = (1 << 14),
48
+ mqpQueueGenericAll = (1 << 15)
49
+};
50
+
51
+
52
+// private structs
53
+
54
+struct MQI_MESSAGE_QUEUE_ATTRIBUTES
55
+{
56
+ LPWSTR pwzKey;
57
+ int iBasePriority;
58
+ int iJournalQuota;
59
+ LPWSTR pwzLabel;
60
+ LPWSTR pwzMulticastAddress;
61
+ LPWSTR pwzPathName;
62
+ int iPrivLevel;
63
+ int iQuota;
64
+ LPWSTR pwzServiceTypeGuid;
65
+ int iAttributes;
66
+};
67
+
68
+struct MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES
69
+{
70
+ LPWSTR pwzKey;
71
+ LPWSTR pwzPathName;
72
+ LPWSTR pwzDomain;
73
+ LPWSTR pwzName;
74
+ int iPermissions;
75
+};
76
+
77
+
78
+// prototypes for private helper functions
79
+
80
+static HRESULT ReadMessageQueueAttributes(
81
+ LPWSTR* ppwzData,
82
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
83
+ );
84
+static void FreeMessageQueueAttributes(
85
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
86
+ );
87
+static HRESULT ReadMessageQueuePermissionAttributes(
88
+ LPWSTR* ppwzData,
89
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
90
+ );
91
+static void FreeMessageQueuePermissionAttributes(
92
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
93
+ );
94
+static HRESULT CreateMessageQueue(
95
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
96
+ );
97
+static HRESULT DeleteMessageQueue(
98
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
99
+ );
100
+static HRESULT SetMessageQueuePermissions(
101
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs,
102
+ BOOL fRevoke
103
+ );
104
+static void SetAccessPermissions(
105
+ int iPermissions,
106
+ LPDWORD pgrfAccessPermissions
107
+ );
108
+
109
+
110
+// private variables
111
+
112
+static HMODULE ghMQRT;
113
+static MQCreateQueueFunc gpfnMQCreateQueue;
114
+static MQDeleteQueueFunc gpfnMQDeleteQueue;
115
+static MQPathNameToFormatNameFunc gpfnMQPathNameToFormatName;
116
+static MQGetQueueSecurityFunc gpfnMQGetQueueSecurity;
117
+static MQSetQueueSecurityFunc gpfnMQSetQueueSecurity;
118
+
119
+
120
+// function definitions
121
+
122
+HRESULT MqiInitialize()
123
+{
124
+ HRESULT hr = S_OK;
125
+
126
+ // load mqrt.dll
127
+ ghMQRT = ::LoadLibraryW(L"mqrt.dll");
128
+ ExitOnNull(ghMQRT, hr, E_FAIL, "Failed to load mqrt.dll");
129
+
130
+ // get MQCreateQueue function address
131
+ gpfnMQCreateQueue = (MQCreateQueueFunc)::GetProcAddress(ghMQRT, "MQCreateQueue");
132
+ ExitOnNull(gpfnMQCreateQueue, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for MQCreateQueue() function");
133
+
134
+ // get MQDeleteQueue function address
135
+ gpfnMQDeleteQueue = (MQDeleteQueueFunc)::GetProcAddress(ghMQRT, "MQDeleteQueue");
136
+ ExitOnNull(gpfnMQDeleteQueue, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for MQDeleteQueue() function");
137
+
138
+ // get MQPathNameToFormatName function address
139
+ gpfnMQPathNameToFormatName = (MQPathNameToFormatNameFunc)::GetProcAddress(ghMQRT, "MQPathNameToFormatName");
140
+ ExitOnNull(gpfnMQPathNameToFormatName, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for MQPathNameToFormatName() function");
141
+
142
+ // get MQGetQueueSecurity function address
143
+ gpfnMQGetQueueSecurity = (MQGetQueueSecurityFunc)::GetProcAddress(ghMQRT, "MQGetQueueSecurity");
144
+ ExitOnNull(gpfnMQGetQueueSecurity, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for MQGetQueueSecurity() function");
145
+
146
+ // get MQSetQueueSecurity function address
147
+ gpfnMQSetQueueSecurity = (MQSetQueueSecurityFunc)::GetProcAddress(ghMQRT, "MQSetQueueSecurity");
148
+ ExitOnNull(gpfnMQSetQueueSecurity, hr, HRESULT_FROM_WIN32(::GetLastError()), "Failed get address for MQSetQueueSecurity() function");
149
+
150
+ hr = S_OK;
151
+
152
+LExit:
153
+ return hr;
154
+}
155
+
156
+void MqiUninitialize()
157
+{
158
+ if (ghMQRT)
159
+ ::FreeLibrary(ghMQRT);
160
+}
161
+
162
+HRESULT MqiCreateMessageQueues(
163
+ LPWSTR* ppwzData
164
+ )
165
+{
166
+ HRESULT hr = S_OK;
167
+
168
+ int iCnt = 0;
169
+
170
+ MQI_MESSAGE_QUEUE_ATTRIBUTES attrs;
171
+ ::ZeroMemory(&attrs, sizeof(attrs));
172
+
173
+ // ger count
174
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
175
+ ExitOnFailure(hr, "Failed to read count");
176
+
177
+ for (int i = 0; i < iCnt; i++)
178
+ {
179
+ // read attributes from CustomActionData
180
+ hr = ReadMessageQueueAttributes(ppwzData, &attrs);
181
+ ExitOnFailure(hr, "Failed to read attributes");
182
+
183
+ // progress message
184
+ hr = PcaActionDataMessage(1, attrs.pwzPathName);
185
+ ExitOnFailure(hr, "Failed to send progress messages, key: %S", attrs.pwzKey);
186
+
187
+ // create message queue
188
+ hr = CreateMessageQueue(&attrs);
189
+ ExitOnFailure(hr, "Failed to create message queue, key: %S", attrs.pwzKey);
190
+
191
+ // progress tics
192
+ hr = WcaProgressMessage(COST_MESSAGE_QUEUE_CREATE, FALSE);
193
+ ExitOnFailure(hr, "Failed to update progress");
194
+ }
195
+
196
+ hr = S_OK;
197
+
198
+LExit:
199
+ // clean up
200
+ FreeMessageQueueAttributes(&attrs);
201
+
202
+ return hr;
203
+}
204
+
205
+HRESULT MqiRollbackCreateMessageQueues(
206
+ LPWSTR* ppwzData
207
+ )
208
+{
209
+ HRESULT hr = S_OK;
210
+
211
+ int iCnt = 0;
212
+
213
+ MQI_MESSAGE_QUEUE_ATTRIBUTES attrs;
214
+ ::ZeroMemory(&attrs, sizeof(attrs));
215
+
216
+ // ger count
217
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
218
+ ExitOnFailure(hr, "Failed to read count");
219
+
220
+ for (int i = 0; i < iCnt; i++)
221
+ {
222
+ // read attributes from CustomActionData
223
+ hr = ReadMessageQueueAttributes(ppwzData, &attrs);
224
+ ExitOnFailure(hr, "Failed to read attributes");
225
+
226
+ // create message queue
227
+ hr = DeleteMessageQueue(&attrs);
228
+ if (FAILED(hr))
229
+ WcaLog(LOGMSG_STANDARD, "Failed to delete message queue, hr: 0x%x, key: %S", hr, attrs.pwzKey);
230
+ }
231
+
232
+ hr = S_OK;
233
+
234
+LExit:
235
+ // clean up
236
+ FreeMessageQueueAttributes(&attrs);
237
+
238
+ return hr;
239
+}
240
+
241
+HRESULT MqiDeleteMessageQueues(
242
+ LPWSTR* ppwzData
243
+ )
244
+{
245
+ HRESULT hr = S_OK;
246
+
247
+ int iCnt = 0;
248
+
249
+ MQI_MESSAGE_QUEUE_ATTRIBUTES attrs;
250
+ ::ZeroMemory(&attrs, sizeof(attrs));
251
+
252
+ // ger count
253
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
254
+ ExitOnFailure(hr, "Failed to read count");
255
+
256
+ for (int i = 0; i < iCnt; i++)
257
+ {
258
+ // read attributes from CustomActionData
259
+ hr = ReadMessageQueueAttributes(ppwzData, &attrs);
260
+ ExitOnFailure(hr, "Failed to read attributes");
261
+
262
+ // progress message
263
+ hr = PcaActionDataMessage(1, attrs.pwzPathName);
264
+ ExitOnFailure(hr, "Failed to send progress messages, key: %S", attrs.pwzKey);
265
+
266
+ // create message queue
267
+ hr = DeleteMessageQueue(&attrs);
268
+ if (FAILED(hr))
269
+ {
270
+ WcaLog(LOGMSG_STANDARD, "Failed to delete queue, hr: 0x%x, key: %S", hr, attrs.pwzKey);
271
+ continue;
272
+ }
273
+
274
+ // progress tics
275
+ hr = WcaProgressMessage(COST_MESSAGE_QUEUE_DELETE, FALSE);
276
+ ExitOnFailure(hr, "Failed to update progress");
277
+ }
278
+
279
+ hr = S_OK;
280
+
281
+LExit:
282
+ // clean up
283
+ FreeMessageQueueAttributes(&attrs);
284
+
285
+ return hr;
286
+}
287
+
288
+HRESULT MqiRollbackDeleteMessageQueues(
289
+ LPWSTR* ppwzData
290
+ )
291
+{
292
+ HRESULT hr = S_OK;
293
+
294
+ int iCnt = 0;
295
+
296
+ MQI_MESSAGE_QUEUE_ATTRIBUTES attrs;
297
+ ::ZeroMemory(&attrs, sizeof(attrs));
298
+
299
+ // ger count
300
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
301
+ ExitOnFailure(hr, "Failed to read count");
302
+
303
+ for (int i = 0; i < iCnt; i++)
304
+ {
305
+ // read attributes from CustomActionData
306
+ hr = ReadMessageQueueAttributes(ppwzData, &attrs);
307
+ ExitOnFailure(hr, "Failed to read attributes");
308
+
309
+ // create message queue
310
+ hr = CreateMessageQueue(&attrs);
311
+ if (FAILED(hr))
312
+ WcaLog(LOGMSG_STANDARD, "Failed to create message queue, hr: 0x%x, key: %S", hr, attrs.pwzKey);
313
+ }
314
+
315
+ hr = S_OK;
316
+
317
+LExit:
318
+ // clean up
319
+ FreeMessageQueueAttributes(&attrs);
320
+
321
+ return hr;
322
+}
323
+
324
+HRESULT MqiAddMessageQueuePermissions(
325
+ LPWSTR* ppwzData
326
+ )
327
+{
328
+ HRESULT hr = S_OK;
329
+
330
+ int iCnt = 0;
331
+
332
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
333
+ ::ZeroMemory(&attrs, sizeof(attrs));
334
+
335
+ // ger count
336
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
337
+ ExitOnFailure(hr, "Failed to read count");
338
+
339
+ for (int i = 0; i < iCnt; i++)
340
+ {
341
+ // read attributes from CustomActionData
342
+ hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
343
+ ExitOnFailure(hr, "Failed to read attributes");
344
+
345
+ // progress message
346
+ hr = PcaActionDataMessage(1, attrs.pwzPathName);
347
+ ExitOnFailure(hr, "Failed to send progress messages");
348
+
349
+ // add message queue permission
350
+ hr = SetMessageQueuePermissions(&attrs, FALSE);
351
+ ExitOnFailure(hr, "Failed to add message queue permission");
352
+
353
+ // progress tics
354
+ hr = WcaProgressMessage(COST_MESSAGE_QUEUE_PERMISSION_ADD, FALSE);
355
+ ExitOnFailure(hr, "Failed to update progress");
356
+ }
357
+
358
+ hr = S_OK;
359
+
360
+LExit:
361
+ // clean up
362
+ FreeMessageQueuePermissionAttributes(&attrs);
363
+
364
+ return hr;
365
+}
366
+
367
+HRESULT MqiRollbackAddMessageQueuePermissions(
368
+ LPWSTR* ppwzData
369
+ )
370
+{
371
+ HRESULT hr = S_OK;
372
+
373
+ int iCnt = 0;
374
+
375
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
376
+ ::ZeroMemory(&attrs, sizeof(attrs));
377
+
378
+ // ger count
379
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
380
+ ExitOnFailure(hr, "Failed to read count");
381
+
382
+ for (int i = 0; i < iCnt; i++)
383
+ {
384
+ // read attributes from CustomActionData
385
+ hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
386
+ ExitOnFailure(hr, "Failed to read attributes");
387
+
388
+ // add message queue permission
389
+ hr = SetMessageQueuePermissions(&attrs, TRUE);
390
+ if (FAILED(hr))
391
+ WcaLog(LOGMSG_STANDARD, "Failed to rollback add message queue permission, hr: 0x%x, key: %S", hr, attrs.pwzKey);
392
+ }
393
+
394
+ hr = S_OK;
395
+
396
+LExit:
397
+ // clean up
398
+ FreeMessageQueuePermissionAttributes(&attrs);
399
+
400
+ return hr;
401
+}
402
+
403
+HRESULT MqiRemoveMessageQueuePermissions(
404
+ LPWSTR* ppwzData
405
+ )
406
+{
407
+ HRESULT hr = S_OK;
408
+
409
+ int iCnt = 0;
410
+
411
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
412
+ ::ZeroMemory(&attrs, sizeof(attrs));
413
+
414
+ // ger count
415
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
416
+ ExitOnFailure(hr, "Failed to read count");
417
+
418
+ for (int i = 0; i < iCnt; i++)
419
+ {
420
+ // read attributes from CustomActionData
421
+ hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
422
+ ExitOnFailure(hr, "Failed to read attributes");
423
+
424
+ // progress message
425
+ hr = PcaActionDataMessage(1, attrs.pwzPathName);
426
+ ExitOnFailure(hr, "Failed to send progress messages");
427
+
428
+ // add message queue permission
429
+ hr = SetMessageQueuePermissions(&attrs, TRUE);
430
+ ExitOnFailure(hr, "Failed to remove message queue permission");
431
+
432
+ // progress tics
433
+ hr = WcaProgressMessage(COST_MESSAGE_QUEUE_PERMISSION_ADD, FALSE);
434
+ ExitOnFailure(hr, "Failed to update progress");
435
+ }
436
+
437
+ hr = S_OK;
438
+
439
+LExit:
440
+ // clean up
441
+ FreeMessageQueuePermissionAttributes(&attrs);
442
+
443
+ return hr;
444
+}
445
+
446
+HRESULT MqiRollbackRemoveMessageQueuePermissions(
447
+ LPWSTR* ppwzData
448
+ )
449
+{
450
+ HRESULT hr = S_OK;
451
+
452
+ int iCnt = 0;
453
+
454
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES attrs;
455
+ ::ZeroMemory(&attrs, sizeof(attrs));
456
+
457
+ // ger count
458
+ hr = WcaReadIntegerFromCaData(ppwzData, &iCnt);
459
+ ExitOnFailure(hr, "Failed to read count");
460
+
461
+ for (int i = 0; i < iCnt; i++)
462
+ {
463
+ // read attributes from CustomActionData
464
+ hr = ReadMessageQueuePermissionAttributes(ppwzData, &attrs);
465
+ ExitOnFailure(hr, "Failed to read attributes");
466
+
467
+ // add message queue permission
468
+ hr = SetMessageQueuePermissions(&attrs, FALSE);
469
+ if (FAILED(hr))
470
+ WcaLog(LOGMSG_STANDARD, "Failed to rollback remove message queue permission, hr: 0x%x, key: %S", hr, attrs.pwzKey);
471
+ }
472
+
473
+ hr = S_OK;
474
+
475
+LExit:
476
+ // clean up
477
+ FreeMessageQueuePermissionAttributes(&attrs);
478
+
479
+ return hr;
480
+}
481
+
482
+
483
+// helper function definitions
484
+
485
+static HRESULT ReadMessageQueueAttributes(
486
+ LPWSTR* ppwzData,
487
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
488
+ )
489
+{
490
+ HRESULT hr = S_OK;
491
+
492
+ // read message queue information from custom action data
493
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
494
+ ExitOnFailure(hr, "Failed to read key from custom action data");
495
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iBasePriority);
496
+ ExitOnFailure(hr, "Failed to read base priority from custom action data");
497
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iJournalQuota);
498
+ ExitOnFailure(hr, "Failed to read journal quota from custom action data");
499
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzLabel);
500
+ ExitOnFailure(hr, "Failed to read label from custom action data");
501
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzMulticastAddress);
502
+ ExitOnFailure(hr, "Failed to read multicast address from custom action data");
503
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPathName);
504
+ ExitOnFailure(hr, "Failed to read path name from custom action data");
505
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iPrivLevel);
506
+ ExitOnFailure(hr, "Failed to read privacy level from custom action data");
507
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iQuota);
508
+ ExitOnFailure(hr, "Failed to read quota from custom action data");
509
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzServiceTypeGuid);
510
+ ExitOnFailure(hr, "Failed to read service type guid from custom action data");
511
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iAttributes);
512
+ ExitOnFailure(hr, "Failed to read attributes from custom action data");
513
+
514
+ hr = S_OK;
515
+
516
+LExit:
517
+ return hr;
518
+}
519
+
520
+static void FreeMessageQueueAttributes(
521
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
522
+ )
523
+{
524
+ ReleaseStr(pAttrs->pwzKey);
525
+ ReleaseStr(pAttrs->pwzLabel);
526
+ ReleaseStr(pAttrs->pwzMulticastAddress);
527
+ ReleaseStr(pAttrs->pwzPathName);
528
+ ReleaseStr(pAttrs->pwzServiceTypeGuid);
529
+}
530
+
531
+static HRESULT ReadMessageQueuePermissionAttributes(
532
+ LPWSTR* ppwzData,
533
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
534
+ )
535
+{
536
+ HRESULT hr = S_OK;
537
+
538
+ // read message queue permission information from custom action data
539
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzKey);
540
+ ExitOnFailure(hr, "Failed to read key from custom action data");
541
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzPathName);
542
+ ExitOnFailure(hr, "Failed to read path name from custom action data");
543
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzDomain);
544
+ ExitOnFailure(hr, "Failed to read domain from custom action data");
545
+ hr = WcaReadStringFromCaData(ppwzData, &pAttrs->pwzName);
546
+ ExitOnFailure(hr, "Failed to read name from custom action data");
547
+ hr = WcaReadIntegerFromCaData(ppwzData, &pAttrs->iPermissions);
548
+ ExitOnFailure(hr, "Failed to read permissions from custom action data");
549
+
550
+ hr = S_OK;
551
+
552
+LExit:
553
+ return hr;
554
+}
555
+
556
+static void FreeMessageQueuePermissionAttributes(
557
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
558
+ )
559
+{
560
+ ReleaseStr(pAttrs->pwzKey);
561
+ ReleaseStr(pAttrs->pwzPathName);
562
+ ReleaseStr(pAttrs->pwzDomain);
563
+ ReleaseStr(pAttrs->pwzName);
564
+}
565
+
566
+static HRESULT CreateMessageQueue(
567
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
568
+ )
569
+{
570
+ HRESULT hr = S_OK;
571
+
572
+ SECURITY_DESCRIPTOR sd;
573
+ PSID pOwner = NULL;
574
+ DWORD cbDacl = 0;
575
+ PACL pDacl = NULL;
576
+ QUEUEPROPID aPropID[11];
577
+ MQPROPVARIANT aPropVar[11];
578
+ MQQUEUEPROPS props;
579
+
580
+ GUID guidType;
581
+
582
+ DWORD dwFormatNameLength = 0;
583
+
584
+ ::ZeroMemory(&sd, sizeof(sd));
585
+ ::ZeroMemory(aPropID, sizeof(aPropID));
586
+ ::ZeroMemory(aPropVar, sizeof(aPropVar));
587
+ ::ZeroMemory(&props, sizeof(props));
588
+ ::ZeroMemory(&guidType, sizeof(guidType));
589
+
590
+ // initialize security descriptor
591
+ if (!::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
592
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to initialize security descriptor");
593
+
594
+ // set security descriptor owner
595
+ hr = PcaAccountNameToSid(L"\\Administrators", &pOwner);
596
+ ExitOnFailure(hr, "Failed to get sid for account name");
597
+
598
+ if (!::SetSecurityDescriptorOwner(&sd, pOwner, FALSE))
599
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set security descriptor owner");
600
+
601
+ // set security descriptor DACL
602
+ cbDacl = sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + ::GetLengthSid(pOwner);
603
+ pDacl = (PACL)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, cbDacl);
604
+ ExitOnNull(pDacl, hr, E_OUTOFMEMORY, "Failed to allocate buffer for DACL");
605
+
606
+ if (!::InitializeAcl(pDacl, cbDacl, ACL_REVISION))
607
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to initialize DACL");
608
+
609
+ if (!::AddAccessAllowedAce(pDacl, ACL_REVISION, MQSEC_QUEUE_GENERIC_ALL, pOwner))
610
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to add ACE to DACL");
611
+
612
+ if (!::SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE))
613
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set security descriptor DACL");
614
+
615
+ // set property values
616
+ props.aPropID = aPropID;
617
+ props.aPropVar = aPropVar;
618
+
619
+ aPropID[0] = PROPID_Q_LABEL;
620
+ aPropVar[0].vt = VT_LPWSTR;
621
+ aPropVar[0].pwszVal = pAttrs->pwzLabel;
622
+
623
+ aPropID[1] = PROPID_Q_PATHNAME;
624
+ aPropVar[1].vt = VT_LPWSTR;
625
+ aPropVar[1].pwszVal = pAttrs->pwzPathName;
626
+
627
+ aPropID[2] = PROPID_Q_AUTHENTICATE;
628
+ aPropVar[2].vt = VT_UI1;
629
+ aPropVar[2].bVal = mqaAuthenticate == (pAttrs->iAttributes & mqaAuthenticate);
630
+
631
+ aPropID[3] = PROPID_Q_JOURNAL;
632
+ aPropVar[3].vt = VT_UI1;
633
+ aPropVar[3].bVal = mqaJournal == (pAttrs->iAttributes & mqaJournal);
634
+
635
+ aPropID[4] = PROPID_Q_TRANSACTION;
636
+ aPropVar[4].vt = VT_UI1;
637
+ aPropVar[4].bVal = mqaTransactional == (pAttrs->iAttributes & mqaTransactional);
638
+
639
+ props.cProp = 5;
640
+
641
+ if (MSI_NULL_INTEGER != pAttrs->iBasePriority)
642
+ {
643
+ aPropID[props.cProp] = PROPID_Q_BASEPRIORITY;
644
+ aPropVar[props.cProp].vt = VT_I2;
645
+ aPropVar[props.cProp].iVal = (SHORT)pAttrs->iBasePriority;
646
+ props.cProp++;
647
+ }
648
+
649
+ if (MSI_NULL_INTEGER != pAttrs->iJournalQuota)
650
+ {
651
+ aPropID[props.cProp] = PROPID_Q_JOURNAL_QUOTA;
652
+ aPropVar[props.cProp].vt = VT_UI4;
653
+ aPropVar[props.cProp].ulVal = (ULONG)pAttrs->iJournalQuota;
654
+ props.cProp++;
655
+ }
656
+
657
+ if (*pAttrs->pwzMulticastAddress)
658
+ {
659
+ aPropID[props.cProp] = PROPID_Q_MULTICAST_ADDRESS;
660
+ aPropVar[props.cProp].vt = VT_LPWSTR;
661
+ aPropVar[props.cProp].pwszVal = pAttrs->pwzMulticastAddress;
662
+ props.cProp++;
663
+ }
664
+
665
+ if (MSI_NULL_INTEGER != pAttrs->iPrivLevel)
666
+ {
667
+ aPropID[props.cProp] = PROPID_Q_PRIV_LEVEL;
668
+ aPropVar[props.cProp].vt = VT_UI4;
669
+ switch (pAttrs->iPrivLevel)
670
+ {
671
+ case mqplNone:
672
+ aPropVar[props.cProp].ulVal = MQ_PRIV_LEVEL_NONE;
673
+ break;
674
+ case mqplBody:
675
+ aPropVar[props.cProp].ulVal = MQ_PRIV_LEVEL_BODY;
676
+ break;
677
+ case mqplOptional:
678
+ aPropVar[props.cProp].ulVal = MQ_PRIV_LEVEL_OPTIONAL;
679
+ break;
680
+ }
681
+ props.cProp++;
682
+ }
683
+
684
+ if (MSI_NULL_INTEGER != pAttrs->iQuota)
685
+ {
686
+ aPropID[props.cProp] = PROPID_Q_QUOTA;
687
+ aPropVar[props.cProp].vt = VT_UI4;
688
+ aPropVar[props.cProp].ulVal = (ULONG)pAttrs->iQuota;
689
+ props.cProp++;
690
+ }
691
+
692
+ if (*pAttrs->pwzServiceTypeGuid)
693
+ {
694
+ // parse guid string
695
+ hr = PcaGuidFromString(pAttrs->pwzServiceTypeGuid, &guidType);
696
+ ExitOnFailure(hr, "Failed to parse service type GUID string");
697
+
698
+ aPropID[props.cProp] = PROPID_Q_TYPE;
699
+ aPropVar[props.cProp].vt = VT_CLSID;
700
+ aPropVar[props.cProp].puuid = &guidType;
701
+ props.cProp++;
702
+ }
703
+
704
+ // create message queue
705
+ hr = gpfnMQCreateQueue(&sd, &props, NULL, &dwFormatNameLength);
706
+ ExitOnFailure(hr, "Failed to create message queue");
707
+
708
+ // log
709
+ WcaLog(LOGMSG_VERBOSE, "Message queue created, key: %S, PathName: '%S'", pAttrs->pwzKey, pAttrs->pwzPathName);
710
+
711
+ hr = S_OK;
712
+
713
+LExit:
714
+ // clean up
715
+ if (pOwner)
716
+ ::HeapFree(::GetProcessHeap(), 0, pOwner);
717
+ if (pDacl)
718
+ ::HeapFree(::GetProcessHeap(), 0, pDacl);
719
+
720
+ return hr;
721
+}
722
+
723
+static HRESULT DeleteMessageQueue(
724
+ MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
725
+ )
726
+{
727
+ HRESULT hr = S_OK;
728
+
729
+ LPWSTR pwzFormatName = NULL;
730
+ DWORD dwCount = 128;
731
+
732
+ // get format name
733
+ hr = StrAlloc(&pwzFormatName, dwCount);
734
+ ExitOnFailure(hr, "Failed to allocate format name string");
735
+ do {
736
+ hr = gpfnMQPathNameToFormatName(pAttrs->pwzPathName, pwzFormatName, &dwCount);
737
+ switch (hr)
738
+ {
739
+ case MQ_ERROR_QUEUE_NOT_FOUND:
740
+ ExitFunction1(hr = S_OK); // nothing to delete
741
+ case MQ_ERROR_FORMATNAME_BUFFER_TOO_SMALL:
742
+ hr = StrAlloc(&pwzFormatName, dwCount);
743
+ ExitOnFailure(hr, "Failed to reallocate format name string");
744
+ hr = S_FALSE; // retry
745
+ break;
746
+ default:
747
+ ExitOnFailure(hr, "Failed to get format name");
748
+ hr = S_OK;
749
+ }
750
+ } while (S_FALSE == hr);
751
+
752
+ // delete queue
753
+ hr = gpfnMQDeleteQueue(pwzFormatName);
754
+ ExitOnFailure(hr, "Failed to delete queue");
755
+
756
+ // log
757
+ WcaLog(LOGMSG_VERBOSE, "Message queue deleted, key: %S, PathName: '%S'", pAttrs->pwzKey, pAttrs->pwzPathName);
758
+
759
+ hr = S_OK;
760
+
761
+LExit:
762
+ // clean up
763
+ ReleaseStr(pwzFormatName);
764
+
765
+ return hr;
766
+}
767
+
768
+static HRESULT SetMessageQueuePermissions(
769
+ MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs,
770
+ BOOL fRevoke
771
+ )
772
+{
773
+ HRESULT hr = S_OK;
774
+ DWORD er = ERROR_SUCCESS;
775
+
776
+ DWORD dw = 0;
777
+
778
+ LPWSTR pwzAccount = NULL;
779
+ LPWSTR pwzFormatName = NULL;
780
+
781
+ PSECURITY_DESCRIPTOR psd = NULL;
782
+ PSECURITY_DESCRIPTOR ptsd = NULL;
783
+
784
+ PACL pAclExisting = NULL;
785
+ PACL pAclNew = NULL;
786
+ BOOL fDaclPresent = FALSE;
787
+ BOOL fDaclDefaulted = FALSE;
788
+
789
+ PSID psid = NULL;
790
+
791
+ EXPLICIT_ACCESSW ea;
792
+ SECURITY_DESCRIPTOR sdNew;
793
+
794
+ ::ZeroMemory(&ea, sizeof(ea));
795
+ ::ZeroMemory(&sdNew, sizeof(sdNew));
796
+
797
+ // get format name
798
+ dw = 128;
799
+ hr = StrAlloc(&pwzFormatName, dw);
800
+ ExitOnFailure(hr, "Failed to allocate format name string");
801
+ do {
802
+ hr = gpfnMQPathNameToFormatName(pAttrs->pwzPathName, pwzFormatName, &dw);
803
+ if (MQ_ERROR_FORMATNAME_BUFFER_TOO_SMALL == hr)
804
+ {
805
+ hr = StrAlloc(&pwzFormatName, dw);
806
+ ExitOnFailure(hr, "Failed to reallocate format name string");
807
+ hr = S_FALSE; // retry
808
+ }
809
+ else
810
+ {
811
+ ExitOnFailure(hr, "Failed to get format name");
812
+ hr = S_OK;
813
+ }
814
+ } while (S_FALSE == hr);
815
+
816
+ // get queue security information
817
+ dw = 256;
818
+ psd = (PSECURITY_DESCRIPTOR)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dw);
819
+ ExitOnNull(psd, hr, E_OUTOFMEMORY, "Failed to allocate buffer for security descriptor");
820
+ do {
821
+ hr = gpfnMQGetQueueSecurity(pwzFormatName, DACL_SECURITY_INFORMATION, psd, dw, &dw);
822
+ if (MQ_ERROR_SECURITY_DESCRIPTOR_TOO_SMALL == hr)
823
+ {
824
+ ptsd = (PSECURITY_DESCRIPTOR)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, psd, dw);
825
+ ExitOnNull(ptsd, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for security descriptor");
826
+ psd = ptsd;
827
+ hr = S_FALSE; // retry
828
+ }
829
+ else
830
+ {
831
+ ExitOnFailure(hr, "Failed to get queue security information");
832
+ hr = S_OK;
833
+ }
834
+ } while (S_FALSE == hr);
835
+
836
+ // get dacl
837
+ if (!::GetSecurityDescriptorDacl(psd, &fDaclPresent, &pAclExisting, &fDaclDefaulted))
838
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get DACL for security descriptor");
839
+ if (!fDaclPresent || !pAclExisting)
840
+ ExitOnFailure(hr = E_ACCESSDENIED, "Failed to get DACL for security descriptor, access denied");
841
+
842
+ // build account name string
843
+ hr = PcaBuildAccountName(pAttrs->pwzDomain, pAttrs->pwzName, &pwzAccount);
844
+ ExitOnFailure(hr, "Failed to build account name string");
845
+
846
+ // get sid for account name
847
+ hr = PcaAccountNameToSid(pwzAccount, &psid);
848
+ ExitOnFailure(hr, "Failed to get SID for account name");
849
+
850
+ // set acl entry
851
+ SetAccessPermissions(pAttrs->iPermissions, &ea.grfAccessPermissions);
852
+ ea.grfAccessMode = fRevoke ? REVOKE_ACCESS : SET_ACCESS;
853
+ ea.grfInheritance = NO_INHERITANCE;
854
+ ::BuildTrusteeWithSidW(&ea.Trustee, psid);
855
+
856
+ er = ::SetEntriesInAclW(1, &ea, pAclExisting, &pAclNew);
857
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set ACL entry");
858
+
859
+ // create new security descriptor
860
+ if (!::InitializeSecurityDescriptor(&sdNew, SECURITY_DESCRIPTOR_REVISION))
861
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to initialize security descriptor");
862
+
863
+ if (!::SetSecurityDescriptorDacl(&sdNew, TRUE, pAclNew, FALSE))
864
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to set DACL for security descriptor");
865
+
866
+ // set queue security information
867
+ hr = gpfnMQSetQueueSecurity(pwzFormatName, DACL_SECURITY_INFORMATION, &sdNew);
868
+ ExitOnFailure(hr, "Failed to set queue security information");
869
+
870
+ // log
871
+ WcaLog(LOGMSG_VERBOSE, "Permission set for message queue, key: %S, PathName: '%S'", pAttrs->pwzKey, pAttrs->pwzPathName);
872
+
873
+ hr = S_OK;
874
+
875
+LExit:
876
+ // clean up
877
+ ReleaseStr(pwzFormatName);
878
+ ReleaseStr(pwzAccount);
879
+
880
+ if (psd)
881
+ ::HeapFree(::GetProcessHeap(), 0, psd);
882
+ if (psid)
883
+ ::HeapFree(::GetProcessHeap(), 0, psid);
884
+ if (pAclNew)
885
+ ::LocalFree(pAclNew);
886
+
887
+ return hr;
888
+}
889
+
890
+static void SetAccessPermissions(
891
+ int iPermissions,
892
+ LPDWORD pgrfAccessPermissions
893
+ )
894
+{
895
+ if (iPermissions & mqpDeleteMessage)
896
+ *pgrfAccessPermissions |= MQSEC_DELETE_MESSAGE;
897
+ if (iPermissions & mqpPeekMessage)
898
+ *pgrfAccessPermissions |= MQSEC_PEEK_MESSAGE;
899
+ if (iPermissions & mqpWriteMessage)
900
+ *pgrfAccessPermissions |= MQSEC_WRITE_MESSAGE;
901
+ if (iPermissions & mqpDeleteJournalMessage)
902
+ *pgrfAccessPermissions |= MQSEC_DELETE_JOURNAL_MESSAGE;
903
+ if (iPermissions & mqpSetQueueProperties)
904
+ *pgrfAccessPermissions |= MQSEC_SET_QUEUE_PROPERTIES;
905
+ if (iPermissions & mqpGetQueueProperties)
906
+ *pgrfAccessPermissions |= MQSEC_GET_QUEUE_PROPERTIES;
907
+ if (iPermissions & mqpDeleteQueue)
908
+ *pgrfAccessPermissions |= MQSEC_DELETE_QUEUE;
909
+ if (iPermissions & mqpGetQueuePermissions)
910
+ *pgrfAccessPermissions |= MQSEC_GET_QUEUE_PERMISSIONS;
911
+ if (iPermissions & mqpChangeQueuePermissions)
912
+ *pgrfAccessPermissions |= MQSEC_CHANGE_QUEUE_PERMISSIONS;
913
+ if (iPermissions & mqpTakeQueueOwnership)
914
+ *pgrfAccessPermissions |= MQSEC_TAKE_QUEUE_OWNERSHIP;
915
+ if (iPermissions & mqpReceiveMessage)
916
+ *pgrfAccessPermissions |= MQSEC_RECEIVE_MESSAGE;
917
+ if (iPermissions & mqpReceiveJournalMessage)
918
+ *pgrfAccessPermissions |= MQSEC_RECEIVE_JOURNAL_MESSAGE;
919
+ if (iPermissions & mqpQueueGenericRead)
920
+ *pgrfAccessPermissions |= MQSEC_QUEUE_GENERIC_READ;
921
+ if (iPermissions & mqpQueueGenericWrite)
922
+ *pgrfAccessPermissions |= MQSEC_QUEUE_GENERIC_WRITE;
923
+ if (iPermissions & mqpQueueGenericExecute)
924
+ *pgrfAccessPermissions |= MQSEC_QUEUE_GENERIC_EXECUTE;
925
+ if (iPermissions & mqpQueueGenericAll)
926
+ *pgrfAccessPermissions |= MQSEC_QUEUE_GENERIC_ALL;
927
+}
src/ca/mqqueueexec.h
new
+30
@@ -0,0 +1,30 @@
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
+HRESULT MqiInitialize();
6
+void MqiUninitialize();
7
+HRESULT MqiCreateMessageQueues(
8
+ LPWSTR* ppwzData
9
+ );
10
+HRESULT MqiRollbackCreateMessageQueues(
11
+ LPWSTR* ppwzData
12
+ );
13
+HRESULT MqiDeleteMessageQueues(
14
+ LPWSTR* ppwzData
15
+ );
16
+HRESULT MqiRollbackDeleteMessageQueues(
17
+ LPWSTR* ppwzData
18
+ );
19
+HRESULT MqiAddMessageQueuePermissions(
20
+ LPWSTR* ppwzData
21
+ );
22
+HRESULT MqiRollbackAddMessageQueuePermissions(
23
+ LPWSTR* ppwzData
24
+ );
25
+HRESULT MqiRemoveMessageQueuePermissions(
26
+ LPWSTR* ppwzData
27
+ );
28
+HRESULT MqiRollbackRemoveMessageQueuePermissions(
29
+ LPWSTR* ppwzData
30
+ );
src/ca/mqqueuesched.cpp
new
+582
@@ -0,0 +1,582 @@
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
+// sql queries
7
+
8
+LPCWSTR vcsMessageQueueQuery =
9
+ L"SELECT `MessageQueue`, `Component_`, `BasePriority`, `JournalQuota`, `Label`, `MulticastAddress`, `PathName`, `PrivLevel`, `Quota`, `ServiceTypeGuid`, `Attributes` FROM `MessageQueue`";
10
+enum eMessageQueueQuery { mqqMessageQueue = 1, mqqComponent, mqqBasePriority, mqqJournalQuota, mqqLabel, mqqMulticastAddress, mqqPathName, mqqPrivLevel, mqqQuota, mqqServiceTypeGuid, mqqAttributes };
11
+
12
+LPCWSTR vcsMessageQueueUserPermissionQuery =
13
+ L"SELECT `MessageQueueUserPermission`, `MessageQueue_`, `MessageQueueUserPermission`.`Component_`, `Domain`, `Name`, `Permissions` FROM `MessageQueueUserPermission`, `User` WHERE `User_` = `User`";
14
+LPCWSTR vcsMessageQueueGroupPermissionQuery =
15
+ L"SELECT `MessageQueueGroupPermission`, `MessageQueue_`, `MessageQueueGroupPermission`.`Component_`, `Domain`, `Name`, `Permissions` FROM `MessageQueueGroupPermission`, `Group` WHERE `Group_` = `Group`";
16
+enum eMessageQueuePermissionQuery { mqpqMessageQueuePermission = 1, mqpqMessageQueue, mqpqComponent, mqpqDomain, mqpqName, mqpqPermissions };
17
+
18
+
19
+// prototypes for private helper functions
20
+
21
+static HRESULT MqiMessageQueueFindByKey(
22
+ MQI_MESSAGE_QUEUE_LIST* pList,
23
+ LPCWSTR pwzKey,
24
+ MQI_MESSAGE_QUEUE** ppItm
25
+ );
26
+static HRESULT AddMessageQueueToActionData(
27
+ MQI_MESSAGE_QUEUE* pItm,
28
+ LPWSTR* ppwzActionData
29
+ );
30
+static HRESULT MessageQueueTrusteePermissionsRead(
31
+ LPCWSTR pwzQuery,
32
+ MQI_MESSAGE_QUEUE_LIST* pMessageQueueList,
33
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
34
+ );
35
+static HRESULT AddMessageQueuePermissionToActionData(
36
+ MQI_MESSAGE_QUEUE_PERMISSION* pItm,
37
+ LPWSTR* ppwzActionData
38
+ );
39
+
40
+
41
+// private typedefs
42
+
43
+typedef HRESULT (__stdcall *MQPathNameToFormatNameFunc)(LPCWSTR, LPWSTR, LPDWORD);
44
+
45
+
46
+// private variables
47
+
48
+static HMODULE ghMQRT;
49
+static MQPathNameToFormatNameFunc gpfnMQPathNameToFormatName;
50
+
51
+
52
+// function definitions
53
+
54
+HRESULT MqiInitialize()
55
+{
56
+ HRESULT hr = S_OK;
57
+
58
+ // load mqrt.dll
59
+ ghMQRT = ::LoadLibraryW(L"mqrt.dll");
60
+ if (!ghMQRT)
61
+ {
62
+ ExitFunction1(hr = S_FALSE);
63
+ }
64
+
65
+ // get MQPathNameToFormatName function address
66
+ gpfnMQPathNameToFormatName = (MQPathNameToFormatNameFunc)::GetProcAddress(ghMQRT, "MQPathNameToFormatName");
67
+ ExitOnNullWithLastError(gpfnMQPathNameToFormatName, hr, "Failed get address for MQPathNameToFormatName() function");
68
+
69
+ hr = S_OK;
70
+
71
+LExit:
72
+ return hr;
73
+}
74
+
75
+void MqiUninitialize()
76
+{
77
+ if (ghMQRT)
78
+ {
79
+ ::FreeLibrary(ghMQRT);
80
+ }
81
+}
82
+
83
+HRESULT MqiMessageQueueRead(
84
+ MQI_MESSAGE_QUEUE_LIST* pList
85
+ )
86
+{
87
+ HRESULT hr = S_OK;
88
+ UINT er = ERROR_SUCCESS;
89
+
90
+ PMSIHANDLE hView, hRec;
91
+
92
+ MQI_MESSAGE_QUEUE* pItm = NULL;
93
+ LPWSTR pwzData = NULL;
94
+
95
+ // loop through all partitions
96
+ hr = WcaOpenExecuteView(vcsMessageQueueQuery, &hView);
97
+ ExitOnFailure(hr, "Failed to execute view on MessageQueue table");
98
+
99
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
100
+ {
101
+ // create entry
102
+ pItm = (MQI_MESSAGE_QUEUE*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MQI_MESSAGE_QUEUE));
103
+ if (!pItm)
104
+ ExitFunction1(hr = E_OUTOFMEMORY);
105
+
106
+ // get key
107
+ hr = WcaGetRecordString(hRec, mqqMessageQueue, &pwzData);
108
+ ExitOnFailure(hr, "Failed to get key");
109
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
110
+
111
+ // get component install state
112
+ hr = WcaGetRecordString(hRec, mqqComponent, &pwzData);
113
+ ExitOnFailure(hr, "Failed to get component");
114
+
115
+ // get component install state
116
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
117
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
118
+
119
+ // get base priority
120
+ hr = WcaGetRecordInteger(hRec, mqqBasePriority, &pItm->iBasePriority);
121
+ ExitOnFailure(hr, "Failed to get base priority");
122
+
123
+ // get journal quota
124
+ hr = WcaGetRecordInteger(hRec, mqqJournalQuota, &pItm->iJournalQuota);
125
+ ExitOnFailure(hr, "Failed to get journal quota");
126
+
127
+ // get label
128
+ hr = WcaGetRecordFormattedString(hRec, mqqLabel, &pwzData);
129
+ ExitOnFailure(hr, "Failed to get label");
130
+ StringCchCopyW(pItm->wzLabel, countof(pItm->wzLabel), pwzData);
131
+
132
+ // get multicast address
133
+ hr = WcaGetRecordFormattedString(hRec, mqqMulticastAddress, &pwzData);
134
+ ExitOnFailure(hr, "Failed to get multicast address");
135
+ StringCchCopyW(pItm->wzMulticastAddress, countof(pItm->wzMulticastAddress), pwzData);
136
+
137
+ // get path name
138
+ hr = WcaGetRecordFormattedString(hRec, mqqPathName, &pwzData);
139
+ ExitOnFailure(hr, "Failed to get path name");
140
+ StringCchCopyW(pItm->wzPathName, countof(pItm->wzPathName), pwzData);
141
+
142
+ // get privacy level
143
+ hr = WcaGetRecordInteger(hRec, mqqPrivLevel, &pItm->iPrivLevel);
144
+ ExitOnFailure(hr, "Failed to get privacy level");
145
+
146
+ // get quota
147
+ hr = WcaGetRecordInteger(hRec, mqqQuota, &pItm->iQuota);
148
+ ExitOnFailure(hr, "Failed to get quota");
149
+
150
+ // get service type guid
151
+ hr = WcaGetRecordFormattedString(hRec, mqqServiceTypeGuid, &pwzData);
152
+ ExitOnFailure(hr, "Failed to get service type guid");
153
+ StringCchCopyW(pItm->wzServiceTypeGuid, countof(pItm->wzServiceTypeGuid), pwzData);
154
+
155
+ // get attributes
156
+ hr = WcaGetRecordInteger(hRec, mqqAttributes, &pItm->iAttributes);
157
+ ExitOnFailure(hr, "Failed to get attributes");
158
+
159
+ // increment counters
160
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
161
+ pList->iInstallCount++;
162
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
163
+ pList->iUninstallCount++;
164
+
165
+ // add entry
166
+ pItm->pNext = pList->pFirst;
167
+ pList->pFirst = pItm;
168
+ pItm = NULL;
169
+ }
170
+
171
+ if (E_NOMOREITEMS == hr)
172
+ hr = S_OK;
173
+
174
+LExit:
175
+ // clean up
176
+ if (pItm)
177
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
178
+
179
+ ReleaseStr(pwzData);
180
+
181
+ return hr;
182
+}
183
+
184
+HRESULT MqiMessageQueueVerify(
185
+ MQI_MESSAGE_QUEUE_LIST* pList
186
+ )
187
+{
188
+ HRESULT hr = S_OK;
189
+ LPWSTR pwzFormatName = NULL;
190
+ DWORD dwCount = 128;
191
+
192
+ for (MQI_MESSAGE_QUEUE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
193
+ {
194
+ // queues that are being installed only
195
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
196
+ continue;
197
+
198
+ // get format name
199
+ hr = StrAlloc(&pwzFormatName, dwCount);
200
+ ExitOnFailure(hr, "Failed to allocate format name string");
201
+ do {
202
+ hr = gpfnMQPathNameToFormatName(pItm->wzPathName, pwzFormatName, &dwCount);
203
+ switch (hr)
204
+ {
205
+ case MQ_ERROR_QUEUE_NOT_FOUND:
206
+ break; // break
207
+ case MQ_ERROR_FORMATNAME_BUFFER_TOO_SMALL:
208
+ hr = StrAlloc(&pwzFormatName, dwCount);
209
+ ExitOnFailure(hr, "Failed to reallocate format name string");
210
+ hr = S_FALSE; // retry
211
+ break;
212
+ default:
213
+ ExitOnFailure(hr, "Failed to get format name");
214
+ hr = S_OK;
215
+ }
216
+ } while (S_FALSE == hr);
217
+
218
+ if (MQ_ERROR_QUEUE_NOT_FOUND == hr)
219
+ {
220
+ continue;
221
+ }
222
+ pItm->fExists = TRUE;
223
+ pList->iInstallCount--;
224
+
225
+ // clean up
226
+ ReleaseNullStr(pwzFormatName);
227
+ }
228
+
229
+ hr = S_OK;
230
+
231
+LExit:
232
+ ReleaseStr(pwzFormatName);
233
+ return hr;
234
+}
235
+
236
+HRESULT MqiMessageQueueInstall(
237
+ MQI_MESSAGE_QUEUE_LIST* pList,
238
+ BOOL fRollback,
239
+ LPWSTR* ppwzActionData
240
+ )
241
+{
242
+ HRESULT hr = S_OK;
243
+
244
+ // add count to action data
245
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
246
+ ExitOnFailure(hr, "Failed to add count to custom action data");
247
+
248
+ for (MQI_MESSAGE_QUEUE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
249
+ {
250
+ // queues that are being installed only
251
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
252
+ continue;
253
+
254
+ // if the queue exists we should not try to create it
255
+ if (pItm->fExists && !fRollback)
256
+ {
257
+ continue;
258
+ }
259
+
260
+ // add message queue to action data
261
+ hr = AddMessageQueueToActionData(pItm, ppwzActionData);
262
+ ExitOnFailure(hr, "Failed to add message queue to action data");
263
+ }
264
+
265
+ hr = S_OK;
266
+
267
+LExit:
268
+ return hr;
269
+}
270
+
271
+HRESULT MqiMessageQueueUninstall(
272
+ MQI_MESSAGE_QUEUE_LIST* pList,
273
+ BOOL fRollback,
274
+ LPWSTR* ppwzActionData
275
+ )
276
+{
277
+ HRESULT hr = S_OK;
278
+
279
+ // add count to action data
280
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
281
+ ExitOnFailure(hr, "Failed to add count to custom action data");
282
+
283
+ for (MQI_MESSAGE_QUEUE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
284
+ {
285
+ // queues that are being uninstalled only
286
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
287
+ continue;
288
+
289
+ // if we did not create the queue we should not try to delete it
290
+ if (pItm->fExists && fRollback)
291
+ {
292
+ continue;
293
+ }
294
+
295
+ // add message queue to action data
296
+ hr = AddMessageQueueToActionData(pItm, ppwzActionData);
297
+ ExitOnFailure(hr, "Failed to add message queue to action data");
298
+ }
299
+
300
+ hr = S_OK;
301
+
302
+LExit:
303
+ return hr;
304
+}
305
+
306
+void MqiMessageQueueFreeList(
307
+ MQI_MESSAGE_QUEUE_LIST* pList
308
+ )
309
+{
310
+ MQI_MESSAGE_QUEUE* pItm = pList->pFirst;
311
+ while (pItm)
312
+ {
313
+ MQI_MESSAGE_QUEUE* pDelete = pItm;
314
+ pItm = pItm->pNext;
315
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
316
+ }
317
+}
318
+
319
+HRESULT MqiMessageQueuePermissionRead(
320
+ MQI_MESSAGE_QUEUE_LIST* pMessageQueueList,
321
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
322
+ )
323
+{
324
+ HRESULT hr = S_OK;
325
+
326
+ // read message queue user permissions
327
+ if (S_OK == WcaTableExists(L"MessageQueueUserPermission"))
328
+ {
329
+ hr = MessageQueueTrusteePermissionsRead(vcsMessageQueueUserPermissionQuery, pMessageQueueList, pList);
330
+ ExitOnFailure(hr, "Failed to read message queue user permissions");
331
+ }
332
+
333
+ // read message queue group permissions
334
+ if (S_OK == WcaTableExists(L"MessageQueueGroupPermission"))
335
+ {
336
+ hr = MessageQueueTrusteePermissionsRead(vcsMessageQueueGroupPermissionQuery, pMessageQueueList, pList);
337
+ ExitOnFailure(hr, "Failed to read message queue group permissions");
338
+ }
339
+
340
+ hr = S_OK;
341
+
342
+LExit:
343
+ return hr;
344
+}
345
+
346
+HRESULT MqiMessageQueuePermissionInstall(
347
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList,
348
+ LPWSTR* ppwzActionData
349
+ )
350
+{
351
+ HRESULT hr = S_OK;
352
+
353
+ // add count to action data
354
+ hr = WcaWriteIntegerToCaData(pList->iInstallCount, ppwzActionData);
355
+ ExitOnFailure(hr, "Failed to add count to custom action data");
356
+
357
+ for (MQI_MESSAGE_QUEUE_PERMISSION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
358
+ {
359
+ // queue permissions that are being installed only
360
+ if (!WcaIsInstalling(pItm->isInstalled, pItm->isAction))
361
+ continue;
362
+
363
+ // add message queue permission to action data
364
+ hr = AddMessageQueuePermissionToActionData(pItm, ppwzActionData);
365
+ ExitOnFailure(hr, "Failed to add message queue permission to action data");
366
+ }
367
+
368
+ hr = S_OK;
369
+
370
+LExit:
371
+ return hr;
372
+}
373
+
374
+HRESULT MqiMessageQueuePermissionUninstall(
375
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList,
376
+ LPWSTR* ppwzActionData
377
+ )
378
+{
379
+ HRESULT hr = S_OK;
380
+
381
+ // add count to action data
382
+ hr = WcaWriteIntegerToCaData(pList->iUninstallCount, ppwzActionData);
383
+ ExitOnFailure(hr, "Failed to add count to custom action data");
384
+
385
+ for (MQI_MESSAGE_QUEUE_PERMISSION* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
386
+ {
387
+ // queue permissions that are being uninstalled only
388
+ if (!WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
389
+ continue;
390
+
391
+ // add message queue permission to action data
392
+ hr = AddMessageQueuePermissionToActionData(pItm, ppwzActionData);
393
+ ExitOnFailure(hr, "Failed to add message queue permission to action data");
394
+ }
395
+
396
+ hr = S_OK;
397
+
398
+LExit:
399
+ return hr;
400
+}
401
+
402
+void MqiMessageQueuePermissionFreeList(
403
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
404
+ )
405
+{
406
+ MQI_MESSAGE_QUEUE_PERMISSION* pItm = pList->pFirst;
407
+ while (pItm)
408
+ {
409
+ MQI_MESSAGE_QUEUE_PERMISSION* pDelete = pItm;
410
+ pItm = pItm->pNext;
411
+ ::HeapFree(::GetProcessHeap(), 0, pDelete);
412
+ }
413
+}
414
+
415
+
416
+// helper function definitions
417
+
418
+static HRESULT MqiMessageQueueFindByKey(
419
+ MQI_MESSAGE_QUEUE_LIST* pList,
420
+ LPCWSTR pwzKey,
421
+ MQI_MESSAGE_QUEUE** ppItm
422
+ )
423
+{
424
+ for (MQI_MESSAGE_QUEUE* pItm = pList->pFirst; pItm; pItm = pItm->pNext)
425
+ {
426
+ if (0 == lstrcmpW(pItm->wzKey, pwzKey))
427
+ {
428
+ *ppItm = pItm;
429
+ return S_OK;
430
+ }
431
+ }
432
+
433
+ return S_FALSE;
434
+}
435
+
436
+static HRESULT AddMessageQueueToActionData(
437
+ MQI_MESSAGE_QUEUE* pItm,
438
+ LPWSTR* ppwzActionData
439
+ )
440
+{
441
+ HRESULT hr = S_OK;
442
+
443
+ // add message queue information to custom action data
444
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
445
+ ExitOnFailure(hr, "Failed to add key to custom action data");
446
+ hr = WcaWriteIntegerToCaData(pItm->iBasePriority, ppwzActionData);
447
+ ExitOnFailure(hr, "Failed to add base priority to custom action data");
448
+ hr = WcaWriteIntegerToCaData(pItm->iJournalQuota, ppwzActionData);
449
+ ExitOnFailure(hr, "Failed to add journal quota to custom action data");
450
+ hr = WcaWriteStringToCaData(pItm->wzLabel, ppwzActionData);
451
+ ExitOnFailure(hr, "Failed to add label to custom action data");
452
+ hr = WcaWriteStringToCaData(pItm->wzMulticastAddress, ppwzActionData);
453
+ ExitOnFailure(hr, "Failed to add multicast address to custom action data");
454
+ hr = WcaWriteStringToCaData(pItm->wzPathName, ppwzActionData);
455
+ ExitOnFailure(hr, "Failed to add path name to custom action data");
456
+ hr = WcaWriteIntegerToCaData(pItm->iPrivLevel, ppwzActionData);
457
+ ExitOnFailure(hr, "Failed to add privacy level to custom action data");
458
+ hr = WcaWriteIntegerToCaData(pItm->iQuota, ppwzActionData);
459
+ ExitOnFailure(hr, "Failed to add quota to custom action data");
460
+ hr = WcaWriteStringToCaData(pItm->wzServiceTypeGuid, ppwzActionData);
461
+ ExitOnFailure(hr, "Failed to add service type guid to custom action data");
462
+ hr = WcaWriteIntegerToCaData(pItm->iAttributes, ppwzActionData);
463
+ ExitOnFailure(hr, "Failed to add attributes to custom action data");
464
+
465
+ hr = S_OK;
466
+
467
+LExit:
468
+ return hr;
469
+}
470
+
471
+static HRESULT MessageQueueTrusteePermissionsRead(
472
+ LPCWSTR pwzQuery,
473
+ MQI_MESSAGE_QUEUE_LIST* pMessageQueueList,
474
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
475
+ )
476
+{
477
+ HRESULT hr = S_OK;
478
+ UINT er = ERROR_SUCCESS;
479
+
480
+ PMSIHANDLE hView, hRec;
481
+
482
+ LPWSTR pwzData = NULL;
483
+
484
+ MQI_MESSAGE_QUEUE_PERMISSION* pItm = NULL;
485
+
486
+ // loop through all application roles
487
+ hr = WcaOpenExecuteView(pwzQuery, &hView);
488
+ ExitOnFailure(hr, "Failed to execute view on table");
489
+
490
+ while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
491
+ {
492
+ // create entry
493
+ pItm = (MQI_MESSAGE_QUEUE_PERMISSION*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MQI_MESSAGE_QUEUE_PERMISSION));
494
+ if (!pItm)
495
+ ExitFunction1(hr = E_OUTOFMEMORY);
496
+
497
+ // get key
498
+ hr = WcaGetRecordString(hRec, mqpqMessageQueuePermission, &pwzData);
499
+ ExitOnFailure(hr, "Failed to get key");
500
+ StringCchCopyW(pItm->wzKey, countof(pItm->wzKey), pwzData);
501
+
502
+ // get component
503
+ hr = WcaGetRecordString(hRec, mqpqComponent, &pwzData);
504
+ ExitOnFailure(hr, "Failed to get component");
505
+
506
+ // get component install state
507
+ er = ::MsiGetComponentStateW(WcaGetInstallHandle(), pwzData, &pItm->isInstalled, &pItm->isAction);
508
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to get component state");
509
+
510
+ // get message queue
511
+ hr = WcaGetRecordString(hRec, mqpqMessageQueue, &pwzData);
512
+ ExitOnFailure(hr, "Failed to get application role");
513
+
514
+ hr = MqiMessageQueueFindByKey(pMessageQueueList, pwzData, &pItm->pMessageQueue);
515
+ if (S_FALSE == hr)
516
+ hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
517
+ ExitOnFailure(hr, "Failed to find message queue, key: %S", pwzData);
518
+
519
+ // get user domain
520
+ hr = WcaGetRecordFormattedString(hRec, mqpqDomain, &pwzData);
521
+ ExitOnFailure(hr, "Failed to get domain");
522
+ StringCchCopyW(pItm->wzDomain, countof(pItm->wzDomain), pwzData);
523
+
524
+ // get user name
525
+ hr = WcaGetRecordFormattedString(hRec, mqpqName, &pwzData);
526
+ ExitOnFailure(hr, "Failed to get name");
527
+ StringCchCopyW(pItm->wzName, countof(pItm->wzName), pwzData);
528
+
529
+ // get permissions
530
+ hr = WcaGetRecordInteger(hRec, mqpqPermissions, &pItm->iPermissions);
531
+ ExitOnFailure(hr, "Failed to get permissions");
532
+
533
+ // set references & increment counters
534
+ if (WcaIsInstalling(pItm->isInstalled, pItm->isAction))
535
+ pList->iInstallCount++;
536
+ if (WcaIsUninstalling(pItm->isInstalled, pItm->isAction))
537
+ pList->iUninstallCount++;
538
+
539
+ // add entry
540
+ if (pList->pFirst)
541
+ pItm->pNext = pList->pFirst;
542
+ pList->pFirst = pItm;
543
+ pItm = NULL;
544
+ }
545
+
546
+ if (E_NOMOREITEMS == hr)
547
+ hr = S_OK;
548
+
549
+LExit:
550
+ // clean up
551
+ ReleaseStr(pwzData);
552
+
553
+ if (pItm)
554
+ ::HeapFree(::GetProcessHeap(), 0, pItm);
555
+
556
+ return hr;
557
+}
558
+
559
+static HRESULT AddMessageQueuePermissionToActionData(
560
+ MQI_MESSAGE_QUEUE_PERMISSION* pItm,
561
+ LPWSTR* ppwzActionData
562
+ )
563
+{
564
+ HRESULT hr = S_OK;
565
+
566
+ // add message queue information to custom action data
567
+ hr = WcaWriteStringToCaData(pItm->wzKey, ppwzActionData);
568
+ ExitOnFailure(hr, "Failed to add key to custom action data");
569
+ hr = WcaWriteStringToCaData(pItm->pMessageQueue->wzPathName, ppwzActionData);
570
+ ExitOnFailure(hr, "Failed to add path name to custom action data");
571
+ hr = WcaWriteStringToCaData(pItm->wzDomain, ppwzActionData);
572
+ ExitOnFailure(hr, "Failed to add domain to custom action data");
573
+ hr = WcaWriteStringToCaData(pItm->wzName, ppwzActionData);
574
+ ExitOnFailure(hr, "Failed to add name to custom action data");
575
+ hr = WcaWriteIntegerToCaData(pItm->iPermissions, ppwzActionData);
576
+ ExitOnFailure(hr, "Failed to add permissions to custom action data");
577
+
578
+ hr = S_OK;
579
+
580
+LExit:
581
+ return hr;
582
+}
src/ca/mqqueuesched.h
new
+92
@@ -0,0 +1,92 @@
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
+struct MQI_MESSAGE_QUEUE
6
+{
7
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
8
+ int iBasePriority;
9
+ int iJournalQuota;
10
+ WCHAR wzLabel[MAX_DARWIN_COLUMN + 1];
11
+ WCHAR wzMulticastAddress[MAX_DARWIN_COLUMN + 1];
12
+ WCHAR wzPathName[MAX_DARWIN_COLUMN + 1];
13
+ int iPrivLevel;
14
+ int iQuota;
15
+ WCHAR wzServiceTypeGuid[MAX_DARWIN_COLUMN + 1];
16
+ int iAttributes;
17
+
18
+ INSTALLSTATE isInstalled, isAction;
19
+ BOOL fExists;
20
+
21
+ MQI_MESSAGE_QUEUE* pNext;
22
+};
23
+
24
+struct MQI_MESSAGE_QUEUE_LIST
25
+{
26
+ MQI_MESSAGE_QUEUE* pFirst;
27
+
28
+ int iInstallCount;
29
+ int iUninstallCount;
30
+};
31
+
32
+struct MQI_MESSAGE_QUEUE_PERMISSION
33
+{
34
+ WCHAR wzKey[MAX_DARWIN_KEY + 1];
35
+ WCHAR wzDomain[MAX_DARWIN_COLUMN + 1];
36
+ WCHAR wzName[MAX_DARWIN_COLUMN + 1];
37
+ int iPermissions;
38
+
39
+ MQI_MESSAGE_QUEUE* pMessageQueue;
40
+
41
+ INSTALLSTATE isInstalled, isAction;
42
+
43
+ MQI_MESSAGE_QUEUE_PERMISSION* pNext;
44
+};
45
+
46
+struct MQI_MESSAGE_QUEUE_PERMISSION_LIST
47
+{
48
+ MQI_MESSAGE_QUEUE_PERMISSION* pFirst;
49
+
50
+ int iInstallCount;
51
+ int iUninstallCount;
52
+};
53
+
54
+
55
+// function prototypes
56
+
57
+HRESULT MqiInitialize();
58
+void MqiUninitialize();
59
+HRESULT MqiMessageQueueRead(
60
+ MQI_MESSAGE_QUEUE_LIST* pList
61
+ );
62
+HRESULT MqiMessageQueueVerify(
63
+ MQI_MESSAGE_QUEUE_LIST* pList
64
+ );
65
+HRESULT MqiMessageQueueInstall(
66
+ MQI_MESSAGE_QUEUE_LIST* pList,
67
+ BOOL fRollback,
68
+ LPWSTR* ppwzActionData
69
+ );
70
+HRESULT MqiMessageQueueUninstall(
71
+ MQI_MESSAGE_QUEUE_LIST* pList,
72
+ BOOL fRollback,
73
+ LPWSTR* ppwzActionData
74
+ );
75
+void MqiMessageQueueFreeList(
76
+ MQI_MESSAGE_QUEUE_LIST* pList
77
+ );
78
+HRESULT MqiMessageQueuePermissionRead(
79
+ MQI_MESSAGE_QUEUE_LIST* pMessageQueueList,
80
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
81
+ );
82
+HRESULT MqiMessageQueuePermissionInstall(
83
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList,
84
+ LPWSTR* ppwzActionData
85
+ );
86
+HRESULT MqiMessageQueuePermissionUninstall(
87
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList,
88
+ LPWSTR* ppwzActionData
89
+ );
90
+void MqiMessageQueuePermissionFreeList(
91
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST* pList
92
+ );
src/ca/mqsched.cpp
new
+219
@@ -0,0 +1,219 @@
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
+/********************************************************************
7
+ DllMain - standard entry point for all WiX CustomActions
8
+
9
+********************************************************************/
10
+extern "C" BOOL WINAPI DllMain(
11
+ IN HINSTANCE hInst,
12
+ IN ULONG ulReason,
13
+ IN LPVOID)
14
+{
15
+ switch(ulReason)
16
+ {
17
+ case DLL_PROCESS_ATTACH:
18
+ WcaGlobalInitialize(hInst);
19
+ break;
20
+
21
+ case DLL_PROCESS_DETACH:
22
+ WcaGlobalFinalize();
23
+ break;
24
+ }
25
+
26
+ return TRUE;
27
+}
28
+
29
+/********************************************************************
30
+ MessageQueuingInstall - CUSTOM ACTION ENTRY POINT for installing MSMQ message queues
31
+
32
+********************************************************************/
33
+extern "C" UINT __stdcall MessageQueuingInstall(MSIHANDLE hInstall)
34
+{
35
+ HRESULT hr = S_OK;
36
+ UINT er = ERROR_SUCCESS;
37
+
38
+ MQI_MESSAGE_QUEUE_LIST lstMessageQueues;
39
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST lstMessageQueuePermissions;
40
+
41
+ int iCost = 0;
42
+ LPWSTR pwzRollbackActionData = NULL;
43
+ LPWSTR pwzExecuteActionData = NULL;
44
+
45
+ ::ZeroMemory(&lstMessageQueues, sizeof(lstMessageQueues));
46
+ ::ZeroMemory(&lstMessageQueuePermissions, sizeof(lstMessageQueuePermissions));
47
+
48
+ // initialize
49
+ hr = WcaInitialize(hInstall, "MessageQueuingInstall");
50
+ ExitOnFailure(hr, "Failed to initialize");
51
+
52
+ do
53
+ {
54
+ hr = MqiInitialize();
55
+ if (S_FALSE == hr)
56
+ {
57
+ WcaLog(LOGMSG_STANDARD, "Failed to load mqrt.dll.");
58
+ er = WcaErrorMessage(msierrMsmqCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
59
+ switch (er)
60
+ {
61
+ case IDABORT:
62
+ ExitFunction1(hr = E_FAIL); // bail with error
63
+ case IDRETRY:
64
+ break; // retry
65
+ case IDIGNORE: __fallthrough;
66
+ default:
67
+ ExitFunction1(hr = S_OK); // pretend everything is okay and bail
68
+ }
69
+ }
70
+ ExitOnFailure(hr, "Failed to initialize MSMQ.");
71
+ } while (S_FALSE == hr);
72
+
73
+ // read message queues
74
+ hr = MqiMessageQueueRead(&lstMessageQueues);
75
+ ExitOnFailure(hr, "Failed to read MessageQueue table");
76
+
77
+ // read message queue permissions
78
+ hr = MqiMessageQueuePermissionRead(&lstMessageQueues, &lstMessageQueuePermissions);
79
+ ExitOnFailure(hr, "Failed to read message queue permissions");
80
+
81
+ // verify message queue elementes
82
+ hr = MqiMessageQueueVerify(&lstMessageQueues);
83
+ ExitOnFailure(hr, "Failed to verify message queue elements.");
84
+
85
+ if (lstMessageQueues.iInstallCount || lstMessageQueuePermissions.iInstallCount)
86
+ {
87
+ // schedule rollback action
88
+ hr = MqiMessageQueuePermissionInstall(&lstMessageQueuePermissions, &pwzRollbackActionData);
89
+ ExitOnFailure(hr, "Failed to add message queue permissions to rollback action data");
90
+
91
+ hr = MqiMessageQueueInstall(&lstMessageQueues, TRUE, &pwzRollbackActionData);
92
+ ExitOnFailure(hr, "Failed to add message queues to rollback action data");
93
+
94
+ hr = WcaDoDeferredAction(L"MessageQueuingRollbackInstall", pwzRollbackActionData, 0);
95
+ ExitOnFailure(hr, "Failed to schedule MessageQueuingRollbackInstall");
96
+
97
+ // schedule execute action
98
+ hr = MqiMessageQueueInstall(&lstMessageQueues, FALSE, &pwzExecuteActionData);
99
+ ExitOnFailure(hr, "Failed to add message queues to execute action data");
100
+ iCost += lstMessageQueues.iInstallCount * COST_MESSAGE_QUEUE_CREATE;
101
+
102
+ hr = MqiMessageQueuePermissionInstall(&lstMessageQueuePermissions, &pwzExecuteActionData);
103
+ ExitOnFailure(hr, "Failed to add message queue permissions to execute action data");
104
+ iCost += lstMessageQueues.iInstallCount * COST_MESSAGE_QUEUE_PERMISSION_ADD;
105
+
106
+ hr = WcaDoDeferredAction(L"MessageQueuingExecuteInstall", pwzExecuteActionData, iCost);
107
+ ExitOnFailure(hr, "Failed to schedule MessageQueuingExecuteInstall");
108
+ }
109
+
110
+ hr = S_OK;
111
+
112
+LExit:
113
+ // clean up
114
+ MqiMessageQueueFreeList(&lstMessageQueues);
115
+ MqiMessageQueuePermissionFreeList(&lstMessageQueuePermissions);
116
+
117
+ ReleaseStr(pwzRollbackActionData);
118
+ ReleaseStr(pwzExecuteActionData);
119
+
120
+ // uninitialize
121
+ MqiUninitialize();
122
+
123
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
124
+ return WcaFinalize(er);
125
+}
126
+
127
+
128
+/********************************************************************
129
+ MessageQueuingUninstall - CUSTOM ACTION ENTRY POINT for uninstalling MSMQ message queues
130
+
131
+********************************************************************/
132
+extern "C" UINT __stdcall MessageQueuingUninstall(MSIHANDLE hInstall)
133
+{
134
+ HRESULT hr = S_OK;
135
+ UINT er = ERROR_SUCCESS;
136
+
137
+ MQI_MESSAGE_QUEUE_LIST lstMessageQueues;
138
+ MQI_MESSAGE_QUEUE_PERMISSION_LIST lstMessageQueuePermissions;
139
+
140
+ int iCost = 0;
141
+ LPWSTR pwzRollbackActionData = NULL;
142
+ LPWSTR pwzExecuteActionData = NULL;
143
+
144
+ ::ZeroMemory(&lstMessageQueues, sizeof(lstMessageQueues));
145
+ ::ZeroMemory(&lstMessageQueuePermissions, sizeof(lstMessageQueuePermissions));
146
+
147
+ // initialize
148
+ hr = WcaInitialize(hInstall, "MessageQueuingUninstall");
149
+ ExitOnFailure(hr, "Failed to initialize");
150
+
151
+ do
152
+ {
153
+ hr = MqiInitialize();
154
+ if (S_FALSE == hr)
155
+ {
156
+ WcaLog(LOGMSG_STANDARD, "Failed to load mqrt.dll.");
157
+ er = WcaErrorMessage(msierrMsmqCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
158
+ switch (er)
159
+ {
160
+ case IDABORT:
161
+ ExitFunction1(hr = E_FAIL); // bail with error
162
+ case IDRETRY:
163
+ break; // retry
164
+ case IDIGNORE: __fallthrough;
165
+ default:
166
+ ExitFunction1(hr = S_OK); // pretend everything is okay and bail
167
+ }
168
+ }
169
+ ExitOnFailure(hr, "Failed to initialize MSMQ.");
170
+ } while (S_FALSE == hr);
171
+
172
+ // read message queues
173
+ hr = MqiMessageQueueRead(&lstMessageQueues);
174
+ ExitOnFailure(hr, "Failed to read MessageQueue table");
175
+
176
+ // read message queue permissions
177
+ hr = MqiMessageQueuePermissionRead(&lstMessageQueues, &lstMessageQueuePermissions);
178
+ ExitOnFailure(hr, "Failed to read message queue permissions");
179
+
180
+ if (lstMessageQueues.iUninstallCount || lstMessageQueuePermissions.iUninstallCount)
181
+ {
182
+ // schedule rollback action
183
+ hr = MqiMessageQueueUninstall(&lstMessageQueues, TRUE, &pwzRollbackActionData);
184
+ ExitOnFailure(hr, "Failed to add message queues to rollback action data");
185
+
186
+ hr = MqiMessageQueuePermissionUninstall(&lstMessageQueuePermissions, &pwzRollbackActionData);
187
+ ExitOnFailure(hr, "Failed to add message queue permissions to rollback action data");
188
+
189
+ hr = WcaDoDeferredAction(L"MessageQueuingRollbackUninstall", pwzRollbackActionData, 0);
190
+ ExitOnFailure(hr, "Failed to schedule MessageQueuingRollbackUninstall");
191
+
192
+ // schedule execute action
193
+ hr = MqiMessageQueuePermissionUninstall(&lstMessageQueuePermissions, &pwzExecuteActionData);
194
+ ExitOnFailure(hr, "Failed to add message queue permissions to execute action data");
195
+
196
+ hr = MqiMessageQueueUninstall(&lstMessageQueues, FALSE, &pwzExecuteActionData);
197
+ ExitOnFailure(hr, "Failed to add message queues to execute action data");
198
+ iCost += lstMessageQueues.iUninstallCount * COST_MESSAGE_QUEUE_DELETE;
199
+
200
+ hr = WcaDoDeferredAction(L"MessageQueuingExecuteUninstall", pwzExecuteActionData, iCost);
201
+ ExitOnFailure(hr, "Failed to schedule MessageQueuingExecuteUninstall");
202
+ }
203
+
204
+ hr = S_OK;
205
+
206
+LExit:
207
+ // clean up
208
+ MqiMessageQueueFreeList(&lstMessageQueues);
209
+ MqiMessageQueuePermissionFreeList(&lstMessageQueuePermissions);
210
+
211
+ ReleaseStr(pwzRollbackActionData);
212
+ ReleaseStr(pwzExecuteActionData);
213
+
214
+ // uninitialize
215
+ MqiUninitialize();
216
+
217
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
218
+ return WcaFinalize(er);
219
+}
src/ca/mqutilexec.cpp
new
+380
@@ -0,0 +1,380 @@
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
+// private structs
7
+
8
+struct PCA_WELLKNOWN_SID
9
+{
10
+ LPCWSTR pwzName;
11
+ SID_IDENTIFIER_AUTHORITY iaIdentifierAuthority;
12
+ BYTE nSubAuthorityCount;
13
+ DWORD dwSubAuthority[8];
14
+};
15
+
16
+
17
+// well known SIDs
18
+
19
+PCA_WELLKNOWN_SID wsWellKnownSids[] = {
20
+ {L"\\Everyone", SECURITY_WORLD_SID_AUTHORITY, 1, {SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0}},
21
+ {L"\\Administrators", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0}},
22
+ {L"\\LocalSystem", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0}},
23
+ {L"\\LocalService", SECURITY_NT_AUTHORITY, 1, {SECURITY_LOCAL_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}},
24
+ {L"\\NetworkService", SECURITY_NT_AUTHORITY, 1, {SECURITY_NETWORK_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0}},
25
+ {L"\\AuthenticatedUser", SECURITY_NT_AUTHORITY, 1, {SECURITY_AUTHENTICATED_USER_RID, 0, 0, 0, 0, 0, 0, 0}},
26
+ {L"\\Guests", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS, 0, 0, 0, 0, 0, 0}},
27
+ {L"\\Users", SECURITY_NT_AUTHORITY, 2, {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0}},
28
+ {L"\\CREATOR OWNER", SECURITY_NT_AUTHORITY, 1, {SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0}},
29
+ {NULL, SECURITY_NULL_SID_AUTHORITY, 0, {0, 0, 0, 0, 0, 0, 0, 0}}
30
+};
31
+
32
+
33
+// prototypes for private helper functions
34
+
35
+static HRESULT CreateSidFromDomainRidPair(
36
+ PSID pDomainSid,
37
+ DWORD dwRid,
38
+ PSID* ppSid
39
+ );
40
+static HRESULT InitLsaUnicodeString(
41
+ PLSA_UNICODE_STRING plusStr,
42
+ LPCWSTR pwzStr,
43
+ DWORD dwLen
44
+ );
45
+static void FreeLsaUnicodeString(
46
+ PLSA_UNICODE_STRING plusStr
47
+ );
48
+
49
+
50
+// function definitions
51
+
52
+HRESULT PcaActionDataMessage(
53
+ DWORD cArgs,
54
+ ...
55
+ )
56
+{
57
+ HRESULT hr = S_OK;
58
+ UINT er = ERROR_SUCCESS;
59
+
60
+ PMSIHANDLE hRec;
61
+ va_list args;
62
+
63
+ // record
64
+ hRec = ::MsiCreateRecord(cArgs);
65
+ ExitOnNull(hRec, hr, E_OUTOFMEMORY, "Failed to create record");
66
+
67
+ va_start(args, cArgs);
68
+ for (DWORD i = 1; i <= cArgs; i++)
69
+ {
70
+ LPCWSTR pwzArg = va_arg(args, WCHAR*);
71
+ if (pwzArg && *pwzArg)
72
+ {
73
+ er = ::MsiRecordSetStringW(hRec, i, pwzArg);
74
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to set record field string");
75
+ }
76
+ }
77
+ va_end(args);
78
+
79
+ // message
80
+ er = WcaProcessMessage(INSTALLMESSAGE_ACTIONDATA, hRec);
81
+ if (0 == er || IDOK == er || IDYES == er)
82
+ {
83
+ hr = S_OK;
84
+ }
85
+ else if (ERROR_INSTALL_USEREXIT == er || IDABORT == er || IDCANCEL == er)
86
+ {
87
+ WcaSetReturnValue(ERROR_INSTALL_USEREXIT); // note that the user said exit
88
+ hr = S_FALSE;
89
+ }
90
+ else
91
+ hr = E_UNEXPECTED;
92
+
93
+LExit:
94
+ return hr;
95
+}
96
+
97
+HRESULT PcaAccountNameToSid(
98
+ LPCWSTR pwzAccountName,
99
+ PSID* ppSid
100
+ )
101
+{
102
+ HRESULT hr = S_OK;
103
+ UINT er = ERROR_SUCCESS;
104
+ NTSTATUS st = 0;
105
+
106
+ PSID pSid = NULL;
107
+ LSA_OBJECT_ATTRIBUTES loaAttributes;
108
+ LSA_HANDLE lsahPolicy = NULL;
109
+ LSA_UNICODE_STRING lusName;
110
+ PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
111
+ PLSA_TRANSLATED_SID pltsSid = NULL;
112
+
113
+ ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
114
+ ::ZeroMemory(&lusName, sizeof(lusName));
115
+
116
+ // identify well known SIDs
117
+ for (PCA_WELLKNOWN_SID* pWS = wsWellKnownSids; pWS->pwzName; pWS++)
118
+ {
119
+ if (0 == lstrcmpiW(pwzAccountName, pWS->pwzName))
120
+ {
121
+ // allocate SID buffer
122
+ pSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, ::GetSidLengthRequired(pWS->nSubAuthorityCount));
123
+ ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID");
124
+
125
+ // initialize SID
126
+ ::InitializeSid(pSid, &pWS->iaIdentifierAuthority, pWS->nSubAuthorityCount);
127
+
128
+ // copy sub autorities
129
+ for (DWORD i = 0; i < pWS->nSubAuthorityCount; i++)
130
+ *::GetSidSubAuthority(pSid, i) = pWS->dwSubAuthority[i];
131
+
132
+ break;
133
+ }
134
+ }
135
+
136
+ // lookup name
137
+ if (!pSid)
138
+ {
139
+ // open policy handle
140
+ st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
141
+ er = ::LsaNtStatusToWinError(st);
142
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
143
+
144
+ // create account name lsa unicode string
145
+ hr = InitLsaUnicodeString(&lusName, pwzAccountName, wcslen(pwzAccountName));
146
+ ExitOnFailure(hr, "Failed to initialize account name string");
147
+
148
+ // lookup name
149
+ st = ::LsaLookupNames(lsahPolicy, 1, &lusName, &plrdsDomains, &pltsSid);
150
+ er = ::LsaNtStatusToWinError(st);
151
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup account names");
152
+
153
+ if (SidTypeDomain == pltsSid->Use)
154
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
155
+
156
+ // convert sid
157
+ hr = CreateSidFromDomainRidPair(plrdsDomains->Domains[pltsSid->DomainIndex].Sid, pltsSid->RelativeId, &pSid);
158
+ ExitOnFailure(hr, "Failed to convert SID");
159
+ }
160
+
161
+ *ppSid = pSid;
162
+ pSid = NULL;
163
+
164
+ hr = S_OK;
165
+
166
+LExit:
167
+ // clean up
168
+ if (pSid)
169
+ ::HeapFree(::GetProcessHeap(), 0, pSid);
170
+ if (lsahPolicy)
171
+ ::LsaClose(lsahPolicy);
172
+ if (plrdsDomains)
173
+ ::LsaFreeMemory(plrdsDomains);
174
+ if (pltsSid)
175
+ ::LsaFreeMemory(pltsSid);
176
+ FreeLsaUnicodeString(&lusName);
177
+
178
+ return hr;
179
+}
180
+
181
+HRESULT PcaSidToAccountName(
182
+ PSID pSid,
183
+ LPWSTR* ppwzAccountName
184
+ )
185
+{
186
+ HRESULT hr = S_OK;
187
+ UINT er = ERROR_SUCCESS;
188
+ NTSTATUS st = 0;
189
+
190
+ LSA_OBJECT_ATTRIBUTES loaAttributes;
191
+ LSA_HANDLE lsahPolicy = NULL;
192
+ PLSA_REFERENCED_DOMAIN_LIST plrdsDomains = NULL;
193
+ PLSA_TRANSLATED_NAME pltnName = NULL;
194
+
195
+ LPWSTR pwzDomain = NULL;
196
+ LPWSTR pwzName = NULL;
197
+
198
+ ::ZeroMemory(&loaAttributes, sizeof(loaAttributes));
199
+
200
+ // open policy handle
201
+ st = ::LsaOpenPolicy(NULL, &loaAttributes, POLICY_ALL_ACCESS, &lsahPolicy);
202
+ er = ::LsaNtStatusToWinError(st);
203
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to open policy handle");
204
+
205
+ // lookup SID
206
+ st = ::LsaLookupSids(lsahPolicy, 1, &pSid, &plrdsDomains, &pltnName);
207
+ er = ::LsaNtStatusToWinError(st);
208
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(er), "Failed to lookup SID");
209
+
210
+ if (SidTypeDomain == pltnName->Use)
211
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), "Domain SIDs not supported");
212
+
213
+ // format account name string
214
+ if (SidTypeWellKnownGroup != pltnName->Use)
215
+ {
216
+ PLSA_UNICODE_STRING plusDomain = &plrdsDomains->Domains[pltnName->DomainIndex].Name;
217
+ hr = StrAllocString(&pwzDomain, plusDomain->Buffer, plusDomain->Length / sizeof(WCHAR));
218
+ ExitOnFailure(hr, "Failed to allocate name string");
219
+ }
220
+
221
+ hr = StrAllocString(&pwzName, pltnName->Name.Buffer, pltnName->Name.Length / sizeof(WCHAR));
222
+ ExitOnFailure(hr, "Failed to allocate domain string");
223
+
224
+ hr = StrAllocFormatted(ppwzAccountName, L"%s\\%s", pwzDomain ? pwzDomain : L"", pwzName);
225
+ ExitOnFailure(hr, "Failed to format account name string");
226
+
227
+ hr = S_OK;
228
+
229
+LExit:
230
+ // clean up
231
+ if (lsahPolicy)
232
+ ::LsaClose(lsahPolicy);
233
+ if (plrdsDomains)
234
+ ::LsaFreeMemory(plrdsDomains);
235
+ if (pltnName)
236
+ ::LsaFreeMemory(pltnName);
237
+
238
+ ReleaseStr(pwzDomain);
239
+ ReleaseStr(pwzName);
240
+
241
+ return hr;
242
+}
243
+
244
+HRESULT PcaBuildAccountName(
245
+ LPCWSTR pwzDomain,
246
+ LPCWSTR pwzName,
247
+ LPWSTR* ppwzAccount
248
+ )
249
+{
250
+ HRESULT hr = S_OK;
251
+
252
+ WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1];
253
+ ::ZeroMemory(wzComputerName, sizeof(wzComputerName));
254
+
255
+ // if domain is '.', get computer name
256
+ if (0 == lstrcmpW(pwzDomain, L"."))
257
+ {
258
+ DWORD dwSize = countof(wzComputerName);
259
+ if (!::GetComputerNameW(wzComputerName, &dwSize))
260
+ ExitOnFailure(hr = HRESULT_FROM_WIN32(::GetLastError()), "Failed to get computer name");
261
+ }
262
+
263
+ // build account name
264
+ hr = StrAllocFormatted(ppwzAccount, L"%s\\%s", *wzComputerName ? wzComputerName : pwzDomain, pwzName);
265
+ ExitOnFailure(hr, "Failed to build domain user name");
266
+
267
+ hr = S_OK;
268
+
269
+LExit:
270
+ return hr;
271
+}
272
+
273
+HRESULT PcaGuidFromString(
274
+ LPCWSTR pwzGuid,
275
+ LPGUID pGuid
276
+ )
277
+{
278
+ HRESULT hr = S_OK;
279
+
280
+ int cch = 0;
281
+
282
+ WCHAR wz[39];
283
+ ::ZeroMemory(wz, sizeof(wz));
284
+
285
+ cch = lstrlenW(pwzGuid);
286
+
287
+ if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37])
288
+ StringCchCopyW(wz, countof(wz), pwzGuid);
289
+ else if (36 == cch)
290
+ StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid);
291
+ else
292
+ ExitFunction1(hr = E_INVALIDARG);
293
+
294
+ hr = ::CLSIDFromString(wz, pGuid);
295
+
296
+LExit:
297
+ return hr;
298
+}
299
+
300
+
301
+// helper function definitions
302
+
303
+static HRESULT CreateSidFromDomainRidPair(
304
+ PSID pDomainSid,
305
+ DWORD dwRid,
306
+ PSID* ppSid
307
+ )
308
+{
309
+ HRESULT hr = S_OK;
310
+
311
+ PSID pSid = NULL;
312
+
313
+ // get domain SID sub authority count
314
+ UCHAR ucSubAuthorityCount = *::GetSidSubAuthorityCount(pDomainSid);
315
+
316
+ // allocate SID buffer
317
+ DWORD dwLengthRequired = ::GetSidLengthRequired(ucSubAuthorityCount + (UCHAR)1);
318
+ if (*ppSid)
319
+ {
320
+ SIZE_T ccb = ::HeapSize(::GetProcessHeap(), 0, *ppSid);
321
+ if (-1 == ccb)
322
+ ExitOnFailure(hr = E_FAIL, "Failed to get size of SID buffer");
323
+
324
+ if (ccb < dwLengthRequired)
325
+ {
326
+ pSid = (PSID)::HeapReAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, *ppSid, dwLengthRequired);
327
+ ExitOnNull(pSid, hr, E_OUTOFMEMORY, "Failed to reallocate buffer for SID, len: %d", dwLengthRequired);
328
+ *ppSid = pSid;
329
+ }
330
+ }
331
+ else
332
+ {
333
+ *ppSid = (PSID)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, dwLengthRequired);
334
+ ExitOnNull(*ppSid, hr, E_OUTOFMEMORY, "Failed to allocate buffer for SID, len: %d", dwLengthRequired);
335
+ }
336
+
337
+ ::InitializeSid(*ppSid, ::GetSidIdentifierAuthority(pDomainSid), ucSubAuthorityCount + (UCHAR)1);
338
+
339
+ // copy sub autorities
340
+ DWORD i = 0;
341
+ for (; i < ucSubAuthorityCount; i++)
342
+ *::GetSidSubAuthority(*ppSid, i) = *::GetSidSubAuthority(pDomainSid, i);
343
+ *::GetSidSubAuthority(*ppSid, i) = dwRid;
344
+
345
+ hr = S_OK;
346
+
347
+LExit:
348
+ return hr;
349
+}
350
+
351
+static HRESULT InitLsaUnicodeString(
352
+ PLSA_UNICODE_STRING plusStr,
353
+ LPCWSTR pwzStr,
354
+ DWORD dwLen
355
+ )
356
+{
357
+ HRESULT hr = S_OK;
358
+
359
+ plusStr->Length = (USHORT)dwLen * sizeof(WCHAR);
360
+ plusStr->MaximumLength = (USHORT)(dwLen + 1) * sizeof(WCHAR);
361
+
362
+ plusStr->Buffer = (WCHAR*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR) * (dwLen + 1));
363
+ ExitOnNull(plusStr->Buffer, hr, E_OUTOFMEMORY, "Failed to allocate account name string");
364
+
365
+ hr = StringCchCopyW(plusStr->Buffer, dwLen + 1, pwzStr);
366
+ ExitOnFailure(hr, "Failed to copy buffer");
367
+
368
+ hr = S_OK;
369
+
370
+LExit:
371
+ return hr;
372
+}
373
+
374
+static void FreeLsaUnicodeString(
375
+ PLSA_UNICODE_STRING plusStr
376
+ )
377
+{
378
+ if (plusStr->Buffer)
379
+ ::HeapFree(::GetProcessHeap(), 0, plusStr->Buffer);
380
+}
src/ca/mqutilexec.h
new
+23
@@ -0,0 +1,23 @@
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
+HRESULT PcaActionDataMessage(
4
+ DWORD cArgs,
5
+ ...
6
+ );
7
+HRESULT PcaAccountNameToSid(
8
+ LPCWSTR pwzAccountName,
9
+ PSID* ppSid
10
+ );
11
+HRESULT PcaSidToAccountName(
12
+ PSID pSid,
13
+ LPWSTR* ppwzAccountName
14
+ );
15
+HRESULT PcaBuildAccountName(
16
+ LPCWSTR pwzDomain,
17
+ LPCWSTR pwzName,
18
+ LPWSTR* ppwzAccount
19
+ );
20
+HRESULT PcaGuidFromString(
21
+ LPCWSTR pwzGuid,
22
+ GUID* pGuid
23
+ );
src/ca/mqutilsched.cpp
new
+43
@@ -0,0 +1,43 @@
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
+// function definitions
7
+
8
+HRESULT PcaGuidToRegFormat(
9
+ LPWSTR pwzGuid,
10
+ LPWSTR pwzDest,
11
+ SIZE_T cchDest
12
+ )
13
+{
14
+ HRESULT hr = S_OK;
15
+
16
+ GUID guid = GUID_NULL;
17
+ int cch = 0;
18
+
19
+ WCHAR wz[39];
20
+ ::ZeroMemory(wz, sizeof(wz));
21
+
22
+ cch = lstrlenW(pwzGuid);
23
+
24
+ if (38 == cch && L'{' == pwzGuid[0] && L'}' == pwzGuid[37])
25
+ StringCchCopyW(wz, countof(wz), pwzGuid);
26
+ else if (36 == cch)
27
+ StringCchPrintfW(wz, countof(wz), L"{%s}", pwzGuid);
28
+ else
29
+ ExitFunction1(hr = E_INVALIDARG);
30
+
31
+ // convert string to guid
32
+ hr = ::CLSIDFromString(wz, &guid);
33
+ ExitOnFailure(hr, "Failed to parse guid string");
34
+
35
+ // convert guid to string
36
+ if (0 == ::StringFromGUID2(guid, pwzDest, cchDest))
37
+ ExitOnFailure(hr = E_FAIL, "Failed to convert guid to string");
38
+
39
+ hr = S_OK;
40
+
41
+LExit:
42
+ return hr;
43
+}
src/ca/mqutilsched.h
new
+9
@@ -0,0 +1,9 @@
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
+HRESULT PcaGuidToRegFormat(
6
+ LPWSTR pwzGuid,
7
+ LPWSTR pwzDest,
8
+ SIZE_T cchDest
9
+ );
src/wixext/MsmqCompiler.cs
new
+536
@@ -0,0 +1,536 @@
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.Collections.Generic;
8
+ using System.Globalization;
9
+ using System.Reflection;
10
+ using System.Xml;
11
+ using System.Xml.Linq;
12
+ using System.Xml.Schema;
13
+ using WixToolset.Data;
14
+ using WixToolset.Extensibility;
15
+
16
+ /// <summary>
17
+ /// The compiler for the WiX Toolset Internet Information Services Extension.
18
+ /// </summary>
19
+ public sealed class MsmqCompiler : CompilerExtension
20
+ {
21
+ /// <summary>
22
+ /// Instantiate a new MsmqCompiler.
23
+ /// </summary>
24
+ public MsmqCompiler()
25
+ {
26
+ this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/msmq";
27
+ }
28
+
29
+ /// <summary>
30
+ /// </summary>
31
+ /// <remarks></remarks>
32
+ public enum MqiMessageQueueAttributes
33
+ {
34
+ Authenticate = (1 << 0),
35
+ Journal = (1 << 1),
36
+ Transactional = (1 << 2)
37
+ }
38
+
39
+ /// <summary>
40
+ /// </summary>
41
+ /// <remarks></remarks>
42
+ public enum MqiMessageQueuePrivacyLevel
43
+ {
44
+ None = 0,
45
+ Optional = 1,
46
+ Body = 2
47
+ }
48
+
49
+ /// <summary>
50
+ /// </summary>
51
+ /// <remarks></remarks>
52
+ public enum MqiMessageQueuePermission
53
+ {
54
+ DeleteMessage = (1 << 0),
55
+ PeekMessage = (1 << 1),
56
+ WriteMessage = (1 << 2),
57
+ DeleteJournalMessage = (1 << 3),
58
+ SetQueueProperties = (1 << 4),
59
+ GetQueueProperties = (1 << 5),
60
+ DeleteQueue = (1 << 6),
61
+ GetQueuePermissions = (1 << 7),
62
+ ChangeQueuePermissions = (1 << 8),
63
+ TakeQueueOwnership = (1 << 9),
64
+ ReceiveMessage = (1 << 10),
65
+ ReceiveJournalMessage = (1 << 11),
66
+ QueueGenericRead = (1 << 12),
67
+ QueueGenericWrite = (1 << 13),
68
+ QueueGenericExecute = (1 << 14),
69
+ QueueGenericAll = (1 << 15)
70
+ }
71
+
72
+ /// <summary>
73
+ /// Processes an element for the Compiler.
74
+ /// </summary>
75
+ /// <param name="parentElement">Parent element of element to process.</param>
76
+ /// <param name="element">Element to process.</param>
77
+ /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
78
+ public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context)
79
+ {
80
+ switch (parentElement.Name.LocalName)
81
+ {
82
+ case "Component":
83
+ string componentId = context["ComponentId"];
84
+ string directoryId = context["DirectoryId"];
85
+
86
+ switch (element.Name.LocalName)
87
+ {
88
+ case "MessageQueue":
89
+ this.ParseMessageQueueElement(element, componentId);
90
+ break;
91
+ case "MessageQueuePermission":
92
+ this.ParseMessageQueuePermissionElement(element, componentId, null);
93
+ break;
94
+ default:
95
+ this.Core.UnexpectedElement(parentElement, element);
96
+ break;
97
+ }
98
+ break;
99
+ default:
100
+ this.Core.UnexpectedElement(parentElement, element);
101
+ break;
102
+ }
103
+ }
104
+
105
+ /// <summary>
106
+ /// Parses an MSMQ message queue element.
107
+ /// </summary>
108
+ /// <param name="node">Element to parse.</param>
109
+ /// <param name="componentKey">Identifier of parent component.</param>
110
+ private void ParseMessageQueueElement(XElement node, string componentId)
111
+ {
112
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
113
+
114
+ string id = null;
115
+ int basePriority = CompilerConstants.IntegerNotSet;
116
+ int journalQuota = CompilerConstants.IntegerNotSet;
117
+ string label = null;
118
+ string multicastAddress = null;
119
+ string pathName = null;
120
+ int privLevel = CompilerConstants.IntegerNotSet;
121
+ int quota = CompilerConstants.IntegerNotSet;
122
+ string serviceTypeGuid = null;
123
+ int attributes = 0;
124
+
125
+ foreach (XAttribute attrib in node.Attributes())
126
+ {
127
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
128
+ {
129
+ switch (attrib.Name.LocalName)
130
+ {
131
+ case "Id":
132
+ id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
133
+ break;
134
+ case "Authenticate":
135
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
136
+ {
137
+ attributes |= (int)MqiMessageQueueAttributes.Authenticate;
138
+ }
139
+ else
140
+ {
141
+ attributes &= ~(int)MqiMessageQueueAttributes.Authenticate;
142
+ }
143
+ break;
144
+ case "BasePriority":
145
+ basePriority = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
146
+ break;
147
+ case "Journal":
148
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
149
+ {
150
+ attributes |= (int)MqiMessageQueueAttributes.Journal;
151
+ }
152
+ else
153
+ {
154
+ attributes &= ~(int)MqiMessageQueueAttributes.Journal;
155
+ }
156
+ break;
157
+ case "JournalQuota":
158
+ journalQuota = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
159
+ break;
160
+ case "Label":
161
+ label = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
162
+ break;
163
+ case "MulticastAddress":
164
+ multicastAddress = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
165
+ break;
166
+ case "PathName":
167
+ pathName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
168
+ break;
169
+ case "PrivLevel":
170
+ string privLevelAttr = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
171
+ switch (privLevelAttr)
172
+ {
173
+ case "none":
174
+ privLevel = (int)MqiMessageQueuePrivacyLevel.None;
175
+ break;
176
+ case "optional":
177
+ privLevel = (int)MqiMessageQueuePrivacyLevel.Optional;
178
+ break;
179
+ case "body":
180
+ privLevel = (int)MqiMessageQueuePrivacyLevel.Body;
181
+ break;
182
+ default:
183
+ this.Core.OnMessage(WixErrors.IllegalAttributeValue(sourceLineNumbers, "MessageQueue", "PrivLevel", privLevelAttr, "none", "body", "optional"));
184
+ break;
185
+ }
186
+ break;
187
+ case "Quota":
188
+ quota = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
189
+ break;
190
+ case "Transactional":
191
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
192
+ {
193
+ attributes |= (int)MqiMessageQueueAttributes.Transactional;
194
+ }
195
+ else
196
+ {
197
+ attributes &= ~(int)MqiMessageQueueAttributes.Transactional;
198
+ }
199
+ break;
200
+ case "ServiceTypeGuid":
201
+ serviceTypeGuid = TryFormatGuidValue(this.Core.GetAttributeValue(sourceLineNumbers, attrib));
202
+ break;
203
+ default:
204
+ this.Core.UnexpectedAttribute(node, attrib);
205
+ break;
206
+ }
207
+ }
208
+ else
209
+ {
210
+ this.Core.ParseExtensionAttribute(node, attrib);
211
+ }
212
+ }
213
+
214
+ foreach (XElement child in node.Elements())
215
+ {
216
+ if (this.Namespace == child.Name.Namespace)
217
+ {
218
+ switch (child.Name.LocalName)
219
+ {
220
+ case "MessageQueuePermission":
221
+ this.ParseMessageQueuePermissionElement(child, componentId, id);
222
+ break;
223
+ default:
224
+ this.Core.UnexpectedElement(node, child);
225
+ break;
226
+ }
227
+ }
228
+ else
229
+ {
230
+ this.Core.ParseExtensionElement(node, child);
231
+ }
232
+ }
233
+
234
+ Row row = this.Core.CreateRow(sourceLineNumbers, "MessageQueue");
235
+ row[0] = id;
236
+ row[1] = componentId;
237
+ if (CompilerConstants.IntegerNotSet != basePriority)
238
+ {
239
+ row[2] = basePriority;
240
+ }
241
+ if (CompilerConstants.IntegerNotSet != journalQuota)
242
+ {
243
+ row[3] = journalQuota;
244
+ }
245
+ row[4] = label;
246
+ row[5] = multicastAddress;
247
+ row[6] = pathName;
248
+ if (CompilerConstants.IntegerNotSet != privLevel)
249
+ {
250
+ row[7] = privLevel;
251
+ }
252
+ if (CompilerConstants.IntegerNotSet != quota)
253
+ {
254
+ row[8] = quota;
255
+ }
256
+ row[9] = serviceTypeGuid;
257
+ row[10] = attributes;
258
+
259
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "MessageQueuingInstall");
260
+ this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "MessageQueuingUninstall");
261
+ }
262
+
263
+ /// <summary>
264
+ /// Parses an MSMQ message queue permission element.
265
+ /// </summary>
266
+ /// <param name="node">Element to parse.</param>
267
+ /// <param name="componentKey">Identifier of parent component.</param>
268
+ /// <param name="applicationKey">Optional identifier of parent message queue.</param>
269
+ private void ParseMessageQueuePermissionElement(XElement node, string componentId, string messageQueueId)
270
+ {
271
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
272
+
273
+ string id = null;
274
+ string user = null;
275
+ string group = null;
276
+ int permissions = 0;
277
+
278
+ foreach (XAttribute attrib in node.Attributes())
279
+ {
280
+ if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
281
+ {
282
+ switch (attrib.Name.LocalName)
283
+ {
284
+ case "Id":
285
+ id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
286
+ break;
287
+ case "MessageQueue":
288
+ if (null != messageQueueId)
289
+ {
290
+ this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName));
291
+ }
292
+ messageQueueId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
293
+ this.Core.CreateSimpleReference(sourceLineNumbers, "MessageQueue", messageQueueId);
294
+ break;
295
+ case "User":
296
+ if (null != group)
297
+ {
298
+ this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "User", "Group"));
299
+ }
300
+ user = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
301
+ this.Core.CreateSimpleReference(sourceLineNumbers, "User", user);
302
+ break;
303
+ case "Group":
304
+ if (null != user)
305
+ {
306
+ this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "Group", "User"));
307
+ }
308
+ group = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
309
+ this.Core.CreateSimpleReference(sourceLineNumbers, "Group", group);
310
+ break;
311
+ case "DeleteMessage":
312
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
313
+ {
314
+ permissions |= (int)MqiMessageQueuePermission.DeleteMessage;
315
+ }
316
+ else
317
+ {
318
+ permissions &= ~(int)MqiMessageQueuePermission.DeleteMessage;
319
+ }
320
+ break;
321
+ case "PeekMessage":
322
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
323
+ {
324
+ permissions |= (int)MqiMessageQueuePermission.PeekMessage;
325
+ }
326
+ else
327
+ {
328
+ permissions &= ~(int)MqiMessageQueuePermission.PeekMessage;
329
+ }
330
+ break;
331
+ case "WriteMessage":
332
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
333
+ {
334
+ permissions |= (int)MqiMessageQueuePermission.WriteMessage;
335
+ }
336
+ else
337
+ {
338
+ permissions &= ~(int)MqiMessageQueuePermission.WriteMessage;
339
+ }
340
+ break;
341
+ case "DeleteJournalMessage":
342
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
343
+ {
344
+ permissions |= (int)MqiMessageQueuePermission.DeleteJournalMessage;
345
+ }
346
+ else
347
+ {
348
+ permissions &= ~(int)MqiMessageQueuePermission.DeleteJournalMessage;
349
+ }
350
+ break;
351
+ case "SetQueueProperties":
352
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
353
+ {
354
+ permissions |= (int)MqiMessageQueuePermission.SetQueueProperties;
355
+ }
356
+ else
357
+ {
358
+ permissions &= ~(int)MqiMessageQueuePermission.SetQueueProperties;
359
+ }
360
+ break;
361
+ case "GetQueueProperties":
362
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
363
+ {
364
+ permissions |= (int)MqiMessageQueuePermission.GetQueueProperties;
365
+ }
366
+ else
367
+ {
368
+ permissions &= ~(int)MqiMessageQueuePermission.GetQueueProperties;
369
+ }
370
+ break;
371
+ case "DeleteQueue":
372
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
373
+ {
374
+ permissions |= (int)MqiMessageQueuePermission.DeleteQueue;
375
+ }
376
+ else
377
+ {
378
+ permissions &= ~(int)MqiMessageQueuePermission.DeleteQueue;
379
+ }
380
+ break;
381
+ case "GetQueuePermissions":
382
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
383
+ {
384
+ permissions |= (int)MqiMessageQueuePermission.GetQueuePermissions;
385
+ }
386
+ else
387
+ {
388
+ permissions &= ~(int)MqiMessageQueuePermission.GetQueuePermissions;
389
+ }
390
+ break;
391
+ case "ChangeQueuePermissions":
392
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
393
+ {
394
+ permissions |= (int)MqiMessageQueuePermission.ChangeQueuePermissions;
395
+ }
396
+ else
397
+ {
398
+ permissions &= ~(int)MqiMessageQueuePermission.ChangeQueuePermissions;
399
+ }
400
+ break;
401
+ case "TakeQueueOwnership":
402
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
403
+ {
404
+ permissions |= (int)MqiMessageQueuePermission.TakeQueueOwnership;
405
+ }
406
+ else
407
+ {
408
+ permissions &= ~(int)MqiMessageQueuePermission.TakeQueueOwnership;
409
+ }
410
+ break;
411
+ case "ReceiveMessage":
412
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
413
+ {
414
+ permissions |= (int)MqiMessageQueuePermission.ReceiveMessage;
415
+ }
416
+ else
417
+ {
418
+ permissions &= ~(int)MqiMessageQueuePermission.ReceiveMessage;
419
+ }
420
+ break;
421
+ case "ReceiveJournalMessage":
422
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
423
+ {
424
+ permissions |= (int)MqiMessageQueuePermission.ReceiveJournalMessage;
425
+ }
426
+ else
427
+ {
428
+ permissions &= ~(int)MqiMessageQueuePermission.ReceiveJournalMessage;
429
+ }
430
+ break;
431
+ case "QueueGenericRead":
432
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
433
+ {
434
+ permissions |= (int)MqiMessageQueuePermission.QueueGenericRead;
435
+ }
436
+ else
437
+ {
438
+ permissions &= ~(int)MqiMessageQueuePermission.QueueGenericRead;
439
+ }
440
+ break;
441
+ case "QueueGenericWrite":
442
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
443
+ {
444
+ permissions |= (int)MqiMessageQueuePermission.QueueGenericWrite;
445
+ }
446
+ else
447
+ {
448
+ permissions &= ~(int)MqiMessageQueuePermission.QueueGenericWrite;
449
+ }
450
+ break;
451
+ case "QueueGenericExecute":
452
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
453
+ {
454
+ permissions |= (int)MqiMessageQueuePermission.QueueGenericExecute;
455
+ }
456
+ else
457
+ {
458
+ permissions &= ~(int)MqiMessageQueuePermission.QueueGenericExecute;
459
+ }
460
+ break;
461
+ case "QueueGenericAll":
462
+ if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
463
+ {
464
+ permissions |= (int)MqiMessageQueuePermission.QueueGenericAll;
465
+ }
466
+ else
467
+ {
468
+ permissions &= ~(int)MqiMessageQueuePermission.QueueGenericAll;
469
+ }
470
+ break;
471
+ default:
472
+ this.Core.UnexpectedAttribute(node, attrib);
473
+ break;
474
+ }
475
+ }
476
+ else
477
+ {
478
+ this.Core.ParseExtensionAttribute(node, attrib);
479
+ }
480
+ }
481
+
482
+ if (null == messageQueueId)
483
+ {
484
+ this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "MessageQueue"));
485
+ }
486
+ if (null == user && null == group)
487
+ {
488
+ this.Core.OnMessage(WixErrors.ExpectedAttributes(sourceLineNumbers, node.Name.LocalName, "User", "Group"));
489
+ }
490
+
491
+ this.Core.ParseForExtensionElements(node);
492
+
493
+ if (null != user)
494
+ {
495
+ Row row = this.Core.CreateRow(sourceLineNumbers, "MessageQueueUserPermission");
496
+ row[0] = id;
497
+ row[1] = componentId;
498
+ row[2] = messageQueueId;
499
+ row[3] = user;
500
+ row[4] = permissions;
501
+ }
502
+ if (null != group)
503
+ {
504
+ Row row = this.Core.CreateRow(sourceLineNumbers, "MessageQueueGroupPermission");
505
+ row[0] = id;
506
+ row[1] = componentId;
507
+ row[2] = messageQueueId;
508
+ row[3] = group;
509
+ row[4] = permissions;
510
+ }
511
+ }
512
+
513
+ /// <summary>
514
+ /// Attempts to parse the input value as a GUID, and in case the value is a valid
515
+ /// GUID returnes it in the format "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}".
516
+ /// </summary>
517
+ /// <param name="val"></param>
518
+ /// <returns></returns>
519
+ string TryFormatGuidValue(string val)
520
+ {
521
+ try
522
+ {
523
+ Guid guid = new Guid(val);
524
+ return guid.ToString("B").ToUpper();
525
+ }
526
+ catch (FormatException)
527
+ {
528
+ return val;
529
+ }
530
+ catch (OverflowException)
531
+ {
532
+ return val;
533
+ }
534
+ }
535
+ }
536
+}
src/wixext/MsmqDecompiler.cs
new
+303
@@ -0,0 +1,303 @@
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.Globalization;
8
+ using WixToolset.Data;
9
+ using WixToolset.Extensibility;
10
+ using Msmq = WixToolset.Extensions.Serialize.Msmq;
11
+ using Wix = WixToolset.Data.Serialize;
12
+
13
+ /// <summary>
14
+ /// The decompiler for the WiX Toolset MSMQ Extension.
15
+ /// </summary>
16
+ public sealed class MsmqDecompiler : DecompilerExtension
17
+ {
18
+ /// <summary>
19
+ /// Creates a decompiler for MSMQ Extension.
20
+ /// </summary>
21
+ public MsmqDecompiler()
22
+ {
23
+ this.TableDefinitions = MsmqExtensionData.GetExtensionTableDefinitions();
24
+ }
25
+
26
+ /// <summary>
27
+ /// Get the extensions library to be removed.
28
+ /// </summary>
29
+ /// <param name="tableDefinitions">Table definitions for library.</param>
30
+ /// <returns>Library to remove from decompiled output.</returns>
31
+ public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
32
+ {
33
+ return MsmqExtensionData.GetExtensionLibrary(tableDefinitions);
34
+ }
35
+
36
+ /// <summary>
37
+ /// Decompiles an extension table.
38
+ /// </summary>
39
+ /// <param name="table">The table to decompile.</param>
40
+ public override void DecompileTable(Table table)
41
+ {
42
+ switch (table.Name)
43
+ {
44
+ case "MessageQueue":
45
+ this.DecompileMessageQueueTable(table);
46
+ break;
47
+ case "MessageQueueUserPermission":
48
+ this.DecompileMessageQueueUserPermissionTable(table);
49
+ break;
50
+ case "MessageQueueGroupPermission":
51
+ this.DecompileMessageQueueGroupPermissionTable(table);
52
+ break;
53
+ default:
54
+ base.DecompileTable(table);
55
+ break;
56
+ }
57
+ }
58
+
59
+ /// <summary>
60
+ /// Decompile the MessageQueue table.
61
+ /// </summary>
62
+ /// <param name="table">The table to decompile.</param>
63
+ private void DecompileMessageQueueTable(Table table)
64
+ {
65
+ foreach (Row row in table.Rows)
66
+ {
67
+ Msmq.MessageQueue queue = new Msmq.MessageQueue();
68
+
69
+ queue.Id = (string)row[0];
70
+
71
+ if (null != row[2])
72
+ {
73
+ queue.BasePriority = (int)row[2];
74
+ }
75
+
76
+ if (null != row[3])
77
+ {
78
+ queue.JournalQuota = (int)row[3];
79
+ }
80
+
81
+ queue.Label = (string)row[4];
82
+
83
+ if (null != row[5])
84
+ {
85
+ queue.MulticastAddress = (string)row[5];
86
+ }
87
+
88
+ queue.PathName = (string)row[6];
89
+
90
+ if (null != row[7])
91
+ {
92
+ switch ((MsmqCompiler.MqiMessageQueuePrivacyLevel)row[7])
93
+ {
94
+ case MsmqCompiler.MqiMessageQueuePrivacyLevel.None:
95
+ queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.none;
96
+ break;
97
+ case MsmqCompiler.MqiMessageQueuePrivacyLevel.Optional:
98
+ queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.optional;
99
+ break;
100
+ case MsmqCompiler.MqiMessageQueuePrivacyLevel.Body:
101
+ queue.PrivLevel = Msmq.MessageQueue.PrivLevelType.body;
102
+ break;
103
+ default:
104
+ break;
105
+ }
106
+ }
107
+
108
+ if (null != row[8])
109
+ {
110
+ queue.Quota = (int)row[8];
111
+ }
112
+
113
+ if (null != row[9])
114
+ {
115
+ queue.ServiceTypeGuid = (string)row[9];
116
+ }
117
+
118
+ int attributes = (int)row[10];
119
+
120
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Authenticate))
121
+ {
122
+ queue.Authenticate = Msmq.YesNoType.yes;
123
+ }
124
+
125
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Journal))
126
+ {
127
+ queue.Journal = Msmq.YesNoType.yes;
128
+ }
129
+
130
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueueAttributes.Transactional))
131
+ {
132
+ queue.Transactional = Msmq.YesNoType.yes;
133
+ }
134
+
135
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
136
+ if (null != component)
137
+ {
138
+ component.AddChild(queue);
139
+ }
140
+ else
141
+ {
142
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
143
+ }
144
+ }
145
+ }
146
+
147
+ /// <summary>
148
+ /// Decompile the MessageQueueUserPermission table.
149
+ /// </summary>
150
+ /// <param name="table">The table to decompile.</param>
151
+ private void DecompileMessageQueueUserPermissionTable(Table table)
152
+ {
153
+ foreach (Row row in table.Rows)
154
+ {
155
+ Msmq.MessageQueuePermission queuePermission = new Msmq.MessageQueuePermission();
156
+
157
+ queuePermission.Id = (string)row[0];
158
+
159
+ if (null != row[2])
160
+ {
161
+ queuePermission.MessageQueue = (string)row[2];
162
+ }
163
+
164
+ queuePermission.User = (string)row[3];
165
+
166
+ DecompileMessageQueuePermissionAttributes(row, queuePermission);
167
+
168
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
169
+ if (null != component)
170
+ {
171
+ component.AddChild(queuePermission);
172
+ }
173
+ else
174
+ {
175
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
176
+ }
177
+ }
178
+ }
179
+
180
+ /// <summary>
181
+ /// Decompile the MessageQueueGroupPermission table.
182
+ /// </summary>
183
+ /// <param name="table">The table to decompile.</param>
184
+ private void DecompileMessageQueueGroupPermissionTable(Table table)
185
+ {
186
+ foreach (Row row in table.Rows)
187
+ {
188
+ Msmq.MessageQueuePermission queuePermission = new Msmq.MessageQueuePermission();
189
+
190
+ queuePermission.Id = (string)row[0];
191
+
192
+ if (null != row[2])
193
+ {
194
+ queuePermission.MessageQueue = (string)row[2];
195
+ }
196
+
197
+ queuePermission.Group = (string)row[3];
198
+
199
+ DecompileMessageQueuePermissionAttributes(row, queuePermission);
200
+
201
+ Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[1]);
202
+ if (null != component)
203
+ {
204
+ component.AddChild(queuePermission);
205
+ }
206
+ else
207
+ {
208
+ this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[1], "Component"));
209
+ }
210
+ }
211
+ }
212
+
213
+ /// <summary>
214
+ /// Decompile row attributes for the MessageQueueUserPermission and MessageQueueGroupPermission tables.
215
+ /// </summary>
216
+ /// <param name="row">The row to decompile.</param>
217
+ /// <param name="table">Target element.</param>
218
+ private void DecompileMessageQueuePermissionAttributes(Row row, Msmq.MessageQueuePermission queuePermission)
219
+ {
220
+ int attributes = (int)row[4];
221
+
222
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.DeleteMessage))
223
+ {
224
+ queuePermission.DeleteMessage = Msmq.YesNoType.yes;
225
+ }
226
+
227
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.PeekMessage))
228
+ {
229
+ queuePermission.PeekMessage = Msmq.YesNoType.yes;
230
+ }
231
+
232
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.WriteMessage))
233
+ {
234
+ queuePermission.WriteMessage = Msmq.YesNoType.yes;
235
+ }
236
+
237
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.DeleteJournalMessage))
238
+ {
239
+ queuePermission.DeleteJournalMessage = Msmq.YesNoType.yes;
240
+ }
241
+
242
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.SetQueueProperties))
243
+ {
244
+ queuePermission.SetQueueProperties = Msmq.YesNoType.yes;
245
+ }
246
+
247
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.GetQueueProperties))
248
+ {
249
+ queuePermission.GetQueueProperties = Msmq.YesNoType.yes;
250
+ }
251
+
252
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.DeleteQueue))
253
+ {
254
+ queuePermission.DeleteQueue = Msmq.YesNoType.yes;
255
+ }
256
+
257
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.GetQueuePermissions))
258
+ {
259
+ queuePermission.GetQueuePermissions = Msmq.YesNoType.yes;
260
+ }
261
+
262
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.ChangeQueuePermissions))
263
+ {
264
+ queuePermission.ChangeQueuePermissions = Msmq.YesNoType.yes;
265
+ }
266
+
267
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.TakeQueueOwnership))
268
+ {
269
+ queuePermission.TakeQueueOwnership = Msmq.YesNoType.yes;
270
+ }
271
+
272
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.ReceiveMessage))
273
+ {
274
+ queuePermission.ReceiveMessage = Msmq.YesNoType.yes;
275
+ }
276
+
277
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.ReceiveJournalMessage))
278
+ {
279
+ queuePermission.ReceiveJournalMessage = Msmq.YesNoType.yes;
280
+ }
281
+
282
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.QueueGenericRead))
283
+ {
284
+ queuePermission.QueueGenericRead = Msmq.YesNoType.yes;
285
+ }
286
+
287
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.QueueGenericWrite))
288
+ {
289
+ queuePermission.QueueGenericWrite = Msmq.YesNoType.yes;
290
+ }
291
+
292
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.QueueGenericExecute))
293
+ {
294
+ queuePermission.QueueGenericExecute = Msmq.YesNoType.yes;
295
+ }
296
+
297
+ if (0 != (attributes & (int)MsmqCompiler.MqiMessageQueuePermission.QueueGenericAll))
298
+ {
299
+ queuePermission.QueueGenericAll = Msmq.YesNoType.yes;
300
+ }
301
+ }
302
+ }
303
+}
src/wixext/MsmqExtensionData.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 MSMQ Extension.
12
+ /// </summary>
13
+ public sealed class MsmqExtensionData : 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 MsmqExtensionData.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 MsmqExtensionData.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.msmq.wixlib", tableDefinitions);
62
+ }
63
+ }
64
+}
src/wixext/WixMsmqExtension.csproj
new
+49
@@ -0,0 +1,49 @@
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>{B990D81B-9F60-4EEE-B31D-B5D1EAA799EE}</ProjectGuid>
8
+ <AssemblyName>WixMsmqExtension</AssemblyName>
9
+ <OutputType>Library</OutputType>
10
+ <RootNamespace>WixToolset.Extensions</RootNamespace>
11
+ </PropertyGroup>
12
+ <ItemGroup>
13
+ <Compile Include="AssemblyInfo.cs" />
14
+ <Compile Include="MsmqCompiler.cs" />
15
+ <Compile Include="MsmqDecompiler.cs" />
16
+ <Compile Include="MsmqExtensionData.cs" />
17
+ <EmbeddedFlattenedResource Include="Data\tables.xml">
18
+ <LogicalName>$(RootNamespace).Data.tables.xml</LogicalName>
19
+ </EmbeddedFlattenedResource>
20
+ <EmbeddedFlattenedResource Include="Xsd\msmq.xsd">
21
+ <LogicalName>$(RootNamespace).Xsd.msmq.xsd</LogicalName>
22
+ </EmbeddedFlattenedResource>
23
+ <XsdGenSource Include="Xsd\msmq.xsd">
24
+ <CommonNamespace>WixToolset.Data.Serialize</CommonNamespace>
25
+ <Namespace>WixToolset.Extensions.Serialize.Msmq</Namespace>
26
+ </XsdGenSource>
27
+ <None Include="Xsd\msmq.xsd">
28
+ <Link>msmq.xsd</Link>
29
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
30
+ </None>
31
+ <EmbeddedResource Include="$(OutputPath)\msmq.wixlib">
32
+ <Link>Data\msmq.wixlib</Link>
33
+ </EmbeddedResource>
34
+ </ItemGroup>
35
+
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\MsmqExtension.wixproj">
44
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
45
+ </ProjectReference>
46
+ </ItemGroup>
47
+
48
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
49
+</Project>
src/wixext/messages.xml
new
+77
@@ -0,0 +1,77 @@
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="MsmqErrors" ContainerName="MsmqErrorEventArgs" BaseContainerName="WixErrorEventArgs">
7
+ <Message Id="IllegalAttributeWithoutComponent" Number="6000">
8
+ <Instance>
9
+ The {0}/@{1} attribute cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed.
10
+ <Parameter Type="System.String" Name="elementName" />
11
+ <Parameter Type="System.String" Name="attributeName" />
12
+ </Instance>
13
+ </Message>
14
+ <Message Id="IllegalElementWithoutComponent" Number="6001">
15
+ <Instance>
16
+ The {0} element cannot be specified unless the element has a component as an ancestor. A {0} that does not have a component ancestor is not installed.
17
+ <Parameter Type="System.String" Name="elementName" />
18
+ </Instance>
19
+ </Message>
20
+ <Message Id="UnexpectedAttributeWithOtherValue" Number="6002">
21
+ <Instance>
22
+ The {0}/@{1} attribute cannot coexist with the {2} attribute's value of '{3}'.
23
+ <Parameter Type="System.String" Name="elementName" />
24
+ <Parameter Type="System.String" Name="attributeName" />
25
+ <Parameter Type="System.String" Name="otherAttributeName" />
26
+ <Parameter Type="System.String" Name="otherValue" />
27
+ </Instance>
28
+ <Instance>
29
+ The {0}/@{1} attribute's value, '{2}', cannot coexist with the {3} attribute's value of '{4}'.
30
+ <Parameter Type="System.String" Name="elementName" />
31
+ <Parameter Type="System.String" Name="attributeName" />
32
+ <Parameter Type="System.String" Name="value" />
33
+ <Parameter Type="System.String" Name="otherAttributeName" />
34
+ <Parameter Type="System.String" Name="otherValue" />
35
+ </Instance>
36
+ </Message>
37
+ <Message Id="UnexpectedAttributeWithoutOtherValue" Number="6003">
38
+ <Instance>
39
+ The {0}/@{1} cannot be provided unless the {2} attribute is provided with a value of '{3}'.
40
+ <Parameter Type="System.String" Name="elementName" />
41
+ <Parameter Type="System.String" Name="attributeName" />
42
+ <Parameter Type="System.String" Name="otherAttributeName" />
43
+ <Parameter Type="System.String" Name="otherValue" />
44
+ </Instance>
45
+ </Message>
46
+ <Message Id="RequiredAttributeUnderComponent" Number="6004">
47
+ <Instance>
48
+ The {0}/@{1} attribute must be provided when {0} element is nested under a component.
49
+ <Parameter Type="System.String" Name="elementName" />
50
+ <Parameter Type="System.String" Name="attributeName" />
51
+ </Instance>
52
+ </Message>
53
+ <Message Id="RequiredAttribute" Number="6005">
54
+ <Instance>
55
+ A {0} element must have either a {1} attribute or a {2} attribute, or both set.
56
+ <Parameter Type="System.String" Name="elementName" />
57
+ <Parameter Type="System.String" Name="attributeName1" />
58
+ <Parameter Type="System.String" Name="attributeName2" />
59
+ </Instance>
60
+ </Message>
61
+ <Message Id="RequiredAttributeNotUnderComponent" Number="6006">
62
+ <Instance>
63
+ A {0} element not nested under a component must have either a {1} attribute or a {2} attribute, or both set.
64
+ <Parameter Type="System.String" Name="elementName" />
65
+ <Parameter Type="System.String" Name="attributeName1" />
66
+ <Parameter Type="System.String" Name="attributeName2" />
67
+ </Instance>
68
+ </Message>
69
+ </Class>
70
+ <Class Name="MsmqWarnings" ContainerName="MsmqWarningEventArgs" BaseContainerName="WixWarningEventArgs">
71
+ <Message Id="MissingComponents" Number="6007">
72
+ <Instance>The MsmqAssembly element has a Type attribute with a value of 'native', but the element does not contain any MsmqComponent elements. All components contained in a native assembly must be listed, or they will not be correctly removed during uninstall.</Instance>
73
+ </Message>
74
+ </Class>
75
+ <Class Name="MsmqVerboses" ContainerName="MsmqVerboseEventArgs" BaseContainerName="WixVerboseEventArgs">
76
+ </Class>
77
+</Messages>
src/wixext/msmq.xsd
new
+121
@@ -0,0 +1,121 @@
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:html="http://www.w3.org/1999/xhtml"
6
+ xmlns:wix="http://wixtoolset.org/schemas/v4/wxs"
7
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
8
+ xmlns:xse=" http://wixtoolset.org/schemas/XmlSchemaExtension"
9
+ targetNamespace="http://wixtoolset.org/schemas/v4/wxs/msmq"
10
+ xmlns="http://wixtoolset.org/schemas/v4/wxs/msmq">
11
+ <xs:annotation>
12
+ <xs:documentation>
13
+ The source code schema for the WiX Toolset MSMQ Extension.
14
+ </xs:documentation>
15
+ </xs:annotation>
16
+
17
+ <xs:import namespace="http://wixtoolset.org/schemas/v4/wxs" />
18
+
19
+ <xs:element name="MessageQueue">
20
+ <xs:annotation><xs:documentation>
21
+ </xs:documentation>
22
+ <xs:appinfo>
23
+ <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" />
24
+ </xs:appinfo>
25
+ </xs:annotation>
26
+ <xs:complexType>
27
+ <xs:sequence>
28
+ <xs:element ref="MessageQueuePermission" minOccurs="0" maxOccurs="unbounded" />
29
+ </xs:sequence>
30
+ <xs:attribute name="Id" use="required" type="xs:string">
31
+ <xs:annotation><xs:documentation>
32
+ </xs:documentation></xs:annotation>
33
+ </xs:attribute>
34
+ <xs:attribute name="Authenticate" use="optional" type="YesNoType">
35
+ <xs:annotation><xs:documentation>
36
+ Default: No.
37
+ </xs:documentation></xs:annotation>
38
+ </xs:attribute>
39
+ <xs:attribute name="BasePriority" use="optional" type="xs:integer" />
40
+ <xs:attribute name="Journal" use="optional" type="YesNoType">
41
+ <xs:annotation><xs:documentation>
42
+ Default: No.
43
+ </xs:documentation></xs:annotation>
44
+ </xs:attribute>
45
+ <xs:attribute name="JournalQuota" use="optional" type="xs:integer" />
46
+ <xs:attribute name="Label" use="required" type="xs:string" />
47
+ <xs:attribute name="MulticastAddress" use="optional" type="xs:string" />
48
+ <xs:attribute name="PathName" use="required" type="xs:string" />
49
+ <xs:attribute name="PrivLevel" use="optional">
50
+ <xs:simpleType>
51
+ <xs:restriction base="xs:NMTOKEN">
52
+ <xs:enumeration value="none" />
53
+ <xs:enumeration value="optional" />
54
+ <xs:enumeration value="body" />
55
+ </xs:restriction>
56
+ </xs:simpleType>
57
+ </xs:attribute>
58
+ <xs:attribute name="Quota" use="optional" type="xs:integer" />
59
+ <xs:attribute name="Transactional" use="optional" type="YesNoType">
60
+ <xs:annotation><xs:documentation>
61
+ Default: No.
62
+ </xs:documentation></xs:annotation>
63
+ </xs:attribute>
64
+ <xs:attribute name="ServiceTypeGuid" use="optional" type="xs:string" />
65
+ </xs:complexType>
66
+ </xs:element>
67
+
68
+ <xs:element name="MessageQueuePermission">
69
+ <xs:annotation><xs:documentation>
70
+ </xs:documentation>
71
+ <xs:appinfo>
72
+ <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" />
73
+ </xs:appinfo>
74
+ </xs:annotation>
75
+ <xs:complexType>
76
+ <xs:attribute name="Id" use="required" type="xs:string">
77
+ <xs:annotation><xs:documentation>
78
+ </xs:documentation></xs:annotation>
79
+ </xs:attribute>
80
+ <xs:attribute name="MessageQueue" use="optional" type="xs:string">
81
+ <xs:annotation><xs:documentation>
82
+ </xs:documentation></xs:annotation>
83
+ </xs:attribute>
84
+ <xs:attribute name="User" use="optional" type="xs:string">
85
+ <xs:annotation><xs:documentation>
86
+ </xs:documentation></xs:annotation>
87
+ </xs:attribute>
88
+ <xs:attribute name="Group" use="optional" type="xs:string">
89
+ <xs:annotation><xs:documentation>
90
+ </xs:documentation></xs:annotation>
91
+ </xs:attribute>
92
+ <xs:attribute name="DeleteMessage" use="optional" type="YesNoType" />
93
+ <xs:attribute name="PeekMessage" use="optional" type="YesNoType" />
94
+ <xs:attribute name="WriteMessage" use="optional" type="YesNoType" />
95
+ <xs:attribute name="DeleteJournalMessage" use="optional" type="YesNoType" />
96
+ <xs:attribute name="SetQueueProperties" use="optional" type="YesNoType" />
97
+ <xs:attribute name="GetQueueProperties" use="optional" type="YesNoType" />
98
+ <xs:attribute name="DeleteQueue" use="optional" type="YesNoType" />
99
+ <xs:attribute name="GetQueuePermissions" use="optional" type="YesNoType" />
100
+ <xs:attribute name="ChangeQueuePermissions" use="optional" type="YesNoType" />
101
+ <xs:attribute name="TakeQueueOwnership" use="optional" type="YesNoType" />
102
+ <xs:attribute name="ReceiveMessage" use="optional" type="YesNoType" />
103
+ <xs:attribute name="ReceiveJournalMessage" use="optional" type="YesNoType" />
104
+ <xs:attribute name="QueueGenericRead" use="optional" type="YesNoType" />
105
+ <xs:attribute name="QueueGenericWrite" use="optional" type="YesNoType" />
106
+ <xs:attribute name="QueueGenericExecute" use="optional" type="YesNoType" />
107
+ <xs:attribute name="QueueGenericAll" use="optional" type="YesNoType" />
108
+ </xs:complexType>
109
+ </xs:element>
110
+
111
+ <xs:simpleType name="YesNoType">
112
+ <xs:annotation>
113
+ <xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation>
114
+ </xs:annotation>
115
+ <xs:restriction base="xs:NMTOKEN">
116
+ <xs:enumeration value="no" />
117
+ <xs:enumeration value="yes" />
118
+ </xs:restriction>
119
+ </xs:simpleType>
120
+
121
+</xs:schema>
src/wixext/tables.xml
new
+54
@@ -0,0 +1,54 @@
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="MessageQueue" createSymbols="yes">
7
+ <columnDefinition name="MessageQueue" type="string" length="72" primaryKey="yes" modularize="column"
8
+ category="identifier" description=""/>
9
+ <columnDefinition name="Component_" type="string" length="72" modularize="column"
10
+ keyTable="Component" keyColumn="1" category="identifier" description=""/>
11
+ <columnDefinition name="BasePriority" type="number" length="4" nullable="yes"
12
+ description=""/>
13
+ <columnDefinition name="JournalQuota" type="number" length="4" nullable="yes"
14
+ description=""/>
15
+ <columnDefinition name="Label" type="localized" length="255" modularize="property" escapeIdtCharacters="yes"
16
+ category="formatted" description=""/>
17
+ <columnDefinition name="MulticastAddress" type="string" length="255" nullable="yes" modularize="property"
18
+ category="formatted" description=""/>
19
+ <columnDefinition name="PathName" type="string" length="255" modularize="property"
20
+ category="formatted" description=""/>
21
+ <columnDefinition name="PrivLevel" type="number" length="4" nullable="yes"
22
+ description=""/>
23
+ <columnDefinition name="Quota" type="number" length="4" nullable="yes"
24
+ description=""/>
25
+ <columnDefinition name="ServiceTypeGuid" type="string" length="72" nullable="yes" modularize="property"
26
+ category="formatted" description=""/>
27
+ <columnDefinition name="Attributes" type="number" length="4"
28
+ description=""/>
29
+ </tableDefinition>
30
+ <tableDefinition name="MessageQueueUserPermission" createSymbols="yes">
31
+ <columnDefinition name="MessageQueueUserPermission" type="string" length="72" primaryKey="yes" modularize="column"
32
+ category="identifier" description=""/>
33
+ <columnDefinition name="Component_" type="string" length="72" modularize="column"
34
+ keyTable="Component" keyColumn="1" category="identifier" description=""/>
35
+ <columnDefinition name="MessageQueue_" type="string" length="72" modularize="column"
36
+ keyTable="MessageQueue" keyColumn="1" category="identifier" description=""/>
37
+ <columnDefinition name="User_" type="string" length="72" modularize="column"
38
+ category="identifier" description=""/>
39
+ <columnDefinition name="Permissions" type="number" length="4"
40
+ description=""/>
41
+ </tableDefinition>
42
+ <tableDefinition name="MessageQueueGroupPermission" createSymbols="yes">
43
+ <columnDefinition name="MessageQueueGroupPermission" type="string" length="72" primaryKey="yes" modularize="column"
44
+ category="identifier" description=""/>
45
+ <columnDefinition name="Component_" type="string" length="72" modularize="column"
46
+ keyTable="Component" keyColumn="1" category="identifier" description=""/>
47
+ <columnDefinition name="MessageQueue_" type="string" length="72" modularize="column"
48
+ keyTable="MessageQueue" keyColumn="1" category="identifier" description=""/>
49
+ <columnDefinition name="Group_" type="string" length="72" modularize="column"
50
+ category="identifier" description=""/>
51
+ <columnDefinition name="Permissions" type="number" length="4"
52
+ description=""/>
53
+ </tableDefinition>
54
+</tableDefinitions>
src/wixlib/MsmqExtension.wixproj
new
+24
@@ -0,0 +1,24 @@
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>{42493058-5FC8-4F85-9884-FF3190E084B6}</ProjectGuid>
8
+ <OutputName>msmq</OutputName>
9
+ <OutputType>Library</OutputType>
10
+ <BindFiles>true</BindFiles>
11
+ </PropertyGroup>
12
+
13
+ <ItemGroup>
14
+ <Compile Include="MsmqExtension.wxs" />
15
+ <EmbeddedResource Include="en-us.wxl" />
16
+ <EmbeddedResource Include="ja-jp.wxl" />
17
+ </ItemGroup>
18
+
19
+ <ItemGroup>
20
+ <ProjectReference Include="..\ca\msmqca.proj" />
21
+ </ItemGroup>
22
+
23
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
24
+</Project>
src/wixlib/MsmqExtension.wxs
new
+31
@@ -0,0 +1,31 @@
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
+
8
+ <Fragment>
9
+ <UI>
10
+ <ProgressText Action="MessageQueuingExecuteInstall" Template="!(loc.MessageQueuingExecuteInstallTemplate)">!(loc.MessageQueuingExecuteInstall)</ProgressText>
11
+ <ProgressText Action="MessageQueuingExecuteUninstall" Template="!(loc.MessageQueuingExecuteUninstallTemplate)">!(loc.MessageQueuingExecuteUninstall)</ProgressText>
12
+ </UI>
13
+
14
+ <CustomAction Id="MessageQueuingInstall" BinaryKey="WixMsmqSched" DllEntry="MessageQueuingInstall" Execute="immediate" Return="check" SuppressModularization="yes"/>
15
+ <CustomAction Id="MessageQueuingUninstall" BinaryKey="WixMsmqSched" DllEntry="MessageQueuingUninstall" Execute="immediate" Return="check" SuppressModularization="yes"/>
16
+ <CustomAction Id="MessageQueuingExecuteInstall" BinaryKey="WixMsmqExec" DllEntry="MessageQueuingExecuteInstall" Execute="deferred" Return="check" Impersonate="no" SuppressModularization="yes"/>
17
+ <CustomAction Id="MessageQueuingRollbackInstall" BinaryKey="WixMsmqExec" DllEntry="MessageQueuingRollbackInstall" Execute="rollback" Return="check" Impersonate="no" SuppressModularization="yes"/>
18
+ <CustomAction Id="MessageQueuingExecuteUninstall" BinaryKey="WixMsmqExec" DllEntry="MessageQueuingExecuteUninstall" Execute="deferred" Return="check" Impersonate="no" SuppressModularization="yes"/>
19
+ <CustomAction Id="MessageQueuingRollbackUninstall" BinaryKey="WixMsmqExec" DllEntry="MessageQueuingRollbackUninstall" Execute="rollback" Return="check" Impersonate="no" SuppressModularization="yes"/>
20
+
21
+ <InstallExecuteSequence>
22
+ <Custom Action="MessageQueuingUninstall" After="DeleteServices" Overridable="yes">VersionNT >= 500</Custom>
23
+ <Custom Action="MessageQueuingInstall" Before="InstallServices" Overridable="yes">VersionNT >= 500</Custom>
24
+ </InstallExecuteSequence>
25
+ </Fragment>
26
+
27
+ <Fragment>
28
+ <Binary Id="WixMsmqExec" SourceFile="mqexec.dll"/>
29
+ <Binary Id="WixMsmqSched" SourceFile="mqsched.dll"/>
30
+ </Fragment>
31
+</Wix>
src/wixlib/en-us.wxl
new
+10
@@ -0,0 +1,10 @@
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="MessageQueuingExecuteInstall" Overridable="yes">Configuring message queues</String>
7
+ <String Id="MessageQueuingExecuteInstallTemplate" Overridable="yes">Queue: [1]</String>
8
+ <String Id="MessageQueuingExecuteUninstall" Overridable="yes">Configuring message queues</String>
9
+ <String Id="MessageQueuingExecuteUninstallTemplate" Overridable="yes">Queue: [1]</String>
10
+</WixLocalization>
src/wixlib/ja-jp.wxl
new
+10
@@ -0,0 +1,10 @@
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="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl">
6
+ <String Id="MessageQueuingExecuteInstall" Overridable="yes">メッセージ キューを構成しています</String>
7
+ <String Id="MessageQueuingExecuteInstallTemplate" Overridable="yes">キュー: [1]</String>
8
+ <String Id="MessageQueuingExecuteUninstall" Overridable="yes">メッセージ キューを構成しています</String>
9
+ <String Id="MessageQueuingExecuteUninstallTemplate" Overridable="yes">キュー: [1]</String>
10
+</WixLocalization>