ActiveXSerializer.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. //----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //----------------------------------------------------------------------------
  4. namespace System.ServiceModel.MsmqIntegration
  5. {
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Threading;
  9. using System.Runtime.Serialization;
  10. using System.Diagnostics;
  11. using System;
  12. using System.IO;
  13. using System.Globalization;
  14. class ActiveXSerializer
  15. {
  16. byte[] byteBuffer;
  17. char[] charBuffer;
  18. object bufferLock = new object();
  19. TKind[] TakeLockedBuffer<TKind>(out bool lockHeld, int size)
  20. {
  21. lockHeld = false;
  22. Monitor.Enter(this.bufferLock, ref lockHeld);
  23. if (typeof(byte) == typeof(TKind))
  24. {
  25. if (null == this.byteBuffer || size > this.byteBuffer.Length)
  26. this.byteBuffer = new byte[size];
  27. return this.byteBuffer as TKind[];
  28. }
  29. else if (typeof(char) == typeof(TKind))
  30. {
  31. if (null == this.charBuffer || size > this.charBuffer.Length)
  32. this.charBuffer = new char[size];
  33. return this.charBuffer as TKind[];
  34. }
  35. else
  36. return null;
  37. }
  38. void ReleaseLockedBuffer()
  39. {
  40. Monitor.Exit(this.bufferLock);
  41. }
  42. public object Deserialize(MemoryStream stream, int bodyType)
  43. {
  44. if (stream == null)
  45. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
  46. VarEnum variantType = (VarEnum)bodyType;
  47. byte[] bytes;
  48. byte[] newBytes;
  49. int size;
  50. int count;
  51. bool lockHeld;
  52. switch (variantType)
  53. {
  54. case VarEnum.VT_LPSTR:
  55. bytes = stream.ToArray();
  56. size = bytes.Length;
  57. lockHeld = false;
  58. try
  59. {
  60. char[] buffer = TakeLockedBuffer<char>(out lockHeld, size);
  61. System.Text.Encoding.ASCII.GetChars(bytes, 0, size, buffer, 0);
  62. return new String(buffer, 0, size);
  63. }
  64. finally
  65. {
  66. if (lockHeld)
  67. {
  68. ReleaseLockedBuffer();
  69. }
  70. }
  71. case VarEnum.VT_BSTR:
  72. case VarEnum.VT_LPWSTR:
  73. bytes = stream.ToArray();
  74. size = bytes.Length / 2;
  75. lockHeld = false;
  76. try
  77. {
  78. char[] buffer = TakeLockedBuffer<char>(out lockHeld, size);
  79. System.Text.Encoding.Unicode.GetChars(bytes, 0, size * 2, buffer, 0);
  80. return new String(buffer, 0, size);
  81. }
  82. finally
  83. {
  84. if (lockHeld)
  85. {
  86. ReleaseLockedBuffer();
  87. }
  88. }
  89. case VarEnum.VT_VECTOR | VarEnum.VT_UI1:
  90. bytes = stream.ToArray();
  91. newBytes = new byte[bytes.Length];
  92. Array.Copy(bytes, newBytes, bytes.Length);
  93. return newBytes;
  94. case VarEnum.VT_BOOL:
  95. bytes = new byte[1];
  96. count = stream.Read(bytes, 0, 1);
  97. if (count != 1)
  98. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  99. return (bytes[0] != 0);
  100. case VarEnum.VT_CLSID:
  101. bytes = new byte[16];
  102. count = stream.Read(bytes, 0, 16);
  103. if (count != 16)
  104. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  105. return new Guid(bytes);
  106. case VarEnum.VT_CY:
  107. bytes = new byte[8];
  108. count = stream.Read(bytes, 0, 8);
  109. if (count != 8)
  110. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  111. return Decimal.FromOACurrency(BitConverter.ToInt64(bytes, 0));
  112. case VarEnum.VT_DATE:
  113. bytes = new byte[8];
  114. count = stream.Read(bytes, 0, 8);
  115. if (count != 8)
  116. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  117. return new DateTime(BitConverter.ToInt64(bytes, 0));
  118. case VarEnum.VT_I1:
  119. case VarEnum.VT_UI1:
  120. bytes = new byte[1];
  121. count = stream.Read(bytes, 0, 1);
  122. if (count != 1)
  123. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  124. return bytes[0];
  125. case VarEnum.VT_I2:
  126. bytes = new byte[2];
  127. count = stream.Read(bytes, 0, 2);
  128. if (count != 2)
  129. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  130. return BitConverter.ToInt16(bytes, 0);
  131. case VarEnum.VT_UI2:
  132. bytes = new byte[2];
  133. count = stream.Read(bytes, 0, 2);
  134. if (count != 2)
  135. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  136. return BitConverter.ToUInt16(bytes, 0);
  137. case VarEnum.VT_I4:
  138. bytes = new byte[4];
  139. count = stream.Read(bytes, 0, 4);
  140. if (count != 4)
  141. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  142. return BitConverter.ToInt32(bytes, 0);
  143. case VarEnum.VT_UI4:
  144. bytes = new byte[4];
  145. count = stream.Read(bytes, 0, 4);
  146. if (count != 4)
  147. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  148. return BitConverter.ToUInt32(bytes, 0);
  149. case VarEnum.VT_I8:
  150. bytes = new byte[8];
  151. count = stream.Read(bytes, 0, 8);
  152. if (count != 8)
  153. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  154. return BitConverter.ToInt64(bytes, 0);
  155. case VarEnum.VT_UI8:
  156. bytes = new byte[8];
  157. count = stream.Read(bytes, 0, 8);
  158. if (count != 8)
  159. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  160. return BitConverter.ToUInt64(bytes, 0);
  161. case VarEnum.VT_R4:
  162. bytes = new byte[4];
  163. count = stream.Read(bytes, 0, 4);
  164. if (count != 4)
  165. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  166. return BitConverter.ToSingle(bytes, 0);
  167. case VarEnum.VT_R8:
  168. bytes = new byte[8];
  169. count = stream.Read(bytes, 0, 8);
  170. if (count != 8)
  171. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqCannotDeserializeActiveXMessage)));
  172. return BitConverter.ToDouble(bytes, 0);
  173. case VarEnum.VT_NULL:
  174. return null;
  175. default:
  176. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.GetString(SR.MsmqInvalidTypeDeserialization)));
  177. }
  178. }
  179. public void Serialize(Stream stream, object obj, ref int bodyType)
  180. {
  181. if (stream == null)
  182. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
  183. VarEnum variantType;
  184. if (obj is string)
  185. {
  186. int size = ((string)obj).Length * 2;
  187. bool lockHeld = false;
  188. try
  189. {
  190. byte[] buffer = TakeLockedBuffer<byte>(out lockHeld, size);
  191. System.Text.Encoding.Unicode.GetBytes(((string)obj).ToCharArray(), 0, size / 2, buffer, 0);
  192. stream.Write(buffer, 0, size);
  193. }
  194. finally
  195. {
  196. if (lockHeld)
  197. {
  198. ReleaseLockedBuffer();
  199. }
  200. }
  201. variantType = VarEnum.VT_LPWSTR;
  202. }
  203. else if (obj is byte[])
  204. {
  205. byte[] bytes = (byte[])obj;
  206. stream.Write(bytes, 0, bytes.Length);
  207. variantType = VarEnum.VT_UI1 | VarEnum.VT_VECTOR;
  208. }
  209. else if (obj is char[])
  210. {
  211. char[] chars = (char[])obj;
  212. int size = chars.Length * 2;
  213. bool lockHeld = false;
  214. try
  215. {
  216. byte[] buffer = TakeLockedBuffer<byte>(out lockHeld, size);
  217. System.Text.Encoding.Unicode.GetBytes(chars, 0, size / 2, buffer, 0);
  218. stream.Write(buffer, 0, size);
  219. }
  220. finally
  221. {
  222. if (lockHeld)
  223. {
  224. ReleaseLockedBuffer();
  225. }
  226. }
  227. variantType = VarEnum.VT_LPWSTR;
  228. }
  229. else if (obj is byte)
  230. {
  231. stream.Write(new byte[] { (byte)obj }, 0, 1);
  232. variantType = VarEnum.VT_UI1;
  233. }
  234. else if (obj is bool)
  235. {
  236. if ((bool)obj)
  237. stream.Write(new byte[] { 0xff }, 0, 1);
  238. else
  239. stream.Write(new byte[] { 0x00 }, 0, 1);
  240. variantType = VarEnum.VT_BOOL;
  241. }
  242. else if (obj is char)
  243. {
  244. byte[] bytes = BitConverter.GetBytes((Char)obj);
  245. stream.Write(bytes, 0, 2);
  246. variantType = VarEnum.VT_UI2;
  247. }
  248. else if (obj is Decimal)
  249. {
  250. byte[] bytes = BitConverter.GetBytes(Decimal.ToOACurrency((Decimal)obj));
  251. stream.Write(bytes, 0, 8);
  252. variantType = VarEnum.VT_CY;
  253. }
  254. else if (obj is DateTime)
  255. {
  256. byte[] bytes = BitConverter.GetBytes(((DateTime)obj).Ticks);
  257. stream.Write(bytes, 0, 8);
  258. variantType = VarEnum.VT_DATE;
  259. }
  260. else if (obj is Double)
  261. {
  262. byte[] bytes = BitConverter.GetBytes((Double)obj);
  263. stream.Write(bytes, 0, 8);
  264. variantType = VarEnum.VT_R8;
  265. }
  266. else if (obj is Guid)
  267. {
  268. byte[] bytes = ((Guid)obj).ToByteArray();
  269. stream.Write(bytes, 0, 16);
  270. variantType = VarEnum.VT_CLSID;
  271. }
  272. else if (obj is Int16)
  273. {
  274. byte[] bytes = BitConverter.GetBytes((short)obj);
  275. stream.Write(bytes, 0, 2);
  276. variantType = VarEnum.VT_I2;
  277. }
  278. else if (obj is UInt16)
  279. {
  280. byte[] bytes = BitConverter.GetBytes((UInt16)obj);
  281. stream.Write(bytes, 0, 2);
  282. variantType = VarEnum.VT_UI2;
  283. }
  284. else if (obj is Int32)
  285. {
  286. byte[] bytes = BitConverter.GetBytes((int)obj);
  287. stream.Write(bytes, 0, 4);
  288. variantType = VarEnum.VT_I4;
  289. }
  290. else if (obj is UInt32)
  291. {
  292. byte[] bytes = BitConverter.GetBytes((UInt32)obj);
  293. stream.Write(bytes, 0, 4);
  294. variantType = VarEnum.VT_UI4;
  295. }
  296. else if (obj is Int64)
  297. {
  298. byte[] bytes = BitConverter.GetBytes((Int64)obj);
  299. stream.Write(bytes, 0, 8);
  300. variantType = VarEnum.VT_I8;
  301. }
  302. else if (obj is UInt64)
  303. {
  304. byte[] bytes = BitConverter.GetBytes((UInt64)obj);
  305. stream.Write(bytes, 0, 8);
  306. variantType = VarEnum.VT_UI8;
  307. }
  308. else if (obj is Single)
  309. {
  310. byte[] bytes = BitConverter.GetBytes((float)obj);
  311. stream.Write(bytes, 0, 4);
  312. variantType = VarEnum.VT_R4;
  313. }
  314. else
  315. {
  316. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MsmqInvalidTypeSerialization)));
  317. }
  318. bodyType = (int)variantType;
  319. }
  320. }
  321. }