Skip to content

Commit

Permalink
41 nativeaot cant marshal safearray (#42)
Browse files Browse the repository at this point in the history
Replaced SafeArray marshalling with custom marshalling to get GetNames method working with NativeAOT and added missing method doc.
  • Loading branch information
MartinKuschnik authored Dec 3, 2024
1 parent b00d4ed commit a717554
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 31 deletions.
8 changes: 4 additions & 4 deletions WmiLight.Native/WmiLight.Native.rc
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ END
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION 6,8,0,0
PRODUCTVERSION 6,8,0,0
FILEVERSION 6,9,0,0
PRODUCTVERSION 6,9,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -70,12 +70,12 @@ BEGIN
VALUE "FileDescription", "The native part of the WmiLight lib."
#endif

VALUE "FileVersion", "6.8.0.0"
VALUE "FileVersion", "6.9.0.0"
VALUE "InternalName", "WmiLight.Native"
VALUE "LegalCopyright", "Copyright 2024 Martin Kuschnik"
VALUE "OriginalFilename", "WmiLight.Native.dll"
VALUE "ProductName", "WmiLight"
VALUE "ProductVersion", "6.8.0.0"
VALUE "ProductVersion", "6.9.0.0"
END
END
BLOCK "VarFileInfo"
Expand Down
2 changes: 1 addition & 1 deletion WmiLight/Internal/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public static extern HResult Get(
public static extern HResult GetType(IntPtr pClassObject, [MarshalAs(UnmanagedType.LPWStr)] string propertyName, out CimType cimType);

[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.StdCall)]
public static extern HResult GetNames(IntPtr pClassObject, [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pNames);
public static extern HResult GetNames(IntPtr pClassObject, out IntPtr pNames);

#endregion

Expand Down
63 changes: 63 additions & 0 deletions WmiLight/Internal/SafeArray.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace WmiLight
{
internal static class SafeArray
{
internal static IEnumerable<IntPtr> ForEach(IntPtr pSafeArray, uint nDim = 1)
{
int lBound, uBound;

HResult hResult = NativeMethods.SafeArrayGetLBound(pSafeArray, nDim, out lBound);

if (hResult.Failed)
throw (Exception)hResult;

hResult = NativeMethods.SafeArrayGetUBound(pSafeArray, nDim, out uBound);

if (hResult.Failed)
throw (Exception)hResult;

for (int i = lBound; i <= uBound; i++)
{
hResult = NativeMethods.SafeArrayGetElement(pSafeArray, i, out IntPtr pElement);

if (hResult.Failed)
throw (Exception)hResult;

yield return pElement;
}
}

internal static IEnumerable<string> ForEachBSTR(IntPtr pSafeArray, uint nDim = 1)
{
foreach (IntPtr pElement in ForEach(pSafeArray, nDim))
{
string stringValue = Marshal.PtrToStringBSTR(pElement);

Marshal.FreeBSTR(pElement);

yield return stringValue;
}
}

internal static int GetLength(IntPtr pSafeArray, uint nDim = 1)
{
int lBound, uBound;

HResult hResult = NativeMethods.SafeArrayGetLBound(pSafeArray, nDim, out lBound);

if (hResult.Failed)
throw (Exception)hResult;

hResult = NativeMethods.SafeArrayGetUBound(pSafeArray, nDim, out uBound);

if (hResult.Failed)
throw (Exception)hResult;

return uBound - lBound + 1;
}
}
}
40 changes: 15 additions & 25 deletions WmiLight/Wbem/WbemClassObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,20 @@ internal IEnumerable<string> GetNames()
if (this.Disposed)
throw new ObjectDisposedException(nameof(WbemClassObject));

string[] names;

HResult hResult = NativeMethods.GetNames(this, out names);
HResult hResult = NativeMethods.GetNames(this, out IntPtr pSafeArrayWithNames);

if (hResult.Failed)
throw (Exception)hResult;

return names;
try
{
foreach (string name in SafeArray.ForEachBSTR(pSafeArrayWithNames))
yield return name;
}
finally
{
NativeMethods.SafeArrayDestroy(pSafeArrayWithNames);
}
}

internal void GetMethod(string methodName, out WbemClassObject inSignatur, out WbemClassObject outSignatur)
Expand Down Expand Up @@ -475,33 +481,17 @@ private static T[] VariantToArray<T>(ref VARIANT value, CimType type)
if (arrayDims != 1)
throw new NotSupportedException("Only single-dimensional arrays are supported");

int lBound, uBound;

HResult hResult = NativeMethods.SafeArrayGetLBound(value.Object, arrayDims, out lBound);
T[] array = new T[SafeArray.GetLength(value.Object, arrayDims)];

if (hResult.Failed)
throw (Exception)hResult;
int index = 0;

hResult = NativeMethods.SafeArrayGetUBound(value.Object, arrayDims, out uBound);

if (hResult.Failed)
throw (Exception)hResult;

T[] array = new T[uBound - lBound + 1];

for (int i = lBound; i <= uBound; i++)
foreach (IntPtr pElement in SafeArray.ForEach(value.Object, arrayDims))
{
VARIANT variant = default;
VARIANT variant = new VARIANT() { vt = value.vt & ~VARENUM.VT_ARRAY, Object = pElement };

try
{
variant.vt = value.vt & ~VARENUM.VT_ARRAY;
hResult = NativeMethods.SafeArrayGetElement(value.Object, i, out variant.Object);

if (hResult.Failed)
throw (Exception)hResult;

array[i] = (T)VariantToObject(ref variant, type);
array[index++] = (T)VariantToObject(ref variant, type);
}
finally
{
Expand Down
2 changes: 1 addition & 1 deletion WmiLight/WmiLight.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</Target>
<PropertyGroup />
<PropertyGroup>
<Version>6.8.0</Version>
<Version>6.9.0</Version>
<PackageId>WmiLight</PackageId>
<Authors>Martin Kuschnik</Authors>
<Company>Martin Kuschnik</Company>
Expand Down
7 changes: 7 additions & 0 deletions WmiLight/WmiMethodParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ public void SetPropertyValue(string propertyName, string propertyValue)
this.signatur.Put(propertyName, propertyValue);
}

#region Description
/// <summary>
/// Sets the value of a property.
/// </summary>
/// <param name="propertyName">The name of the property that should be changed.</param>
/// <param name="propertyValue">The new property value.</param>
#endregion
public void SetPropertyValue(string propertyName, string[] propertyValue)
{
this.signatur.Put(propertyName, propertyValue);
Expand Down

0 comments on commit a717554

Please sign in to comment.