@joebigelow / wix / commits / a12b13c3

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>