Skip to content

Commit

Permalink
38 getdeviceproperties need setpropertyvalue method has an array over…
Browse files Browse the repository at this point in the history
…load (#40)

Changes WmiMethodParameters class to work with string arrays and WmiObjects.
  • Loading branch information
MartinKuschnik authored Dec 1, 2024
1 parent 8ff653b commit b00d4ed
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 89 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
dotnet-version: 8.x

- name: Setup MSBuild
uses: microsoft/setup-msbuild@v1.1.3
uses: microsoft/setup-msbuild@v2

- name: Restore NuGet packages
run: dotnet restore
Expand All @@ -35,18 +35,18 @@ jobs:
run: |
echo "${{ secrets.PRIVATE_KEY }}" > WmiLight\private_key.base64
certutil -decode WmiLight\private_key.base64 WmiLight\private_key.snk
rm WmiLight\private_key.base64 -v
rm WmiLight\private_key.base64
- name: Build .Net Lib
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} WmiLight\WmiLight.csproj

- name: Cleanup Private Key
run: rm WmiLight\private_key.snk -v
run: rm WmiLight\private_key.snk

- name: Build Native dynamic Lib (x64)
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:ConfigurationType=DynamicLibrary /p:Platform=x64 WmiLight.Native\WmiLight.Native.vcxproj

- name: Build Native dynamic Lib (x86)
# See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference
run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} /p:ConfigurationType=DynamicLibrary /p:Platform=x86 WmiLight.Native\WmiLight.Native.vcxproj
Expand Down
14 changes: 7 additions & 7 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,7,0,0
PRODUCTVERSION 6,7,0,0
FILEVERSION 6,8,0,0
PRODUCTVERSION 6,8,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
Expand All @@ -60,22 +60,22 @@ BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Martin Kuschnik"
#if _x86
#if __x86
VALUE "FileDescription", "The native (x86) part of the WmiLight lib."
#elif _x64
#elif __x64
VALUE "FileDescription", "The native (x64) part of the WmiLight lib."
#elif _arm64
#elif __arm64
VALUE "FileDescription", "The native (ARM64) part of the WmiLight lib."
#else
VALUE "FileDescription", "The native part of the WmiLight lib."
#endif

VALUE "FileVersion", "6.7.0.0"
VALUE "FileVersion", "6.8.0.0"
VALUE "InternalName", "WmiLight.Native"
VALUE "LegalCopyright", "Copyright 2024 Martin Kuschnik"
VALUE "OriginalFilename", "WmiLight.Native.dll"
VALUE "ProductName", "WmiLight"
VALUE "ProductVersion", "6.7.0.0"
VALUE "ProductVersion", "6.8.0.0"
END
END
BLOCK "VarFileInfo"
Expand Down
24 changes: 12 additions & 12 deletions WmiLight.Native/WmiLight.Native.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_x86;WIN32;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>___x86;WIN32;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -138,7 +138,7 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_x86;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x86;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
Expand All @@ -147,7 +147,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_x86;WIN32;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x86;WIN32;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -162,14 +162,14 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_x86;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x86;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_x64;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x64;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -182,14 +182,14 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_x64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_arm64;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__arm64;_DEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -202,7 +202,7 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_arm64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__arm64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
Expand All @@ -211,7 +211,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_x64;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;x64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x64;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;x64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -226,7 +226,7 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_x64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__x64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
Expand All @@ -235,7 +235,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_arm64;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;x64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__arm64;NDEBUG;WMILIGHTNATIVE_EXPORTS;_WINDOWS;_USRDLL;x64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
Expand All @@ -250,7 +250,7 @@
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_arm64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>__arm64;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
Expand Down
80 changes: 80 additions & 0 deletions WmiLight.UnitTests/Win32_PnPEntity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
namespace WmiLight.UnitTests
{
[TestClass]
public class Win32_PnPEntity
{
[TestMethod]
public void Win32_PnPEntity_GetDeviceProperties_Can_Be_Called_With_String_Array_Parameter()
{
using (WmiConnection conncetion = new WmiConnection())
{
using (WmiMethod method = conncetion.GetMethod("Win32_PnPEntity", "GetDeviceProperties"))
{
foreach (WmiObject pnpEntity in conncetion.CreateQuery("SELECT * FROM Win32_PnPEntity"))
{
uint result = pnpEntity.ExecuteMethod<uint>(method, out WmiMethodParameters outParameters);

Assert.AreEqual(0u, outParameters.GetPropertyValue<uint>("ReturnValue"));
Assert.AreEqual(result, outParameters.GetPropertyValue<uint>("ReturnValue"));

WmiObject[] allDeviceProperties = outParameters.GetPropertyValue<WmiObject[]>("deviceProperties");

if (allDeviceProperties.Length > 2)
{
WmiMethodParameters inParameters = method.CreateInParameters();

inParameters.SetPropertyValue("devicePropertyKeys", allDeviceProperties.Take(2).Select(x => x.GetPropertyValue<string>("KeyName")).ToArray());

result = pnpEntity.ExecuteMethod<uint>(method, inParameters, out outParameters);

Assert.AreEqual(0u, outParameters.GetPropertyValue<uint>("ReturnValue"));
Assert.AreEqual(result, outParameters.GetPropertyValue<uint>("ReturnValue"));

WmiObject[] requestedDeviceProperties = outParameters.GetPropertyValue<WmiObject[]>("deviceProperties");

// 2 properties expected
Assert.AreEqual(2, requestedDeviceProperties.Length);

return;
}
}

// if no matching Win32_PnPEntity found
Assert.Inconclusive();
}
}
}

[TestMethod]
public void Win32_PnPEntity_GetDeviceProperties_Can_Be_Called_Null_Parameter()
{
using (WmiConnection conncetion = new WmiConnection())
{
using (WmiMethod method = conncetion.GetMethod("Win32_PnPEntity", "GetDeviceProperties"))
{
foreach (WmiObject pnpEntity in conncetion.CreateQuery("SELECT * FROM Win32_PnPEntity"))
{
WmiMethodParameters inParameters = method.CreateInParameters();

inParameters.SetPropertyValue("devicePropertyKeys", null as string[]);

uint result = pnpEntity.ExecuteMethod<uint>(method, inParameters, out WmiMethodParameters outParameters);

Assert.AreEqual(0u, outParameters.GetPropertyValue<uint>("ReturnValue"));
Assert.AreEqual(result, outParameters.GetPropertyValue<uint>("ReturnValue"));

WmiObject[] allDeviceProperties = outParameters.GetPropertyValue<WmiObject[]>("deviceProperties");

Assert.IsTrue(allDeviceProperties.Length > 0);

// Test done!
return;
}

// if no matching Win32_PnPEntity found
Assert.Inconclusive();
}
}
}
}
}
1 change: 1 addition & 0 deletions WmiLight.UnitTestsGenerator/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static void Main(string[] args)
new Tuple<string, string, string[]>( "root\\cimv2","Win32_Printer" , []),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_PhysicalMemory" , []),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_Process" , ["KernelModeTime"]),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_PnPEntity" , []),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_Processor" , ["KernelModeTime", "LoadPercentage", "L3CacheSize"]),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_Registry" , ["KernelModeTime", "LoadPercentage"]),
new Tuple<string, string, string[]>( "root\\cimv2","Win32_Service" , ["DisconnectedSessions", "TotalSessions"]),
Expand Down
13 changes: 11 additions & 2 deletions WmiLight/Internal/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal static class NativeMethods
/// <summary>
/// Name of the native WmiLight DLL.
/// </summary>
private const string NATIVE_DLL_NAME = "WmiLight.Native.dll";
private const string NATIVE_DLL_NAME = "WmiLight.Native.dll";

#endregion

Expand Down Expand Up @@ -112,7 +112,7 @@ public static extern HResult ExecNotificationQueryAsync(

[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.StdCall)]
public static extern HResult DeleteInstance(IntPtr pWbemServices, [MarshalAs(UnmanagedType.LPWStr)] string strObjectPath, IntPtr ctx);

[DllImport(NATIVE_DLL_NAME, CallingConvention = CallingConvention.StdCall)]
public static extern HResult CreateEventSinkStub(IntPtr pUnsecApp, IntPtr pEventSink, Indicate indicateFunction, SetStatus setStatusFunction, out IntPtr eventSinkStub);

Expand Down Expand Up @@ -164,6 +164,15 @@ public static extern HResult Get(
[DllImport("oleaut32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint SafeArrayGetDim(IntPtr psa);

[DllImport("oleaut32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SafeArrayCreateVector(VARENUM vt, int lLbound, uint cElements);

[DllImport("Oleaut32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern HResult SafeArrayPutElement(IntPtr psa, int[] rgIndices, IntPtr pv);

[DllImport("oleaut32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern HResult SafeArrayDestroy(IntPtr psa);

#endregion

#region Propsys.dll
Expand Down
63 changes: 63 additions & 0 deletions WmiLight/Wbem/WbemClassObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,69 @@ internal void Put(string propertyName, string propertyValue)
}
}

internal void Put(string propertyName, string[] propertyValue)
{
if (this.Disposed)
throw new ObjectDisposedException(nameof(WbemClassObject));

if (propertyValue != null)
{
IntPtr pSafeArray = NativeMethods.SafeArrayCreateVector(VARENUM.VT_BSTR, 0, (uint)propertyValue.Length);

int index = 0;

HResult hResult;

try
{
foreach (string currentPropValue in propertyValue)
{
IntPtr pCurrentPropValue = Marshal.StringToBSTR(currentPropValue);

try
{
hResult = NativeMethods.SafeArrayPutElement(pSafeArray, new int[] { index++ }, pCurrentPropValue);

if (hResult.Failed)
throw (Exception)hResult;
}
finally
{
Marshal.FreeBSTR(pCurrentPropValue);
}
}

VARIANT value = new VARIANT() { vt = VARENUM.VT_BSTR | VARENUM.VT_ARRAY, BStrVal = pSafeArray };

hResult = NativeMethods.Put(this, propertyName, ref value, CimType.None); /* Always CimType.None because this parameter is only for new properties. */

if (hResult.Failed)
throw (Exception)hResult;
}
finally
{
NativeMethods.SafeArrayDestroy(pSafeArray);
}
}
else
{
VARIANT value = new VARIANT() { vt = VARENUM.VT_NULL };

try
{
HResult hResult = NativeMethods.Put(this, propertyName, ref value, CimType.None); /* Always CimType.None because this parameter is only for new properties. */

if (hResult.Failed)
throw (Exception)hResult;
}
finally
{
if (value.BStrVal != IntPtr.Zero)
Marshal.FreeBSTR(value.BStrVal);
}
}
}

private static object VariantToObject(ref VARIANT value, CimType type)
{
if (type.HasFlag(CimType.ArrayFlag))
Expand Down
Loading

0 comments on commit b00d4ed

Please sign in to comment.