|
|
/*** 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); } }
|