windows-nt/Source/XPSP1/NT/enduser/windows.com/lib/detect/findoem.cpp
2020-09-26 16:20:57 +08:00

1232 lines
29 KiB
C++

/*** findoem.cpp - OEM detection interface
*
* Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
*
* Author: Yan Leshinsky (YanL)
* Created 10/08/98
*
* MODIFICATION HISTORY
* 10/07/2000 waltw Ripped out auto_hkey, auto_hfile, auto_hlib, _com_ptr_t (_COM_SMARTPTR_TYPEDEF),
* bstr_t, variant_t, & exceptions. Converted to generic text mappings
* (Unicode or ANSI compile)
* 11/02/2000 waltw Stub out VxD functions for Unicode builds and ia64 ANSI builds.
*/
#define _WIN32_DCOM // so we can attempt to call CoInitializeSecurity
#include <comdef.h>
#include <tchar.h>
#include <windows.h>
#include <objbase.h>
#include <ole2.h>
#include<MISTSAFE.h>
// #define __IUENGINE_USES_ATL_
#if defined(__IUENGINE_USES_ATL_)
#include <atlbase.h>
#define USES_IU_CONVERSION USES_CONVERSION
#else
#include <MemUtil.h>
#endif
#include <logging.h>
#include <iucommon.h>
#include <wuiutest.h>
#include <wbemcli.h>
#include <wubios.h>
#include <osdet.h>
#include <wusafefn.h>
//
// Do we really want a VxD?
//
#if defined(IA64) || defined(_IA64_) || defined(UNICODE) || defined(_UNICODE)
// It's gone...
#define NUKE_VXD 1
#else
// We still have friends on Win9x platforms
#define NUKE_VXD 0
#endif
// hardcodes - not defined in any header
const CLSID CLSID_WbemLocator = {0x4590f811,0x1d3a,0x11d0,{0x89,0x1f,0x00,0xaa,0x00,0x4b,0x2e,0x24}};
#if NUKE_VXD == 0
const TCHAR WUBIOS_VXD_NAME[] = {_T("\\\\.\\WUBIOS.VXD")};
#endif
#define BYTEOF(d,i) (((BYTE *)&(d))[i])
// used in UseVxD()
HINSTANCE g_hinst;
/*** Local function prototypes
*/
static void UseOeminfoIni(POEMINFO pOemInfo);
static void UseAcpiReg(POEMINFO pOemInfo);
static void UseWBEM(POEMINFO pOemInfo);
static void UseVxD(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
static const TCHAR REGSTR_VAL_SUPPORTURL[] = _T("OemSupportURL");
//
// forward declarations
//
HRESULT GetOemInfo(POEMINFO pOemInfo, bool fAlwaysDetectAndDontSave = false);
BSTR StringID(DWORD dwID);
//
// 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.
//
// History: No version - original controls
// Version 1 - WUV3 when OEM functions first fixed Aug. 2000
// Version 2 - IU control
#define REG_CURRENT_OEM_VER 2
// Based on V3 MakeAndModel
// Note that for OEMINFO_PNP_PRESENT or
// OEMINFO_INI_PRESENT the model BSTR is an empty string.
HRESULT GetOemBstrs(BSTR& bstrManufacturer, BSTR& bstrModel, BSTR& bstrSupportURL)
{
USES_IU_CONVERSION;
LOG_Block("GetOemBstrs");
if(NULL != bstrManufacturer || NULL != bstrModel || NULL != bstrSupportURL)
{
// BSTRs must be NULL on entry
LOG_ErrorMsg(E_INVALIDARG);
return E_INVALIDARG;
}
// Collect all the data possible, but always prefer in the following order
// Win98 WinME NT4 Win2k/WinXP
// -----------------------------------------
// WBEM/WMI 1 1 1 1
// SMBIOS/DMI 3 3 // wubios.vxd
// ACPI 2 2 2 // UseAcpiReg or wubios.vxd
// PNP 4 4 // wubios.vxd
// OEMInfo.ini 5 5 2
//
// Move OEMINFO to heap per Prefast warning 831: GetOemBstrs uses 5792 bytes
// of stack, consider moving some data to heap.
//
POEMINFO pOemInfo = NULL;
HRESULT hr;
pOemInfo = (POEMINFO) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OEMINFO));
if (NULL == pOemInfo)
{
LOG_ErrorMsg(E_OUTOFMEMORY);
return E_OUTOFMEMORY;
}
//
// Fill in the pOemInfo struct.
//
if (SUCCEEDED(hr = GetOemInfo(pOemInfo)))
{
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
bstrManufacturer = SysAllocString(T2OLE(pOemInfo->szWbemOem));
bstrModel = SysAllocString(T2OLE(pOemInfo->szWbemProduct));
}
// NTRAID#NTBUG9-248906-2000/12/13-waltw IU: Improve OEM detection and reporting.
// prefer SMBIOS over ACPI, and always try to report OEM support URL.
else if (pOemInfo->dwMask & OEMINFO_SMB_PRESENT)
{
bstrManufacturer = SysAllocString(T2OLE(pOemInfo->szSmbOem));
bstrModel = SysAllocString(T2OLE(pOemInfo->szSmbProduct));
}
else if (pOemInfo->dwMask & OEMINFO_ACPI_PRESENT)
{
bstrManufacturer = SysAllocString(T2OLE(pOemInfo->szAcpiOem));
bstrModel = SysAllocString(T2OLE(pOemInfo->szAcpiProduct));
}
else if (pOemInfo->dwMask & OEMINFO_PNP_PRESENT)
{
bstrManufacturer = StringID(pOemInfo->dwPnpOemId);
bstrModel = SysAllocString(T2OLE(_T(""))); // empty BSTR
}
else if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
bstrManufacturer = SysAllocString(T2OLE(pOemInfo->szIniOem));
bstrModel = SysAllocString(T2OLE(_T(""))); // empty BSTR
}
//
// Always return the OEMSupportURL if available
//
if (0 < lstrlen(pOemInfo->szIniOemSupportUrl))
{
bstrSupportURL = SysAllocString(T2OLE(pOemInfo->szIniOemSupportUrl));
}
else
{
bstrSupportURL = SysAllocString(T2OLE(_T(""))); // empty BSTR
}
//
// Manufacturer and Model are optional (if !pOemInfo->dwMask)
//
if ( (pOemInfo->dwMask && (NULL == bstrManufacturer || NULL == bstrModel)) ||
NULL == bstrSupportURL )
{
SafeSysFreeString(bstrManufacturer);
SafeSysFreeString(bstrModel);
SafeSysFreeString(bstrSupportURL);
LOG_ErrorMsg(E_OUTOFMEMORY);
hr = E_OUTOFMEMORY;
}
}
SafeHeapFree(pOemInfo);
return hr;
}
/*** 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
*
*/
HRESULT GetOemInfo(POEMINFO pOemInfo, bool fAlwaysDetectAndDontSave /*= false*/)
{
LOG_Block("GetOemInfo");
HRESULT hr;
if (!pOemInfo)
{
LOG_Error(_T("E_INVALIDARG"));
SetHrAndGotoCleanUp(E_INVALIDARG);
}
// Worst case:
ZeroMemory(pOemInfo, sizeof(OEMINFO));
// Do detection if necessary or requested
if (fAlwaysDetectAndDontSave || ! ReadFromReg(pOemInfo))
{
//
// Always attempt to get strings from oeminfo.ini, if present
//
UseOeminfoIni(pOemInfo);
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{
if (VER_PLATFORM_WIN32_WINDOWS == osvi.dwPlatformId)
{
UseWBEM(pOemInfo);
UseVxD(pOemInfo);
}
else if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
{
if (4 < osvi.dwMajorVersion)
{
// Win2k and higher
UseWBEM(pOemInfo);
UseAcpiReg(pOemInfo);
}
else
{
UseWBEM(pOemInfo);
}
}
// Save info to the registry
if (!fAlwaysDetectAndDontSave)
{
SaveToReg(pOemInfo);
}
}
else
{
LOG_Driver(_T("GetVersionEx:"));
Win32MsgSetHrGotoCleanup(GetLastError());
}
}
//
// Manufacturer and Model are now optional (RAID#337879 IU: can't get latest IU controls
// to work with IU site) so it is OK to return with no information
//
return S_OK;
CleanUp:
//
// Only used for returning errors
//
return hr;
}
/***LP StringID - convert numeric ID to string ID
*
* ENTRY
* dwID - numeric PnP ID
*
* EXIT
* returns string ID
*/
BSTR StringID(DWORD dwID)
{
LOG_Block("StringID");
USES_IU_CONVERSION;
TCHAR szID[8];
WORD wVenID;
int i;
wVenID = (WORD)(((dwID & 0x00ff) << 8) | ((dwID & 0xff00) >> 8));
wVenID <<= 1;
for (i = 0; i < 3; ++i)
{
szID[i] = (TCHAR)(((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] = (TCHAR)(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 SysAllocString(T2OLE(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)
{
LOG_Block("UseOeminfoIni");
static const TCHAR szFile[] = _T("OEMINFO.INI");
static const TCHAR szSection[] = _T("General");
static const TCHAR szKey[] = _T("Manufacturer");
static const TCHAR szSupportURL[] = _T("SupportURL");
HRESULT hr=S_OK;
TCHAR szPath[MAX_PATH + 1];
// OEMINFO.INI is in system directory
if (GetSystemDirectory(szPath, ARRAYSIZE(szPath)) > 0)
{
hr=PathCchAppend(szPath,ARRAYSIZE(szPath),szFile);
if(FAILED(hr))
{
LOG_ErrorMsg(HRESULT_CODE(hr));
return;
}
GetPrivateProfileString(szSection, szKey, _T(""),
pOemInfo->szIniOem, ARRAYSIZE(pOemInfo->szIniOem), szPath);
if (lstrlen(pOemInfo->szIniOem))
{
pOemInfo->dwMask |= OEMINFO_INI_PRESENT;
LOG_Driver(_T("Set OEMINFO_INI_PRESENT bit"));
}
//
// We'll use szIniOemSupportUrl any time we can get it, but don't need to set flag
//
GetPrivateProfileString(szSection, szSupportURL, _T(""),
pOemInfo->szIniOemSupportUrl, ARRAYSIZE(pOemInfo->szIniOemSupportUrl), szPath);
}
}
/*** UseAcpiReg - get OemInfo from the registry
*
* Structure of the registry will be:
* HKEY_LOCAL_MACHINE\Hardware\ACPI\<TableSig>\<OEMID>\<TableID>\<TableRev>
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* POEMINFO pOemInfo
* All fields that aren't available will be filled with 0
* returns NULL
*/
void UseAcpiReg(POEMINFO pOemInfo)
{
LOG_Block("UseAcpiReg");
static const TCHAR szRSDT[] = _T("Hardware\\ACPI\\DSDT");
HKEY hKeyTable;
LONG lRet;
if (NO_ERROR ==(lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRSDT, 0, MAXIMUM_ALLOWED, &hKeyTable)))
{
if (NO_ERROR == (lRet = RegEnumKey(hKeyTable, 0, pOemInfo->szAcpiOem, sizeof(pOemInfo->szAcpiOem)/sizeof(TCHAR))))
{
HKEY hKeyOEM;
if (NO_ERROR == (lRet = RegOpenKeyEx(hKeyTable, pOemInfo->szAcpiOem, 0, MAXIMUM_ALLOWED, &hKeyOEM)))
{
if (NO_ERROR == (lRet = RegEnumKey(hKeyOEM, 0, pOemInfo->szAcpiProduct, sizeof(pOemInfo->szAcpiProduct)/sizeof(TCHAR))))
{
pOemInfo->dwMask |= OEMINFO_ACPI_PRESENT;
LOG_Driver(_T("Set OEMINFO_ACPI_PRESENT bit"));
}
else
{
LOG_Error(_T("RegEnumKey:"));
LOG_ErrorMsg(lRet);
}
RegCloseKey(hKeyOEM);
}
else
{
LOG_Error(_T("RegOpenKeyEx:"));
LOG_ErrorMsg(lRet);
}
}
else
{
LOG_Error(_T("RegEnumKey:"));
LOG_ErrorMsg(lRet);
}
RegCloseKey(hKeyTable);
}
else
{
LOG_Error(_T("RegOpenKeyEx:"));
LOG_ErrorMsg(lRet);
}
}
/*** 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)
{
LOG_Block("UseWBEM");
USES_IU_CONVERSION;
IWbemLocator* pWbemLocator = NULL;
IWbemServices* pWbemServices = NULL;
IEnumWbemClassObject* pEnum = NULL;
IWbemClassObject* pObject = NULL;
BSTR bstrNetworkResource = NULL;
BSTR bstrComputerSystem = NULL;
VARIANT var;
VariantInit(&var);
HRESULT hr;
if (NULL == pOemInfo)
return;
// Create Locator
if (FAILED(hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*) &pWbemLocator)))
{
LOG_Error(_T("CoCreateInstance returned 0x%08x in UseWBEM"), hr);
goto CleanUp;
}
// Get services
if (bstrNetworkResource = SysAllocString(L"\\\\.\\root\\cimv2"))
{
if (FAILED(pWbemLocator->ConnectServer(bstrNetworkResource, NULL, NULL, 0L, 0L, NULL, NULL, &pWbemServices)))
{
LOG_Error(_T("pWbemLocator->ConnectServer returned 0x%08x in UseWBEM"), hr);
goto CleanUp;
}
if (FAILED(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)))
{
LOG_Error(_T("CoSetProxyBlanket returned 0x%08x in UseWBEM"), hr);
goto CleanUp;
}
// Create enumerator
if (bstrComputerSystem = SysAllocString(L"Win32_ComputerSystem"))
{
if (FAILED(hr = pWbemServices->CreateInstanceEnum(bstrComputerSystem, 0, NULL, &pEnum)))
{
goto CleanUp;
}
if (FAILED(CoSetProxyBlanket(pEnum, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE)))
{
goto CleanUp;
}
// Get our object now
ULONG uReturned = 1;
hr = pEnum->Next(
6000, // timeout in six seconds
1, // return just one storage device
&pObject, // pointer to storage device
&uReturned); // number obtained: one or zero
//
// 569939 Need to verify IEnumWbemClassObject::Next uReturned value
//
if (FAILED(hr) || 0 == uReturned || NULL == pObject)
{
goto CleanUp;
}
if (FAILED(hr = pObject->Get(L"Manufacturer", 0L, &var, NULL, NULL)))
{
goto CleanUp;
}
if (VT_BSTR == var.vt)
{
lstrcpyn(pOemInfo->szWbemOem, OLE2T(var.bstrVal), ARRAYSIZE(pOemInfo->szWbemOem));
}
//
// 569968 Call VariantClear before line 549 to prevent leak of BSTR
//
VariantClear(&var);
if (FAILED(hr = pObject->Get(L"Model", 0L, &var, NULL, NULL)))
{
goto CleanUp;
}
if (VT_BSTR == var.vt)
{
lstrcpyn(pOemInfo->szWbemProduct, OLE2T(var.bstrVal), ARRAYSIZE(pOemInfo->szWbemProduct));
}
if (0 != lstrlen(pOemInfo->szWbemOem) || 0 != lstrlen(pOemInfo->szWbemProduct))
{
pOemInfo->dwMask |= OEMINFO_WBEM_PRESENT;
LOG_Driver(_T("Set OEMINFO_WBEM_PRESENT"));
}
}
else
{
LOG_Error(_T("SysAllocString failed in UseWBEM"));
}
}
CleanUp:
SafeReleaseNULL(pWbemLocator);
SafeReleaseNULL(pWbemServices);
SafeReleaseNULL(pEnum);
SafeReleaseNULL(pObject);
SysFreeString(bstrNetworkResource);
SysFreeString(bstrComputerSystem);
if (VT_EMPTY != var.vt)
VariantClear(&var);
return;
}
/*** Calls to wubios.vxd
*/
class CWubiosVxD
{
public:
bool Init(HMODULE hModuleGlobal);
PBYTE GetAcpiTable(DWORD dwTabSig);
PBYTE GetSmbTable(DWORD dwTableType);
DWORD GetPnpOemId();
CWubiosVxD();
~CWubiosVxD();
private:
HANDLE m_hVxD;
TCHAR m_szVxdPath[MAX_PATH + 1];
};
CWubiosVxD::CWubiosVxD()
{
LOG_Block("CWubiosVxD::CWubiosVxD");
m_hVxD = INVALID_HANDLE_VALUE;
m_szVxdPath[0] = _T('\0');
}
CWubiosVxD::~CWubiosVxD()
{
LOG_Block("CWubiosVxD::~CWubiosVxD");
if (INVALID_HANDLE_VALUE != m_hVxD)
{
CloseHandle(m_hVxD);
}
if (0 != lstrlen(m_szVxdPath))
{
DeleteFile(m_szVxdPath);
}
}
/***LP CWubiosVxD::Init - Loads VxD
*
* ENTRY
* none
*
* EXIT
* path
*/
bool CWubiosVxD::Init(HMODULE hModuleGlobal)
{
LOG_Block("CWubiosVxD::Init");
#if NUKE_VXD == 1
LOG_Error(_T("Not supported"));
return false;
#else
bool fRet = false;
HMODULE hModule = NULL;
HRSRC hrscVxd = 0;
HGLOBAL hRes = 0;
PBYTE pImage = NULL;
DWORD dwResSize = 0;
DWORD dwWritten = 0;
DWORD dwVersion = ~WUBIOS_VERSION;
HANDLE hfile = INVALID_HANDLE_VALUE;
TCHAR szMyFileName[MAX_PATH + 1];
HRESULT hr=S_OK;
// Init
if (0 == GetSystemDirectory(m_szVxdPath, ARRAYSIZE(m_szVxdPath)))
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
hr=PathCchAppend(m_szVxdPath,ARRAYSIZE(m_szVxdPath),_T("\\wubios.vxd"));
if(FAILED(hr))
{
LOG_ErrorMsg(HRESULT_CODE(hr));
goto CleanUp;
}
if (0 == GetModuleFileName(hModuleGlobal, szMyFileName, ARRAYSIZE(szMyFileName)))
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
hModule = LoadLibraryEx(szMyFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
if (INVALID_HANDLE_VALUE == hModule)
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
// Get Vxd from resource and save it
hrscVxd = FindResource(hModule, _T("WUBIOS"), RT_VXD);
if (0 == hrscVxd)
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
if (0 == (hRes = LoadResource(hModule, hrscVxd)))
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
pImage = (PBYTE) LockResource(hRes);
if (NULL == pImage)
{
LOG_Error(_T("LockResource failed"));
goto CleanUp;
}
dwResSize = SizeofResource(hModule, hrscVxd);
if (0 == dwResSize)
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
hfile = CreateFile(m_szVxdPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hfile)
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
else
{
LOG_Driver(_T("Success: CreateFile \"%s\""), m_szVxdPath);
}
if (0 == WriteFile(hfile, pImage, dwResSize, &dwWritten, NULL))
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
if (0 == CloseHandle(hfile))
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
hfile = INVALID_HANDLE_VALUE;
if (dwWritten != dwResSize)
{
LOG_Error(_T("WriteFile wrote %d bytes to \"%s\", should be %d"), dwWritten, m_szVxdPath, dwResSize);
goto CleanUp;
}
// Load Vxd
if (INVALID_HANDLE_VALUE != (m_hVxD = CreateFile(WUBIOS_VXD_NAME, 0, 0, NULL, 0, FILE_FLAG_DELETE_ON_CLOSE, NULL)))
{
// Check version
if (DeviceIoControl(m_hVxD, WUBIOCTL_GET_VERSION, NULL, 0, &dwVersion, sizeof(dwVersion), NULL, NULL))
{
if (dwVersion == WUBIOS_VERSION)
{
fRet = true;
}
else
{
LOG_Error(_T("Wrong VxD Version"));
CloseHandle(m_hVxD);
m_hVxD = INVALID_HANDLE_VALUE;
goto CleanUp;
}
}
else
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
}
else
{
LOG_ErrorMsg(GetLastError());
goto CleanUp;
}
CleanUp:
if (INVALID_HANDLE_VALUE != hfile)
CloseHandle(hfile);
if (hModule)
FreeLibrary(hModule);
return fRet;
#endif // NUKE_VXD
}
/***LP CWubiosVxD::GetAcpiTable - Get table
*
* ENTRY
* m_hVxD - VxD handle
* dwTabSig - table signature
*
* EXIT-SUCCESS
* returns pointer to table
* EXIT-FAILURE
* returns NULL
*/
PBYTE CWubiosVxD::GetAcpiTable(DWORD dwTabSig)
{
LOG_Block("CWubiosVxD::GetAcpiTable");
PBYTE pb = NULL;
#if NUKE_VXD == 1
LOG_Error(_T("Not supported"));
#else
ACPITABINFO TabInfo;
TabInfo.dwTabSig = dwTabSig;
if (INVALID_HANDLE_VALUE == m_hVxD)
{
LOG_Error(_T("INVALID_HANDLE_VALUE == m_hVxD"));
return NULL;
}
if (DeviceIoControl(m_hVxD, WUBIOCTL_GET_ACPI_TABINFO, NULL, 0, &TabInfo, sizeof(TabInfo), NULL, NULL))
{
if (pb = (PBYTE) HeapAlloc(GetProcessHeap(), 0, TabInfo.dh.Length))
{
if (0 == DeviceIoControl(m_hVxD, WUBIOCTL_GET_ACPI_TABLE,
(PVOID)TabInfo.dwPhyAddr, 0, pb,TabInfo.dh.Length, NULL, NULL))
{
SafeHeapFree(pb);
LOG_Error(_T("Second DeviceIoControl:"));
LOG_ErrorMsg(GetLastError());
return NULL;
}
}
else
{
LOG_ErrorMsg(E_OUTOFMEMORY);
}
}
else
{
LOG_Error(_T("First DeviceIoControl:"));
LOG_ErrorMsg(GetLastError());
}
#endif // NUKE_VXD
return pb;
}//GetAcpiTable
/***LP CWubiosVxD::GetSmbTable - Get table
*
* ENTRY
* dwTableType - table type
*
* EXIT-SUCCESS
* returns pointer to table
* EXIT-FAILURE
* returns NULL
*/
PBYTE CWubiosVxD::GetSmbTable(DWORD dwTableType)
{
LOG_Block("CWubiosVxD::GetSmbTable");
PBYTE pb = NULL;
#if NUKE_VXD == 1
LOG_Error(_T("Not supported"));
#else
if (INVALID_HANDLE_VALUE == m_hVxD)
{
LOG_Error(_T("m_hVxD invalid"));
return NULL;
}
DWORD dwMaxSize = 0;
if (DeviceIoControl(m_hVxD, WUBIOCTL_GET_SMB_STRUCTSIZE, NULL, 0, &dwMaxSize, sizeof(dwMaxSize), NULL, NULL) && dwMaxSize)
{
if (pb = (PBYTE) HeapAlloc(GetProcessHeap(), 0, dwMaxSize))
{
if (0 == DeviceIoControl(m_hVxD, WUBIOCTL_GET_SMB_STRUCT,
(PVOID)dwTableType, 0, pb, dwMaxSize, NULL, NULL))
{
SafeHeapFree(pb);
LOG_Error(_T("Second DeviceIoControl:"));
LOG_ErrorMsg(GetLastError());
return NULL;
}
}
else
{
LOG_Error(_T("HeapAlloc failed"));
}
}
else
{
LOG_Error(_T("First DeviceIoControl:"));
LOG_ErrorMsg(GetLastError());
}
#endif // NUKE_VXD
return pb;
}// GetSmbTable
/***LP CWubiosVxD::GetPnpOemId - Do it
*
* ENTRY
* none
*
* EXIT
* path
*/
DWORD CWubiosVxD::GetPnpOemId()
{
LOG_Block("CWubiosVxD::GetPnpOemId");
#if NUKE_VXD == 1
LOG_Error(_T("Not supported"));
return 0;
#else
// PnP last
DWORD dwOemId = 0;
if (INVALID_HANDLE_VALUE == m_hVxD)
{
LOG_Error(_T("m_hVxD invalid"));
return 0;
}
if (0 == DeviceIoControl(m_hVxD, WUBIOCTL_GET_PNP_OEMID, NULL, 0,
&dwOemId, sizeof(dwOemId), NULL, NULL))
{
// make sure it didn't mess with the size on error
dwOemId = 0;
LOG_Error(_T("DeviceIoControl:"));
LOG_ErrorMsg(GetLastError());
}
return dwOemId;
#endif // NUKE_VXD
}
/*** UseVxD - Get bios info from it
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* POEMINFO pOemInfo
* All fields that aren't available will be filled with 0
* returns NULL
*/
void UseVxD(POEMINFO pOemInfo)
{
HRESULT hr=S_OK;
LOG_Block("CWubiosVxD::UseVxD");
#if NUKE_VXD == 1
LOG_Error(_T("Not supported"));
return;
#else
USES_IU_CONVERSION;
CWubiosVxD vxd;
if(false == vxd.Init(g_hinst))
return;
// ISSUE-2000/10/10-waltw I don't have a machine to test vxd.GetAcpiTable on...
// ACPI first
PDESCRIPTION_HEADER pHeader = (PDESCRIPTION_HEADER)vxd.GetAcpiTable(DSDT_SIGNATURE);
if (NULL != pHeader)
{
memcpy(pOemInfo->szAcpiOem, pHeader->OEMID, sizeof(pHeader->OEMID));
memcpy(pOemInfo->szAcpiProduct, pHeader->OEMTableID, sizeof(pHeader->OEMTableID));
HeapFree(GetProcessHeap(), 0, pHeader);
pOemInfo->dwMask |= OEMINFO_ACPI_PRESENT;
LOG_Driver(_T("Set OEMINFO_ACPI_PRESENT bit"));
}
// SMBIOS second
PSMBIOSSYSINFO pTable = (PSMBIOSSYSINFO)vxd.GetSmbTable(SMBIOS_SYSTEM_INFO_TABLE);
if (NULL != pTable)
{
// Search counter
int cnStrs = max(pTable->bManufacturer, pTable->bProductName);
char* sz = (char*)pTable + pTable->bLength;
for (int i = 1; i <= cnStrs && sz; i ++)
{
if (pTable->bManufacturer == i)
{
hr=StringCchCopyEx(pOemInfo->szSmbOem,ARRAYSIZE(pOemInfo->szSmbOem),A2T(sz),NULL,NULL,MISTSAFE_STRING_FLAGS);
if(FAILED(hr))
{
LOG_ErrorMsg(HRESULT_CODE(hr));
return;
}
}
else if (pTable->bProductName == i)
{
hr=StringCchCopyEx(pOemInfo->szSmbProduct,ARRAYSIZE(pOemInfo->szSmbProduct),A2T(sz),NULL,NULL,MISTSAFE_STRING_FLAGS);
if(FAILED(hr))
{
LOG_ErrorMsg(HRESULT_CODE(hr));
return;
}
}
sz += strlen(sz) + 1;
}
pOemInfo->dwMask |= OEMINFO_SMB_PRESENT;
SafeHeapFree(pTable);
LOG_Driver(_T("Set OEMINFO_SMB_PRESENT bit"));
}
// ISSUE-2000/10/10-waltw I don't have a machine to test vxd.GetPnpOemId on...
// PnP last
pOemInfo->dwPnpOemId = vxd.GetPnpOemId();
if (pOemInfo->dwPnpOemId != 0)
{
pOemInfo->dwMask |= OEMINFO_PNP_PRESENT;
LOG_Driver(_T("Set OEMINFO_PNP_PRESENT bit"));
}
#endif // NUKE_VXD
}
/*** ReadFromReg - read OEMINFO from registry
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* true if info is present
* false otherwise
*/
bool ReadFromReg(POEMINFO pOemInfo)
{
LOG_Block("ReadFromReg");
DWORD dwVersion = 0;
bool fReturn = false;
bool fRegKeyOpened = false;
LONG lReg;
//read registry first
HKEY hKeyOemInfo;
HRESULT hr;
int cchValueSize;
if (NULL == pOemInfo)
{
return false;
}
if (NO_ERROR == (lReg = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_KEY_OEMINFO, 0, KEY_READ, &hKeyOemInfo)))
{
fRegKeyOpened = true;
DWORD dwCount = sizeof(pOemInfo->dwMask);
if (ERROR_SUCCESS != RegQueryValueEx(hKeyOemInfo, REGSTR_VAL_MASK, 0, 0, (LPBYTE)&(pOemInfo->dwMask), &dwCount))
{
goto CleanUp;
}
//
// ***** WU Bug# 11921 *****
//
//
// No bits set requires detection
//
if(!pOemInfo->dwMask)
{
LOG_Error(_T("No pOemInfo->dwMask bits set in ReadFromReg"));
goto CleanUp;
}
//
// 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 == (lReg = RegQueryValueEx(hKeyOemInfo, REGSTR_VAL_OEMINFO_VER, 0, 0, (LPBYTE)&dwVersion, &dwCount)))
{
if(REG_CURRENT_OEM_VER > dwVersion)
{
LOG_Error(_T("REG_CURRENT_OEM_VER > %lu in Registry"), dwVersion);
goto CleanUp;
}
}
else
{
Win32MsgSetHrGotoCleanup(lReg);
}
//
// ***** end WU Bug *****
//
if (pOemInfo->dwMask & OEMINFO_ACPI_PRESENT)
{
cchValueSize = ARRAYSIZE(pOemInfo->szAcpiOem);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_ACPIOEM, pOemInfo->szAcpiOem, cchValueSize, &cchValueSize));
cchValueSize = ARRAYSIZE(pOemInfo->szAcpiProduct);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_ACPIPRODUCT, pOemInfo->szAcpiProduct, cchValueSize, &cchValueSize));
}
if (pOemInfo->dwMask & OEMINFO_SMB_PRESENT)
{
cchValueSize = ARRAYSIZE(pOemInfo->szSmbOem);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_SMBOEM, pOemInfo->szSmbOem, cchValueSize, &cchValueSize));
cchValueSize = ARRAYSIZE(pOemInfo->szSmbProduct);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_SMBPRODUCT, pOemInfo->szSmbProduct, cchValueSize, &cchValueSize));
}
if (pOemInfo->dwMask & OEMINFO_PNP_PRESENT)
{
dwCount = sizeof(pOemInfo->dwPnpOemId);
if (NO_ERROR != (lReg = RegQueryValueEx(hKeyOemInfo, REGSTR_VAL_PNPOEMID, 0, 0, (LPBYTE)&(pOemInfo->dwPnpOemId), &dwCount)))
goto CleanUp;
}
if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
cchValueSize = ARRAYSIZE(pOemInfo->szIniOem);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_INIOEM, pOemInfo->szIniOem, cchValueSize, &cchValueSize));
}
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
cchValueSize = ARRAYSIZE(pOemInfo->szWbemOem);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_WBEMOEM, pOemInfo->szWbemOem, cchValueSize, &cchValueSize));
cchValueSize = ARRAYSIZE(pOemInfo->szWbemProduct);
CleanUpIfFailedAndSetHrMsg(SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_WBEMPRODUCT, pOemInfo->szWbemProduct, cchValueSize, &cchValueSize));
}
//
// Always try to get the OEM Support URL, but don't bail if we don't have it.
//
cchValueSize = ARRAYSIZE(pOemInfo->szIniOemSupportUrl);
(void) SafeRegQueryStringValueCch(hKeyOemInfo, REGSTR_VAL_SUPPORTURL, pOemInfo->szIniOemSupportUrl, cchValueSize, &cchValueSize);
//
// We got everything we had a dwMask bit set for - drop through to CleanUp
//
fReturn = true;
}
else
{
LOG_ErrorMsg(lReg);
goto CleanUp;
}
CleanUp:
if (true == fRegKeyOpened)
{
RegCloseKey(hKeyOemInfo);
}
return fReturn;
}
/*** SaveToReg - Save OEMINFO
*
* ENTRY
* POEMINFO pOemInfo
*
* EXIT
* none
*/
void SaveToReg(POEMINFO pOemInfo)
{
LOG_Block("SaveToReg");
DWORD dwDisp;
DWORD dwVersion = REG_CURRENT_OEM_VER;
LONG lReg;
HKEY hKey;
//
// Nuke the existing key (it has no subkeys)
//
if (NO_ERROR != (lReg = RegDeleteKey(HKEY_LOCAL_MACHINE, REGSTR_KEY_OEMINFO)))
{
//
// Log error but don't bail - it may not have existed before
//
LOG_Driver(_T("Optional RegDeleteKey:"));
LOG_ErrorMsg(lReg);
}
if (NO_ERROR == (lReg = RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_KEY_OEMINFO, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_WRITE, 0, &hKey, &dwDisp)))
{
//
// Ignore errors from RegSetValueEx - we check for errors in ReadFromReg
//
RegSetValueEx(hKey, 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(hKey, REGSTR_VAL_OEMINFO_VER, 0, REG_DWORD, (LPBYTE)&dwVersion, sizeof(dwVersion));
if (pOemInfo->dwMask & OEMINFO_ACPI_PRESENT)
{
RegSetValueEx(hKey, REGSTR_VAL_ACPIOEM, 0, REG_SZ, (LPBYTE)&(pOemInfo->szAcpiOem), (lstrlen(pOemInfo->szAcpiOem) + 1) * sizeof(TCHAR));
RegSetValueEx(hKey, REGSTR_VAL_ACPIPRODUCT, 0, REG_SZ, (LPBYTE)&(pOemInfo->szAcpiProduct), (lstrlen(pOemInfo->szAcpiProduct) + 1) * sizeof(TCHAR));
}
if (pOemInfo->dwMask & OEMINFO_SMB_PRESENT)
{
RegSetValueEx(hKey, REGSTR_VAL_SMBOEM, 0, REG_SZ, (LPBYTE)&(pOemInfo->szSmbOem), (lstrlen(pOemInfo->szSmbOem) + 1) * sizeof(TCHAR));
RegSetValueEx(hKey, REGSTR_VAL_SMBPRODUCT, 0, REG_SZ, (LPBYTE)&(pOemInfo->szSmbProduct), (lstrlen(pOemInfo->szSmbProduct) + 1) * sizeof(TCHAR));
}
if (pOemInfo->dwMask & OEMINFO_PNP_PRESENT)
{
RegSetValueEx(hKey, REGSTR_VAL_PNPOEMID, 0, REG_DWORD, (LPBYTE)&(pOemInfo->dwPnpOemId), sizeof(pOemInfo->dwPnpOemId));
}
if (pOemInfo->dwMask & OEMINFO_INI_PRESENT)
{
RegSetValueEx(hKey, REGSTR_VAL_INIOEM, 0, REG_SZ, (LPBYTE)&(pOemInfo->szIniOem), (lstrlen(pOemInfo->szIniOem) + 1) * sizeof(TCHAR));
}
if (pOemInfo->dwMask & OEMINFO_WBEM_PRESENT)
{
RegSetValueEx(hKey, REGSTR_VAL_WBEMOEM, 0, REG_SZ, (LPBYTE)&(pOemInfo->szWbemOem), (lstrlen(pOemInfo->szWbemOem) + 1) * sizeof(TCHAR));
RegSetValueEx(hKey, REGSTR_VAL_WBEMPRODUCT, 0, REG_SZ, (LPBYTE)&(pOemInfo->szWbemProduct), (lstrlen(pOemInfo->szWbemProduct) + 1) * sizeof(TCHAR));
}
//
// Always save REGSTR_VAL_SUPPORTURL if we have it
//
int nUrlLen = lstrlen(pOemInfo->szIniOemSupportUrl);
if (0 < nUrlLen)
{
RegSetValueEx(hKey, REGSTR_VAL_SUPPORTURL, 0, REG_SZ, (LPBYTE)&(pOemInfo->szIniOemSupportUrl), (nUrlLen + 1) * sizeof(TCHAR));
}
RegCloseKey(hKey);
}
else
{
LOG_Error(_T("RegCreateKeyEx returned 0x%08x in SaveToReg"), lReg);
}
}