windows-nt/Source/XPSP1/NT/enduser/windows.com/wuv3/cdmlib/findoem.cpp

481 lines
12 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*** findoem.cpp - OEM detection interface
*
* Copyright (c) 1998-1999 Microsoft Corporation. All Rights Reserved.
*
* Author: Yan Leshinsky (YanL)
* Created 10/08/98
*
* MODIFICATION HISTORY
*/
//#define _WIN32_WINNT 0x0400
#include <comdef.h>
#include <windows.h>
#include <ole2.h>
#include <stdlib.h>
#include <wbemcli.h>
#include <tchar.h>
#include <atlconv.h>
#include <wustl.h>
#include "cdmlibp.h"
// Smart pointers
_COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator));
_COM_SMARTPTR_TYPEDEF(IWbemServices, __uuidof(IWbemServices));
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
_COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
// hardcodes - not defined in any header
const CLSID CLSID_WbemLocator = {0x4590f811,0x1d3a,0x11d0,{0x89,0x1f,0x00,0xaa,0x00,0x4b,0x2e,0x24}};
#include "try_catch.h"
#include "findoem.h"
#define BYTEOF(d,i) (((BYTE *)&(d))[i])
/*** That will let me to include file into queryoem and avoid having additional dll
*/
extern HMODULE GetModule();
/*** Local function prototypes
*/
static void UseOeminfoIni(POEMINFO pOemInfo);
static void UseWBEM(POEMINFO pOemInfo);
static bool ReadFromReg(POEMINFO pOemInfo);
static void SaveToReg(POEMINFO pOemInfo);
/*** Registry access
*/
static const TCHAR REGSTR_KEY_OEMINFO[] = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\OemInfo");
static const TCHAR REGSTR_VAL_MASK[] = _T("Mask");
static const TCHAR REGSTR_VAL_ACPIOEM[] = _T("AcpiOem");
static const TCHAR REGSTR_VAL_ACPIPRODUCT[] = _T("AcpiProduct");
static const TCHAR REGSTR_VAL_SMBOEM[] = _T("SmbOem");
static const TCHAR REGSTR_VAL_SMBPRODUCT[] = _T("SmbProduct");
static const TCHAR REGSTR_VAL_PNPOEMID[] = _T("PnpOemId");
static const TCHAR REGSTR_VAL_INIOEM[] = _T("IniOem");
static const TCHAR REGSTR_VAL_WBEMOEM[] = _T("WbemOem");
static const TCHAR REGSTR_VAL_WBEMPRODUCT[] = _T("WbemProduct");
static const TCHAR REGSTR_VAL_OEMINFO_VER[] = _T("OemInfoVersion"); // used to determine if we need to nuke old values
//
// Increment REG_CURRENT_OEM_VER whenever you need to force override of
// old values written to the OemInfo key. Doesn't need to change for each
// new control version.
//
#define REG_CURRENT_OEM_VER 1
/*** GetMachinePnPID - Find IDs corresponding to Make and Model code
*
* ENTRY
* PSZ szTable
* Table format is
*
* |##| ... |##|00|##|##|##|##|
* | | | |
* OEM Model \0 PnP ID
*
* |00|00|00|00|
* | |
* 00000
*
* EXIT
* PnP ID or 0
*/
DWORD GetMachinePnPID(PBYTE pbTable)
{
USES_CONVERSION;
LPTSTR sz = (LPTSTR)DetectMachineID();
LPSTR szMnM = T2A(sz);
if (NULL == szMnM)
{
return 0;
}
while (*pbTable)
{
PDWORD pId = (PDWORD)(pbTable + strlen((LPSTR)pbTable) + 1); // Skip code position on IDs
if (0 == strcmp((LPSTR)pbTable, szMnM))
return *pId;
pbTable = (PBYTE)(pId + 1); // Skip last 0
}
return 0;
}
/*** DetectMachineID - Gather all available machine OEM and model information nad return ID
*
* EXIT
* returns ID
*/
LPCTSTR DetectMachineID(bool fAlwaysDetectAndDontSave /*= false*/)
{
OEMINFO oi;
GetOemInfo(&oi, fAlwaysDetectAndDontSave);
return MakeAndModel(&oi);
}
/*** MakeAndModel - Return ID for a machine
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* returns ID
*/
LPCTSTR MakeAndModel(POEMINFO pOemInfo)
{
static TCHAR szMnM[256];
#ifdef _WUV3TEST
auto_hkey hkey;
if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey)) {
DWORD dwLangID = 0;
DWORD dwSize = sizeof(szMnM);
if (NO_ERROR == RegQueryValueEx(hkey, _T("MachineID"), 0, 0, (LPBYTE)szMnM, &dwSize))
{
return szMnM;
}
}
#endif
szMnM[0] = 0;
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
lstrcpy(szMnM, pOemInfo->szWbemOem);
lstrcat(szMnM, _T(" "));
lstrcat(szMnM, pOemInfo->szWbemProduct);
lstrcat(szMnM, _T(";"));
}
else if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
lstrcat(szMnM, pOemInfo->szIniOem);
lstrcat(szMnM, _T(";"));
}
return szMnM;
}
/*** GetOemInfo - Gather all available machine OEM and model information
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* POEMINFO pOemInfo
* All fields that aren't available will be filled with 0
* returns NULL
*/
void GetOemInfo(POEMINFO pOemInfo, bool fAlwaysDetectAndDontSave /*= false*/)
{
// Worst case:
memset(pOemInfo, 0, sizeof(OEMINFO));
// Do detection if necessary or requested
if (fAlwaysDetectAndDontSave || ! ReadFromReg(pOemInfo))
{
UseWBEM(pOemInfo);
UseOeminfoIni(pOemInfo);
// Save info to the registry
if (!fAlwaysDetectAndDontSave)
{
SaveToReg(pOemInfo);
}
}
}
/***LP IsValidStringID - check if string ID is valid
*
* ENTRY
* pszID pOemInfo-> Pnp ID string
*
* EXIT-SUCCESS
* returns TRUE
* EXIT-FAILURE
* returns FALSE
*/
BOOL IsValidStringID(PSZ pszID)
{
return (strlen(pszID) == 7) &&
isupper(pszID[0]) && isupper(pszID[1]) && isupper(pszID[2]) &&
isxdigit(pszID[3]) && isxdigit(pszID[4]) && isxdigit(pszID[5]) && isxdigit(pszID[6]);
} //IsValidStringID
/***LP NumericID - convert string ID to numeric ID
*
* ENTRY
* psz pOemInfo-> PnP ID string
*
* EXIT
* returns numeric ID
*/
DWORD NumericID(PSZ psz)
{
DWORD dwID;
WORD wVenID;
int i;
for (i = 0, wVenID = 0; i < 3; ++i)
{
wVenID <<= 5;
wVenID |= (psz[i] - 0x40) & 0x1f;
}
dwID = strtoul(&psz[3], NULL, 16);
dwID = ((dwID & 0x00ff) << 8) | ((dwID & 0xff00) >> 8);
dwID <<= 16;
dwID |= (wVenID & 0x00ff) << 8;
dwID |= (wVenID & 0xff00) >> 8;
return dwID;
} //NumericID
/***LP StringID - convert numeric ID to string ID
*
* ENTRY
* dwID - numeric PnP ID
*
* EXIT
* returns string ID
*/
PSZ StringID(DWORD dwID)
{
static char szID[8];
WORD wVenID;
int i;
wVenID = (WORD)(((dwID & 0x00ff) << 8) | ((dwID & 0xff00) >> 8));
wVenID <<= 1;
for (i = 0; i < 3; ++i)
{
szID[i] = (char)(((wVenID & 0xf800) >> 11) + 0x40);
wVenID <<= 5;
}
wVenID = HIWORD(dwID);
wVenID = (WORD)(((wVenID & 0x00ff) << 8) | ((wVenID & 0xff00) >> 8));
for (i = 6; i > 2; --i)
{
szID[i] = (char)(wVenID & 0x000F);
if(szID[i] > 9)
{
szID[i] += 0x37; // 'A' - 0xA for digits A to F
}
else
{
szID[i] += 0x30; // '0' for digits 0 to 9
}
wVenID >>= 4;
}
return szID;
} //StringID
/*** UseOeminfoIni - get OemInfo from OEMINFO.INI
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* POEMINFO pOemInfo
* All fields that aren't available will be filled with 0
* returns NULL
*/
void UseOeminfoIni(POEMINFO pOemInfo)
{
USES_CONVERSION;
static const TCHAR szFile[] = _T("OEMINFO.INI");
static const TCHAR szSection[] = _T("General");
static const TCHAR szKey[] = _T("Manufacturer");
TCHAR szPath[MAX_PATH];
// WU Bug# 11921 -- OEMINFO.INI is in system directory not Windows directory
if (GetSystemDirectory(szPath, sizeOfArray(szPath)) > 0)
{
// check for "c:\"
if (szPath[lstrlen(szPath)-1] != '\\')
{
lstrcat(szPath, _T("\\"));
}
lstrcat(szPath, szFile);
GetPrivateProfileString(szSection, szKey, _T(""),
pOemInfo->szIniOem, sizeOfArray(pOemInfo->szIniOem), szPath);
if (lstrlen(pOemInfo->szIniOem))
{
pOemInfo->dwMask |= OEMINFO_INI_PRESENT;
}
}
}
/*** UseWBEM - Get info through WBEM access
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* POEMINFO pOemInfo
* All fields that aren't available will be filled with 0
* returns NULL
*/
void UseWBEM(POEMINFO pOemInfo)
{
try_block
{
USES_CONVERSION;
// Create Locator
IWbemLocatorPtr pWbemLocator;
throw_hr(pWbemLocator.CreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER));
// Get services
IWbemServicesPtr pWbemServices;
throw_hr(pWbemLocator->ConnectServer(bstr_t(L"\\\\.\\root\\cimv2"), NULL, NULL, 0L, 0L, NULL, NULL, &pWbemServices));
throw_hr(CoSetProxyBlanket(pWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE));
// Create enumerator
IEnumWbemClassObjectPtr pEnum;
throw_hr(pWbemServices->CreateInstanceEnum(bstr_t(L"Win32_ComputerSystem"), 0, NULL, &pEnum));
throw_hr(CoSetProxyBlanket(pEnum, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE));
// Get our object now
ULONG uReturned = 1;
IWbemClassObjectPtr pObject;
throw_hr(pEnum->Next(
6000, // timeout in two seconds
1, // return just one storage device
&pObject, // pointer to storage device
&uReturned)); // number obtained: one or zero
variant_t var;
throw_hr(pObject->Get(L"Manufacturer", 0L, &var, NULL, NULL));
if (VT_BSTR == var.vt)
{
lstrcpy(pOemInfo->szWbemOem, W2T(var.bstrVal));
}
throw_hr(pObject->Get(L"Model", 0L, &var, NULL, NULL));
if (VT_BSTR == var.vt)
{
lstrcpy(pOemInfo->szWbemProduct, W2T(var.bstrVal));
}
if (0 != lstrlen(pOemInfo->szWbemOem) || 0 != lstrlen(pOemInfo->szWbemProduct))
{
pOemInfo->dwMask |= OEMINFO_WBEM_PRESENT;
}
} catch_all;
}
/*** ReadFromReg - read OEMINFO from registry
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* true if info is present
* false otherwise
*/
bool ReadFromReg(POEMINFO pOemInfo)
{
DWORD dwVersion = 0;
//read registry first
auto_hkey hkeyOemInfo;
if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_KEY_OEMINFO, 0, KEY_READ, &hkeyOemInfo))
{
DWORD dwCount = sizeof(pOemInfo->dwMask);
RegQueryValueEx(hkeyOemInfo, REGSTR_VAL_MASK, 0, 0, (LPBYTE)&(pOemInfo->dwMask), &dwCount);
//
// ***** WU Bug# 11921 *****
//
//
// No bits set requires detection
//
if(!pOemInfo->dwMask)
return false;
//
// If an older version of the detection wrote the OemInfo return false to force detection.
// This value is written starting with 1 around August 2000 for the Classic control.
//
dwCount = sizeof(dwVersion);
if (NO_ERROR == RegQueryValueEx(hkeyOemInfo, REGSTR_VAL_OEMINFO_VER, 0, 0, (LPBYTE)&dwVersion, &dwCount))
{
if(REG_CURRENT_OEM_VER > dwVersion)
return false;
}
else
{
return false;
}
//
// ***** end WU Bug *****
//
if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
dwCount = sizeof(pOemInfo->szIniOem);
RegQueryValueEx(hkeyOemInfo, REGSTR_VAL_INIOEM, 0, 0, (LPBYTE)&(pOemInfo->szIniOem), &dwCount);
}
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
dwCount = sizeof(pOemInfo->szWbemOem);
RegQueryValueEx(hkeyOemInfo, REGSTR_VAL_WBEMOEM, 0, 0, (LPBYTE)&(pOemInfo->szWbemOem), &dwCount);
dwCount = sizeof(pOemInfo->szWbemProduct);
RegQueryValueEx(hkeyOemInfo, REGSTR_VAL_WBEMPRODUCT, 0, 0, (LPBYTE)&(pOemInfo->szWbemProduct), &dwCount);
}
return true;
}
else
{
return false;
}
}
/*** SaveToReg - Save OEMINFO
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* none
*/
void SaveToReg(POEMINFO pOemInfo)
{
DWORD dwDisp;
DWORD dwVersion = REG_CURRENT_OEM_VER;
auto_hkey hkeyOemInfo;
if (NO_ERROR == RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_KEY_OEMINFO, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hkeyOemInfo, &dwDisp))
{
RegSetValueEx(hkeyOemInfo, REGSTR_VAL_MASK, 0, REG_DWORD, (LPBYTE)&(pOemInfo->dwMask), sizeof(pOemInfo->dwMask));
//
// Write the current version so future controls can check version of detection that wrote this key.
// WU RAID # 11921
//
RegSetValueEx(hkeyOemInfo, REGSTR_VAL_OEMINFO_VER, 0, REG_DWORD, (LPBYTE)&dwVersion, sizeof(dwVersion));
if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
RegSetValueEx(hkeyOemInfo, REGSTR_VAL_INIOEM, 0, REG_SZ,
(LPBYTE)&(pOemInfo->szIniOem), (lstrlen(pOemInfo->szIniOem) + 1) * sizeof(TCHAR));
}
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
RegSetValueEx(hkeyOemInfo, REGSTR_VAL_WBEMOEM, 0, REG_SZ,
(LPBYTE)&(pOemInfo->szWbemOem),(lstrlen(pOemInfo->szWbemOem) + 1) * sizeof(TCHAR));
RegSetValueEx(hkeyOemInfo, REGSTR_VAL_WBEMPRODUCT, 0, REG_SZ,
(LPBYTE)&(pOemInfo->szWbemProduct), (lstrlen(pOemInfo->szWbemProduct) + 1) * sizeof(TCHAR));
}
}
}