I have installed an instance provider according to the following description:
https://learn.microsoft.com/en-us/windows/win32/wmisdk/supplying-data-to-wmi-by-writing-a-provider
It was registered with regsvr32 and an instance was created:
#PRAGMA AUTORECOVER
#PRAGMA NAMESPACE ("\\\\.\\Root\\MyNamespace")
instance of __Win32Provider as $P
{
Name = "myprovider";
CLSID = "{014D660A-59C4-483F-9F99-1237308B8E98}";
};
instance of __InstanceProviderRegistration
{
Provider = $P;
SupportsGet = TRUE;
SupportsEnumeration = TRUE;
SupportsPut = FALSE;
SupportsDelete = FALSE;
QuerySupportLevels;
};
When I start the Windows Powershell with administrator rights and execute the following command, it fails:
Get-WmiObject -Namespace "root/MyNamespace" -Class "MyInfoClass"
Get-WmiObject :
At line:1 char:1
+ Get-WmiObject -Namespace "root/MyNamespace" -Class "MyInfoClass"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
The event log says:
Id = {ABDF9D5E-3FCE-000A-4B9F-DFABCE3FDB01}; ClientMachine = XYZ; User = XYZ\AnUser;
ClientProcessId = 3884; Component = Unknown; Operation = Start IWbemServices::ExecQuery - root\MyNamespace: select * from MyInfoClass;
ResultCode = 0x800706BE; PossibleCause = Unknown
Based on the traces of my provider I can see that DllGetClassObject is called, the factory of type IClassFactory is created and the reference of the factory is set to 1 before it is returned. The last trace shows that the process WmiPrvSE.exe was terminated with 0xc0000005 (EXCEPTION_ACCESS_VIOLATION).
The CreateInstance method of the factory is never called.
Attempts with changed properties for __Win32Provider and __InstanceProviderRegistration did not help.
Even repairing the WMI repository using ‘winmgmt /resetrepository’ did nothing.
Does anyone have an idea where the problem could be?
Update:
Instead of the Windows Powershell I used a console programme to get the information from the provider. The error handling is missing here for the sake of clarity:
CoInitializeEx(
nullptr, //[in, optional] LPVOID pvReserved,
COINIT_MULTITHREADED //[in] DWORD dwCoInit
);
{
CoInitializeSecurity(
nullptr, //[in, optional] PSECURITY_DESCRIPTOR pSecDesc,
-1, //[in] LONG cAuthSvc,
nullptr, //[in, optional] SOLE_AUTHENTICATION_SERVICE * asAuthSvc,
nullptr, //[in, optional] void* pReserved1,
RPC_C_AUTHN_LEVEL_DEFAULT, //[in] DWORD dwAuthnLevel,
RPC_C_IMP_LEVEL_IMPERSONATE,//[in] DWORD dwImpLevel,
nullptr, //[in, optional] void* pAuthList,
EOAC_NONE, //[in] DWORD dwCapabilities,
nullptr //[in, optional] void* pReserved3
);
CComPtr<IWbemLocator> locator = nullptr;
locator.CoCreateInstance(
CLSID_WbemLocator, //[in] REFCLSID rclsid,
nullptr, //[in] LPUNKNOWN pUnkOuter,
CLSCTX_INPROC_SERVER //[in] DWORD dwClsContext
);
CComPtr<IWbemServices> myNamespace = nullptr;
hr = locator->ConnectServer(
bstr_t(L"\\\\.\\root\\MyNamespace"), //[in] const BSTR strNetworkResource,
nullptr, //[in] const BSTR strUser,
nullptr, //[in] const BSTR strPassword,
nullptr, //[in] const BSTR strLocale,
0, //[in] long lSecurityFlags,
nullptr, //[in] const BSTR strAuthority,
nullptr, //[in] IWbemContext * pCtx,
&myNamespace //[out] IWbemServices * *ppNamespace
);
CoSetProxyBlanket(
myNamespace, //[in] IUnknown * pProxy,
RPC_C_AUTHN_WINNT, //[in] DWORD dwAuthnSvc,
RPC_C_AUTHZ_NONE, //[in] DWORD dwAuthzSvc,
nullptr, //[in, optional] OLECHAR * pServerPrincName,
RPC_C_AUTHN_LEVEL_CALL, //[in] DWORD dwAuthnLevel,
RPC_C_IMP_LEVEL_IMPERSONATE, //[in] DWORD dwImpLevel,
nullptr, //[in, optional] RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
EOAC_NONE //[in] DWORD dwCapabilities
);
CComPtr<IEnumWbemClassObject> enumerator = nullptr;
myNamespace->ExecQuery(
bstr_t(L"WQL"), //[in] const BSTR strQueryLanguage,
bstr_t(L"SELECT * FROM MyInfoClass"), //[in] const BSTR strQuery,
(WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY), //[in] long lFlags,
nullptr, //[in] IWbemContext * pCtx,
&enumerator //[out] IEnumWbemClassObject * *ppEnum
);
ULONG returnedObjCount = 0;
for (;;) {
CComPtr<IWbemClassObject> classObj = nullptr;
enumerator->Next(
WBEM_INFINITE, ///* [in] */ long lTimeout,
1, ///* [in] */ ULONG uCount,
&classObj, ///* [length_is][size_is][out] */ __RPC__out_ecount_part(uCount, *puReturned) IWbemClassObject * *apObjects,
&returnedObjCount ///* [out] */ __RPC__out ULONG * puReturned
);
!!! => ERROR 0x800706BE
...
}
}
CoUninitialize();
I also extended the access rights to the namespace ‘MyNamespace’ using the management console as a test. No success. The use of existing namespaces, such as ‘cimv2’ or ‘default’, also had no effect.
To see if the code works in general, I queried another WMI provider:
SELECT * FROM Win32_Process (in namespace cimv2).
This worked without any problems!?
What could be the reason that my provider is already rejected before it can do anything?
The error 0x800706BE is apparently quite commonly used by the WMI framework, if you look at the various reports on the Internet. Unfortunately, the event logs are also unusable.
In my case, the cause was ultimately quite simple. When restructuring the sample code in https://learn.microsoft.com/en-us/windows/win32/wmisdk/supplying-data-to-wmi-by-writing-a-provider, I had built in an error: The method DllGetClassObject deleted the factory after its use even if QueryInterface was successful. As a result, the CreateInstance method could of course never be called.