// ConsoleWMI.cpp : Defines the entry point for the console application.
//
#include <atlbase.h>
#include <atlstr.h>
#include <comutil.h>
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
void GetPhysicalDriveSerialNumber(UINT nDriveNumber IN, CString& strSerialNumber OUT);
int _tmain(int argc, _TCHAR* argv[])
{
CString strResult;
try
{
// 1. Initialize COM
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa390885(v=vs.85).aspx
HRESULT hr = ::CoInitializeEx(0, COINIT_MULTITHREADED);
ATLENSURE_SUCCEEDED(hr);
CString strSerialNumber;
UINT nDriveNumber = 0;
GetPhysicalDriveSerialNumber(nDriveNumber, strSerialNumber);
strResult.Format(_T("Serial number for drive #%u is %s"),
nDriveNumber, strSerialNumber);
}
catch(CAtlException& e)
{
strResult.Format(_T("Get serial number failure. Error code: 0x%08X"),
(HRESULT)e);
}
// Show result
::MessageBox(NULL, strResult, _T("Serial number demo"), MB_OK);
// Uninitialize COM
::CoUninitialize();
return 0;
}
void GetPhysicalDriveSerialNumber(UINT nDriveNumber IN, CString& strSerialNumber OUT)
{
strSerialNumber.Empty();
// Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
CString strDrivePath;
strDrivePath.Format(_T("\\\\.\\PhysicalDrive%u"), nDriveNumber);
// 2. Set the default process security level
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa393617(v=vs.85).aspx
HRESULT hr = ::CoInitializeSecurity(
NULL, // Security descriptor
-1, // COM negotiates authentication service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication level for proxies
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation level for proxies
NULL, // Authentication info
EOAC_NONE, // Additional capabilities of the client or server
NULL); // Reserved
ATLENSURE_SUCCEEDED(hr);
// 3. Create a connection to WMI namespace
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa389749(v=vs.85).aspx
// 3.1. Initialize the IWbemLocator interface
CComPtr<IWbemLocator> pIWbemLocator;
hr = ::CoCreateInstance(CLSID_WbemLocator, 0,
CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator);
ATLENSURE_SUCCEEDED(hr);
// 3.2. Call IWbemLocator::ConnectServer for connecting to WMI
CComPtr<IWbemServices> pIWbemServices;
hr = pIWbemLocator->ConnectServer(L"ROOT\\CIMV2",
NULL, NULL, 0, NULL, 0, 0, &pIWbemServices);
ATLENSURE_SUCCEEDED(hr);
// 4. Set the security levels on WMI connection
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa393619(v=vs.85).aspx
hr = ::CoSetProxyBlanket(
pIWbemServices,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_CALL,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE);
ATLENSURE_SUCCEEDED(hr);
// 5. Execute a WQL (WMI Query Language) query to get physical media info
const BSTR szQueryLanguage = L"WQL";
const BSTR szQuery = L"SELECT Tag, SerialNumber FROM Win32_PhysicalMedia";
CComPtr<IEnumWbemClassObject> pIEnumWbemClassObject;
hr = pIWbemServices->ExecQuery(
szQueryLanguage, // Query language
szQuery, // Query
WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, // Flags
NULL, // Context
&pIEnumWbemClassObject); // Enumerator
ATLENSURE_SUCCEEDED(hr);
// 6. Get each enumerator element until find the desired physical drive
ULONG uReturn = 0;
while(pIEnumWbemClassObject)
{
CComPtr<IWbemClassObject> pIWbemClassObject;
hr = pIEnumWbemClassObject->Next(WBEM_INFINITE, 1, &pIWbemClassObject, &uReturn);
if(0 == uReturn || FAILED(hr))
break;
variant_t vtTag; // unique tag, e.g. '\\.\PHYSICALDRIVE0'
variant_t vtSerialNumber; // manufacturer-provided serial number
hr = pIWbemClassObject->Get(L"Tag", 0, &vtTag, NULL, NULL);
ATLENSURE_SUCCEEDED(hr);
CString strTag(vtTag.bstrVal);
if(!strTag.CompareNoCase(strDrivePath)) // physical drive found
{
hr = pIWbemClassObject->Get(L"SerialNumber", 0, &vtSerialNumber, NULL, NULL);
ATLENSURE_SUCCEEDED(hr);
strSerialNumber = vtSerialNumber.bstrVal; // get the serial number
break;
}
}
}