diff options
Diffstat (limited to 'src/ext/Msmq/ca/mqqueuesched.cpp')
-rw-r--r-- | src/ext/Msmq/ca/mqqueuesched.cpp | 582 |
1 files changed, 582 insertions, 0 deletions
diff --git a/src/ext/Msmq/ca/mqqueuesched.cpp b/src/ext/Msmq/ca/mqqueuesched.cpp new file mode 100644 index 00000000..01777ea4 --- /dev/null +++ b/src/ext/Msmq/ca/mqqueuesched.cpp | |||
@@ -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 MqiSchedInitialize() | ||
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 MqiSchedUninitialize() | ||
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 | } | ||