Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

246 lines
7.9 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. typedef enum {
  4. ACPIAPIC_UP,
  5. MPS_UP,
  6. HAL_TYPE_OTHER
  7. } HalType;
  8. typedef BOOL (WINAPI *UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC) (
  9. HWND hwndParent,
  10. LPCTSTR HardwareId,
  11. LPCTSTR FullInfPath,
  12. DWORD InstallFlags,
  13. PBOOL bRebootRequired
  14. );
  15. DWORD
  16. GetCurrentlyInstalledHal(
  17. HDEVINFO hDeviceInfo,
  18. PSP_DEVINFO_DATA DeviceInfoData
  19. )
  20. /*++
  21. Routine Description:
  22. This routine will determine if the currently installed HAL on this machine.
  23. Arguments:
  24. hDeviceInfo - handle to the device information set that contains the HAL for
  25. this machine.
  26. DeviceInfoData - pointer to the SP_DEVINFO_DATA structure that contains the
  27. specific HAL devnode for this machine.
  28. Return Value:
  29. The return value will be one of the HalType enums:
  30. ACPIAPIC_UP
  31. MPS_UP
  32. HAL_TYPE_OTHER
  33. We only care about the ACPIAPIC_UP and the MPS_UP case since those are the only
  34. ones we can currently update to MP Hals.
  35. --*/
  36. {
  37. DWORD CurrentlyInstalledHalType = HAL_TYPE_OTHER;
  38. HKEY hKey = INVALID_HANDLE_VALUE;
  39. TCHAR InfSection[LINE_LEN];
  40. DWORD RegDataType, RegDataLength;
  41. //
  42. // The "InfSection" is stored in the devnodes driver key
  43. //
  44. hKey = SetupDiOpenDevRegKey(hDeviceInfo,
  45. DeviceInfoData,
  46. DICS_FLAG_GLOBAL,
  47. 0,
  48. DIREG_DRV,
  49. KEY_READ
  50. );
  51. if (hKey != INVALID_HANDLE_VALUE) {
  52. RegDataLength = sizeof(InfSection);
  53. if (RegQueryValueEx(hKey,
  54. REGSTR_VAL_INFSECTION,
  55. NULL,
  56. &RegDataType,
  57. (PBYTE)InfSection,
  58. &RegDataLength
  59. ) == ERROR_SUCCESS) {
  60. printf("Current HAL is using InfSection %ws\n", InfSection);
  61. //
  62. // Compare the InfSection to see if it is one of the two that
  63. // we can change from UP to MP.
  64. //
  65. if (!lstrcmpi(InfSection, TEXT("ACPIAPIC_UP_HAL"))) {
  66. CurrentlyInstalledHalType = ACPIAPIC_UP;
  67. }
  68. if (!lstrcmpi(InfSection, TEXT("MPS_UP_HAL"))) {
  69. CurrentlyInstalledHalType = MPS_UP;
  70. }
  71. }
  72. RegCloseKey(hKey);
  73. }
  74. return CurrentlyInstalledHalType;
  75. }
  76. int
  77. __cdecl
  78. main(
  79. IN int argc,
  80. IN char *argv[]
  81. )
  82. {
  83. HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
  84. SP_DEVINFO_DATA DeviceInfoData;
  85. DWORD CurrentlyInstalledHalType = HAL_TYPE_OTHER;
  86. TCHAR HardwareId[MAX_DEVICE_ID_LEN];
  87. TCHAR FullInfPath[MAX_PATH];
  88. HMODULE hNewDev;
  89. UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC pfnUpdateDriverForPlugAndPlayDevices;
  90. //
  91. // Ask setupapi to build up a list of all the COMPUTER class devnodes
  92. // on this machine.
  93. //
  94. hDeviceInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_COMPUTER,
  95. NULL,
  96. NULL,
  97. DIGCF_PRESENT
  98. );
  99. if (hDeviceInfo == INVALID_HANDLE_VALUE) {
  100. printf("ERROR could not find a HAL devnode on this machine!\n");
  101. return 0;
  102. }
  103. //
  104. // There is only one HAL per machine, so we will just grab the 1st device
  105. // information data element in the list.
  106. //
  107. DeviceInfoData.cbSize = sizeof(DeviceInfoData);
  108. if (!SetupDiEnumDeviceInfo(hDeviceInfo,
  109. 0,
  110. &DeviceInfoData
  111. )) {
  112. goto clean0;
  113. }
  114. //
  115. // Get the currently installed Hal Type.
  116. // The currently installed Hal must be ACPIAPIC_UP or MPS_UP in order for us
  117. // to upgrade it to an MP Hal.
  118. //
  119. CurrentlyInstalledHalType = GetCurrentlyInstalledHal(hDeviceInfo, &DeviceInfoData);
  120. if (CurrentlyInstalledHalType == HAL_TYPE_OTHER) {
  121. printf("The currently installed HAL is not upgradable to MP!\n");
  122. goto clean0;
  123. }
  124. //
  125. // At this point we know what the currently installed Hal is and we know that it
  126. // has a corresponding MP Hal that it can be upgraded to. In order to upgrade
  127. // the Hal we will replace the Hals Hardware Id registry key with the appropriate
  128. // MP Hardware Id and then call the newdev.dll API UpdateDriverForPlugAndPlayDevices
  129. // which will do the rest of the work.
  130. //
  131. memset(HardwareId, 0, sizeof(HardwareId));
  132. if (CurrentlyInstalledHalType == ACPIAPIC_UP) {
  133. lstrcpy(HardwareId, TEXT("ACPIAPIC_MP"));
  134. } else {
  135. lstrcpy(HardwareId, TEXT("MPS_MP"));
  136. }
  137. if (SetupDiSetDeviceRegistryProperty(hDeviceInfo,
  138. &DeviceInfoData,
  139. SPDRP_HARDWAREID,
  140. (CONST BYTE*)HardwareId,
  141. (sizeof(HardwareId) + 2) * sizeof(TCHAR)
  142. )) {
  143. //
  144. // The Hardware Id has now been changed so call UpdateDriverForPlugAndPlayDevices
  145. // to upate the driver on this device.
  146. //
  147. // UpdateDriverForPlugAndPlayDevices needs to have a full path to the INF file.
  148. // For this sample code we will always be using the hal.inf in the %windir%\inf
  149. // directory.
  150. //
  151. if (GetWindowsDirectory(FullInfPath, sizeof(FullInfPath)/sizeof(TCHAR))) {
  152. lstrcat(FullInfPath, TEXT("\\INF\\HAL.INF"));
  153. hNewDev = LoadLibrary(TEXT("newdev.dll"));
  154. if (hNewDev) {
  155. pfnUpdateDriverForPlugAndPlayDevices = (UPDATE_DRIVER_FOR_PLUG_AND_PLAY_DEVICES_PROC)GetProcAddress(hNewDev,
  156. "UpdateDriverForPlugAndPlayDevicesW"
  157. );
  158. if (pfnUpdateDriverForPlugAndPlayDevices) {
  159. BOOL bRet;
  160. //
  161. // Call UpdateDriverForPlugAndPlayDevices with the appropriate HardwareId and
  162. // FullInfPath. We will pass in 0 for the flags and NULL for the bRebootRequired
  163. // pointer. By passing in NULL for bRebootRequired this will tell newdev.dll to
  164. // prompt for a reboot if one is needed. Since we are replacing a Hal a reboot
  165. // will always be needed. If the caller of this program wants to handle the reboot
  166. // logic themselves then just pass a PBOOL as the last parameter to
  167. // UpdateDriverForPlugAndPlayDevices and then handle the reboot yourself
  168. // if this value is TRUE.
  169. //
  170. bRet = pfnUpdateDriverForPlugAndPlayDevices(NULL,
  171. HardwareId,
  172. FullInfPath,
  173. 0,
  174. NULL
  175. );
  176. printf("UpdateDriverForPlugAndPlayDevices(%ws, %ws) returned 0x%X, 0x%X\n",
  177. HardwareId, FullInfPath, bRet, GetLastError());
  178. }
  179. else {
  180. printf("ERROR GetProcAddress() failed with 0x%X\n", GetLastError());
  181. }
  182. FreeLibrary(hNewDev);
  183. }
  184. }
  185. }
  186. clean0:
  187. if (hDeviceInfo != INVALID_HANDLE_VALUE) {
  188. SetupDiDestroyDeviceInfoList(hDeviceInfo);
  189. }
  190. return 0;
  191. }