1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** Class: NativeWrapper
9 **
10 ** Purpose:
11 ** This internal class contains wrapper methods over the Native
12 ** Methods of the Eventlog API.   Unlike the raw Native Methods,
13 ** these methods throw EventLogExceptions, check platform
14 ** availablity and perform additional helper functionality
15 ** specific to function.  Also, all methods of this class expose
16 ** the Link Demand for Unmanaged Permission to callers.
17 **
18 ============================================================*/
19 
20 using System;
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.Runtime.InteropServices;
24 using System.Text;
25 using System.Security.Principal;
26 using System.Security.Permissions;
27 using Microsoft.Win32.SafeHandles;
28 using Microsoft.Win32;
29 
30 namespace System.Diagnostics.Eventing.Reader {
31     internal class NativeWrapper {
32         private static bool s_platformNotSupported = (Environment.OSVersion.Version.Major < 6);
33 
34         [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
35         public class SystemProperties {
36             //indicates if the SystemProperties values were already computed (for this event Instance, surely).
37             public bool filled = false;
38 
39             public ushort? Id = null;
40             public byte? Version = null;
41             public ushort? Qualifiers = null;
42             public byte? Level = null;
43             public ushort? Task = null;
44             public byte? Opcode = null;
45             public ulong? Keywords = null;
46             public ulong? RecordId = null;
47             public string ProviderName = null;
48             public Guid? ProviderId = null;
49             public string ChannelName = null;
50             public uint? ProcessId = null;
51             public uint? ThreadId = null;
52             public string ComputerName = null;
53             public System.Security.Principal.SecurityIdentifier UserId = null;
54             public DateTime? TimeCreated = null;
55             public Guid? ActivityId = null;
56             public Guid? RelatedActivityId = null;
57 
SystemProperties()58             public SystemProperties() {
59             }
60         }
61 
62         [System.Security.SecurityCritical]
EvtQuery( EventLogHandle session, string path, string query, int flags)63         public static EventLogHandle EvtQuery(
64                             EventLogHandle session,
65                             string path,
66                             string query,
67                             int flags) {
68             if (s_platformNotSupported)
69                 throw new System.PlatformNotSupportedException();
70             EventLogHandle handle = UnsafeNativeMethods.EvtQuery(session, path, query, flags);
71             int win32Error = Marshal.GetLastWin32Error();
72             if (handle.IsInvalid)
73                 EventLogException.Throw(win32Error);
74             return handle;
75         }
76 
77 
78         [System.Security.SecurityCritical]
EvtSeek( EventLogHandle resultSet, long position, EventLogHandle bookmark, int timeout, UnsafeNativeMethods.EvtSeekFlags flags)79         public static void EvtSeek(
80                             EventLogHandle resultSet,
81                             long position,
82                             EventLogHandle bookmark,
83                             int timeout,
84                             UnsafeNativeMethods.EvtSeekFlags flags) {
85             bool status = UnsafeNativeMethods.EvtSeek(resultSet, position, bookmark, timeout, flags);
86             int win32Error = Marshal.GetLastWin32Error();
87             if (!status)
88                 EventLogException.Throw(win32Error);
89         }
90 
91         [System.Security.SecurityCritical]
EvtSubscribe( EventLogHandle session, SafeWaitHandle signalEvent, string path, string query, EventLogHandle bookmark, IntPtr context, IntPtr callback, int flags)92         public static EventLogHandle EvtSubscribe(
93                             EventLogHandle session,
94                             SafeWaitHandle signalEvent,
95                             string path,
96                             string query,
97                             EventLogHandle bookmark,
98                             IntPtr context,
99                             IntPtr callback,
100                             int flags) {
101             if (s_platformNotSupported)
102                 throw new System.PlatformNotSupportedException();
103 
104             EventLogHandle handle = UnsafeNativeMethods.EvtSubscribe(
105                             session,
106                             signalEvent,
107                             path,
108                             query,
109                             bookmark,
110                             context,
111                             callback,
112                             flags);
113 
114             int win32Error = Marshal.GetLastWin32Error();
115             if (handle.IsInvalid)
116                 EventLogException.Throw(win32Error);
117 
118             return handle;
119         }
120 
121         [System.Security.SecurityCritical]
EvtNext( EventLogHandle queryHandle, int eventSize, IntPtr[] events, int timeout, int flags, ref int returned)122         public static bool EvtNext(
123                             EventLogHandle queryHandle,
124                             int eventSize,
125                             IntPtr[] events,
126                             int timeout,
127                             int flags,
128                             ref int returned) {
129             bool status = UnsafeNativeMethods.EvtNext(queryHandle, eventSize, events, timeout, flags, ref returned);
130             int win32Error = Marshal.GetLastWin32Error();
131             if (!status && win32Error != UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
132                 EventLogException.Throw(win32Error);
133             return win32Error == 0;
134         }
135 
136         [System.Security.SecuritySafeCritical]
EvtCancel(EventLogHandle handle)137         public static void EvtCancel(EventLogHandle handle) {
138 
139             EventLogPermissionHolder.GetEventLogPermission().Demand();
140 
141             if (!UnsafeNativeMethods.EvtCancel(handle)) {
142                 int win32Error = Marshal.GetLastWin32Error();
143                 EventLogException.Throw(win32Error);
144             }
145         }
146 
147 
148         [System.Security.SecurityCritical]
EvtClose(IntPtr handle)149         public static void EvtClose(IntPtr handle) {
150             //
151             // purposely don't check and throw - this is
152             // always called in cleanup / finalize / etc..
153             //
154             UnsafeNativeMethods.EvtClose(handle);
155         }
156 
157         [System.Security.SecurityCritical]
EvtOpenProviderMetadata( EventLogHandle session, string ProviderId, string logFilePath, int locale, int flags)158         public static EventLogHandle EvtOpenProviderMetadata(
159                             EventLogHandle session,
160                             string ProviderId,
161                             string logFilePath,
162                             int locale,
163                             int flags) {
164 
165             if (s_platformNotSupported)
166                 throw new System.PlatformNotSupportedException();
167 
168             //
169             // ignore locale and pass 0 instead: that way, the thread locale will be retrieved in the API layer
170             // and the "strict rendering" flag will NOT be set.  Otherwise, the fall back logic is broken and the descriptions
171             // are not returned if the exact locale is not present on the server.
172             //
173             EventLogHandle handle = UnsafeNativeMethods.EvtOpenPublisherMetadata(session, ProviderId, logFilePath, 0, flags);
174 
175             int win32Error = Marshal.GetLastWin32Error();
176             if (handle.IsInvalid)
177                 EventLogException.Throw(win32Error);
178             return handle;
179         }
180 
181         [System.Security.SecurityCritical]
EvtGetObjectArraySize(EventLogHandle objectArray)182         public static int EvtGetObjectArraySize(EventLogHandle objectArray) {
183             int arraySize;
184             bool status = UnsafeNativeMethods.EvtGetObjectArraySize(objectArray, out arraySize);
185             int win32Error = Marshal.GetLastWin32Error();
186             if (!status)
187                 EventLogException.Throw(win32Error);
188             return arraySize;
189         }
190 
191         [System.Security.SecurityCritical]
EvtOpenEventMetadataEnum(EventLogHandle ProviderMetadata, int flags)192         public static EventLogHandle EvtOpenEventMetadataEnum(EventLogHandle ProviderMetadata, int flags) {
193             EventLogHandle emEnumHandle = UnsafeNativeMethods.EvtOpenEventMetadataEnum(ProviderMetadata, flags);
194             int win32Error = Marshal.GetLastWin32Error();
195             if (emEnumHandle.IsInvalid)
196                 EventLogException.Throw(win32Error);
197             return emEnumHandle;
198         }
199 
200         // returns null if EOF
201         [System.Security.SecurityCritical]
EvtNextEventMetadata(EventLogHandle eventMetadataEnum, int flags)202         public static EventLogHandle EvtNextEventMetadata(EventLogHandle eventMetadataEnum, int flags) {
203             EventLogHandle emHandle = UnsafeNativeMethods.EvtNextEventMetadata(eventMetadataEnum, flags);
204             int win32Error = Marshal.GetLastWin32Error();
205 
206             if (emHandle.IsInvalid) {
207                 if (win32Error != UnsafeNativeMethods.ERROR_NO_MORE_ITEMS)
208                     EventLogException.Throw(win32Error);
209                 return null;
210             }
211 
212             return emHandle;
213         }
214 
215         [System.Security.SecurityCritical]
EvtOpenChannelEnum(EventLogHandle session, int flags)216         public static EventLogHandle EvtOpenChannelEnum(EventLogHandle session, int flags) {
217             if (s_platformNotSupported)
218                 throw new System.PlatformNotSupportedException();
219 
220             EventLogHandle channelEnum = UnsafeNativeMethods.EvtOpenChannelEnum(session, flags);
221             int win32Error = Marshal.GetLastWin32Error();
222             if (channelEnum.IsInvalid)
223                 EventLogException.Throw(win32Error);
224             return channelEnum;
225         }
226 
227         [System.Security.SecurityCritical]
EvtOpenProviderEnum(EventLogHandle session, int flags)228         public static EventLogHandle EvtOpenProviderEnum(EventLogHandle session, int flags) {
229             if (s_platformNotSupported)
230                 throw new System.PlatformNotSupportedException();
231 
232             EventLogHandle pubEnum = UnsafeNativeMethods.EvtOpenPublisherEnum(session, flags);
233             int win32Error = Marshal.GetLastWin32Error();
234             if (pubEnum.IsInvalid)
235                 EventLogException.Throw(win32Error);
236             return pubEnum;
237         }
238 
239         [System.Security.SecurityCritical]
EvtOpenChannelConfig(EventLogHandle session, String channelPath, int flags)240         public static EventLogHandle EvtOpenChannelConfig(EventLogHandle session, String channelPath, int flags) {
241             if (s_platformNotSupported)
242                 throw new System.PlatformNotSupportedException();
243 
244             EventLogHandle handle = UnsafeNativeMethods.EvtOpenChannelConfig(session, channelPath, flags);
245             int win32Error = Marshal.GetLastWin32Error();
246             if (handle.IsInvalid)
247                 EventLogException.Throw(win32Error);
248             return handle;
249         }
250 
251         [System.Security.SecuritySafeCritical]
EvtSaveChannelConfig(EventLogHandle channelConfig, int flags)252         public static void EvtSaveChannelConfig(EventLogHandle channelConfig, int flags) {
253             EventLogPermissionHolder.GetEventLogPermission().Demand();
254             bool status = UnsafeNativeMethods.EvtSaveChannelConfig(channelConfig, flags);
255             int win32Error = Marshal.GetLastWin32Error();
256             if (!status)
257                 EventLogException.Throw(win32Error);
258         }
259 
260 
261         [System.Security.SecurityCritical]
EvtOpenLog(EventLogHandle session, string path, PathType flags)262         public static EventLogHandle EvtOpenLog(EventLogHandle session, string path, PathType flags) {
263             if (s_platformNotSupported)
264                 throw new System.PlatformNotSupportedException();
265 
266             EventLogHandle logHandle = UnsafeNativeMethods.EvtOpenLog(session, path, flags);
267             int win32Error = Marshal.GetLastWin32Error();
268             if (logHandle.IsInvalid)
269                 EventLogException.Throw(win32Error);
270             return logHandle;
271         }
272 
273         [System.Security.SecuritySafeCritical]
EvtExportLog( EventLogHandle session, string channelPath, string query, string targetFilePath, int flags)274         public static void EvtExportLog(
275                             EventLogHandle session,
276                             string channelPath,
277                             string query,
278                             string targetFilePath,
279                             int flags) {
280 
281             if (s_platformNotSupported)
282                 throw new System.PlatformNotSupportedException();
283 
284             EventLogPermissionHolder.GetEventLogPermission().Demand();
285 
286             bool status;
287             status = UnsafeNativeMethods.EvtExportLog(session, channelPath, query, targetFilePath, flags);
288             int win32Error = Marshal.GetLastWin32Error();
289             if (!status)
290                 EventLogException.Throw(win32Error);
291         }
292 
293         [System.Security.SecuritySafeCritical]
EvtArchiveExportedLog( EventLogHandle session, string logFilePath, int locale, int flags)294         public static void EvtArchiveExportedLog(
295                             EventLogHandle session,
296                             string logFilePath,
297                             int locale,
298                             int flags) {
299 
300             if (s_platformNotSupported)
301                 throw new System.PlatformNotSupportedException();
302 
303             EventLogPermissionHolder.GetEventLogPermission().Demand();
304 
305             bool status;
306             status = UnsafeNativeMethods.EvtArchiveExportedLog(session, logFilePath, locale, flags);
307             int win32Error = Marshal.GetLastWin32Error();
308             if (!status)
309                 EventLogException.Throw(win32Error);
310         }
311 
312         [System.Security.SecuritySafeCritical]
EvtClearLog( EventLogHandle session, string channelPath, string targetFilePath, int flags)313         public static void EvtClearLog(
314                             EventLogHandle session,
315                             string channelPath,
316                             string targetFilePath,
317                             int flags) {
318 
319             if (s_platformNotSupported)
320                 throw new System.PlatformNotSupportedException();
321 
322             EventLogPermissionHolder.GetEventLogPermission().Demand();
323 
324             bool status;
325             status = UnsafeNativeMethods.EvtClearLog(session, channelPath, targetFilePath, flags);
326             int win32Error = Marshal.GetLastWin32Error();
327             if (!status)
328                 EventLogException.Throw(win32Error);
329         }
330 
331         [System.Security.SecurityCritical]
EvtCreateRenderContext( Int32 valuePathsCount, String[] valuePaths, UnsafeNativeMethods.EvtRenderContextFlags flags)332         public static EventLogHandle EvtCreateRenderContext(
333                             Int32 valuePathsCount,
334                             String[] valuePaths,
335                             UnsafeNativeMethods.EvtRenderContextFlags flags) {
336             if (s_platformNotSupported)
337                 throw new System.PlatformNotSupportedException();
338 
339             EventLogHandle renderContextHandleValues = UnsafeNativeMethods.EvtCreateRenderContext(valuePathsCount, valuePaths, flags);
340             int win32Error = Marshal.GetLastWin32Error();
341             if (renderContextHandleValues.IsInvalid)
342                 EventLogException.Throw(win32Error);
343             return renderContextHandleValues;
344         }
345 
346         [System.Security.SecurityCritical]
EvtRender( EventLogHandle context, EventLogHandle eventHandle, UnsafeNativeMethods.EvtRenderFlags flags, StringBuilder buffer)347         public static void EvtRender(
348                             EventLogHandle context,
349                             EventLogHandle eventHandle,
350                             UnsafeNativeMethods.EvtRenderFlags flags,
351                             StringBuilder buffer) {
352             if (s_platformNotSupported)
353                 throw new System.PlatformNotSupportedException();
354 
355             int buffUsed;
356             int propCount;
357             bool status = UnsafeNativeMethods.EvtRender(context, eventHandle, flags, buffer.Capacity, buffer, out buffUsed, out propCount);
358             int win32Error = Marshal.GetLastWin32Error();
359 
360             if (!status) {
361                 if (win32Error == UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER) {
362                     //reallocate the new RenderBuffer with the right size.
363                     buffer.Capacity = buffUsed;
364                     status = UnsafeNativeMethods.EvtRender(context, eventHandle, flags, buffer.Capacity, buffer, out buffUsed, out propCount);
365                     win32Error = Marshal.GetLastWin32Error();
366                 }
367                 if (!status) {
368                     EventLogException.Throw(win32Error);
369                 }
370             }
371         }
372 
373         [System.Security.SecurityCritical]
EvtOpenSession(UnsafeNativeMethods.EvtLoginClass loginClass, ref UnsafeNativeMethods.EvtRpcLogin login, int timeout, int flags)374         public static EventLogHandle EvtOpenSession(UnsafeNativeMethods.EvtLoginClass loginClass, ref UnsafeNativeMethods.EvtRpcLogin login, int timeout, int flags) {
375             if (s_platformNotSupported)
376                 throw new System.PlatformNotSupportedException();
377 
378             EventLogHandle handle = UnsafeNativeMethods.EvtOpenSession(loginClass, ref login, timeout, flags);
379             int win32Error = Marshal.GetLastWin32Error();
380             if (handle.IsInvalid)
381                 EventLogException.Throw(win32Error);
382             return handle;
383         }
384 
385         [System.Security.SecurityCritical]
EvtCreateBookmark(string bookmarkXml)386         public static EventLogHandle EvtCreateBookmark(string bookmarkXml) {
387             if (s_platformNotSupported)
388                 throw new System.PlatformNotSupportedException();
389 
390             EventLogHandle handle = UnsafeNativeMethods.EvtCreateBookmark(bookmarkXml);
391             int win32Error = Marshal.GetLastWin32Error();
392             if (handle.IsInvalid)
393                 EventLogException.Throw(win32Error);
394             return handle;
395         }
396 
397         [System.Security.SecurityCritical]
EvtUpdateBookmark(EventLogHandle bookmark, EventLogHandle eventHandle)398         public static void EvtUpdateBookmark(EventLogHandle bookmark, EventLogHandle eventHandle) {
399             bool status = UnsafeNativeMethods.EvtUpdateBookmark(bookmark, eventHandle);
400             int win32Error = Marshal.GetLastWin32Error();
401             if (!status)
402                 EventLogException.Throw(win32Error);
403         }
404 
405         [System.Security.SecuritySafeCritical]
EvtGetEventInfo(EventLogHandle handle, UnsafeNativeMethods.EvtEventPropertyId enumType)406         public static object EvtGetEventInfo(EventLogHandle handle, UnsafeNativeMethods.EvtEventPropertyId enumType) {
407             IntPtr buffer = IntPtr.Zero;
408             int bufferNeeded;
409 
410             EventLogPermissionHolder.GetEventLogPermission().Demand();
411 
412             try {
413                 bool status = UnsafeNativeMethods.EvtGetEventInfo(handle, enumType, 0, IntPtr.Zero, out bufferNeeded);
414                 int error = Marshal.GetLastWin32Error();
415                 if (!status) {
416                     if (error == UnsafeNativeMethods.ERROR_SUCCESS) { }
417                     else
418                         if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
419                             EventLogException.Throw(error);
420                 }
421                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
422                 status = UnsafeNativeMethods.EvtGetEventInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded);
423                 error = Marshal.GetLastWin32Error();
424                 if (!status)
425                     EventLogException.Throw(error);
426 
427                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
428                 return ConvertToObject(varVal);
429 
430             }
431             finally {
432                 if (buffer != IntPtr.Zero)
433                     Marshal.FreeHGlobal(buffer);
434             }
435         }
436 
437         [System.Security.SecurityCritical]
EvtGetQueryInfo(EventLogHandle handle, UnsafeNativeMethods.EvtQueryPropertyId enumType)438         public static object EvtGetQueryInfo(EventLogHandle handle, UnsafeNativeMethods.EvtQueryPropertyId enumType) {
439             IntPtr buffer = IntPtr.Zero;
440             int bufferNeeded = 0;
441             try {
442                 bool status = UnsafeNativeMethods.EvtGetQueryInfo(handle, enumType, 0, IntPtr.Zero, ref bufferNeeded);
443                 int error = Marshal.GetLastWin32Error();
444                 if (!status) {
445                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
446                         EventLogException.Throw(error);
447                 }
448                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
449                 status = UnsafeNativeMethods.EvtGetQueryInfo(handle, enumType, bufferNeeded, buffer, ref bufferNeeded);
450                 error = Marshal.GetLastWin32Error();
451                 if (!status)
452                     EventLogException.Throw(error);
453 
454                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
455                 return ConvertToObject(varVal);
456             }
457             finally {
458                 if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer);
459             }
460         }
461 
462         [System.Security.SecuritySafeCritical]
EvtGetPublisherMetadataProperty(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId)463         public static object EvtGetPublisherMetadataProperty(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId) {
464             IntPtr buffer = IntPtr.Zero;
465             int bufferNeeded;
466 
467             EventLogPermissionHolder.GetEventLogPermission().Demand();
468 
469             try {
470                 bool status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, 0, IntPtr.Zero, out bufferNeeded);
471                 int error = Marshal.GetLastWin32Error();
472                 if (!status) {
473                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
474                         EventLogException.Throw(error);
475                 }
476                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
477                 status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded);
478                 error = Marshal.GetLastWin32Error();
479                 if (!status)
480                     EventLogException.Throw(error);
481 
482                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
483                 return ConvertToObject(varVal);
484             }
485             finally {
486                 if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer);
487             }
488         }
489 
490 
491         [System.Security.SecurityCritical]
EvtGetPublisherMetadataPropertyHandle(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId)492         internal static EventLogHandle EvtGetPublisherMetadataPropertyHandle(EventLogHandle pmHandle, UnsafeNativeMethods.EvtPublisherMetadataPropertyId thePropertyId) {
493             IntPtr buffer = IntPtr.Zero;
494             try {
495                 int bufferNeeded;
496                 bool status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, 0, IntPtr.Zero, out bufferNeeded);
497                 int error = Marshal.GetLastWin32Error();
498                 if (!status) {
499                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
500                         EventLogException.Throw(error);
501                 }
502                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
503                 status = UnsafeNativeMethods.EvtGetPublisherMetadataProperty(pmHandle, thePropertyId, 0, bufferNeeded, buffer, out bufferNeeded);
504                 error = Marshal.GetLastWin32Error();
505                 if (!status)
506                     EventLogException.Throw(error);
507 
508                 //
509                 // note: there is a case where returned variant does have allocated native resources
510                 // associated with (e.g. ConfigArrayHandle).  If PtrToStructure throws, then we would
511                 // leak that resource - fortunately PtrToStructure only throws InvalidArgument which
512                 // is a logic error - not a possible runtime condition here.  Other System exceptions
513                 // shouldn't be handled anyhow and the application will terminate.
514                 //
515                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
516                 return ConvertToSafeHandle(varVal);
517             }
518             finally {
519                 if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer);
520             }
521         }
522 
523 
524         // implies UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId flag.
525         [System.Security.SecurityCritical]
EvtFormatMessage(EventLogHandle handle, uint msgId)526         public static string EvtFormatMessage(EventLogHandle handle, uint msgId) {
527             if (s_platformNotSupported)
528                 throw new System.PlatformNotSupportedException();
529 
530             int bufferNeeded;
531 
532             StringBuilder sb = new StringBuilder(null);
533             bool status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null,   UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, 0, sb, out bufferNeeded);
534             int error = Marshal.GetLastWin32Error();
535 
536             // ERROR_EVT_UNRESOLVED_VALUE_INSERT and its cousins are commonly returned for raw message text.
537             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
538                         && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT
539                         && error != UnsafeNativeMethods.ERROR_EVT_MAX_INSERTS_REACHED ) {
540                 switch (error) {
541                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
542                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
543                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
544                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
545                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
546                         return null;
547                 }
548                 if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
549                     EventLogException.Throw(error);
550             }
551 
552             sb.EnsureCapacity(bufferNeeded);
553             status = UnsafeNativeMethods.EvtFormatMessage(handle, EventLogHandle.Zero, msgId, 0, null,   UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageId, bufferNeeded, sb, out bufferNeeded);
554             error = Marshal.GetLastWin32Error();
555 
556             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT
557                         && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_PARAMETER_INSERT
558                         && error != UnsafeNativeMethods.ERROR_EVT_MAX_INSERTS_REACHED ) {
559                 switch (error) {
560                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
561                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
562                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
563                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
564                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
565                         return null;
566                 }
567                 if (error == UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
568                     return null;
569                 }
570                 EventLogException.Throw(error);
571             }
572             return sb.ToString();
573         }
574 
575         [System.Security.SecurityCritical]
EvtGetObjectArrayProperty(EventLogHandle objArrayHandle, int index, int thePropertyId)576         public static object EvtGetObjectArrayProperty(EventLogHandle objArrayHandle, int index, int thePropertyId) {
577             IntPtr buffer = IntPtr.Zero;
578             int bufferNeeded;
579 
580             try {
581                 bool status = UnsafeNativeMethods.EvtGetObjectArrayProperty(objArrayHandle, thePropertyId, index, 0, 0, IntPtr.Zero, out bufferNeeded);
582                 int error = Marshal.GetLastWin32Error();
583 
584                 if (!status) {
585                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
586                         EventLogException.Throw(error);
587                 }
588                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
589                 status = UnsafeNativeMethods.EvtGetObjectArrayProperty(objArrayHandle, thePropertyId, index, 0, bufferNeeded, buffer, out bufferNeeded);
590                 error = Marshal.GetLastWin32Error();
591                 if (!status)
592                     EventLogException.Throw(error);
593 
594                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
595                 return ConvertToObject(varVal);
596             }
597             finally {
598                 if (buffer != IntPtr.Zero) Marshal.FreeHGlobal(buffer);
599             }
600         }
601 
602         [System.Security.SecurityCritical]
EvtGetEventMetadataProperty(EventLogHandle handle, UnsafeNativeMethods.EvtEventMetadataPropertyId enumType)603         public static object EvtGetEventMetadataProperty(EventLogHandle handle, UnsafeNativeMethods.EvtEventMetadataPropertyId enumType) {
604             IntPtr buffer = IntPtr.Zero;
605             int bufferNeeded;
606 
607             try {
608                 bool status = UnsafeNativeMethods.EvtGetEventMetadataProperty(handle, enumType, 0, 0, IntPtr.Zero, out bufferNeeded);
609                 int win32Error = Marshal.GetLastWin32Error();
610                 if (!status) {
611                     if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
612                         EventLogException.Throw(win32Error);
613                 }
614                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
615                 status = UnsafeNativeMethods.EvtGetEventMetadataProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded);
616                 win32Error = Marshal.GetLastWin32Error();
617                 if (!status)
618                     EventLogException.Throw(win32Error);
619 
620                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
621                 return ConvertToObject(varVal);
622             }
623             finally {
624                 if (buffer != IntPtr.Zero)
625                     Marshal.FreeHGlobal(buffer);
626             }
627         }
628 
629         [System.Security.SecuritySafeCritical]
EvtGetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType)630         public static object EvtGetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType) {
631             IntPtr buffer = IntPtr.Zero;
632             int bufferNeeded;
633 
634             EventLogPermissionHolder.GetEventLogPermission().Demand();
635 
636             try {
637 
638                 bool status = UnsafeNativeMethods.EvtGetChannelConfigProperty(handle, enumType, 0, 0, IntPtr.Zero, out bufferNeeded);
639                 int win32Error = Marshal.GetLastWin32Error();
640                 if (!status) {
641                     if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
642                         EventLogException.Throw(win32Error);
643                 }
644                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
645                 status = UnsafeNativeMethods.EvtGetChannelConfigProperty(handle, enumType, 0, bufferNeeded, buffer, out bufferNeeded);
646                 win32Error = Marshal.GetLastWin32Error();
647                 if (!status)
648                     EventLogException.Throw(win32Error);
649 
650                 //
651                 // note: there is a case where returned variant does have allocated native resources
652                 // associated with (e.g. ConfigArrayHandle).  If PtrToStructure throws, then we would
653                 // leak that resource - fortunately PtrToStructure only throws InvalidArgument which
654                 // is a logic error - not a possible runtime condition here.  Other System exceptions
655                 // shouldn't be handled anyhow and the application will terminate.
656                 //
657                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
658                 return ConvertToObject(varVal);
659             }
660             finally {
661                 if (buffer != IntPtr.Zero)
662                     Marshal.FreeHGlobal(buffer);
663             }
664         }
665 
666         [System.Security.SecuritySafeCritical]
EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType, object val)667         public static void EvtSetChannelConfigProperty(EventLogHandle handle, UnsafeNativeMethods.EvtChannelConfigPropertyId enumType, object val) {
668 
669             EventLogPermissionHolder.GetEventLogPermission().Demand();
670 
671             UnsafeNativeMethods.EvtVariant varVal = new UnsafeNativeMethods.EvtVariant();
672 
673             CoTaskMemSafeHandle taskMem = new CoTaskMemSafeHandle();
674 
675             using (taskMem) {
676 
677                 if (val != null) {
678 
679                     switch (enumType) {
680                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigEnabled: {
681                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
682                                 if ((bool)val == true) varVal.Bool = 1;
683                                 else varVal.Bool = 0;
684                             }
685                             break;
686                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelConfigAccess: {
687                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
688                                 taskMem.SetMemory(Marshal.StringToCoTaskMemAuto((string)val));
689                                 varVal.StringVal = taskMem.GetMemory();
690                             }
691                             break;
692                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigLogFilePath: {
693                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
694                                 taskMem.SetMemory(Marshal.StringToCoTaskMemAuto((string)val));
695                                 varVal.StringVal = taskMem.GetMemory();
696                             }
697                             break;
698                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigMaxSize: {
699                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64;
700                                 varVal.ULong = (ulong)((long)val);
701                             }
702                             break;
703                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigLevel: {
704                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32;
705                                 varVal.UInteger = (uint)((int)val);
706                             }
707                             break;
708                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelPublishingConfigKeywords: {
709                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64;
710                                 varVal.ULong = (ulong)((long)val);
711                             }
712                             break;
713                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigRetention: {
714                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
715                                 if ((bool)val == true) varVal.Bool = 1;
716                                 else varVal.Bool = 0;
717                             }
718                             break;
719                         case UnsafeNativeMethods.EvtChannelConfigPropertyId.EvtChannelLoggingConfigAutoBackup: {
720                                 varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean;
721                                 if ((bool)val == true) varVal.Bool = 1;
722                                 else varVal.Bool = 0;
723                             }
724                             break;
725                         default:
726                             throw new InvalidOperationException();
727                     }
728                 }
729                 else {
730                     varVal.Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull;
731                 }
732                 bool status = UnsafeNativeMethods.EvtSetChannelConfigProperty(handle, enumType, 0, ref varVal);
733                 int win32Error = Marshal.GetLastWin32Error();
734                 if (!status)
735                     EventLogException.Throw(win32Error);
736             }
737         }
738 
739         [System.Security.SecurityCritical]
EvtNextChannelPath(EventLogHandle handle, ref bool finish)740         public static string EvtNextChannelPath(EventLogHandle handle, ref bool finish) {
741             StringBuilder sb = new StringBuilder(null);
742             int channelNameNeeded;
743 
744             bool status = UnsafeNativeMethods.EvtNextChannelPath(handle, 0, sb, out channelNameNeeded);
745             int win32Error = Marshal.GetLastWin32Error();
746             if (!status) {
747                 if (win32Error == UnsafeNativeMethods.ERROR_NO_MORE_ITEMS) {
748                     finish = true;
749                     return null;
750                 }
751 
752                 if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
753                     EventLogException.Throw(win32Error);
754             }
755 
756             sb.EnsureCapacity(channelNameNeeded);
757             status = UnsafeNativeMethods.EvtNextChannelPath(handle, channelNameNeeded, sb, out channelNameNeeded);
758             win32Error = Marshal.GetLastWin32Error();
759             if (!status)
760                 EventLogException.Throw(win32Error);
761 
762             return sb.ToString();
763         }
764 
765         [System.Security.SecurityCritical]
EvtNextPublisherId(EventLogHandle handle, ref bool finish)766         public static string EvtNextPublisherId(EventLogHandle handle, ref bool finish) {
767             StringBuilder sb = new StringBuilder(null);
768             int ProviderIdNeeded;
769 
770             bool status = UnsafeNativeMethods.EvtNextPublisherId(handle, 0, sb, out ProviderIdNeeded);
771             int win32Error = Marshal.GetLastWin32Error();
772             if (!status) {
773                 if (win32Error == UnsafeNativeMethods.ERROR_NO_MORE_ITEMS) {
774                     finish = true;
775                     return null;
776                 }
777 
778                 if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
779                     EventLogException.Throw(win32Error);
780             }
781 
782             sb.EnsureCapacity(ProviderIdNeeded);
783             status = UnsafeNativeMethods.EvtNextPublisherId(handle, ProviderIdNeeded, sb, out ProviderIdNeeded);
784             win32Error = Marshal.GetLastWin32Error();
785             if (!status)
786                 EventLogException.Throw(win32Error);
787 
788             return sb.ToString();
789         }
790 
791         [System.Security.SecurityCritical]
EvtGetLogInfo(EventLogHandle handle, UnsafeNativeMethods.EvtLogPropertyId enumType)792         public static object EvtGetLogInfo(EventLogHandle handle, UnsafeNativeMethods.EvtLogPropertyId enumType) {
793             IntPtr buffer = IntPtr.Zero;
794             int bufferNeeded;
795 
796             try {
797                 bool status = UnsafeNativeMethods.EvtGetLogInfo(handle, enumType, 0, IntPtr.Zero, out bufferNeeded);
798                 int win32Error = Marshal.GetLastWin32Error();
799                 if (!status) {
800                     if (win32Error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
801                         EventLogException.Throw(win32Error);
802                 }
803                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
804                 status = UnsafeNativeMethods.EvtGetLogInfo(handle, enumType, bufferNeeded, buffer, out bufferNeeded);
805                 win32Error = Marshal.GetLastWin32Error();
806                 if (!status)
807                     EventLogException.Throw(win32Error);
808 
809                 UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(buffer, typeof(UnsafeNativeMethods.EvtVariant));
810                 return ConvertToObject(varVal);
811             }
812             finally {
813                 if (buffer != IntPtr.Zero)
814                     Marshal.FreeHGlobal(buffer);
815             }
816         }
817 
818         [System.Security.SecuritySafeCritical]
EvtRenderBufferWithContextSystem(EventLogHandle contextHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtRenderFlags flag, SystemProperties systemProperties, int SYSTEM_PROPERTY_COUNT)819         public static void EvtRenderBufferWithContextSystem(EventLogHandle contextHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtRenderFlags flag, SystemProperties systemProperties, int SYSTEM_PROPERTY_COUNT) {
820             IntPtr buffer = IntPtr.Zero;
821             IntPtr pointer = IntPtr.Zero;
822             int bufferNeeded;
823             int propCount;
824 
825             EventLogPermissionHolder.GetEventLogPermission().Demand();
826 
827             try {
828                 bool status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
829                 if (!status) {
830                     int error = Marshal.GetLastWin32Error();
831                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
832                         EventLogException.Throw(error);
833                 }
834 
835                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
836                 status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
837                 int win32Error = Marshal.GetLastWin32Error();
838                 if (!status)
839                     EventLogException.Throw(win32Error);
840 
841                 if (propCount != SYSTEM_PROPERTY_COUNT)
842                     throw new InvalidOperationException("We do not have " + SYSTEM_PROPERTY_COUNT + " variants given for the  UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues flag. (System Properties)");
843 
844                 pointer = buffer;
845                 //read each Variant structure
846                 for (int i = 0; i < propCount; i++) {
847                     UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(pointer, typeof(UnsafeNativeMethods.EvtVariant));
848                     switch (i) {
849                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProviderName:
850                             systemProperties.ProviderName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
851                             break;
852                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProviderGuid:
853                             systemProperties.ProviderId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
854                             break;
855                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemEventID:
856                             systemProperties.Id = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
857                             break;
858                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemQualifiers:
859                             systemProperties.Qualifiers = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
860                             break;
861                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemLevel:
862                             systemProperties.Level = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
863                             break;
864                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemTask:
865                             systemProperties.Task = (ushort?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16);
866                             break;
867                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemOpcode:
868                             systemProperties.Opcode = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
869                             break;
870                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemKeywords:
871                             systemProperties.Keywords = (ulong?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64);
872                             break;
873                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemTimeCreated:
874                             systemProperties.TimeCreated = (DateTime?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime);
875                             break;
876                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemEventRecordId:
877                             systemProperties.RecordId = (ulong?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64);
878                             break;
879                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemActivityID:
880                             systemProperties.ActivityId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
881                             break;
882                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemRelatedActivityID:
883                             systemProperties.RelatedActivityId = (Guid?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid);
884                             break;
885                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemProcessID:
886                             systemProperties.ProcessId = (uint?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32);
887                             break;
888                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemThreadID:
889                             systemProperties.ThreadId = (uint?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32);
890                             break;
891                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemChannel:
892                             systemProperties.ChannelName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
893                             break;
894                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemComputer:
895                             systemProperties.ComputerName = (string)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeString);
896                             break;
897                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemUserID:
898                             systemProperties.UserId = (SecurityIdentifier)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid);
899                             break;
900                         case (int) UnsafeNativeMethods.EvtSystemPropertyId.EvtSystemVersion:
901                             systemProperties.Version = (byte?)ConvertToObject(varVal, UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte);
902                             break;
903                     }
904                     pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal)));
905                 }
906             }
907             finally {
908                 if (buffer != IntPtr.Zero)
909                     Marshal.FreeHGlobal(buffer);
910             }
911         }
912 
913         //EvtRenderContextFlags can be both: EvtRenderContextFlags.EvtRenderContextUser and  EvtRenderContextFlags.EvtRenderContextValues
914         //Render with Context = ContextUser or ContextValues (with user defined Xpath query strings)
915         [System.Security.SecuritySafeCritical]
EvtRenderBufferWithContextUserOrValues(EventLogHandle contextHandle, EventLogHandle eventHandle)916         public static IList<object> EvtRenderBufferWithContextUserOrValues(EventLogHandle contextHandle, EventLogHandle eventHandle) {
917             IntPtr buffer = IntPtr.Zero;
918             IntPtr pointer = IntPtr.Zero;
919             int bufferNeeded;
920             int propCount;
921              UnsafeNativeMethods.EvtRenderFlags flag =  UnsafeNativeMethods.EvtRenderFlags.EvtRenderEventValues;
922 
923             EventLogPermissionHolder.GetEventLogPermission().Demand();
924 
925             try {
926                 bool status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
927                 if (!status) {
928                     int error = Marshal.GetLastWin32Error();
929                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
930                         EventLogException.Throw(error);
931                 }
932 
933                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
934                 status = UnsafeNativeMethods.EvtRender(contextHandle, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
935                 int win32Error = Marshal.GetLastWin32Error();
936                 if (!status)
937                     EventLogException.Throw(win32Error);
938 
939                 List<object> valuesList = new List<object>(propCount);
940                 if (propCount > 0) {
941                     pointer = buffer;
942                     for (int i = 0; i < propCount; i++) {
943                         UnsafeNativeMethods.EvtVariant varVal = (UnsafeNativeMethods.EvtVariant)Marshal.PtrToStructure(pointer, typeof(UnsafeNativeMethods.EvtVariant));
944                         valuesList.Add(ConvertToObject(varVal));
945                         pointer = new IntPtr(((Int64)pointer + Marshal.SizeOf(varVal)));
946                     }
947                 }
948                 return valuesList;
949             }
950             finally {
951                 if (buffer != IntPtr.Zero)
952                     Marshal.FreeHGlobal(buffer);
953             }
954         }
955 
956         [System.Security.SecuritySafeCritical]
EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag)957         public static string EvtFormatMessageRenderName(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag) {
958 
959             EventLogPermissionHolder.GetEventLogPermission().Demand();
960 
961             int bufferNeeded;
962             StringBuilder sb = new StringBuilder(null);
963 
964             bool status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, 0, sb, out bufferNeeded);
965             int error = Marshal.GetLastWin32Error();
966 
967             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
968                 //
969                 // ERROR_EVT_UNRESOLVED_VALUE_INSERT can be returned.  It means
970                 // message may have one or more unsubstitued strings.  This is
971                 // not an exception, but we have no way to convey the partial
972                 // success out to enduser.
973                 //
974                 switch (error) {
975                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
976                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
977                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
978                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
979                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
980                         return null;
981                 }
982                 if (error != (int)UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
983                     EventLogException.Throw(error);
984             }
985 
986             sb.EnsureCapacity(bufferNeeded);
987             status = UnsafeNativeMethods.EvtFormatMessage(pmHandle, eventHandle, 0, 0, null, flag, bufferNeeded, sb, out bufferNeeded);
988             error = Marshal.GetLastWin32Error();
989 
990             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT)
991             {
992                 switch (error) {
993                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
994                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
995                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
996                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
997                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
998                         return null;
999                 }
1000                 EventLogException.Throw(error);
1001             }
1002             return sb.ToString();
1003         }
1004 
1005 
1006         //The EvtFormatMessage used for the obtaining of the Keywords names.
1007         [System.Security.SecuritySafeCritical]
EvtFormatMessageRenderKeywords(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag)1008         public static IEnumerable<string> EvtFormatMessageRenderKeywords(EventLogHandle pmHandle, EventLogHandle eventHandle, UnsafeNativeMethods.EvtFormatMessageFlags flag) {
1009 
1010             EventLogPermissionHolder.GetEventLogPermission().Demand();
1011 
1012             IntPtr buffer = IntPtr.Zero;
1013             int bufferNeeded;
1014 
1015             try {
1016                 List<string> keywordsList = new List<string>();
1017                 bool status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, 0, IntPtr.Zero, out bufferNeeded);
1018                 int error = Marshal.GetLastWin32Error();
1019 
1020                 if (!status) {
1021                     switch (error) {
1022                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
1023                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
1024                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
1025                         case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
1026                         case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
1027                             return keywordsList.AsReadOnly();
1028                     }
1029                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
1030                         EventLogException.Throw(error);
1031                 }
1032 
1033                 buffer = Marshal.AllocHGlobal(bufferNeeded * 2);
1034                 status = UnsafeNativeMethods.EvtFormatMessageBuffer(pmHandle, eventHandle, 0, 0, IntPtr.Zero, flag, bufferNeeded, buffer, out bufferNeeded);
1035                 error = Marshal.GetLastWin32Error();
1036                 if (!status) {
1037                     switch (error)
1038                     {
1039                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
1040                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
1041                         case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
1042                         case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
1043                         case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
1044                             return keywordsList;
1045                     }
1046                     EventLogException.Throw(error);
1047                 }
1048 
1049                 IntPtr pointer = buffer;
1050 
1051                 while (true) {
1052                     string s = Marshal.PtrToStringAuto(pointer);
1053                     if (String.IsNullOrEmpty(s))
1054                         break;
1055                     keywordsList.Add(s);
1056                     //nr of bytes = # chars * 2 + 2 bytes for character '\0'.
1057                     pointer = new IntPtr((Int64)pointer + (s.Length * 2) + 2);
1058                 }
1059 
1060                 return keywordsList.AsReadOnly();
1061             }
1062             finally {
1063                 if (buffer != IntPtr.Zero)
1064                     Marshal.FreeHGlobal(buffer);
1065             }
1066         }
1067 
1068         [System.Security.SecurityCritical]
EvtRenderBookmark(EventLogHandle eventHandle)1069         public static string EvtRenderBookmark(EventLogHandle eventHandle) {
1070             IntPtr buffer = IntPtr.Zero;
1071             int bufferNeeded;
1072             int propCount;
1073              UnsafeNativeMethods.EvtRenderFlags flag =  UnsafeNativeMethods.EvtRenderFlags.EvtRenderBookmark;
1074 
1075             try {
1076                 bool status = UnsafeNativeMethods.EvtRender(EventLogHandle.Zero, eventHandle, flag, 0, IntPtr.Zero, out bufferNeeded, out propCount);
1077                 int error = Marshal.GetLastWin32Error();
1078                 if (!status) {
1079                     if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
1080                         EventLogException.Throw(error);
1081                 }
1082 
1083                 buffer = Marshal.AllocHGlobal((int)bufferNeeded);
1084                 status = UnsafeNativeMethods.EvtRender(EventLogHandle.Zero, eventHandle, flag, bufferNeeded, buffer, out bufferNeeded, out propCount);
1085                 error = Marshal.GetLastWin32Error();
1086                 if (!status)
1087                     EventLogException.Throw(error);
1088 
1089                 return Marshal.PtrToStringAuto(buffer);
1090             }
1091             finally {
1092                 if (buffer != IntPtr.Zero)
1093                     Marshal.FreeHGlobal(buffer);
1094             }
1095         }
1096 
1097 
1098         //Get the formatted description, using the msgId for FormatDescription(string [])
1099         [System.Security.SecuritySafeCritical]
EvtFormatMessageFormatDescription(EventLogHandle handle, EventLogHandle eventHandle, string[] values)1100         public static string EvtFormatMessageFormatDescription(EventLogHandle handle, EventLogHandle eventHandle, string[] values) {
1101             if (s_platformNotSupported)
1102                 throw new System.PlatformNotSupportedException();
1103 
1104             EventLogPermissionHolder.GetEventLogPermission().Demand();
1105 
1106             int bufferNeeded;
1107 
1108             UnsafeNativeMethods.EvtStringVariant [] stringVariants = new UnsafeNativeMethods.EvtStringVariant[values.Length];
1109             for (int i = 0; i < values.Length; i++) {
1110                 stringVariants[i].Type = (uint)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString;
1111                 stringVariants[i].StringVal = values[i];
1112             }
1113 
1114             StringBuilder sb = new StringBuilder(null);
1115             bool status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, 0, sb, out bufferNeeded);
1116             int error = Marshal.GetLastWin32Error();
1117 
1118             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
1119                 //
1120                 // ERROR_EVT_UNRESOLVED_VALUE_INSERT can be returned.  It means
1121                 // message may have one or more unsubstitued strings.  This is
1122                 // not an exception, but we have no way to convey the partial
1123                 // success out to enduser.
1124                 //
1125                 switch (error)
1126                 {
1127                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
1128                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
1129                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
1130                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
1131                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
1132                         return null;
1133                 }
1134                 if (error != UnsafeNativeMethods.ERROR_INSUFFICIENT_BUFFER)
1135                     EventLogException.Throw(error);
1136             }
1137 
1138             sb.EnsureCapacity(bufferNeeded);
1139             status = UnsafeNativeMethods.EvtFormatMessage(handle, eventHandle, 0xffffffff, values.Length, stringVariants, UnsafeNativeMethods.EvtFormatMessageFlags.EvtFormatMessageEvent, bufferNeeded, sb, out bufferNeeded);
1140             error = Marshal.GetLastWin32Error();
1141 
1142             if (!status && error != UnsafeNativeMethods.ERROR_EVT_UNRESOLVED_VALUE_INSERT) {
1143                 switch (error)
1144                 {
1145                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_NOT_FOUND:
1146                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_ID_NOT_FOUND:
1147                     case UnsafeNativeMethods.ERROR_EVT_MESSAGE_LOCALE_NOT_FOUND:
1148                     case UnsafeNativeMethods.ERROR_RESOURCE_LANG_NOT_FOUND:
1149                     case UnsafeNativeMethods.ERROR_MUI_FILE_NOT_FOUND:
1150                         return null;
1151                 }
1152                 EventLogException.Throw(error);
1153             }
1154             return sb.ToString();
1155 
1156         }
1157 
1158         [System.Security.SecurityCritical]
ConvertToObject(UnsafeNativeMethods.EvtVariant val)1159         private static object ConvertToObject(UnsafeNativeMethods.EvtVariant val) {
1160 
1161             switch (val.Type) {
1162                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32:
1163                     return val.UInteger;
1164                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt32:
1165                     return val.Integer;
1166                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16:
1167                     return val.UShort;
1168                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt16:
1169                     return val.SByte;
1170                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte:
1171                     return val.UInt8;
1172                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSByte:
1173                     return val.SByte;
1174                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64:
1175                     return val.ULong;
1176                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt64:
1177                     return val.Long;
1178                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64:
1179                     return val.ULong;
1180                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt32:
1181                     return val.Integer;
1182                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSingle:
1183                     return val.Single;
1184                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeDouble:
1185                     return val.Double;
1186                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull:
1187                     return null;
1188                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString:
1189                     return ConvertToString(val);
1190                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeAnsiString:
1191                     return ConvertToAnsiString(val);
1192                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid:
1193                     return (val.SidVal == IntPtr.Zero) ? null : new SecurityIdentifier(val.SidVal);
1194                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid:
1195                     return  (val.GuidReference == IntPtr.Zero) ? Guid.Empty : Marshal.PtrToStructure(val.GuidReference, typeof(Guid));
1196                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeEvtHandle:
1197                     return ConvertToSafeHandle(val);
1198                 case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime:
1199                     return DateTime.FromFileTime((long)val.FileTime);
1200                 case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSysTime:
1201                     UnsafeNativeMethods.SystemTime sysTime = (UnsafeNativeMethods.SystemTime)Marshal.PtrToStructure(val.SystemTime, typeof(UnsafeNativeMethods.SystemTime));
1202                     return new DateTime(sysTime.Year, sysTime.Month, sysTime.Day, sysTime.Hour, sysTime.Minute, sysTime.Second, sysTime.Milliseconds);
1203                 case (int)(int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSizeT:
1204                     return val.SizeT;
1205                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean:
1206                     if (val.Bool != 0) return true;
1207                     else return false;
1208                 case (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBinary:
1209                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeByte):
1210                     if (val.Reference == IntPtr.Zero) return new Byte[0];
1211                     Byte[] arByte = new Byte[val.Count];
1212                     Marshal.Copy(val.Reference, arByte, 0, (int)val.Count);
1213                     return arByte;
1214                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt16):
1215                     if (val.Reference == IntPtr.Zero) return new Int16[0];
1216                     Int16[] arInt16 = new Int16[val.Count];
1217                     Marshal.Copy(val.Reference, arInt16, 0, (int)val.Count);
1218                     return arInt16;
1219                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt32):
1220                     if (val.Reference == IntPtr.Zero) return new Int32[0];
1221                     Int32[] arInt32 = new Int32[val.Count];
1222                     Marshal.Copy(val.Reference, arInt32, 0, (int)val.Count);
1223                     return arInt32;
1224                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeInt64):
1225                     if (val.Reference == IntPtr.Zero) return new Int64[0];
1226                     Int64[] arInt64 = new Int64[val.Count];
1227                     Marshal.Copy(val.Reference, arInt64, 0, (int)val.Count);
1228                     return arInt64;
1229                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSingle):
1230                     if (val.Reference == IntPtr.Zero) return new Single[0];
1231                     Single[] arSingle = new Single[val.Count];
1232                     Marshal.Copy(val.Reference, arSingle, 0, (int)val.Count);
1233                     return arSingle;
1234                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeDouble):
1235                     if (val.Reference == IntPtr.Zero) return new Double[0];
1236                     Double[] arDouble = new Double[val.Count];
1237                     Marshal.Copy(val.Reference, arDouble, 0, (int)val.Count);
1238                     return arDouble;
1239                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSByte):
1240                     return ConvertToArray (val,typeof(SByte), sizeof(SByte)); // not CLS-compliant
1241                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt16):
1242                     return ConvertToArray (val,typeof(UInt16), sizeof(UInt16));
1243                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt64):
1244                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt64):
1245                     return ConvertToArray (val,typeof(UInt64), sizeof(UInt64));
1246                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeUInt32):
1247                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeHexInt32):
1248                     return ConvertToArray (val,typeof(UInt32), sizeof(UInt32));
1249                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeString):
1250                     return ConvertToStringArray(val, false);
1251                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeAnsiString):
1252                     return ConvertToStringArray(val, true);
1253                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBoolean):
1254                     return ConvertToBoolArray(val);
1255                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeGuid):
1256                     return ConvertToArray (val, typeof(Guid), 16 * sizeof(byte));
1257                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeFileTime):
1258                     return ConvertToFileTimeArray(val);
1259                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSysTime):
1260                     return ConvertToSysTimeArray(val);
1261                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeBinary): //both length and count in the manifest: tracrpt supports, Crimson APIs don't
1262                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSizeT):  //unused: array of win:pointer is returned as HexIntXX
1263                 case ((int) UnsafeNativeMethods.EvtMasks.EVT_VARIANT_TYPE_ARRAY | (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeSid): //unsupported by native APIs
1264                 default:
1265                     throw new EventLogInvalidDataException();
1266             }
1267         }
1268 
1269                 [System.Security.SecurityCritical]
ConvertToObject(UnsafeNativeMethods.EvtVariant val, UnsafeNativeMethods.EvtVariantType desiredType)1270         public static object ConvertToObject(UnsafeNativeMethods.EvtVariant val, UnsafeNativeMethods.EvtVariantType desiredType) {
1271             if (val.Type == (int)UnsafeNativeMethods.EvtVariantType.EvtVarTypeNull) return null;
1272             if (val.Type != (int)desiredType)
1273                 throw new EventLogInvalidDataException();
1274 
1275 
1276             return ConvertToObject(val);
1277         }
1278 
1279         [System.Security.SecurityCritical]
ConvertToString(UnsafeNativeMethods.EvtVariant val)1280         public static string ConvertToString(UnsafeNativeMethods.EvtVariant val) {
1281             if (val.StringVal == IntPtr.Zero)
1282                 return string.Empty;
1283             else
1284                 return Marshal.PtrToStringAuto(val.StringVal);
1285         }
1286 
1287         [System.Security.SecurityCritical]
ConvertToAnsiString(UnsafeNativeMethods.EvtVariant val)1288         public static string ConvertToAnsiString(UnsafeNativeMethods.EvtVariant val) {
1289             if (val.AnsiString == IntPtr.Zero)
1290                 return string.Empty;
1291             else
1292                 return Marshal.PtrToStringAnsi(val.AnsiString);
1293         }
1294 
1295 
1296         [System.Security.SecurityCritical]
ConvertToSafeHandle(UnsafeNativeMethods.EvtVariant val)1297         public static EventLogHandle ConvertToSafeHandle(UnsafeNativeMethods.EvtVariant val) {
1298             if (val.Handle == IntPtr.Zero)
1299                 return EventLogHandle.Zero;
1300             else
1301                 return new EventLogHandle(val.Handle, true);
1302         }
1303 
1304 
1305         [System.Security.SecurityCritical]
ConvertToArray(UnsafeNativeMethods.EvtVariant val, Type objType, int size)1306         public static Array ConvertToArray(UnsafeNativeMethods.EvtVariant val, Type objType, int size) {
1307            IntPtr ptr = val.Reference;
1308            if (ptr == IntPtr.Zero) {
1309                 return Array.CreateInstance(objType, 0);
1310             }
1311             else {
1312                 Array array = Array.CreateInstance(objType, val.Count);
1313                 for (int i = 0; i < val.Count; i++) {
1314                     array.SetValue(Marshal.PtrToStructure(ptr, objType), i);
1315                     ptr = new IntPtr ((Int64)ptr + size);
1316                 }
1317                 return array;
1318             }
1319         }
1320 
1321         [System.Security.SecurityCritical]
ConvertToBoolArray(UnsafeNativeMethods.EvtVariant val)1322         public static Array ConvertToBoolArray(UnsafeNativeMethods.EvtVariant val) {
1323 
1324            //NOTE: booleans are padded to 4 bytes in ETW
1325            IntPtr ptr = val.Reference;
1326            if (ptr == IntPtr.Zero) {
1327                 return new bool[0];
1328             }
1329             else {
1330                 bool[] array = new bool[val.Count];
1331                 for (int i = 0; i < val.Count; i++) {
1332                     bool value = (Marshal.ReadInt32(ptr) != 0) ? true : false;
1333                     array[i] = value;
1334                     ptr = new IntPtr ((Int64)ptr + 4);
1335                 }
1336                 return array;
1337             }
1338         }
1339 
1340         [System.Security.SecurityCritical]
ConvertToFileTimeArray(UnsafeNativeMethods.EvtVariant val)1341         public static Array ConvertToFileTimeArray(UnsafeNativeMethods.EvtVariant val) {
1342            IntPtr ptr = val.Reference;
1343            if (ptr == IntPtr.Zero) {
1344                 return new DateTime[0];
1345             }
1346             else {
1347                 DateTime[] array = new DateTime[val.Count];
1348                 for (int i = 0; i < val.Count; i++) {
1349                     array[i] = DateTime.FromFileTime(Marshal.ReadInt64(ptr));
1350                     ptr = new IntPtr((Int64)ptr + 8*sizeof(byte)); // FILETIME values are 8 bytes
1351                 }
1352                 return array;
1353             }
1354         }
1355 
1356         [System.Security.SecurityCritical]
ConvertToSysTimeArray(UnsafeNativeMethods.EvtVariant val)1357         public static Array ConvertToSysTimeArray(UnsafeNativeMethods.EvtVariant val) {
1358            IntPtr ptr = val.Reference;
1359            if (ptr == IntPtr.Zero) {
1360                 return new DateTime[0];
1361             }
1362             else {
1363                 DateTime[] array = new DateTime[val.Count];
1364                 for (int i = 0; i < val.Count; i++) {
1365 
1366                     UnsafeNativeMethods.SystemTime sysTime = (UnsafeNativeMethods.SystemTime)Marshal.PtrToStructure(ptr, typeof(UnsafeNativeMethods.SystemTime));
1367                     array[i] = new DateTime(sysTime.Year, sysTime.Month, sysTime.Day, sysTime.Hour, sysTime.Minute, sysTime.Second, sysTime.Milliseconds);
1368                     ptr = new IntPtr((Int64)ptr + 16*sizeof(byte)); // SystemTime values are 16 bytes
1369 
1370                 }
1371                 return array;
1372             }
1373         }
1374 
1375 
1376         [System.Security.SecurityCritical]
ConvertToStringArray(UnsafeNativeMethods.EvtVariant val, bool ansi)1377         public static string[] ConvertToStringArray(UnsafeNativeMethods.EvtVariant val, bool ansi) {
1378             if (val.Reference == IntPtr.Zero) {
1379                 return new string[0];
1380             }
1381             else {
1382                 IntPtr ptr = val.Reference;
1383                 IntPtr[] pointersToString = new IntPtr[val.Count];
1384                 Marshal.Copy(ptr, pointersToString, 0, (int)val.Count);
1385                 string[] stringArray = new string[val.Count];
1386                 for (int i = 0; i < val.Count; i++) {
1387                     stringArray[i] = ansi ? Marshal.PtrToStringAnsi(pointersToString[i]) : Marshal.PtrToStringAuto(pointersToString[i]);
1388                 }
1389                 return stringArray;
1390             }
1391         }
1392 
1393     }
1394 }
1395