WMI: "REFERENCES OF" query failure during Provider startup could be disastrous

Hello, my name is Venkatesh Ganga. I’m a Senior Escalation Engineer on the Microsoft Platform Global Escalation Services team. In this blog I would like to talk about an interesting WMI issue I worked a few months ago. The idea behind this blog is to discuss how WMI works under the hood. In this article I show a few call stacks but the focus of the article is really to point out WMI concepts.

The issue was interesting. The customer encountered the error, "Provider cannot perform the requested operation" for all WMI queries to any provider on some of his Windows XP machines.

Also the WMI Control (wmimgmt.msc) properties showed the following:-

Figure 1:
image 

 

Moreover, nothing happened when he clicked on other tabs like Logging, Backup/Restore, etc. Running WMIDIAG showed the message - “24 error(s) 0x80041024 - (WBEM_E_PROVIDER_NOT_CAPABLE) Provider cannot perform the requested operation“.

All the standard WMI troubleshooting was done before I was engaged, like rebuilding the WMI repository, checking DCOM permissions, etc. But nothing easily resolved the issue so I had the customer send a machine image to Microsoft for a local repro of the problem. Initially I didn’t know where to start with the issue because there were multiple symptoms. I decided to trace the execution of the inbox provider CIMWin32.dll by issuing the WMI query “Select * from Win32_Processor”, next find where it fails, and then go from there.

WMI maintains each provider’s physical implementation information such as the CLSID of the provider’s COM object, the hosting model, etc. in an instance of the __Win32Provider system class. Each provider can support one or more types mentioned below. Based on the type(s) the provider supports, WMI will create an instance of each supported type.

· __ClassProviderRegistration

· __EventConsumerProviderRegistration

· __EventProvideRegistration

· __InstanceProviderRegistration

· __MethodProviderRegistration

· __ObjectProviderRegistration

· __PropertyProviderRegisration

For example, looking at the Windows inbox .mof file for the Cimwin32 provider, we can quickly determine that the provider registers for two types - the Instance Provider, and the Method Provider as Figure 2 displays. The inbox mof files are usually stored in c:\Windows\System32\wbem

 

Figure 2:

image

 

In Memory at Runtime 

Since our test query “select * from Win32_Processor” retrieves the instances of Win32_Processor class, WMI checks the CIMWin32’s __InstanceProviderRegistration object to see if the SupportsEnumeration property is set. While debugging the customer’s image, I found the runtime object WMI maintains for CIMWin32 provider, set to “False” for the ”SupportsEnumeration” property.

 WMI maintains an in-memory structure for each provider and fills that structure out with information from the repository. The CreateInstanceEnumAsync checks the provider’s in-memory structure to determine whether it supports enumeration. From my debugging on the customer’s system, I determined the provider did not support enumeration.

image

Here's a snippet from my debugging-

0:003> kL

ChildEBP RetAddr

0091f560 77e7a1ac wmiprvse!CInterceptor_IWbemSyncProvider::CreateInstanceEnumAsync+0x21

0091f588 77ef421a rpcrt4!Invoke+0x30

0091f998 77ef4bf3 rpcrt4!NdrStubCall2+0x297

0091f9f0 756bd7fe rpcrt4!CStdStubBuffer_Invoke+0xc6

0091fa04 77600c31 fastprox!CBaseStublet::Invoke+0x22

0091fa44 77600bdb ole32!SyncStubInvoke+0x33

0091fa8c 7750f237 ole32!StubInvoke+0xa7

0091fb64 7750f15c ole32!CCtxComChnl::ContextInvoke+0xe3

0091fb80 77600b11 ole32!MTAInvoke+0x1a

0091fbb0 776009bc ole32!AppInvoke+0x9c

0091fc84 77600715 ole32!ComInvokeWithLockAndIPID+0x2e0

0091fcd0 77e79c75 ole32!ThreadInvoke+0x1cd

0091fd04 77e79bda rpcrt4!DispatchToStubInC+0x38

0091fd58 77e79b06 rpcrt4!RPC_INTERFACE::DispatchToStubWorker+0x113

0091fd7c 77e89f9c rpcrt4!RPC_INTERFACE::DispatchToStub+0x84

0091fdbc 77e89fdd rpcrt4!RPC_INTERFACE::DispatchToStubWithObject+0xc0

0091fdfc 77e7be65 rpcrt4!LRPC_SCALL::DealWithRequestMessage+0x2cd

0091fe20 77e76794 rpcrt4!LRPC_ADDRESS::DealWithLRPCRequest+0x16d

0091ff80 00000000 rpcrt4!LRPC_ADDRESS::ReceiveLotsaCalls+0x28f

Repository 

In contrast, when we checked the customer’s system, we determined the repository showed the provider’s “SupportEnumeration” property was set to true. Verification steps below:

1. Run wbemtest and connect to root\cimv2

2. Enter the following query-

                                select * from __InstanceProviderRegistration where provider="__Win32Provider.Name=\"CIMWin32\""

3. After running the query, you should see one object in the Query Result window. Double click it and look at the properties. On a working system you will see the SupportEnumeration property is set to “True” for the CimWin32 provider, as Figure 3 shows.

 

Figure 3:

image

 

Discrepancy Between the In-Memory and Repository

Now we know WMI is not initializing the provider correctly because there is a discrepancy between the in-memory objects it maintains, and the repository.

So I started debugging the CIMWin32 provider initialization where WMI fills the in-memory structure. During provider initialization, WMI makes a REFERENCES OF query to get all types CIMWin32 supports. On our customer’s machine, this query returned zero objects, whereas on a working system it returned two objects (one for __InstanceProviderRegistration and other for __MethodProviderRegistration). Here's a screenshot of this action. 

"references of {__Win32Provider.Name="CimWin32"}"

image

Here is a stack of how we found the exact “REFERENCES OF“ query being issued.

0:007> kL

ChildEBP RetAddr

0164fa38 59841a6c wbemcore!CWbemNamespace::ExecQuery

0164fa88 59841c41 wmiprvsd!CServerObject_ProviderRegistrationV1::QueryRepositoryUsingQuery+0x47

0164faac 59841d31 wmiprvsd!CServerObject_ProviderRegistrationV1::QueryRepository+0x42

0164fac8 5980f056 wmiprvsd!CServerObject_ProviderRegistrationV1::Load+0x33

0164fba8 762e9cfd wmiprvsd!CServerObject_BindingFactory::GetProvider+0x1f5

0164fc24 76301d1e wbemcore!CWbemNamespace::DynAux_ExecQueryExtendedAsync+0x81

0164fce0 76302912 wbemcore!CQueryEngine::ExecComplexQuery+0x1f4

0164fdec 763032bd wbemcore!CQueryEngine::ExecQlQuery+0x37

0164fe90 762fc769 wbemcore!CQueryEngine::ExecQuery+0x228

0164feac 762cef24 wbemcore!CAsyncReq_ExecQueryAsync::Execute+0x19

0164fed8 762ced4e wbemcore!CCoreQueue::pExecute+0x3c

0164ff08 762f25cb wbemcore!CCoreQueue::Execute+0x18

0164ff50 762cee89 wbemcore!CWbemQueue::Execute+0xf6

0164ff84 762cf055 wbemcore!CCoreQueue::ThreadMain+0x111

0164ffb4 7c80b683 wbemcore!CCoreQueue::_ThreadEntry+0x45

0164ffec 00000000 kernel32!BaseThreadStart+0x37

0:044> du 04f57424

04f57424 "references of {__Win32Provider.N"

04f57464 "ame="CIMWin32"}"

The repository driver, repdrvfs.dll, works on the query above. The references query failed with error 80041017 (WBEM_E_INVALID_QUERY) due to an apostrophe in the computer name. While parsing the query, the repository driver considers anything between the apostrophes, or quotes, as a name. This apostrophe in the computer name misleads WMI to look for a closing apostrophe, which is not there, subsequently the references query fails with error.

0:005> kL
ChildEBP RetAddr

05cbfec8 75214a74 repdrvfs!CNamespaceHandle::ExecReferencesQuery+0x1dd

05cbff88 75215518 repdrvfs!CNamespaceHandle::ExecQuerySink+0xc2

05cbffac 7520e11c repdrvfs!CExecQueryObject::Execute+0x28

05cbffb4 7c80b683 repdrvfs!A51FiberBase+0xd

05cbffec 7c82ffa9 kernel32!BaseThreadStart+0x37

05cbffec 00000000 kernel32!BaseFiberStart+0x17

 

0:005> du 00b56218
00b56218 "references of {\\COMPUTERNAME'User1"
00b56258 "\ROOT\cimv2:__Win32Provider.Name"
00b56298 "="CIMWin32"}"

0:005>r

image

WMI makes a similar REFERENCES OF query for all the providers to get the types they support. But they all fail for the same reason. Hence, WMI queries to all the providers fail. We renamed the computer name without an apostrophe and rebooted the box. After the rename, WMI initialized properly, and the WMI queries started working again. An apostrophe is not a valid character for the computer name. Unfortunately, we never found out how the computer name got set with an apostrophe. If we try to set the computer name through GUI, it throws an error saying the computer name has invalid characters. Hopefully through this experience, you have a better understanding of how WMI implements providers to help you better troubleshoot your next WMI issue.

Here are the main takeaways from this article-

1. WMI maintains an instance of __Win32Provider system class for each provider. Based on the provider’s registration (see .mof file above) it maintains one or more registration system classes such as __InstanceProviderRegistration.

2. WMI uses the REFERENCES OF query to map the instance of __Win32Provider to the providers registration types (e.g. __InstanceProviderRegistration).

3. To view the various providers registered on your system, connect to root\Cimv2 and issue the following query: “Select * from __Win32Provider”.

4. And to get the types that each provider supports, issue the following query:references of {__Win32Provider.Name="<PROVIDER_NAME>"}

 

Share this post :