aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Msmq/ca/mqqueueexec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Msmq/ca/mqqueueexec.cpp')
-rw-r--r--src/ext/Msmq/ca/mqqueueexec.cpp927
1 files changed, 927 insertions, 0 deletions
diff --git a/src/ext/Msmq/ca/mqqueueexec.cpp b/src/ext/Msmq/ca/mqqueueexec.cpp
new file mode 100644
index 00000000..e4304ab8
--- /dev/null
+++ b/src/ext/Msmq/ca/mqqueueexec.cpp
@@ -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
8typedef HRESULT (__stdcall *MQCreateQueueFunc)(PSECURITY_DESCRIPTOR, MQQUEUEPROPS*, LPWSTR, LPDWORD);
9typedef HRESULT (__stdcall *MQDeleteQueueFunc)(LPCWSTR);
10typedef HRESULT (__stdcall *MQPathNameToFormatNameFunc)(LPCWSTR, LPWSTR, LPDWORD);
11typedef HRESULT (__stdcall *MQGetQueueSecurityFunc)(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, DWORD, LPDWORD);
12typedef HRESULT (__stdcall *MQSetQueueSecurityFunc)(LPCWSTR, SECURITY_INFORMATION, PSECURITY_DESCRIPTOR);
13
14
15// private enums
16
17enum eMessageQueueAttributes
18{
19 mqaAuthenticate = (1 << 0),
20 mqaJournal = (1 << 1),
21 mqaTransactional = (1 << 2)
22};
23
24enum eMessageQueuePrivacyLevel
25{
26 mqplNone = 0,
27 mqplOptional = 1,
28 mqplBody = 2
29};
30
31enum 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
54struct 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
68struct 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
80static HRESULT ReadMessageQueueAttributes(
81 LPWSTR* ppwzData,
82 MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
83 );
84static void FreeMessageQueueAttributes(
85 MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
86 );
87static HRESULT ReadMessageQueuePermissionAttributes(
88 LPWSTR* ppwzData,
89 MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
90 );
91static void FreeMessageQueuePermissionAttributes(
92 MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs
93 );
94static HRESULT CreateMessageQueue(
95 MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
96 );
97static HRESULT DeleteMessageQueue(
98 MQI_MESSAGE_QUEUE_ATTRIBUTES* pAttrs
99 );
100static HRESULT SetMessageQueuePermissions(
101 MQI_MESSAGE_QUEUE_PERMISSION_ATTRIBUTES* pAttrs,
102 BOOL fRevoke
103 );
104static void SetAccessPermissions(
105 int iPermissions,
106 LPDWORD pgrfAccessPermissions
107 );
108
109
110// private variables
111
112static HMODULE ghMQRT;
113static MQCreateQueueFunc gpfnMQCreateQueue;
114static MQDeleteQueueFunc gpfnMQDeleteQueue;
115static MQPathNameToFormatNameFunc gpfnMQPathNameToFormatName;
116static MQGetQueueSecurityFunc gpfnMQGetQueueSecurity;
117static MQSetQueueSecurityFunc gpfnMQSetQueueSecurity;
118
119
120// function definitions
121
122HRESULT MqiExecInitialize()
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
152LExit:
153 return hr;
154}
155
156void MqiExecUninitialize()
157{
158 if (ghMQRT)
159 ::FreeLibrary(ghMQRT);
160}
161
162HRESULT 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
198LExit:
199 // clean up
200 FreeMessageQueueAttributes(&attrs);
201
202 return hr;
203}
204
205HRESULT 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
234LExit:
235 // clean up
236 FreeMessageQueueAttributes(&attrs);
237
238 return hr;
239}
240
241HRESULT 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
281LExit:
282 // clean up
283 FreeMessageQueueAttributes(&attrs);
284
285 return hr;
286}
287
288HRESULT 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
317LExit:
318 // clean up
319 FreeMessageQueueAttributes(&attrs);
320
321 return hr;
322}
323
324HRESULT 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
360LExit:
361 // clean up
362 FreeMessageQueuePermissionAttributes(&attrs);
363
364 return hr;
365}
366
367HRESULT 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
396LExit:
397 // clean up
398 FreeMessageQueuePermissionAttributes(&attrs);
399
400 return hr;
401}
402
403HRESULT 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
439LExit:
440 // clean up
441 FreeMessageQueuePermissionAttributes(&attrs);
442
443 return hr;
444}
445
446HRESULT 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
475LExit:
476 // clean up
477 FreeMessageQueuePermissionAttributes(&attrs);
478
479 return hr;
480}
481
482
483// helper function definitions
484
485static 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
516LExit:
517 return hr;
518}
519
520static 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
531static 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
552LExit:
553 return hr;
554}
555
556static 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
566static 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
713LExit:
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
723static 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
761LExit:
762 // clean up
763 ReleaseStr(pwzFormatName);
764
765 return hr;
766}
767
768static 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
875LExit:
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
890static 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}