Nytro Posted May 16, 2011 Report Posted May 16, 2011 Finding If a Computer Is a LaptopMarius Bancila C++, COM 2011-01-05 I’ve ran recently across this question: how to find (using C++) if a computer is a laptop? That is possible with WMI and many answers (such as this) point to the Win32_SystemEnclosure class. This class has a member called ChassisTypes, which is an array of integers indicating possible chassis types. At least one of them should indicate a laptop. However, there might be several problems with this solution. First, there are several values for “laptops”: * 8 – Portable * 9 – Laptop * 10 – NotebookDifferent machines might return different values. And more important, this property might not be defined on all computers. A more reliable solution is explained in this TechNet article Finding Computers That Are Laptops. The solution described there suggests checking for several properties: * Win32_SystemEnclosure, ChassisTypes(1)=10. * Win32_Battery or Win32_PortableBattery. * Win32_PCMCIAController * Win32_DriverVXD.Name = “pccard” * Win32_ComputerSystem.Manufacturer * Win32_ComputerSystem.ModelThe following code shows how one can query for the chassis types using C++. Run queries for the other properties to make sure you are running on a laptop.#define _WIN32_DCOM#include < iostream >using namespace std;#include < comdef.h >#include < Wbemidl.h >#pragma comment(lib, "wbemuuid.lib")class WMIQuery{ IWbemLocator* m_pLocator; IWbemServices* m_pServices;public: WMIQuery(): m_pLocator(NULL), m_pServices(NULL) { } bool Initialize() { // Obtain the initial locator to WMI HRESULT hr = ::CoCreateInstance( CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &m_pLocator); if (FAILED(hr)) { cerr << "Failed to create IWbemLocator object. Err code = 0x" << hex << hr << endl; return false; } // Connect to WMI through the IWbemLocator::ConnectServer method // Connect to the root\cimv2 namespace with the current user hr = m_pLocator->ConnectServer( _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace NULL, // User name. NULL = current user NULL, // User password. NULL = current 0, // Locale. NULL indicates current NULL, // Security flags. 0, // Authority (e.g. Kerberos) 0, // Context object &m_pServices // pointer to IWbemServices proxy ); if (FAILED(hr)) { cerr << "Could not connect. Error code = 0x" << hex << hr << endl; m_pLocator->Release(); m_pLocator = NULL; return false; } // Set security levels on the proxy hr = ::CoSetProxyBlanket( m_pServices, // Indicates the proxy to set RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx NULL, // Server principal name RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx NULL, // client identity EOAC_NONE // proxy capabilities ); if (FAILED(hr)) { cerr << "Could not set proxy blanket. Error code = 0x" << hex << hr << endl; m_pServices->Release(); m_pServices = NULL; m_pLocator->Release(); m_pLocator = NULL; return false; } return true; } IEnumWbemClassObject* Query(LPCTSTR strquery) { IEnumWbemClassObject* pEnumerator = NULL; HRESULT hr = m_pServices->ExecQuery( bstr_t("WQL"), bstr_t(strquery), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hr)) { cerr << "Query for operating system name failed. Error code = 0x" << hex << hr << endl; return NULL; } return pEnumerator; } ~WMIQuery() { if(m_pServices != NULL) { m_pServices->Release(); m_pServices = NULL; } if(m_pLocator != NULL) { m_pLocator->Release(); m_pLocator = NULL; } }};int _tmain(int argc, _TCHAR* argv[]){ HRESULT hres; // Initialize COM. hres = ::CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl; return 1; } // Set general COM security levels hres = ::CoInitializeSecurity( NULL, -1, // COM authentication NULL, // Authentication services NULL, // Reserved RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation NULL, // Authentication info EOAC_NONE, // Additional capabilities NULL // Reserved ); if (FAILED(hres)) { cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl; ::CoUninitialize(); return 1; } else { WMIQuery query; if(query.Initialize()) { IEnumWbemClassObject* pEnumerator = query.Query(_T("SELECT * FROM Win32_SystemEnclosure")); if(pEnumerator != NULL) { // Get the data from the query IWbemClassObject *pclsObj; ULONG uReturn = 0; while (pEnumerator) { HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if(0 == uReturn) { break; } VARIANT vtProp; hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0); wcout << "Name: " << vtProp.bstrVal << endl; hr = pclsObj->Get(L"ChassisTypes", 0, &vtProp, 0, 0); wcout << "Chassis: "; SAFEARRAY* parrValues = NULL; if (vtProp.vt & VT_ARRAY) { if (VT_BYREF & vtProp.vt) parrValues = *vtProp.pparray; else parrValues = vtProp.parray; } if (parrValues != NULL) { SAFEARRAYBOUND arrayBounds[1]; arrayBounds[0].lLbound = 0; arrayBounds[0].cElements = 0; SafeArrayGetLBound(parrValues, 1, &arrayBounds[0].lLbound); SafeArrayGetUBound(parrValues, 1, (long*)&arrayBounds[0].cElements); arrayBounds[0].cElements -= arrayBounds[0].lLbound; arrayBounds[0].cElements += 1; if (arrayBounds[0].cElements > 0) { for (ULONG i = 0; i < arrayBounds[0].cElements; i++) { LONG lIndex = (LONG)i; INT item; HRESULT hr = ::SafeArrayGetElement(parrValues, &lIndex, &item); if(SUCCEEDED(hr)) { LPCTSTR szType = NULL; switch(item) { case 1: szType = _T("Other"); break; case 2: szType = _T("Unknown"); break; case 3: szType = _T("Desktop"); break; case 4: szType = _T("Low Profile Desktop"); break; case 5: szType = _T("Pizza Box"); break; case 6: szType = _T("Mini Tower"); break; case 7: szType = _T("Tower"); break; case 8: szType = _T("Portable"); break; case 9: szType = _T("Laptop"); break; case 10:szType = _T("Notebook"); break; case 11:szType = _T("Hand Held"); break; case 12:szType = _T("Docking Station"); break; case 13:szType = _T("All in One"); break; case 14:szType = _T("Sub Notebook"); break; case 15:szType = _T("Space-Saving"); break; case 16:szType = _T("Lunch Box"); break; case 17:szType = _T("Main System Chassis"); break; case 18:szType = _T("Expansion Chassis"); break; case 19:szType = _T("SubChassis"); break; case 20:szType = _T("Bus Expansion Chassis"); break; case 21:szType = _T("Peripheral Chassis"); break; case 22:szType = _T("Storage Chassis"); break; case 23:szType = _T("Rack Mount Chassis"); break; case 24:szType = _T("Sealed-Case PC"); break; } wcout << szType; if(i+1 < arrayBounds[0].cElements) wcout << ", "; } } wcout << endl; } } VariantClear(&vtProp); pclsObj->Release(); } pEnumerator->Release(); } } } ::CoUninitialize(); return 0;}On my laptop, the program output was:Name: System EnclosureChassis: NotebookSursa: Finding If a Computer Is a Laptop | Marius Bancila's Blog Quote