Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

41 nativeaot cant marshal safearray #42

Merged
merged 3 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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