Win32_USBControllerDevice

Win32_USBControllerDeviceは、Win32_USBControllerとCIM_LogicalDeviceの関連性を列挙するクラス。

Win32_USBControllerDevice クラス - Win32 apps | Microsoft Docs

まずは、Win32_USBControllerDevice.cppで、

	// クエリの実行.
	BSTR strQueryLanguage = SysAllocString(L"WQL");	// SysAllocStringでstrQueryLanguageを"WQL"で初期化.
	BSTR strQuery = SysAllocString(L"SELECT * FROM Win32_USBControllerDevice");	// SysAllocStringでstrQueryを"SELECT * FROM Win32_USBControllerDevice"で初期化.
	hr6 = pServices->ExecQuery(strQueryLanguage, strQuery, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);	// IWbemServices::ExecQueryでクエリ実行.
	if (FAILED(hr6)){	// FAILEDマクロで判定.
		_tprintf(_T("FAILED!\n"));	// "FAILED!"と出力.
		SysFreeString(strQuery);	// SysFreeStringでstrQueryを解放.
		SysFreeString(strQueryLanguage);	// SysFreeStringでstrQueryLanguageを解放.
		pServices->Release();	// IWbemServices::Releaseで解放.
		SysFreeString(strNetworkResource);	// SysFreeStringでstrNetworkResourceを解放.
		pLocator->Release();	// IWbemLocator::Releaseで解放.
		CoUninitialize();	// CoUninitializeで終了処理.
		return -6;	// -6を返して異常終了.
	}

	// pServices->ExecQueryは成功.
	_tprintf(_T("pServices->ExecQuery OK!\n"));	// "pServices->ExecQuery OK!"と出力.

	// 取得したIEnumWbemClassObjectインターフェースポインタpEnumeratorを出力.
	_tprintf(_T("pEnumerator = 0x%08x\n"), (unsigned long)pEnumerator);	// pEnumeratorを出力.

	// pEnumeratorの各要素を列挙.
	ULONG uReturn = 0;
	while (pEnumerator){	// pEnumeratorがNULLで無い限り続ける.
		hr7 = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObject, &uReturn);	// IEnumWbemClassObject::Nextで次の要素を取得.
		if (uReturn == 0){	// 終了.
			break;
		}
		if (SUCCEEDED(hr7)){	// SUCCEEDEDマクロで判定.
			// pEnumerator->Nextは成功.
			_tprintf(_T("pEnumerator->Next OK!\n"));	// "pEnumerator->Next OK!"と出力.
			// 取得したIWbemClassObjectインターフェースポインタpClassObjectを出力.
			_tprintf(_T("pClassObject = 0x%08x\n"), (unsigned long)pClassObject);	// pClassObjectを出力.
			// オブジェクトテキストの取得.
			BSTR strObjectText;
			hr8 = pClassObject->GetObjectText(0, &strObjectText);	// IWbemClassObject::GetObjectTextでオブジェクトの内容をテキスト形式で取得.
			if (SUCCEEDED(hr8) && strObjectText){	// SUCCEEDEDマクロとstrObjectTextで判定.
				// pClassObject->GetObjectTextは成功.
				_tprintf(_T("pClassObject->GetObjectText OK!\n"));	// "pClassObject->GetObjectText OK!"と出力.
				// ワイド文字をマルチバイト文字に変換する.
				int iBufLen = WideCharToMultiByte(CP_ACP, 0, strObjectText, -1, NULL, 0, NULL, NULL);	// まずは長さを取得.
				char *pszBuf = new char[iBufLen];	// iBufLenのchar型バッファを確保.
				WideCharToMultiByte(CP_ACP, 0, strObjectText, -1, pszBuf, iBufLen, NULL, NULL);	// 変換.
				printf("%s", pszBuf);	// printfでpszBufを出力.
				delete [] pszBuf;	// delete [] でpszBufを解放.
				SysFreeString(strObjectText);	// SysFreeStringでstrObjectTextを解放.
			}
		}
		pClassObject->Release();	// IWbemClassObject::Releaseで解放.
	}

SELECT文で列挙してGetObjectTextで中身を見てみる。

結構ある・・・。
結構ある・・・。

結構な数はある・・・。
次に、

	// クエリの実行.
	BSTR strQueryLanguage = SysAllocString(L"WQL");	// SysAllocStringでstrQueryLanguageを"WQL"で初期化.
	BSTR strQuery = SysAllocString(L"SELECT * FROM Win32_USBController");	// SysAllocStringでstrQueryを"SELECT * FROM Win32_USBController"で初期化.
	hr6 = pServices->ExecQuery(strQueryLanguage, strQuery, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);	// IWbemServices::ExecQueryでクエリ実行.
	if (FAILED(hr6)){	// FAILEDマクロで判定.
		_tprintf(_T("FAILED!\n"));	// "FAILED!"と出力.
		SysFreeString(strQuery);	// SysFreeStringでstrQueryを解放.
		SysFreeString(strQueryLanguage);	// SysFreeStringでstrQueryLanguageを解放.
		pServices->Release();	// IWbemServices::Releaseで解放.
		SysFreeString(strNetworkResource);	// SysFreeStringでstrNetworkResourceを解放.
		pLocator->Release();	// IWbemLocator::Releaseで解放.
		CoUninitialize();	// CoUninitializeで終了処理.
		return -6;	// -6を返して異常終了.
	}

	// pServices->ExecQueryは成功.
	_tprintf(_T("pServices->ExecQuery OK!\n"));	// "pServices->ExecQuery OK!"と出力.

	// 取得したIEnumWbemClassObjectインターフェースポインタpEnumeratorを出力.
	_tprintf(_T("pEnumerator = 0x%08x\n"), (unsigned long)pEnumerator);	// pEnumeratorを出力.

	// pEnumeratorの各要素を列挙.
	ULONG uReturn = 0;
	while (pEnumerator){	// pEnumeratorがNULLで無い限り続ける.
		hr7 = pEnumerator->Next(WBEM_INFINITE, 1, &pClassObject, &uReturn);	// IEnumWbemClassObject::Nextで次の要素を取得.
		if (uReturn == 0){	// 終了.
			break;
		}
		if (SUCCEEDED(hr7)){	// SUCCEEDEDマクロで判定.
			// pEnumerator->Nextは成功.
			//_tprintf(_T("pEnumerator->Next OK!\n"));	// "pEnumerator->Next OK!"と出力.
			// 取得したIWbemClassObjectインターフェースポインタpClassObjectを出力.
			//_tprintf(_T("pClassObject = 0x%08x\n"), (unsigned long)pClassObject);	// pClassObjectを出力.
			// オブジェクトテキストの取得.
			BSTR strObjectText;
			hr8 = pClassObject->GetObjectText(0, &strObjectText);	// IWbemClassObject::GetObjectTextでオブジェクトの内容をテキスト形式で取得.
			if (SUCCEEDED(hr8) && strObjectText){	// SUCCEEDEDマクロとstrObjectTextで判定.
				// pClassObject->GetObjectTextは成功.
				//_tprintf(_T("pClassObject->GetObjectText OK!\n"));	// "pClassObject->GetObjectText OK!"と出力.
				// ワイド文字をマルチバイト文字に変換する.
				int iBufLen = WideCharToMultiByte(CP_ACP, 0, strObjectText, -1, NULL, 0, NULL, NULL);	// まずは長さを取得.
				char *pszBuf = new char[iBufLen];	// iBufLenのchar型バッファを確保.
				WideCharToMultiByte(CP_ACP, 0, strObjectText, -1, pszBuf, iBufLen, NULL, NULL);	// 変換.
				//printf("%s", pszBuf);	// printfでpszBufを出力.
				delete [] pszBuf;	// delete [] でpszBufを解放.
				SysFreeString(strObjectText);	// SysFreeStringでstrObjectTextを解放.
			}
			// プロパティの取得.
			VARIANT vrDeviceID;	// デバイスID.
			hr9 = pClassObject->Get(L"DeviceID", 0, &vrDeviceID, 0, 0);	// IWbemClassObject::Getで"DeviceID"プロパティの値を取得.
			if (SUCCEEDED(hr9)){	// SUCCEEDEDマクロで判定.
				// pClassObject->Getは成功.
				//_tprintf(_T("pClassObject->Get OK!\n"));	// "pClassObject->Get OK!"と出力.
				//wprintf(L"DeviceID: %s\n", vrDeviceID.bstrVal);	// vrDeviceID.bstrValを出力.

				// クエリの実行.
				std::wstring q = L"ASSOCIATORS OF{Win32_USBController.DeviceID=\'";	// "ASSOCIATORS OF{Win32_USBController.DeviceID=\'"をqにセット.
				q = q + vrDeviceID.bstrVal;	// vrDeviceID.bstrValを連結.
				q = q + L"\'}";	// "\'}"を連結.
				q = q + L" WHERE AssocClass = Win32_USBControllerDevice";	// " WHERE AssocClass = Win32_USBControllerDevice"を連結.
				BSTR strQuery2 = SysAllocString(q.c_str());	// SysAllocStringでstrQuery2をq.c_str()で初期化.
				hr10 = pServices->ExecQuery(strQueryLanguage, strQuery2, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator2);	// IWbemServices::ExecQueryでクエリ実行.
				if (SUCCEEDED(hr10)){	// SUCCEEDEDマクロで判定.
					// pServices->ExecQueryは成功.
					//_tprintf(_T("pServices->ExecQuery OK!\n"));	// "pServices->ExecQuery OK!"と出力.
					// 取得したIEnumWbemClassObjectインターフェースポインタpEnumerator2を出力.
					//_tprintf(_T("pEnumerator2 = 0x%08x\n"), (unsigned long)pEnumerator2);	// pEnumerator2を出力.
					// pEnumerator2の各要素を列挙.
					ULONG uReturn2 = 0;
					while (pEnumerator2){	// pEnumerator2がNULLで無い限り続ける.
						hr11 = pEnumerator2->Next(WBEM_INFINITE, 1, &pClassObject2, &uReturn2);	// IEnumWbemClassObject::Nextで次の要素を取得.
						if (uReturn2 == 0){	// 終了.
							break;
						}
						if (SUCCEEDED(hr11)){	// SUCCEEDEDマクロで判定.
							// pEnumerator2->Nextは成功.
							//_tprintf(_T("pEnumerator2->Next OK!\n"));	// "pEnumerator2->Next OK!"と出力.
							// 取得したIWbemClassObjectインターフェースポインタpClassObject2を出力.
							//_tprintf(_T("pClassObject2 = 0x%08x\n"), (unsigned long)pClassObject2);	// pClassObject2を出力.
							// オブジェクトテキストの取得.
							BSTR strObjectText2;
							hr12 = pClassObject2->GetObjectText(0, &strObjectText2);	// IWbemClassObject::GetObjectTextでオブジェクトの内容をテキスト形式で取得.
							if (SUCCEEDED(hr12) && strObjectText2){	// SUCCEEDEDマクロとstrObjectText2で判定.
								// pClassObject2->GetObjectTextは成功.
								//_tprintf(_T("pClassObject2->GetObjectText OK!\n"));	// "pClassObject2->GetObjectText OK!"と出力.
								// ワイド文字をマルチバイト文字に変換する.
								int iBufLen2 = WideCharToMultiByte(CP_ACP, 0, strObjectText2, -1, NULL, 0, NULL, NULL);	// まずは長さを取得.
								char *pszBuf2 = new char[iBufLen2];	// iBufLen2のchar型バッファを確保.
								WideCharToMultiByte(CP_ACP, 0, strObjectText2, -1, pszBuf2, iBufLen2, NULL, NULL);	// 変換.
								//printf("%s", pszBuf2);	// printfでpszBuf2を出力.
								delete [] pszBuf2;	// delete [] でpszBuf2を解放.
								SysFreeString(strObjectText2);	// SysFreeStringでstrObjectText2を解放.
							}
							// プロパティの取得.
							VARIANT vrDeviceID2;	// デバイスID.
							hr13 = pClassObject2->Get(L"DeviceID", 0, &vrDeviceID2, 0, 0);	// IWbemClassObject::Getで"DeviceID"プロパティの値を取得.
							if (SUCCEEDED(hr13)){	// SUCCEEDEDマクロで判定.
								// pClassObject2->Getは成功.
								//_tprintf(_T("pClassObject2->Get OK!\n"));	// "pClassObject2->Get OK!"と出力.
								//wprintf(L"  DeviceID: %s\n", vrDeviceID2.bstrVal);	// vrDeviceID2.bstrValを出力.

								// vrDeviceID2のクリア.
								VariantClear(&vrDeviceID2);	// VariantClearでvrDeviceID2をクリア.
							}
							VARIANT vrPNPDeviceID2;	// PNPデバイスID.
							hr14 = pClassObject2->Get(L"PNPDeviceID", 0, &vrPNPDeviceID2, 0, 0);	// IWbemClassObject::Getで"PNPDeviceID"プロパティの値を取得.
							if (SUCCEEDED(hr14)){	// SUCCEEDEDマクロで判定.
								// pClassObject2->Getは成功.
								//_tprintf(_T("pClassObject2->Get OK!\n"));	// "pClassObject2->Get OK!"と出力.
								if (vrPNPDeviceID2.vt != VT_NULL){	// VT_NULLになることがあるようなので, この判定が必要.
									wprintf(L"PNPDeviceID: %s\n", vrPNPDeviceID2.bstrVal);	// vrPNPDeviceID2.bstrValを出力.
								}
								// vrPNPDeviceID2のクリア.
								VariantClear(&vrPNPDeviceID2);	// VariantClearでvrPNPDeviceID2をクリア.
							}
						}
						pClassObject2->Release();	// IWbemClassObject::Releaseで解放.
					}
					pEnumerator2->Release();	// IEnumWbemClassObject::Releaseで解放.
				}
				SysFreeString(strQuery2);	// SysFreeStringでstrQuery2を解放.

				// vrDeviceIDのクリア.
				VariantClear(&vrDeviceID);	// VariantClearでvrDeviceIDをクリア.
			}
		}
		pClassObject->Release();	// IWbemClassObject::Releaseで解放.
	}

Win32_USBControllerのDeviceIDを列挙し、それをASSOCIATORS OFのAssocClass = Win32_USBControllerDeviceにかけて、CIM_LogicalDeviceのPNPDeviceIDを列挙する。
USBHDD(旧モデル)を挿入してから実行すると、

一番下に、USBSTORが出てきた。これがUSBHDD(旧モデル)。
一番下に、USBSTORが出てきた。これがUSBHDD(旧モデル)。

一番下に、USBSTORが出てきた。これがUSBHDD(旧モデル)。
さて、これはなんのクラスなのか?

インスタンス名を切り出して表示すると、

Win32_PnPEntityだった
Win32_PnPEntityだった

Win32_PnPEntityだった。
Win32_PnPEntityからWin32_DiskDriveそしてドライブレターに繋がった。

Sample/wmi/Win32_USBControllerDevice/Win32_USBControllerDevice/src/Win32_USBControllerDevice at master · bg1bgst333/Sample · GitHub