Jump to content
Nytro

Finding If a Computer Is a Laptop

Recommended Posts

Posted

Finding If a Computer Is a Laptop

Marius 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 – Notebook

Different 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.Model

The 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 Enclosure

Chassis: Notebook

Sursa: Finding If a Computer Is a Laptop | Marius Bancila's Blog

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...