|
|
#include "precomp.h"
#pragma hdrstop
typedef enum { ACPIAPIC_UP, MPS_UP, HAL_TYPE_OTHER } HalType;
typedef BOOL (WINAPI *UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC) ( HWND hwndParent, LPCTSTR HardwareId, LPCTSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired );
DWORD GetCurrentlyInstalledHal( HDEVINFO hDeviceInfo, PSP_DEVINFO_DATA DeviceInfoData ) /*++
Routine Description:
This routine will determine if the currently installed HAL on this machine. Arguments:
hDeviceInfo - handle to the device information set that contains the HAL for this machine. DeviceInfoData - pointer to the SP_DEVINFO_DATA structure that contains the specific HAL devnode for this machine.
Return Value:
The return value will be one of the HalType enums: ACPIAPIC_UP MPS_UP HAL_TYPE_OTHER We only care about the ACPIAPIC_UP and the MPS_UP case since those are the only ones we can currently update to MP Hals.
--*/ { DWORD CurrentlyInstalledHalType = HAL_TYPE_OTHER; HKEY hKey = INVALID_HANDLE_VALUE; TCHAR InfSection[LINE_LEN]; DWORD RegDataType, RegDataLength;
//
// The "InfSection" is stored in the devnodes driver key
//
hKey = SetupDiOpenDevRegKey(hDeviceInfo, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ );
if (hKey != INVALID_HANDLE_VALUE) { RegDataLength = sizeof(InfSection); if (RegQueryValueEx(hKey, REGSTR_VAL_INFSECTION, NULL, &RegDataType, (PBYTE)InfSection, &RegDataLength ) == ERROR_SUCCESS) { printf("Current HAL is using InfSection %ws\n", InfSection); //
// Compare the InfSection to see if it is one of the two that
// we can change from UP to MP.
//
if (!lstrcmpi(InfSection, TEXT("ACPIAPIC_UP_HAL"))) {
CurrentlyInstalledHalType = ACPIAPIC_UP; } if (!lstrcmpi(InfSection, TEXT("MPS_UP_HAL"))) {
CurrentlyInstalledHalType = MPS_UP; } }
RegCloseKey(hKey); }
return CurrentlyInstalledHalType; }
int __cdecl main( IN int argc, IN char *argv[] ) { HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DeviceInfoData; DWORD CurrentlyInstalledHalType = HAL_TYPE_OTHER; TCHAR HardwareId[MAX_DEVICE_ID_LEN]; TCHAR FullInfPath[MAX_PATH]; HMODULE hNewDev; UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC pfnUpdateDriverForPlugAndPlayDevices;
//
// Ask setupapi to build up a list of all the COMPUTER class devnodes
// on this machine.
//
hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_COMPUTER, NULL, NULL, DIGCF_PRESENT );
if (hDeviceInfo == INVALID_HANDLE_VALUE) {
printf("ERROR could not find a HAL devnode on this machine!\n"); return 0; }
//
// There is only one HAL per machine, so we will just grab the 1st device
// information data element in the list.
//
DeviceInfoData.cbSize = sizeof(DeviceInfoData); if (!SetupDiEnumDeviceInfo(hDeviceInfo, 0, &DeviceInfoData )) {
goto clean0; }
//
// Get the currently installed Hal Type.
// The currently installed Hal must be ACPIAPIC_UP or MPS_UP in order for us
// to upgrade it to an MP Hal.
//
CurrentlyInstalledHalType = GetCurrentlyInstalledHal(hDeviceInfo, &DeviceInfoData);
if (CurrentlyInstalledHalType == HAL_TYPE_OTHER) {
printf("The currently installed HAL is not upgradable to MP!\n"); goto clean0; }
//
// At this point we know what the currently installed Hal is and we know that it
// has a corresponding MP Hal that it can be upgraded to. In order to upgrade
// the Hal we will replace the Hals Hardware Id registry key with the appropriate
// MP Hardware Id and then call the newdev.dll API UpdateDriverForPlugAndPlayDevices
// which will do the rest of the work.
//
memset(HardwareId, 0, sizeof(HardwareId));
if (CurrentlyInstalledHalType == ACPIAPIC_UP) { lstrcpy(HardwareId, TEXT("ACPIAPIC_MP")); } else {
lstrcpy(HardwareId, TEXT("MPS_MP")); }
if (SetupDiSetDeviceRegistryProperty(hDeviceInfo, &DeviceInfoData, SPDRP_HARDWAREID, (CONST BYTE*)HardwareId, (sizeof(HardwareId) + 2) * sizeof(TCHAR) )) { //
// The Hardware Id has now been changed so call UpdateDriverForPlugAndPlayDevices
// to upate the driver on this device.
//
// UpdateDriverForPlugAndPlayDevices needs to have a full path to the INF file.
// For this sample code we will always be using the hal.inf in the %windir%\inf
// directory.
//
if (GetWindowsDirectory(FullInfPath, sizeof(FullInfPath)/sizeof(TCHAR))) {
lstrcat(FullInfPath, TEXT("\\INF\\HAL.INF"));
hNewDev = LoadLibrary(TEXT("newdev.dll"));
if (hNewDev) {
pfnUpdateDriverForPlugAndPlayDevices = (UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC)GetProcAddress(hNewDev, "UpdateDriverForPlugAndPlayDevicesW" );
if (pfnUpdateDriverForPlugAndPlayDevices) { BOOL bRet;
//
// Call UpdateDriverForPlugAndPlayDevices with the appropriate HardwareId and
// FullInfPath. We will pass in 0 for the flags and NULL for the bRebootRequired
// pointer. By passing in NULL for bRebootRequired this will tell newdev.dll to
// prompt for a reboot if one is needed. Since we are replacing a Hal a reboot
// will always be needed. If the caller of this program wants to handle the reboot
// logic themselves then just pass a PBOOL as the last parameter to
// UpdateDriverForPlugAndPlayDevices and then handle the reboot yourself
// if this value is TRUE.
//
bRet = pfnUpdateDriverForPlugAndPlayDevices(NULL, HardwareId, FullInfPath, 0, NULL );
printf("UpdateDriverForPlugAndPlayDevices(%ws, %ws) returned 0x%X, 0x%X\n", HardwareId, FullInfPath, bRet, GetLastError()); } else { printf("ERROR GetProcAddress() failed with 0x%X\n", GetLastError()); } FreeLibrary(hNewDev); } } }
clean0: if (hDeviceInfo != INVALID_HANDLE_VALUE) {
SetupDiDestroyDeviceInfoList(hDeviceInfo); }
return 0; }
|