1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 
5 namespace System.ServiceModel
6 {
7     using System.Text;
8     using System.Globalization;
9     using System.Runtime.Serialization;
10     using System.Runtime.InteropServices;
11     using System.Runtime.Versioning;
12     using System.ServiceModel.Channels;
13 
14     [Serializable]
15     public class MsmqException : ExternalException
16     {
17         [NonSerialized]
18         bool? faultSender = null;
19         [NonSerialized]
20         bool? faultReceiver = null;
21         [NonSerialized]
22         Type outerExceptionType = null;
23 
MsmqException()24         public MsmqException()
25         {
26         }
27 
MsmqException(string message)28         public MsmqException(string message)
29             : base(message)
30         {
31         }
32 
MsmqException(string message, int error)33         public MsmqException(string message, int error)
34             : base(message, error)
35         {
36         }
37 
MsmqException(string message, Exception inner)38         public MsmqException(string message, Exception inner)
39             : base(message, inner)
40         {
41         }
42 
MsmqException(SerializationInfo info, StreamingContext context)43         protected MsmqException(SerializationInfo info, StreamingContext context)
44             : base(info, context)
45         {
46         }
47 
48         internal bool FaultSender
49         {
50             get
51             {
52                 TuneBehavior();
53                 return this.faultSender.Value;
54             }
55         }
56 
57         internal bool FaultReceiver
58         {
59             get
60             {
61                 TuneBehavior();
62                 return this.faultReceiver.Value;
63             }
64         }
65 
TuneBehavior()66         void TuneBehavior()
67         {
68             if (this.faultSender.HasValue && this.faultReceiver.HasValue)
69                 return;
70 
71             switch (this.ErrorCode)
72             {
73                 // configuration erors
74                 case UnsafeNativeMethods.MQ_ERROR_ACCESS_DENIED:
75                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(AddressAccessDeniedException); break;
76                 case UnsafeNativeMethods.MQ_ERROR_NO_INTERNAL_USER_CERT:
77                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
78                 case UnsafeNativeMethods.MQ_ERROR_QUEUE_DELETED:
79                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(EndpointNotFoundException); break;
80                 case UnsafeNativeMethods.MQ_ERROR_QUEUE_NOT_FOUND:
81                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(EndpointNotFoundException); break;
82                 case UnsafeNativeMethods.MQ_ERROR_CERTIFICATE_NOT_PROVIDED:
83                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
84                 case UnsafeNativeMethods.MQ_ERROR_INVALID_CERTIFICATE:
85                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
86                 case UnsafeNativeMethods.MQ_ERROR_CANNOT_CREATE_CERT_STORE:
87                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
88                 case UnsafeNativeMethods.MQ_ERROR_CORRUPTED_PERSONAL_CERT_STORE:
89                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
90                 case UnsafeNativeMethods.MQ_ERROR_COULD_NOT_GET_USER_SID:
91                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
92                 case UnsafeNativeMethods.MQ_ERROR_ILLEGAL_FORMATNAME:
93                     faultSender = false; faultReceiver = false; outerExceptionType = typeof(ArgumentException); break;
94                 case UnsafeNativeMethods.MQ_ERROR_ILLEGAL_QUEUE_PATHNAME:
95                     faultSender = false; faultReceiver = false; outerExceptionType = typeof(ArgumentException); break;
96                 case UnsafeNativeMethods.MQ_ERROR_UNSUPPORTED_FORMATNAME_OPERATION:
97                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(ArgumentException); break;
98                 case UnsafeNativeMethods.MQ_ERROR_CANNOT_HASH_DATA_EX:
99                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
100                 case UnsafeNativeMethods.MQ_ERROR_CANNOT_SIGN_DATA_EX:
101                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
102                 case UnsafeNativeMethods.MQ_ERROR_FAIL_VERIFY_SIGNATURE_EX:
103                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
104                 case UnsafeNativeMethods.MQ_ERROR_BAD_SECURITY_CONTEXT:
105                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
106                 case UnsafeNativeMethods.MQ_ERROR_PRIVILEGE_NOT_HELD:
107                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
108                 case UnsafeNativeMethods.MQ_ERROR_SHARING_VIOLATION:
109                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(AddressAccessDeniedException); break;
110                 // transient errors
111                 case UnsafeNativeMethods.MQ_ERROR_DTC_CONNECT:
112                     faultSender = false; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
113                 case UnsafeNativeMethods.MQ_ERROR_IO_TIMEOUT:
114                     faultSender = false; faultReceiver = false; outerExceptionType = typeof(TimeoutException); break;
115                 case UnsafeNativeMethods.MQ_ERROR_QUEUE_NOT_AVAILABLE:
116                     faultSender = false; faultReceiver = true; outerExceptionType = typeof(EndpointNotFoundException); break;
117                 case UnsafeNativeMethods.MQ_ERROR_REMOTE_MACHINE_NOT_AVAILABLE:
118                     faultSender = false; faultReceiver = true; outerExceptionType = typeof(EndpointNotFoundException); break;
119                 case UnsafeNativeMethods.MQ_ERROR_SERVICE_NOT_AVAILABLE:
120                     faultSender = false; faultReceiver = true; outerExceptionType = typeof(EndpointNotFoundException); break;
121                 case UnsafeNativeMethods.MQ_ERROR_INSUFFICIENT_RESOURCES:
122                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
123                 case UnsafeNativeMethods.MQ_ERROR_MESSAGE_STORAGE_FAILED:
124                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
125                 case UnsafeNativeMethods.MQ_ERROR_TRANSACTION_ENLIST:
126                     faultSender = false; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
127                 case UnsafeNativeMethods.MQ_ERROR_TRANSACTION_IMPORT:
128                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
129                 case UnsafeNativeMethods.MQ_ERROR_TRANSACTION_USAGE:
130                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(InvalidOperationException); break;
131                 case UnsafeNativeMethods.MQ_ERROR_STALE_HANDLE:
132                     faultSender = false; faultReceiver = false; outerExceptionType = typeof(InvalidOperationException); break;
133                 // malformed messages
134                 case UnsafeNativeMethods.MQ_ERROR_ILLEGAL_MQQMPROPS:
135                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
136                 case UnsafeNativeMethods.MQ_ERROR_INSUFFICIENT_PROPERTIES:
137                     faultSender = true; faultReceiver = true; outerExceptionType = typeof(CommunicationException); break;
138                 default:
139                     faultSender = true; faultReceiver = true; outerExceptionType = null; break;
140             }
141         }
142 
143         internal Exception Normalized
144         {
145             get
146             {
147                 TuneBehavior();
148                 if (null != this.outerExceptionType)
149                     return Activator.CreateInstance(this.outerExceptionType, new object[] { this.Message, this }) as Exception;
150                 else
151                     return this;
152             }
153         }
154     }
155 
156     static class MsmqError
157     {
158 
159         [ResourceConsumption(ResourceScope.Process)]
GetErrorString(int error)160         public static string GetErrorString(int error)
161         {
162             StringBuilder stringBuilder = new StringBuilder(512);
163 
164             bool result = false;
165             if ((error & 0x0FFF0000) == 0x000E0000)
166             {
167                 int formatFlags = UnsafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS
168                     | UnsafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY
169                     | UnsafeNativeMethods.FORMAT_MESSAGE_FROM_HMODULE;
170 
171                 result = (0 != UnsafeNativeMethods.FormatMessage(
172                         formatFlags,
173                         Msmq.ErrorStrings,
174                         error,
175                         CultureInfo.CurrentCulture.LCID,
176                         stringBuilder,
177                         stringBuilder.Capacity,
178                         IntPtr.Zero));
179             }
180             else
181             {
182                 int formatFlags = UnsafeNativeMethods.FORMAT_MESSAGE_IGNORE_INSERTS
183                     | UnsafeNativeMethods.FORMAT_MESSAGE_ARGUMENT_ARRAY
184                     | UnsafeNativeMethods.FORMAT_MESSAGE_FROM_SYSTEM;
185 
186                 result = (0 != UnsafeNativeMethods.FormatMessage(
187                         formatFlags,
188                         IntPtr.Zero,
189                         error,
190                         CultureInfo.CurrentCulture.LCID,
191                         stringBuilder,
192                         stringBuilder.Capacity,
193                         IntPtr.Zero));
194             }
195 
196             if (result)
197             {
198                 stringBuilder = stringBuilder.Replace("\n", "");
199                 stringBuilder = stringBuilder.Replace("\r", "");
200                 return SR.GetString(
201                     SR.MsmqKnownWin32Error,
202                     stringBuilder.ToString(),
203                     error.ToString(CultureInfo.InvariantCulture),
204                     Convert.ToString(error, 16));
205             }
206             else
207             {
208                 return SR.GetString(
209                     SR.MsmqUnknownWin32Error,
210                     error.ToString(CultureInfo.InvariantCulture),
211                     Convert.ToString(error, 16));
212             }
213         }
214     }
215 }
216 
217