aboutsummaryrefslogtreecommitdiff
path: root/src/wixext/MsmqCompiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/wixext/MsmqCompiler.cs')
-rw-r--r--src/wixext/MsmqCompiler.cs536
1 files changed, 536 insertions, 0 deletions
diff --git a/src/wixext/MsmqCompiler.cs b/src/wixext/MsmqCompiler.cs
new file mode 100644
index 00000000..b40e2dc1
--- /dev/null
+++ b/src/wixext/MsmqCompiler.cs
@@ -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
3namespace 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}