Skip to content

Commit 84c1323

Browse files
committed
Added additinal evt types
1 parent db9758f commit 84c1323

File tree

2 files changed

+200
-28
lines changed

2 files changed

+200
-28
lines changed

src/EventLogExpert.Eventing.Tests/Helpers/EventMethodsTests.cs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,26 @@ public void ConvertVariant_WhenByteArrayEmpty_ShouldReturnEmptyArray()
150150
Assert.Empty((byte[])result);
151151
}
152152

153+
[Theory]
154+
[InlineData((int)EvtVariantType.ByteArray)]
155+
[InlineData((int)EvtVariantType.UInt16Array)]
156+
[InlineData((int)EvtVariantType.UInt32Array)]
157+
[InlineData((int)EvtVariantType.HexInt32Array)]
158+
[InlineData((int)EvtVariantType.StringArray)]
159+
[InlineData((int)EvtVariantType.Binary)]
160+
public void ConvertVariant_WhenCountOverflows_ShouldThrowInvalidDataException(int variantType)
161+
{
162+
// Arrange
163+
var type = (EvtVariantType)variantType;
164+
var variant = CreateVariantWithCount(type, IntPtr.Zero, uint.MaxValue);
165+
166+
// Act & Assert
167+
var ex = Assert.Throws<InvalidDataException>(() => EventMethods.ConvertVariant(variant));
168+
Assert.Contains(type.ToString(), ex.Message);
169+
Assert.Contains(uint.MaxValue.ToString(), ex.Message);
170+
Assert.IsType<OverflowException>(ex.InnerException);
171+
}
172+
153173
[Fact]
154174
public void ConvertVariant_WhenDouble_ShouldReturnDouble()
155175
{
@@ -227,6 +247,52 @@ public void ConvertVariant_WhenHexInt32_ShouldReturnInt32()
227247
Assert.Equal(expectedValue, result);
228248
}
229249

250+
[Fact]
251+
public void ConvertVariant_WhenHexInt32Array_ShouldReturnInt32Array()
252+
{
253+
// Arrange
254+
int[] expectedValues = [0x1A, 0x2B, 0x3C, 0x4D];
255+
IntPtr arrayPtr = Marshal.AllocHGlobal(sizeof(int) * expectedValues.Length);
256+
257+
try
258+
{
259+
unsafe
260+
{
261+
var dest = new Span<int>((void*)arrayPtr, expectedValues.Length);
262+
expectedValues.CopyTo(dest);
263+
}
264+
265+
var variant = CreateVariantWithCount(EvtVariantType.HexInt32Array, arrayPtr, (uint)expectedValues.Length);
266+
267+
// Act
268+
var result = EventMethods.ConvertVariant(variant);
269+
270+
// Assert
271+
Assert.NotNull(result);
272+
Assert.IsType<int[]>(result);
273+
Assert.Equal(expectedValues, (int[])result);
274+
}
275+
finally
276+
{
277+
Marshal.FreeHGlobal(arrayPtr);
278+
}
279+
}
280+
281+
[Fact]
282+
public void ConvertVariant_WhenHexInt32ArrayEmpty_ShouldReturnEmptyArray()
283+
{
284+
// Arrange
285+
var variant = CreateVariantWithCount(EvtVariantType.HexInt32Array, IntPtr.Zero, 0);
286+
287+
// Act
288+
var result = EventMethods.ConvertVariant(variant);
289+
290+
// Assert
291+
Assert.NotNull(result);
292+
Assert.IsType<int[]>(result);
293+
Assert.Empty((int[])result);
294+
}
295+
230296
[Fact]
231297
public void ConvertVariant_WhenHexInt64_ShouldReturnUInt64()
232298
{
@@ -305,6 +371,24 @@ public void ConvertVariant_WhenInvalidType_ShouldThrowInvalidDataException()
305371
Assert.Contains("9999", exception.Message);
306372
}
307373

374+
[Theory]
375+
[InlineData((int)EvtVariantType.Binary)]
376+
[InlineData((int)EvtVariantType.ByteArray)]
377+
[InlineData((int)EvtVariantType.UInt16Array)]
378+
[InlineData((int)EvtVariantType.UInt32Array)]
379+
[InlineData((int)EvtVariantType.HexInt32Array)]
380+
[InlineData((int)EvtVariantType.StringArray)]
381+
public void ConvertVariant_WhenNonZeroCountWithNullReference_ShouldThrowInvalidDataException(int variantType)
382+
{
383+
// Arrange
384+
var type = (EvtVariantType)variantType;
385+
var variant = CreateVariantWithCount(type, IntPtr.Zero, 5);
386+
387+
// Act & Assert
388+
var ex = Assert.Throws<InvalidDataException>(() => EventMethods.ConvertVariant(variant));
389+
Assert.Contains(type.ToString(), ex.Message);
390+
}
391+
308392
[Fact]
309393
public void ConvertVariant_WhenNull_ShouldReturnNull()
310394
{
@@ -513,6 +597,52 @@ public void ConvertVariant_WhenUInt16_ShouldReturnUInt16()
513597
Assert.Equal(expectedValue, result);
514598
}
515599

600+
[Fact]
601+
public void ConvertVariant_WhenUInt16Array_ShouldReturnUInt16Array()
602+
{
603+
// Arrange
604+
ushort[] expectedValues = [100, 200, 300, 400];
605+
IntPtr arrayPtr = Marshal.AllocHGlobal(sizeof(ushort) * expectedValues.Length);
606+
607+
try
608+
{
609+
unsafe
610+
{
611+
var dest = new Span<ushort>((void*)arrayPtr, expectedValues.Length);
612+
expectedValues.CopyTo(dest);
613+
}
614+
615+
var variant = CreateVariantWithCount(EvtVariantType.UInt16Array, arrayPtr, (uint)expectedValues.Length);
616+
617+
// Act
618+
var result = EventMethods.ConvertVariant(variant);
619+
620+
// Assert
621+
Assert.NotNull(result);
622+
Assert.IsType<ushort[]>(result);
623+
Assert.Equal(expectedValues, (ushort[])result);
624+
}
625+
finally
626+
{
627+
Marshal.FreeHGlobal(arrayPtr);
628+
}
629+
}
630+
631+
[Fact]
632+
public void ConvertVariant_WhenUInt16ArrayEmpty_ShouldReturnEmptyArray()
633+
{
634+
// Arrange
635+
var variant = CreateVariantWithCount(EvtVariantType.UInt16Array, IntPtr.Zero, 0);
636+
637+
// Act
638+
var result = EventMethods.ConvertVariant(variant);
639+
640+
// Assert
641+
Assert.NotNull(result);
642+
Assert.IsType<ushort[]>(result);
643+
Assert.Empty((ushort[])result);
644+
}
645+
516646
[Fact]
517647
public void ConvertVariant_WhenUInt32_ShouldReturnUInt32()
518648
{
@@ -786,7 +916,9 @@ private static EvtVariant CreateVariantWithCount(EvtVariantType type, object? va
786916
case EvtVariantType.Binary:
787917
case EvtVariantType.StringArray:
788918
case EvtVariantType.ByteArray:
919+
case EvtVariantType.UInt16Array:
789920
case EvtVariantType.UInt32Array:
921+
case EvtVariantType.HexInt32Array:
790922
*(nint*)buffer = (IntPtr)value;
791923
break;
792924
case EvtVariantType.SByte:

src/EventLogExpert.Eventing/Helpers/EventMethods.cs

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ internal enum EvtVariantType
169169
// Array types (base type | EVT_VARIANT_TYPE_ARRAY)
170170
StringArray = 129,
171171
ByteArray = 132,
172-
UInt32Array = 136
172+
UInt16Array = 134,
173+
UInt32Array = 136,
174+
HexInt32Array = 148
173175
}
174176

175177
[Flags]
@@ -220,8 +222,21 @@ internal static partial class EventMethods
220222
case (int)EvtVariantType.Boolean:
221223
return variant.Bool != 0;
222224
case (int)EvtVariantType.Binary:
223-
byte[] bytes = new byte[variant.Count];
224-
Marshal.Copy(variant.Binary, bytes, 0, bytes.Length);
225+
if (variant.Count == 0)
226+
{
227+
return Array.Empty<byte>();
228+
}
229+
230+
int byteCount = CheckedCount(variant.Count, EvtVariantType.Binary);
231+
232+
if (variant.Binary == IntPtr.Zero)
233+
{
234+
throw new InvalidDataException(
235+
$"Null reference with non-zero count {variant.Count} for {nameof(EvtVariantType)}.{EvtVariantType.Binary}");
236+
}
237+
238+
byte[] bytes = new byte[byteCount];
239+
Marshal.Copy(variant.Binary, bytes, 0, byteCount);
225240
return bytes;
226241
case (int)EvtVariantType.Guid:
227242
return Marshal.PtrToStructure<Guid>(variant.GuidReference);
@@ -257,9 +272,17 @@ internal static partial class EventMethods
257272
return Array.Empty<string>();
258273
}
259274

260-
var stringArray = new string[variant.Count];
275+
int stringCount = CheckedCount(variant.Count, EvtVariantType.StringArray);
261276

262-
for (int i = 0; i < variant.Count; i++)
277+
if (variant.Reference == IntPtr.Zero)
278+
{
279+
throw new InvalidDataException(
280+
$"Null reference with non-zero count {variant.Count} for {nameof(EvtVariantType)}.{EvtVariantType.StringArray}");
281+
}
282+
283+
var stringArray = new string[stringCount];
284+
285+
for (int i = 0; i < stringCount; i++)
263286
{
264287
IntPtr stringRef = Marshal.ReadIntPtr(variant.Reference, i * IntPtr.Size);
265288

@@ -268,30 +291,13 @@ internal static partial class EventMethods
268291

269292
return stringArray;
270293
case (int)EvtVariantType.ByteArray:
271-
if (variant.Count == 0)
272-
{
273-
return Array.Empty<byte>();
274-
}
275-
276-
var byteArray = new byte[variant.Count];
277-
Marshal.Copy(variant.Reference, byteArray, 0, byteArray.Length);
278-
279-
return byteArray;
294+
return ReadBlittableArray<byte>(variant.Reference, variant.Count, EvtVariantType.ByteArray);
295+
case (int)EvtVariantType.UInt16Array:
296+
return ReadBlittableArray<ushort>(variant.Reference, variant.Count, EvtVariantType.UInt16Array);
280297
case (int)EvtVariantType.UInt32Array:
281-
if (variant.Count == 0)
282-
{
283-
return Array.Empty<uint>();
284-
}
285-
286-
var uintArray = new uint[variant.Count];
287-
288-
unsafe
289-
{
290-
var source = new ReadOnlySpan<uint>((void*)variant.Reference, (int)variant.Count);
291-
source.CopyTo(uintArray);
292-
}
293-
294-
return uintArray;
298+
return ReadBlittableArray<uint>(variant.Reference, variant.Count, EvtVariantType.UInt32Array);
299+
case (int)EvtVariantType.HexInt32Array:
300+
return ReadBlittableArray<int>(variant.Reference, variant.Count, EvtVariantType.HexInt32Array);
295301
default:
296302
throw new InvalidDataException($"Invalid {nameof(EvtVariantType)}: {variant.Type}");
297303
}
@@ -780,6 +786,19 @@ internal static void ThrowEventLogException(int error)
780786
}
781787
}
782788

789+
private static int CheckedCount(uint count, EvtVariantType type)
790+
{
791+
try
792+
{
793+
return checked((int)count);
794+
}
795+
catch (OverflowException ex)
796+
{
797+
throw new InvalidDataException(
798+
$"Invalid {nameof(EvtVariant)} count {count} for {nameof(EvtVariantType)}.{type}", ex);
799+
}
800+
}
801+
783802
/// <summary>Converts a buffer that was returned from <see cref="EvtRender" /> to an <see cref="EventRecord" /></summary>
784803
/// <param name="eventBuffer">Pointer to a buffer returned from <see cref="EvtRender" /></param>
785804
/// <param name="propertyCount">Number of properties returned from <see cref="EvtRender" /></param>
@@ -843,4 +862,25 @@ private static EventRecord GetEventRecord(IntPtr eventBuffer, int propertyCount)
843862

844863
return properties;
845864
}
865+
866+
private static unsafe T[] ReadBlittableArray<T>(IntPtr reference, uint count, EvtVariantType type) where T : unmanaged
867+
{
868+
if (count == 0)
869+
{
870+
return [];
871+
}
872+
873+
int length = CheckedCount(count, type);
874+
875+
if (reference == IntPtr.Zero)
876+
{
877+
throw new InvalidDataException(
878+
$"Null reference with non-zero count {count} for {nameof(EvtVariantType)}.{type}");
879+
}
880+
881+
var result = new T[length];
882+
new ReadOnlySpan<T>((void*)reference, length).CopyTo(result);
883+
884+
return result;
885+
}
846886
}

0 commit comments

Comments
 (0)