I have developing a new WMI instance provider and I am having a bit of trouble. I am able to register my provider successfully using regsvr32.exe
. The regsvr32
application calls my implementation of DllRegisterServer
and creates the following registry keys and values:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F} : (default) = "WMI Provider"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : (default) = "C:\MyWmiProvider.dll"
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\InprocServer32 : ThreadingModel = Neutral
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{00000001-0000-0000-0000-00000000000F}\Version : (default) = 1.0.0
(Where {00000001-0000-0000-0000-00000000000F}
is just a test Class ID (CLSID))
I am also able to successfully add my WMI class definitions defined in my Managed Object Format (MOF) file by using mofcomp.exe
. I am able to verify that my definitions are present in the WMI repository by running the following command:
Get-CimClass -Namespace "root/MyNamespace" | Where-Object CimClassName -like "MyClass_*"
Here is an example of what my MOF file looks like:
#pragma namespace("\\\\.\\root\\MyNamespace")
#pragma autorecover
instance of __Win32Provider as $P
{
Name = "MyWmiProvider";
ClsId = "{00000001-0000-0000-0000-00000000000F}";
};
instance of __InstanceProviderRegistration
{
Provider = $P;
SupportsGet = FALSE;
SupportsPut = FALSE;
SupportsDelete = FALSE;
SupportsEnumeration = TRUE;
};
[dynamic, provider("MyWmiProvider")]
class MyClass_ExampleName
{
[key]
uint14 Id;
[PropertyContext("Name")]
String Name;
};
Now, if I run the following:
Get-CimInstance -Namespace "root/MyNamespace" -Class "MyClass_ExampleName"
This produces the following error in PowerShell:
Get-CimInstance : Provider load failure
At line:1 char:1
+ Get-CimInstance -Namespace "root/MyNamespace" -Class "MyClass_ExampleName"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (root/Surface:Device_Status:String) [Get-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041013,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
Likewise, there are three (3) Event Viewer logs that are generated when this command is executed:
MyWmiProvider provider started with result code 0x80041013. HostProcess = wmiprvse.exe; ProcessID = 2144; ProviderPath = C:\MyWmiProvider.dll
Id = {FB6B3CF7-293E-0002-9316-73FB3E29D601}; ClientMachine = RTR-USERNAME; User = MYDOMAIN\username; ClientProcessId = 19416; Component = Unknown; Operation = Start IWbemServices::CreateInstanceEnum - root\MyNamespace : MyClass_ExampleName; ResultCode = 0x80041013; PossibleCause = Unknown
MyWmiProvider provider started with result code 0x80041013. HostProcess = wmiprvse.exe; ProcessID = 24636; ProviderPath = C:\MyWmiProvider.dll
(It is shown that WMI did find the DLL correctly)
I get similar results if I try calling Get-WMIObject
, except the second Event Viewer log says the "Operation" was "Start IWbemServices::ExecQuery - root\MyNamespace : MyClass_ExampleName".
What exactly are Get-WMIObject
and Get-CimInstance
doing in the background?
I have looked up the source for Get-WMIObject
[here] and despite the simple 6 lines, looking up the respect classes and function calls does not yield detailed specifics. My DLL interface only includes four (4) exported functions: DllGetClassObject()
, DllCanUnloadNow()
, DllRegisterServer()
, and DllUnregisterServer()
. I thought both Get-WMIObject
and Get-CimInstance
first made a call to DllGetClassObject()
in order to get the WMI class factory, however if I place a function call to save a string to a temporary file within DllGetClassObject()
, I notice when calling these PowerShell commands that no temporary file is created.
I got even more specific by creating a new project following this answer so that I could be able to call the following:
DEFINE_GUID(InstanceProviderClassID, 0x00000001, 0x00000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F);
IWbemServices * pLoc = NULL;
CoCreateInstance(InstanceProviderClassID, NULL, CLSCTX_INPROC_SERVER, IID_IWbemServices, (LPVOID *)&pLoc);
The call to CoCreateInstance()
in this case was successful. I even noticed the temporary log file was created, indicating that DllGetClassObject()
was in fact called!
Even if I take a working instance provider that I have and put this same printing statement (or similarly a call to create a registry key/value) in its DllGetClassObject()
function, nothing is ever saved to indicate that this function is called when calling these PowerShell commands.
1. What am I missing here?
2. Why is the DllGetClassObject()
function never called when executing both Get-WMIObject
and Get-CimInstance
?
3. Why am I able to execute CoCreateInstance()
successfully, demonstrating my provider is coded correctly, but get a "provider load failure" when executing one of the PowerShell commands?
(A side note: In order to make things easy, I have labeled all service functions with WBEM_E_NOT_SUPPORTED
. When this is done in the working instance provider, I still do not see "provider load failure," but rather "not supported.")
User contributions licensed under CC BY-SA 3.0