Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1081 lines
37 KiB

  1. //---------------------------------------------------------------------------
  2. // File: TraceEvent
  3. //
  4. // A Managed wrapper for Event Tracing for Windows
  5. //
  6. // Author: Melur Raghuraman
  7. // Extended By: Baskar Sridharan (7 June 2002).
  8. // Date: 10 Oct 2001
  9. //---------------------------------------------------------------------------
  10. using System;
  11. using System.Collections;
  12. using System.Diagnostics;
  13. using System.Runtime.InteropServices;
  14. using System.Reflection;
  15. namespace Microsoft.Win32.Diagnostics
  16. {
  17. //
  18. // TODO: Cover all possible EventTypes
  19. //
  20. [System.CLSCompliant(false)]
  21. public sealed class EventType
  22. {
  23. // Ensure class cannot be instantiated
  24. private EventType() {}
  25. public const uint Info = 0x00; // Information or Point Event
  26. public const uint StartEvent = 0x01; // Start of an activity
  27. public const uint EndEvent = 0x02; // End of an activity
  28. public const uint DcStart = 0x03; // Event at Start of Data Collection
  29. public const uint DcEnd = 0x04; // Event at End of Data Collection
  30. public const uint Extension = 0x05; // Extension Event
  31. public const uint Reply = 0x06; // Request-Reply Event
  32. public const uint Dequeue = 0x07; // Enqueue-Dequeue Event
  33. public const uint Checkpoint = 0x08;// Checkpoint Event
  34. public const uint Reserved = 0x09; // Reserved Event
  35. public const uint Message = 0xFF; // Debug Message Event Type
  36. // new Event Types beyond Win32 types
  37. public const uint Connect = 0x10; // Connect Event Type
  38. public const uint Disconnect = 0x11;// Disconnect Event Type
  39. // Open-Close, Connect-Disconnect, Request-Response
  40. // Send-Receive, Start-End, Enqueue-Dequeue, Lock-Unlock
  41. // Enter-Leave, Parent-child, Read-Write, Create-Delete
  42. // new-dispose, alloc-free, client-server,
  43. // Checkpoint/Marker,
  44. }
  45. [System.CLSCompliant(false)]
  46. internal struct TypeNumberMap
  47. {
  48. internal const byte NULL_NO=0;
  49. internal const byte OBJECT_NO = 1;
  50. internal const byte STRING_NO = 2;
  51. internal const byte SBYTE_NO = 3;
  52. internal const byte BYTE_NO = 4;
  53. internal const byte INT16_NO = 5;
  54. internal const byte UINT16_NO = 6;
  55. internal const byte INT32_NO = 7;
  56. internal const byte UINT32_NO = 8;
  57. internal const byte INT64_NO = 9;
  58. internal const byte UINT64_NO = 10;
  59. internal const byte CHAR_NO = 11;
  60. internal const byte SINGLE_NO = 12;
  61. internal const byte DOUBLE_NO = 13;
  62. internal const byte BOOLEAN_NO = 14;
  63. internal const byte DECIMAL_NO = 15;
  64. }
  65. //
  66. // TODO: Check with Debug Level constants in NT and System.Diagnostics
  67. //
  68. public enum TraceFlags: int
  69. {
  70. Error=1, Warning=2, Info=4, Info1=8, Info2=16, Info3=32, Info4=64, Info5=128, Info6=256, Info7=512, Info8=1024,
  71. Performance=2048, Performance1=4096, Performance2=8192, Performance3=16384, Performance4=32768, Performance5=65536,
  72. Performance6=131072, Performance7=262144, Performance8=524288
  73. }
  74. [Guid("189456B1-2B4C-473f-A249-3856DD93F9D3")]
  75. [System.CLSCompliant(false)]
  76. public interface ITraceMessageDecoder
  77. {
  78. unsafe int DecodeTraceMessage(byte* message, char* buffer, int bufferSize, ref int dataSize);
  79. }
  80. [System.CLSCompliant(false)]
  81. [Guid("748004CA-4959-409a-887C-6546438CF48E")]
  82. public class TraceProvider : ITraceMessageDecoder
  83. {
  84. static private EtwTrace.EtwProc etwProc; // Trace Callback function
  85. private ulong registrationHandle; // Trace Registration Handle
  86. private ulong traceHandle; // Trace Logger Handle from callback
  87. private uint level; // Tracing Level
  88. private uint flags; // Trace Enable Flags
  89. private bool enabled; // Enabled flag from Trace callback
  90. private const byte noOfBytesPerArg = 3;
  91. private string defaultString = "Foo";
  92. private string defaultFmtStr = "Default Format String";
  93. private Hashtable messageFormatTable = new Hashtable();
  94. string applicationName= "CSharp Software Tracing App";
  95. //Default GUID used by Trace Message Strings.
  96. private Guid MessageGuid = new Guid("{b4955bf0-3af1-4740-b475-99055d3fe9aa}");
  97. public TraceProvider()
  98. {
  99. //Such a default constructor is required for COM Interop
  100. }
  101. public TraceProvider(string applicationName, Guid controlGuid)
  102. {
  103. Level = 0;
  104. flags = 0;
  105. IsEnabled= false;
  106. traceHandle = 0;
  107. registrationHandle = 0;
  108. this.applicationName = applicationName; //Currently, we don't use this variable
  109. //
  110. // Register the controlGuid with ETW
  111. //
  112. Register(controlGuid);
  113. }
  114. public TraceProvider(ulong traceHandle)
  115. {
  116. this.traceHandle = traceHandle;
  117. }
  118. ~TraceProvider()
  119. {
  120. //
  121. // Unregister from ETW using the registrationHandle saved from
  122. // the register call.
  123. //
  124. EtwTrace.UnregisterTraceGuids(registrationHandle);
  125. GC.KeepAlive(etwProc);
  126. }
  127. public uint Flags
  128. {
  129. get{
  130. return flags;
  131. }
  132. }
  133. internal uint Level
  134. {
  135. get
  136. {
  137. return level;
  138. }
  139. // set should not be public
  140. set
  141. {
  142. level = value;
  143. }
  144. }
  145. public bool IsEnabled
  146. {
  147. get
  148. {
  149. return enabled;
  150. }
  151. set
  152. {
  153. enabled = value;
  154. }
  155. }
  156. //
  157. // This callback function is called by ETW to enable or disable Tracing dynamically
  158. //
  159. public unsafe uint MyCallback(uint requestCode, System.IntPtr context, System.IntPtr bufferSize, byte* byteBuffer)
  160. {
  161. try
  162. {
  163. BaseEvent* buffer = (BaseEvent *)byteBuffer;
  164. switch(requestCode)
  165. {
  166. case EtwTrace.RequestCodes.EnableEvents:
  167. traceHandle = buffer->HistoricalContext;
  168. //traceHandle = EtwTrace.GetTraceLoggerHandle((BaseEvent *)buffer);
  169. flags = (uint)EtwTrace.GetTraceEnableFlags((ulong)buffer->HistoricalContext);
  170. Level = (uint)EtwTrace.GetTraceEnableLevel((ulong)buffer->HistoricalContext);
  171. IsEnabled = true;
  172. break;
  173. case EtwTrace.RequestCodes.DisableEvents:
  174. IsEnabled = false;
  175. traceHandle = 0;
  176. Level = 0 ;
  177. flags = 0 ;
  178. break;
  179. default:
  180. IsEnabled = false;
  181. traceHandle = 0;
  182. break;
  183. }
  184. return 0;
  185. }
  186. catch(Exception e)
  187. {
  188. Console.WriteLine("Exception caught - '{0}'", e.Message);
  189. return 0;//TODO: Shouldn't we be returning a different value here ?
  190. }
  191. }
  192. //
  193. // Registers a Dynamically Generated GUID automatically with an inbuilt callback
  194. //
  195. private unsafe uint Register(Guid controlGuid)
  196. {
  197. uint status;
  198. TraceGuidRegistration guidReg = new TraceGuidRegistration();
  199. Guid dummyGuid = new Guid("{b4955bf0-3af1-4740-b475-99055d3fe9aa}");
  200. etwProc = new EtwTrace.EtwProc(MyCallback);
  201. guidReg.Guid = &dummyGuid;
  202. guidReg.RegHandle = null;
  203. status = EtwTrace.RegisterTraceGuids(etwProc, null, ref controlGuid, 1, ref guidReg, null, null, out registrationHandle);
  204. if (status != 0)
  205. {
  206. Console.WriteLine("Register() call Failed with Status {0}", status);
  207. }
  208. return status;
  209. }
  210. public unsafe uint TraceEvent(Guid eventGuid, uint evtype)
  211. {
  212. BaseEvent ev; // Takes up 192 bytes on the stack
  213. ev.ClientContext = 0;
  214. ev.Guid = eventGuid;
  215. ev.ProviderId = evtype;
  216. ev.BufferSize = 48; // sizeof(EVENT_TRACE_HEADER)
  217. return EtwTrace.TraceEvent(traceHandle, (char*)&ev);
  218. }
  219. //
  220. // This is the 1 object overload
  221. //
  222. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0)
  223. {
  224. return TraceEvent(eventGuid, evtype, data0, null, null, null, null, null, null, null, null);
  225. }
  226. //
  227. // This is the 2 argument overload
  228. //
  229. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1)
  230. {
  231. return TraceEvent(eventGuid, evtype, data0, data1, null, null, null, null, null, null, null);
  232. }
  233. //
  234. // This is the 3 argument overload
  235. //
  236. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2)
  237. {
  238. return TraceEvent(eventGuid, evtype, data0, data1, data2, null, null, null, null, null, null);
  239. }
  240. //
  241. // This is the 4 argument overload
  242. //
  243. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3)
  244. {
  245. return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, null, null, null, null, null);
  246. }
  247. //
  248. // This is the 5 argument overload
  249. //
  250. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4)
  251. {
  252. return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, null, null, null, null);
  253. }
  254. //
  255. // This is the 6 argument overload
  256. //
  257. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5)
  258. {
  259. return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, null, null, null);
  260. }
  261. //
  262. // This is the 7 argument overload
  263. //
  264. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6)
  265. {
  266. return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, data6, null, null);
  267. }
  268. //
  269. // This is the 8 argument overload
  270. //
  271. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6, object data7)
  272. {
  273. return TraceEvent(eventGuid, evtype, data0, data1, data2, data3, data4, data5, data6, data7, null);
  274. }
  275. public unsafe uint TraceEvent(Guid eventGuid, uint evtype, object data0, object data1, object data2, object data3, object data4, object data5, object data6, object data7, object data8)
  276. {
  277. uint status = 0;
  278. BaseEvent ev; // Takes up 192 bytes on the stack
  279. char* buffer = stackalloc char[128];
  280. uint offset = 0;
  281. char* ptr = buffer;
  282. string s0 , s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8;
  283. int stringMask = 0;
  284. uint argCount=0;
  285. s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = defaultString;
  286. ev.Flags = 0x00120000; // define Constants
  287. ev.Guid = eventGuid;
  288. ev.ProviderId = evtype;
  289. MofField *be = null;
  290. if (data0 != null)
  291. {
  292. argCount++;
  293. be = &(&ev.UserData)[0];
  294. if ((s0 = ProcessOneObject(data0, be, ptr, ref offset)) != null)
  295. {
  296. stringMask |= 0x00000001;
  297. }
  298. }
  299. if (data1 != null)
  300. {
  301. argCount++;
  302. be = &(&ev.UserData)[1];
  303. ptr = buffer + offset;
  304. if ((s1 = ProcessOneObject(data1, be, ptr, ref offset)) != null)
  305. {
  306. stringMask |= 0x00000002;
  307. }
  308. }
  309. if (data2 != null)
  310. {
  311. argCount++;
  312. be = &(&ev.UserData)[2];
  313. ptr = buffer + offset;
  314. if ((s2 = ProcessOneObject(data2, be, ptr, ref offset)) != null)
  315. {
  316. stringMask |= 0x00000004;
  317. }
  318. }
  319. if (data3 != null)
  320. {
  321. argCount++;
  322. be = &(&ev.UserData)[3];
  323. ptr = buffer + offset;
  324. if ((s3 = ProcessOneObject(data3, be, ptr, ref offset)) != null)
  325. {
  326. stringMask |= 0x00000008;
  327. }
  328. }
  329. if (data4 != null)
  330. {
  331. argCount++;
  332. be = &(&ev.UserData)[4];
  333. ptr = buffer + offset;
  334. if ((s4 = ProcessOneObject(data4, be, ptr, ref offset)) != null)
  335. {
  336. stringMask |= 0x00000010;
  337. }
  338. }
  339. if (data5 != null)
  340. {
  341. argCount++;
  342. be = &(&ev.UserData)[5];
  343. ptr = buffer + offset;
  344. if ((s5 = ProcessOneObject(data5, be, ptr, ref offset)) != null)
  345. {
  346. stringMask |= 0x00000020;
  347. }
  348. }
  349. if (data6 != null)
  350. {
  351. argCount++;
  352. be = &(&ev.UserData)[6];
  353. ptr = buffer + offset;
  354. if ((s6 = ProcessOneObject(data6, be, ptr, ref offset)) != null)
  355. {
  356. stringMask |= 0x00000040;
  357. }
  358. }
  359. if (data7 != null)
  360. {
  361. argCount++;
  362. be = &(&ev.UserData)[7];
  363. ptr = buffer + offset;
  364. if ((s7 = ProcessOneObject(data7, be, ptr, ref offset)) != null)
  365. {
  366. stringMask |= 0x00000080;
  367. }
  368. }
  369. if (data8 != null)
  370. {
  371. argCount++;
  372. be = &(&ev.UserData)[8];
  373. ptr = buffer + offset;
  374. if ((s8 = ProcessOneObject(data8, be, ptr, ref offset)) != null)
  375. {
  376. stringMask |= 0x00000100;
  377. }
  378. }
  379. //
  380. // Now pin all the strings and use the stringMask to pass them over through
  381. // mofField.
  382. //
  383. fixed (char* vptr0 = s0, vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8 )
  384. {
  385. if ((stringMask & 0x00000001) != 0)
  386. {
  387. (&ev.UserData)[0].DataLength = (uint) s0.Length * 2;
  388. (&ev.UserData)[0].DataPointer = (void*)vptr0;
  389. }
  390. if ((stringMask & 0x00000002)!= 0)
  391. {
  392. (&ev.UserData)[1].DataLength = (uint) s1.Length * 2;
  393. (&ev.UserData)[1].DataPointer = (void*)vptr1;
  394. }
  395. if ((stringMask & 0x00000004)!= 0)
  396. {
  397. (&ev.UserData)[2].DataLength = (uint) s2.Length * 2;
  398. (&ev.UserData)[2].DataPointer = (void*)vptr2;
  399. }
  400. if ((stringMask & 0x00000008)!= 0)
  401. {
  402. (&ev.UserData)[3].DataLength = (uint) s3.Length * 2;
  403. (&ev.UserData)[3].DataPointer = (void*)vptr3;
  404. }
  405. if ((stringMask & 0x00000010)!= 0)
  406. {
  407. (&ev.UserData)[4].DataLength = (uint) s4.Length * 2;
  408. (&ev.UserData)[4].DataPointer = (void*)vptr4;
  409. }
  410. if ((stringMask & 0x00000020)!= 0)
  411. {
  412. (&ev.UserData)[5].DataLength = (uint) s5.Length * 2;
  413. (&ev.UserData)[5].DataPointer = (void*)vptr5;
  414. }
  415. if ((stringMask & 0x00000040)!= 0)
  416. {
  417. (&ev.UserData)[6].DataLength = (uint) s6.Length * 2;
  418. (&ev.UserData)[6].DataPointer = (void*)vptr6;
  419. }
  420. if ((stringMask & 0x00000080)!= 0)
  421. {
  422. (&ev.UserData)[7].DataLength = (uint) s7.Length * 2;
  423. (&ev.UserData)[7].DataPointer = (void*)vptr7;
  424. }
  425. if ((stringMask & 0x00000100)!= 0)
  426. {
  427. (&ev.UserData)[8].DataLength = (uint) s8.Length * 2;
  428. (&ev.UserData)[8].DataPointer = (void*)vptr8;
  429. }
  430. ev.BufferSize = 48 + argCount * 16;
  431. status = EtwTrace.TraceEvent(traceHandle, (char*)&ev);
  432. }
  433. return status;
  434. }
  435. private unsafe string ProcessOneObject(object data, MofField * mofField, char* ptr, ref uint offSet)
  436. {
  437. return EncodeObject(data, mofField, ptr, ref offSet, (byte *)null);
  438. }
  439. //TODO[1]: Need to accomodate Win64 alignment issues. Code that might cause problems
  440. // have been tagged with "WIN64 Changes".
  441. private unsafe string EncodeObject(object data, MofField * mofField, char* ptr, ref uint offSet, byte* ptrArgInfo)
  442. {
  443. if (data == null)
  444. {
  445. *ptrArgInfo = (byte)0; //NULL type, WIN64 Changes
  446. *(ushort *)(ptrArgInfo+1) = (ushort)0;
  447. mofField->DataLength = 0;
  448. mofField->DataPointer=(void *)null; //WIN64 Changes (?)
  449. return null;
  450. }
  451. string sRet = data as string;
  452. if (sRet != null)
  453. {
  454. *ptrArgInfo = (byte)2; //WIN64 Changes
  455. *(ushort *)(ptrArgInfo+1) = (ushort)(sRet.Length<65535?sRet.Length:65535); //WIN64 Changes
  456. return sRet;
  457. }
  458. if (data is sbyte)
  459. {
  460. mofField->DataLength = sizeof(sbyte);
  461. *ptrArgInfo = (byte)3; //WIN64 Changes
  462. sbyte* sbyteptr = (sbyte*)ptr;
  463. *sbyteptr = (sbyte) data; //WIN64 Changes
  464. mofField->DataPointer = (void *) sbyteptr;
  465. offSet += sizeof(sbyte);
  466. }
  467. else if (data is byte)
  468. {
  469. mofField->DataLength = sizeof(byte);
  470. *ptrArgInfo = (byte)4; //WIN64 Changes
  471. byte* byteptr = (byte*)ptr;
  472. *byteptr = (byte) data; //WIN64 Changes
  473. mofField->DataPointer = (void *) byteptr;
  474. offSet += sizeof(byte);
  475. }
  476. else if (data is short)
  477. {
  478. mofField->DataLength = sizeof(short);
  479. *ptrArgInfo = (byte)5; //WIN64 Changes
  480. short* shortptr = (short*)ptr;
  481. *shortptr = (short) data; //WIN64 Changes
  482. mofField->DataPointer = (void *) shortptr;
  483. offSet += sizeof(short);
  484. }
  485. else if (data is ushort)
  486. {
  487. mofField->DataLength = sizeof(ushort);
  488. *ptrArgInfo = (byte)6; //WIN64 Changes
  489. ushort* ushortptr = (ushort*)ptr;
  490. *ushortptr = (ushort) data; //WIN64 Changes
  491. mofField->DataPointer = (void *) ushortptr;
  492. offSet += sizeof(ushort);
  493. }
  494. else if (data is int)
  495. {
  496. mofField->DataLength = sizeof(int);
  497. *ptrArgInfo = (byte)7; //WIN64 Changes
  498. int* intptr = (int*)ptr;
  499. *intptr = (int) data; //WIN64 Changes
  500. mofField->DataPointer = (void *) intptr;
  501. offSet += sizeof(int);
  502. }
  503. else if (data is uint )
  504. {
  505. mofField->DataLength = sizeof(uint);
  506. *ptrArgInfo = (byte)8; //WIN64 Changes
  507. uint* uintptr = (uint*)ptr;
  508. *uintptr = (uint) data; //WIN64 Changes
  509. mofField->DataPointer = (void *) uintptr;
  510. offSet += sizeof(uint);
  511. }
  512. else if (data is long )
  513. {
  514. mofField->DataLength = sizeof(long);
  515. *ptrArgInfo = (byte)9; //WIN64 Changes
  516. long* longptr = (long*)ptr;
  517. *longptr = (long) data; //WIN64 Changes
  518. mofField->DataPointer = (void *) longptr;
  519. offSet += sizeof(long);
  520. }
  521. else if (data is ulong )
  522. {
  523. mofField->DataLength = sizeof(ulong);
  524. *ptrArgInfo = (byte)10; //WIN64 Changes
  525. ulong* ulongptr = (ulong*)ptr;
  526. *ulongptr = (ulong) data; //WIN64 Changes
  527. mofField->DataPointer = (void *) ulongptr;
  528. offSet += sizeof(ulong);
  529. }
  530. else if (data is char)
  531. {
  532. mofField->DataLength = sizeof(char);
  533. *ptrArgInfo = (byte)11; //WIN64 Changes
  534. char* charptr = (char*)ptr;
  535. *charptr = (char) data; //WIN64 Changes
  536. mofField->DataPointer = (void *) charptr;
  537. offSet += sizeof(char);
  538. }
  539. else if (data is float)
  540. {
  541. mofField->DataLength = sizeof(float);
  542. *ptrArgInfo = (byte)12; //WIN64 Changes
  543. float* floatptr = (float*)ptr;
  544. *floatptr = (float) data; //WIN64 Changes
  545. mofField->DataPointer = (void *) floatptr;
  546. offSet += sizeof(float);
  547. }
  548. else if (data is double)
  549. {
  550. mofField->DataLength = sizeof(double);
  551. *ptrArgInfo = (byte)13; //WIN64 Changes
  552. double* doubleptr = (double*)ptr;
  553. *doubleptr = (double) data; //WIN64 Changes
  554. mofField->DataPointer = (void *) doubleptr;
  555. offSet += sizeof(double);
  556. }
  557. else if (data is bool)
  558. {
  559. mofField->DataLength = sizeof(bool);
  560. *ptrArgInfo = (byte)14; //WIN64 Changes
  561. bool* boolptr = (bool*)ptr;
  562. *boolptr = (bool) data; //WIN64 Changes
  563. mofField->DataPointer = (void *) boolptr;
  564. offSet += sizeof(bool);
  565. }
  566. else if (data is decimal)
  567. {
  568. mofField->DataLength = (uint)sizeof(decimal);
  569. *ptrArgInfo = (byte)15; //WIN64 Changes
  570. decimal* decimalptr = (decimal*)ptr;
  571. *decimalptr = (decimal) data; //WIN64 Changes
  572. mofField->DataPointer = (void *) decimalptr;
  573. offSet += (uint)sizeof(decimal);
  574. }
  575. else
  576. {
  577. //To our eyes, everything else is a just a string
  578. sRet = data.ToString();
  579. *ptrArgInfo = (byte)2; //WIN64 Changes
  580. *(ushort *)(ptrArgInfo+1) = (ushort)(sRet.Length<65535?sRet.Length:65535); //WIN64 Changes
  581. return sRet;
  582. }
  583. *(ushort *)(ptrArgInfo+1) = (ushort)(mofField->DataLength); //WIN64 Changes (?)
  584. return sRet;
  585. }
  586. private unsafe uint EncodeTraceMessage(Guid eventGuid, uint evtype, byte nargs, object formatstring, object data2, object data3, object data4, object data5, object data6, object data7, object data8, object data9)
  587. {
  588. uint status = 0;
  589. BaseEvent ev; // Takes up 208 bytes on the stack
  590. char* buffer = stackalloc char[144+(1+9*noOfBytesPerArg)/sizeof(char)];//28 characters would be 56 bytes!!!. We are allocating more space than we require.
  591. //Header structure:
  592. //1 byte for number of args
  593. //3 byte for format string type information,
  594. //3 bytes each for the type information for a maximum of 8 arguments
  595. byte *header = (byte *)(buffer+144);
  596. uint offset = 0;
  597. char* ptr = buffer;
  598. string s1 , s2 , s3 , s4 , s5 , s6 , s7 , s8, s9;
  599. int stringMask = 0;
  600. uint argCount=0;
  601. byte *ptrHeader = header;
  602. s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = s9 = defaultString;
  603. ev.Flags = 0x00120000; // define Constants
  604. ev.Guid = eventGuid;
  605. //IMP: evtype MUST be the same as the one specified in the typeve field for CSharp in default.tmf
  606. ev.ProviderId = evtype;
  607. MofField *be = null;
  608. if (header != null)
  609. {
  610. be = &(&ev.UserData)[0];
  611. header[0] = (byte)nargs; //WIN64 Changes (?)
  612. be->DataPointer = (void *)header;
  613. be->DataLength = (uint)(1+nargs*noOfBytesPerArg);
  614. }
  615. if (formatstring == null)
  616. formatstring = defaultFmtStr;
  617. if (formatstring != null)
  618. {
  619. //data1 would, in most cases, be the format string
  620. argCount++;
  621. be = &(&ev.UserData)[1];
  622. ptr = buffer + offset;
  623. if ((s1 = EncodeObject(formatstring, be, ptr, ref offset, ++header)) != null)
  624. {
  625. stringMask |= 0x00000002;
  626. }
  627. }
  628. if (argCount <= nargs)
  629. {
  630. argCount++;
  631. be = &(&ev.UserData)[2];
  632. ptr = buffer + offset;
  633. if ((s2 = EncodeObject(data2, be, ptr, ref offset, header+1*noOfBytesPerArg)) != null)
  634. {
  635. stringMask |= 0x00000004;
  636. }
  637. }
  638. if (argCount <= nargs)
  639. {
  640. argCount++;
  641. be = &(&ev.UserData)[3];
  642. ptr = buffer + offset;
  643. if ((s3 = EncodeObject(data3, be, ptr, ref offset, header+2*noOfBytesPerArg)) != null)
  644. {
  645. stringMask |= 0x00000008;
  646. }
  647. }
  648. if (argCount <= nargs)
  649. {
  650. argCount++;
  651. be = &(&ev.UserData)[4];
  652. ptr = buffer + offset;
  653. if ((s4 = EncodeObject(data4, be, ptr, ref offset, header+3*noOfBytesPerArg)) != null)
  654. {
  655. stringMask |= 0x00000010;
  656. }
  657. }
  658. if (argCount <= nargs)
  659. {
  660. argCount++;
  661. be = &(&ev.UserData)[5];
  662. ptr = buffer + offset;
  663. if ((s5 = EncodeObject(data5, be, ptr, ref offset, header+4*noOfBytesPerArg)) != null)
  664. {
  665. stringMask |= 0x00000020;
  666. }
  667. }
  668. if (argCount <= nargs)
  669. {
  670. argCount++;
  671. be = &(&ev.UserData)[6];
  672. ptr = buffer + offset;
  673. if ((s6 = EncodeObject(data6, be, ptr, ref offset,header+5*noOfBytesPerArg)) != null)
  674. {
  675. stringMask |= 0x00000040;
  676. }
  677. }
  678. if (argCount <= nargs)
  679. {
  680. argCount++;
  681. be = &(&ev.UserData)[7];
  682. ptr = buffer + offset;
  683. if ((s7 = EncodeObject(data7, be, ptr, ref offset,header+6*noOfBytesPerArg)) != null)
  684. {
  685. stringMask |= 0x00000080;
  686. }
  687. }
  688. if (argCount <= nargs)
  689. {
  690. argCount++;
  691. be = &(&ev.UserData)[8];
  692. ptr = buffer + offset;
  693. if ((s8 = EncodeObject(data8, be, ptr, ref offset,header+7*noOfBytesPerArg)) != null)
  694. {
  695. stringMask |= 0x00000100;
  696. }
  697. }
  698. if (argCount <= nargs)
  699. {
  700. argCount++;
  701. be = &(&ev.UserData)[9];
  702. ptr = buffer + offset;
  703. if ((s9 = EncodeObject(data9, be, ptr, ref offset, header+8*noOfBytesPerArg)) != null)
  704. {
  705. stringMask |= 0x00000200;
  706. }
  707. }
  708. //
  709. // Now pin all the strings and use the stringMask to pass them over through
  710. // mofField.
  711. //
  712. fixed (char* vptr1 = s1, vptr2 = s2, vptr3 = s3, vptr4 = s4, vptr5 = s5, vptr6 = s6, vptr7 = s7, vptr8 = s8, vptr9 = s9 )
  713. {
  714. if ((stringMask & 0x00000002)!= 0)
  715. {
  716. (&ev.UserData)[1].DataLength = (uint) (s1.Length<65535/2?s1.Length*2:65535);//s1.Length*2;
  717. (&ev.UserData)[1].DataPointer = (void*)(vptr1);
  718. }
  719. if ((stringMask & 0x00000004)!= 0)
  720. {
  721. (&ev.UserData)[2].DataLength = (uint) (s2.Length<65535/2?s2.Length*2:65535);//s2.Length * 2;
  722. (&ev.UserData)[2].DataPointer = (void*)(vptr2);
  723. }
  724. if ((stringMask & 0x00000008)!= 0)
  725. {
  726. (&ev.UserData)[3].DataLength = (uint) (s3.Length<65535/2?s3.Length*2:65535);//s3.Length * 2;
  727. (&ev.UserData)[3].DataPointer = (void*)(vptr3);
  728. }
  729. if ((stringMask & 0x00000010)!= 0)
  730. {
  731. (&ev.UserData)[4].DataLength = (uint) (s4.Length<65535/2?s4.Length*2:65535);//s4.Length * 2;
  732. (&ev.UserData)[4].DataPointer = (void*)(vptr4);
  733. }
  734. if ((stringMask & 0x00000020)!= 0)
  735. {
  736. (&ev.UserData)[5].DataLength = (uint) (s5.Length<65535/2?s5.Length*2:65535);//s5.Length * 2;
  737. (&ev.UserData)[5].DataPointer = (void*)(vptr5);
  738. }
  739. if ((stringMask & 0x00000040)!= 0)
  740. {
  741. (&ev.UserData)[6].DataLength = (uint) (s6.Length<65535/2?s6.Length*2:65535);//s6.Length * 2;
  742. (&ev.UserData)[6].DataPointer = (void*)(vptr6);
  743. }
  744. if ((stringMask & 0x00000080)!= 0)
  745. {
  746. (&ev.UserData)[7].DataLength = (uint) (s7.Length<65535/2?s7.Length*2:65535);//s7.Length * 2;
  747. (&ev.UserData)[7].DataPointer = (void*)(vptr7);
  748. }
  749. if ((stringMask & 0x00000100)!= 0)
  750. {
  751. (&ev.UserData)[8].DataLength = (uint) (s8.Length<65535/2?s8.Length*2:65535);//s8.Length * 2;
  752. (&ev.UserData)[8].DataPointer = (void*)(vptr8);
  753. }
  754. if ((stringMask & 0x00000200)!= 0)
  755. {
  756. (&ev.UserData)[9].DataLength = (uint) (s9.Length<65535/2?s9.Length*2:65535);//s9.Length * 2;
  757. (&ev.UserData)[9].DataPointer = (void*)(vptr9);
  758. }
  759. ev.BufferSize = 48 + (argCount+1) * 16;//the extra mof field is for the header
  760. status = EtwTrace.TraceEvent(traceHandle, (char*)&ev);
  761. }
  762. return status;
  763. }
  764. public unsafe int DecodeTraceMessage(byte* message, char* buffer, int bufferSize /* in chars */, ref int dataSize /*Note: This is # of *chars* and not bytes*/)
  765. {
  766. if (buffer == null || message == null || bufferSize <= 0)
  767. return 0; //TODO[1]: Do we need a more detailed error code ?
  768. try
  769. {
  770. int i=0;
  771. byte nargs = *message;
  772. ushort lenFmtStr = *(ushort *)(message+2);
  773. char* pcFmtStr = (char *)(message+1+nargs*noOfBytesPerArg);//start of the format string
  774. byte* argData = message+1+nargs*noOfBytesPerArg+lenFmtStr*2; //start of the argument data
  775. object[] argObject = new object[nargs];
  776. byte argType;
  777. ushort argLen;
  778. String formatString = new String(pcFmtStr,0,lenFmtStr);
  779. //Excluding the format string
  780. for(i = 0; i < nargs-1; i++)
  781. {
  782. argType = *(message+1+(i+1)*noOfBytesPerArg);
  783. argLen = *(ushort *)(message+1+(i+1)*noOfBytesPerArg+1); //WIN64 Changes (?)
  784. switch(argType)
  785. {
  786. case TypeNumberMap.NULL_NO:
  787. argObject[i] = null;
  788. break;
  789. case TypeNumberMap.STRING_NO:
  790. {
  791. String s;
  792. if (argLen == 0)
  793. s = "";
  794. else s = new String((char *)argData,0,argLen);
  795. argObject[i] = s;
  796. argLen *= 2; //adjust the length
  797. break;
  798. }
  799. case TypeNumberMap.SBYTE_NO:
  800. {
  801. sbyte sb = *(sbyte *)argData; //WIN64 Changes
  802. argObject[i] = sb;
  803. break;
  804. }
  805. case TypeNumberMap.BYTE_NO:
  806. {
  807. byte b = *argData; //WIN64 Changes
  808. argObject[i] = b;
  809. break;
  810. }
  811. case TypeNumberMap.INT16_NO:
  812. {
  813. short s = *(short *)argData; //WIN64 Changes
  814. argObject[i] = s;
  815. break;
  816. }
  817. case TypeNumberMap.UINT16_NO:
  818. {
  819. ushort us = *(ushort *)argData; //WIN64 Changes
  820. argObject[i] = us;
  821. break;
  822. }
  823. case TypeNumberMap.INT32_NO:
  824. {
  825. int id = *(int *)argData; //WIN64 Changes
  826. argObject[i] = id;
  827. break;
  828. }
  829. case TypeNumberMap.UINT32_NO:
  830. {
  831. uint uid = *(uint *)argData; //WIN64 Changes
  832. argObject[i] = uid;
  833. break;
  834. }
  835. case TypeNumberMap.INT64_NO:
  836. {
  837. long l = *(long *)argData; //WIN64 Changes
  838. argObject[i] = l;
  839. break;
  840. }
  841. case TypeNumberMap.UINT64_NO:
  842. {
  843. ulong ul = *(ulong *)argData; //WIN64 Changes
  844. argObject[i] = ul;
  845. break;
  846. }
  847. case TypeNumberMap.CHAR_NO:
  848. {
  849. char c = *(char *)argData; //WIN64 Changes
  850. argObject[i] = c;
  851. break;
  852. }
  853. case TypeNumberMap.SINGLE_NO:
  854. {
  855. float f = *(float *)argData; //WIN64 Changes
  856. argObject[i] = f;
  857. break;
  858. }
  859. case TypeNumberMap.DOUBLE_NO:
  860. {
  861. double d = *(double *)argData; //WIN64 Changes
  862. argObject[i] = d;
  863. break;
  864. }
  865. case TypeNumberMap.BOOLEAN_NO:
  866. {
  867. bool b = *(bool *)argData; //WIN64 Changes
  868. argObject[i] = b;
  869. break;
  870. }
  871. case TypeNumberMap.DECIMAL_NO:
  872. {
  873. decimal d = *(decimal *)argData; //WIN64 Changes
  874. argObject[i] = d;
  875. break;
  876. }
  877. }
  878. argData += argLen;
  879. }
  880. string fStr = String.Format(formatString,argObject);
  881. if (fStr.Length==0)//empty string
  882. fStr="Format string was empty!";
  883. int arrLen = fStr.Length*2;
  884. dataSize = arrLen+1;
  885. fixed(char* carray = fStr.ToCharArray())
  886. {
  887. if (arrLen+1 <= bufferSize)
  888. {
  889. for(i = 0; i < arrLen; i++)
  890. buffer[i] = carray[i]; //WIN64 Changes (?)
  891. //add null terminator
  892. buffer[i+1] = (char)0x00; //WIN64 Changes (?)
  893. return 1;
  894. }
  895. else
  896. {
  897. //TODO[1]: Do we need to copy as many characters as we can ?
  898. //Not sure if it is useful to do so because the caller may have to come back
  899. //with the right buffer size to get all the data. So why copy part of the data twice ?
  900. return 0;
  901. }
  902. }
  903. }
  904. catch(Exception e)
  905. {
  906. Console.WriteLine("Exception caught: {0}", e.Message);
  907. return -1;
  908. }
  909. }
  910. // ========================================================================
  911. // The following are the Message String Wrappers for Software Tracing Messages
  912. // using Flags.
  913. // There are entried for Format string and zero through 8 arguments.
  914. // These are kept small so they will be inlined
  915. // ========================================================================
  916. // Just the format string
  917. public unsafe void TraceMessage(uint traceFlags, object format )
  918. {
  919. if ((traceFlags&Flags) != 0)
  920. {
  921. EncodeTraceMessage(MessageGuid, (int)14,1, format, null, null, null, null, null, null, null, null);
  922. }
  923. }
  924. // Just one argument
  925. public unsafe void TraceMessage(uint traceFlags, object format, object data1 )
  926. {
  927. if ((traceFlags&Flags) != 0)
  928. {
  929. EncodeTraceMessage(MessageGuid, (int)14, 2, format, data1, null, null, null, null, null, null,null);
  930. }
  931. }
  932. // Just two arguments
  933. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2 )
  934. {
  935. if ((traceFlags&Flags) != 0)
  936. {
  937. EncodeTraceMessage(MessageGuid, (int)14, 3, format, data1, data2, null, null, null, null, null, null);
  938. }
  939. }
  940. // Just three arguments
  941. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3 )
  942. {
  943. if ((traceFlags&Flags) != 0)
  944. {
  945. EncodeTraceMessage(MessageGuid, (int)14, 4, format, data1, data2, data3, null, null, null, null, null);
  946. }
  947. }
  948. // Just four arguments
  949. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4 )
  950. {
  951. if ((traceFlags&Flags) != 0)
  952. {
  953. EncodeTraceMessage(MessageGuid, (int)14, 5, format, data1, data2, data3, data4, null, null, null, null);
  954. }
  955. }
  956. // Just five arguments
  957. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5 )
  958. {
  959. if ((traceFlags&Flags) != 0)
  960. {
  961. EncodeTraceMessage(MessageGuid, (int)14, 6, format, data1, data2, data3, data4, data5, null, null, null);
  962. }
  963. }
  964. // Just six arguments
  965. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6 )
  966. {
  967. if ((traceFlags&Flags) != 0)
  968. {
  969. EncodeTraceMessage(MessageGuid, (int)14, 7, format, data1, data2, data3, data4, data5, data6, null, null);
  970. }
  971. }
  972. // Just seven arguments
  973. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6, object data7 )
  974. {
  975. if ((traceFlags&Flags) != 0)
  976. {
  977. EncodeTraceMessage(MessageGuid, (int)14, 8, format, data1, data2, data3, data4, data5, data6, data7, null);
  978. }
  979. }
  980. // Just eight arguments
  981. public unsafe void TraceMessage(uint traceFlags, object format, object data1, object data2, object data3, object data4, object data5, object data6, object data7, object data8 )
  982. {
  983. if ((traceFlags&Flags) != 0)
  984. {
  985. EncodeTraceMessage(MessageGuid, (int)14, 9, format, data1, data2, data3, data4, data5, data6, data7, data8);
  986. }
  987. }
  988. }
  989. }