Leaked source code of windows server 2003
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.

370 lines
11 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <setupapi.h>
  6. #define PNP_NEW_HW_PIPE L"\\\\.\\pipe\\PNP_New_HW_Found"
  7. #define PNP_CREATE_PIPE_EVENT L"PNP_Create_Pipe_Event"
  8. #define PNP_PIPE_TIMEOUT 180000
  9. typedef BOOL (WINAPI *FP_DEVINSTALLW)(HDEVINFO, PSP_DEVINFO_DATA);
  10. typedef HDEVINFO (WINAPI *FP_CREATEDEVICEINFOLIST)(LPGUID, HWND);
  11. typedef BOOL (WINAPI *FP_OPENDEVICEINFO)(HDEVINFO, PCWSTR, HWND, DWORD, PSP_DEVINFO_DATA);
  12. typedef BOOL (WINAPI *FP_DESTROYDEVICEINFOLIST)(HDEVINFO);
  13. typedef BOOL (WINAPI *FP_GETDEVICEINSTALLPARAMS)(HDEVINFO, PSP_DEVINFO_DATA, PSP_DEVINSTALL_PARAMS_W);
  14. typedef BOOL (WINAPI *FP_ENUMDEVICEINFO)(HDEVINFO, DWORD, PSP_DEVINFO_DATA);
  15. typedef INT (WINAPI *FP_PROMPTREBOOT)(HSPFILEQ, HWND, BOOL);
  16. extern
  17. BOOL
  18. CheckEMS(
  19. IN int argc,
  20. WCHAR *argvW[]
  21. );
  22. VOID
  23. InstallNewHardware(
  24. IN HMODULE hSysSetup
  25. );
  26. int
  27. __cdecl
  28. wmain(
  29. IN int argc,
  30. IN wchar_t *argv[]
  31. )
  32. {
  33. BOOL NewSetup = TRUE;
  34. BOOL NewHardware = FALSE;
  35. BOOL CheckedEms = FALSE;
  36. INT i;
  37. HMODULE h = NULL;
  38. FARPROC p = NULL;
  39. WCHAR FileName[MAX_PATH / 2];
  40. //
  41. // Scan Command Line for -newsetup flag
  42. //
  43. for(i = 0; i < argc; i++) {
  44. PCWSTR arg = argv[i];
  45. if(arg[0] == '-') {
  46. arg += 1;
  47. if(_wcsicmp(arg,L"newsetup") == 0) {
  48. NewSetup = TRUE;
  49. } else if (_wcsicmp(arg, L"plugplay") == 0) {
  50. NewHardware = TRUE;
  51. } else if (
  52. _wcsicmp(arg, L"asr") == 0
  53. || _wcsicmp(arg, L"asrquicktest") == 0
  54. || _wcsicmp(arg, L"mini") == 0
  55. ) {
  56. ; // do nothing
  57. } else
  58. return ERROR_INVALID_PARAMETER;
  59. }
  60. }
  61. i = ERROR_INVALID_PARAMETER;
  62. if (NewSetup && !NewHardware) {
  63. //
  64. // Go see if there's a headless port that we need to
  65. // get setup values from.
  66. //
  67. // He'll return FALSE *only* if we shouldn't run
  68. // setup (like if the user rejected the EULA
  69. // through the EMS port). Otherwise he'll return
  70. // TRUE and we should run through setup.
  71. //
  72. CheckedEms = TRUE;
  73. if (!CheckEMS(argc, argv)) {
  74. //
  75. // Set our return code for bailing.
  76. //
  77. i = 0;
  78. }
  79. }
  80. if (!CheckedEms || i != 0 ) {
  81. //
  82. // Load the Appropriate Libary and function pointer
  83. //
  84. h = LoadLibraryW(L"syssetup.dll");
  85. if( h ){
  86. if (NewHardware) {
  87. InstallNewHardware(h);
  88. } else {
  89. const PPEB Peb = NtCurrentPeb();
  90. #if DBG
  91. if ( !RTL_SOFT_ASSERT(Peb->ActivationContextData == NULL)
  92. || !RTL_SOFT_ASSERT(Peb->ProcessAssemblyStorageMap == NULL)
  93. || !RTL_SOFT_ASSERT(Peb->SystemDefaultActivationContextData == NULL)
  94. || !RTL_SOFT_ASSERT(Peb->SystemAssemblyStorageMap == NULL)) {
  95. ASSERTMSG(
  96. "setup -newsetup has a process default or system default\n"
  97. "activation context. Did you forget the -isd switch to ntsd?\n",
  98. FALSE);
  99. }
  100. #endif
  101. // for people debugging with VC
  102. Peb->ActivationContextData = NULL;
  103. Peb->ProcessAssemblyStorageMap = NULL;
  104. Peb->SystemDefaultActivationContextData = NULL;
  105. Peb->SystemAssemblyStorageMap = NULL;
  106. //
  107. // Call the target function.
  108. //
  109. p=GetProcAddress(h,"InstallWindowsNt");
  110. if(p) {
  111. i = (int) p(argc,argv);
  112. }
  113. }
  114. } else {
  115. i = GetLastError();
  116. }
  117. }
  118. //
  119. // Make sure that the library goes away
  120. //
  121. while(h && GetModuleFileNameW(h,FileName,RTL_NUMBER_OF(FileName))) {
  122. FreeLibrary(h);
  123. }
  124. return i;
  125. }
  126. VOID
  127. InstallNewHardware(
  128. IN HMODULE hSysSetup
  129. )
  130. {
  131. FP_DEVINSTALLW fpDevInstallW = NULL;
  132. FP_CREATEDEVICEINFOLIST fpCreateDeviceInfoList = NULL;
  133. FP_OPENDEVICEINFO fpOpenDeviceInfoW = NULL;
  134. FP_DESTROYDEVICEINFOLIST fpDestroyDeviceInfoList;
  135. FP_GETDEVICEINSTALLPARAMS fpGetDeviceInstallParams;
  136. FP_ENUMDEVICEINFO fpEnumDeviceInfo;
  137. FP_PROMPTREBOOT fpPromptReboot;
  138. HMODULE hSetupApi = NULL;
  139. WCHAR szBuffer[MAX_PATH];
  140. ULONG ulSize = 0, Index;
  141. HANDLE hPipe = INVALID_HANDLE_VALUE;
  142. HANDLE hEvent = NULL;
  143. HDEVINFO hDevInfo = INVALID_HANDLE_VALUE;
  144. SP_DEVINFO_DATA DeviceInfoData;
  145. SP_DEVINSTALL_PARAMS_W DeviceInstallParams;
  146. BOOL bReboot = FALSE;
  147. BOOL Status = FALSE;
  148. //
  149. // retrieve a proc address of the DevInstallW procedure in syssetup
  150. //
  151. if (!(fpDevInstallW =
  152. (FP_DEVINSTALLW)GetProcAddress(hSysSetup, "DevInstallW"))) {
  153. goto Clean0;
  154. }
  155. //
  156. // also load setupapi and retrieve following proc addresses
  157. //
  158. hSetupApi = LoadLibraryW(L"setupapi.dll");
  159. if (!(fpCreateDeviceInfoList =
  160. (FP_CREATEDEVICEINFOLIST)GetProcAddress(hSetupApi,
  161. "SetupDiCreateDeviceInfoList"))) {
  162. goto Clean0;
  163. }
  164. if (!(fpOpenDeviceInfoW =
  165. (FP_OPENDEVICEINFO)GetProcAddress(hSetupApi,
  166. "SetupDiOpenDeviceInfoW"))) {
  167. goto Clean0;
  168. }
  169. if (!(fpDestroyDeviceInfoList =
  170. (FP_DESTROYDEVICEINFOLIST)GetProcAddress(hSetupApi,
  171. "SetupDiDestroyDeviceInfoList"))) {
  172. goto Clean0;
  173. }
  174. if (!(fpGetDeviceInstallParams =
  175. (FP_GETDEVICEINSTALLPARAMS)GetProcAddress(hSetupApi,
  176. "SetupDiGetDeviceInstallParamsW"))) {
  177. goto Clean0;
  178. }
  179. if (!(fpEnumDeviceInfo =
  180. (FP_ENUMDEVICEINFO)GetProcAddress(hSetupApi,
  181. "SetupDiEnumDeviceInfo"))) {
  182. goto Clean0;
  183. }
  184. if (!(fpPromptReboot =
  185. (FP_PROMPTREBOOT)GetProcAddress(hSetupApi,
  186. "SetupPromptReboot"))) {
  187. goto Clean0;
  188. }
  189. //
  190. // open the event that will be used to signal the successful
  191. // creation of the named pipe (event should have been created
  192. // before I was called but if this process is started by anyone
  193. // else then it will go away now safely)
  194. //
  195. hEvent = OpenEventW(EVENT_MODIFY_STATE,
  196. FALSE,
  197. PNP_CREATE_PIPE_EVENT);
  198. if (hEvent == NULL) {
  199. goto Clean0;
  200. }
  201. //
  202. // create the named pipe, umpnpmgr will write requests to
  203. // this pipe if new hardware is found
  204. //
  205. hPipe = CreateNamedPipeW(PNP_NEW_HW_PIPE,
  206. PIPE_ACCESS_INBOUND,
  207. PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
  208. 1, // only one connection
  209. MAX_PATH * sizeof(WCHAR), // out buffer size
  210. MAX_PATH * sizeof(WCHAR), // in buffer size
  211. PNP_PIPE_TIMEOUT, // default timeout
  212. NULL // default security
  213. );
  214. //
  215. // signal the event now, whether the pipe was successfully created
  216. // or not (don't keep userinit/cfgmgr32 waiting)
  217. //
  218. SetEvent(hEvent);
  219. if (hPipe == INVALID_HANDLE_VALUE) {
  220. goto Clean0;
  221. }
  222. //
  223. // connect to the newly created named pipe
  224. //
  225. if (ConnectNamedPipe(hPipe, NULL)) {
  226. //
  227. // create a devinfo handle and device info data set to
  228. // pass to DevInstall
  229. //
  230. if((hDevInfo = (fpCreateDeviceInfoList)(NULL, NULL))
  231. == INVALID_HANDLE_VALUE) {
  232. goto Clean0;
  233. }
  234. while (TRUE) {
  235. //
  236. // listen to the named pipe by submitting read
  237. // requests until the named pipe is broken on the
  238. // other end.
  239. //
  240. if (!ReadFile(hPipe,
  241. (LPBYTE)szBuffer, // device instance id
  242. MAX_PATH * sizeof(WCHAR),
  243. &ulSize,
  244. NULL)) {
  245. if (GetLastError() != ERROR_BROKEN_PIPE) {
  246. // Perhaps Log an Event
  247. }
  248. goto Clean0;
  249. }
  250. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  251. if(!(fpOpenDeviceInfoW)(hDevInfo, szBuffer, NULL, 0, &DeviceInfoData)) {
  252. goto Clean0;
  253. }
  254. //
  255. // call syssetup, DevInstallW
  256. //
  257. if ((fpDevInstallW)(hDevInfo, &DeviceInfoData)) {
  258. Status = TRUE; // at least one device installed successfully
  259. }
  260. }
  261. }
  262. Clean0:
  263. //
  264. // If at least one device was successfully installed, then determine
  265. // whether a reboot prompt is necessary.
  266. //
  267. if (Status && hDevInfo != INVALID_HANDLE_VALUE) {
  268. //
  269. // Enumerate each device that is associated with the device info set.
  270. //
  271. Index = 0;
  272. DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
  273. while ((fpEnumDeviceInfo)(hDevInfo,
  274. Index,
  275. &DeviceInfoData)) {
  276. //
  277. // Get device install params, keep track if any report needing
  278. // a reboot.
  279. //
  280. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
  281. if ((fpGetDeviceInstallParams)(hDevInfo,
  282. &DeviceInfoData,
  283. &DeviceInstallParams)) {
  284. if ((DeviceInstallParams.Flags & DI_NEEDREBOOT) ||
  285. (DeviceInstallParams.Flags & DI_NEEDRESTART)) {
  286. bReboot = TRUE;
  287. }
  288. }
  289. Index++;
  290. }
  291. (fpDestroyDeviceInfoList)(hDevInfo);
  292. //
  293. // If any devices need reboot, prompt for reboot now.
  294. //
  295. if (bReboot) {
  296. (fpPromptReboot)(NULL, NULL, FALSE);
  297. }
  298. }
  299. if (hSetupApi != NULL) {
  300. FreeLibrary(hSetupApi);
  301. }
  302. if (hPipe != INVALID_HANDLE_VALUE) {
  303. DisconnectNamedPipe(hPipe);
  304. CloseHandle(hPipe);
  305. }
  306. if (hEvent != NULL) {
  307. CloseHandle(hEvent);
  308. }
  309. return;
  310. } // InstallNewHardware