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.

14713 lines
592 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. devinstd.c
  5. Abstract:
  6. Default install handlers for SetupDiCallClassInstaller DIF_* functions.
  7. Author:
  8. Lonny McMichael (lonnym) 1-Aug-1995
  9. Revision History:
  10. Jamie Hunter (jamiehun) 20-January-1998 Added backup functionality in
  11. _SetupDiInstallDevice - DI_FLAGSEX_BACKUPOLDFILES
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // Global strings for use inside this file only.
  17. //
  18. CONST TCHAR pszDisplayName[] = INFSTR_KEY_DISPLAYNAME,
  19. pszServiceType[] = INFSTR_KEY_SERVICETYPE,
  20. pszStartType[] = INFSTR_KEY_STARTTYPE,
  21. pszErrorControl[] = INFSTR_KEY_ERRORCONTROL,
  22. pszServiceBinary[] = INFSTR_KEY_SERVICEBINARY,
  23. pszLoadOrderGroup[] = INFSTR_KEY_LOADORDERGROUP,
  24. pszDependencies[] = INFSTR_KEY_DEPENDENCIES,
  25. pszStartName[] = INFSTR_KEY_STARTNAME,
  26. pszSystemRoot[] = TEXT("%SystemRoot%\\"),
  27. pszSecurity[] = INFSTR_KEY_SECURITY,
  28. pszDescription[] = INFSTR_KEY_DESCRIPTION;
  29. //
  30. // Define the various copy scenarios that can be returned from GetNewInfName().
  31. //
  32. typedef enum _NEWINF_COPYTYPE {
  33. NewInfCopyYes, // new INF placeholder created--need to copy real INF
  34. NewInfCopyNo, // no need to copy--INF already present in destination
  35. NewInfCopyZeroLength // previously-existing zero-length INF match found
  36. } NEWINF_COPYTYPE, *PNEWINF_COPYTYPE;
  37. //
  38. // Define a list node to hold an interface class to be installed.
  39. //
  40. typedef struct _INTERFACE_CLASS_TO_INSTALL {
  41. struct _INTERFACE_CLASS_TO_INSTALL *Next;
  42. GUID InterfaceGuid;
  43. DWORD Flags;
  44. TCHAR InstallSection[MAX_SECT_NAME_LEN];
  45. } INTERFACE_CLASS_TO_INSTALL, *PINTERFACE_CLASS_TO_INSTALL;
  46. //
  47. // Define a list node to hold an INF that has been newly-installed during
  48. // SetupDiInstallDevice, hence must be cleaned up if SetupDiInstallDevice
  49. // subsequently encounters a failure.
  50. //
  51. typedef struct _INSTALLED_INF_CLEANUP {
  52. struct _INSTALLED_INF_CLEANUP *Next;
  53. TCHAR InfName[MAX_PATH];
  54. } INSTALLED_INF_CLEANUP, *PINSTALLED_INF_CLEANUP;
  55. //
  56. // Private function prototypes
  57. //
  58. BOOL
  59. _SetupDiInstallDevice(
  60. IN HDEVINFO DeviceInfoSet,
  61. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  62. IN BOOL DoFullInstall
  63. );
  64. DWORD
  65. InstallHW(
  66. IN HDEVINFO DeviceInfoSet,
  67. IN PSP_DEVINFO_DATA DeviceInfoData,
  68. IN HINF hDeviceInf,
  69. IN PCTSTR szSectionName,
  70. OUT PBOOL DeleteDevKey
  71. );
  72. BOOL
  73. AssociateDevInstWithDefaultService(
  74. IN PDEVINFO_ELEM DevInfoElem,
  75. OUT PTSTR ServiceName,
  76. IN OUT PDWORD ServiceNameSize
  77. );
  78. BOOL
  79. CheckIfDevStarted(
  80. IN PDEVINFO_ELEM DevInfoElem,
  81. IN PDEVICE_INFO_SET pDeviceInfoSet
  82. );
  83. DWORD
  84. pSetupAddService(
  85. IN PINFCONTEXT LineContext,
  86. OUT PSVCNAME_NODE * SvcListHead,
  87. IN DWORD Flags,
  88. IN DEVINST DevInst, OPTIONAL
  89. OUT PBOOL NullDriverInstalled,
  90. IN PSETUP_LOG_CONTEXT LogContext
  91. );
  92. DWORD
  93. pSetupDeleteService(
  94. IN PINFCONTEXT LineContext,
  95. IN DWORD Flags,
  96. IN PSETUP_LOG_CONTEXT LogContext
  97. );
  98. DWORD
  99. DeleteServicesInList(
  100. IN PSVCNAME_NODE ServicesToDelete,
  101. IN PSETUP_LOG_CONTEXT LogContext
  102. );
  103. BOOL
  104. IsDevRemovedFromAllHwProfiles(
  105. IN PCTSTR DeviceInstanceId,
  106. IN HMACHINE hMachine
  107. );
  108. DWORD
  109. GetDevInstConfigFlags(
  110. IN DEVINST DevInst,
  111. IN DWORD Default,
  112. IN HMACHINE hMachine
  113. );
  114. PTSTR
  115. pSetupCmdLineAppendString(
  116. IN PTSTR CmdLine,
  117. IN PCTSTR Key,
  118. IN PCTSTR Value, OPTIONAL
  119. IN OUT PUINT StrLen,
  120. IN OUT PUINT BufSize
  121. );
  122. BOOL
  123. _SetupDiInstallDeviceInterfaces(
  124. IN HDEVINFO DeviceInfoSet,
  125. IN PSP_DEVINFO_DATA DeviceInfoData,
  126. IN BOOL DoFullInstall,
  127. IN HINF hDeviceInf, OPTIONAL
  128. IN HSPFILEQ UserFileQ OPTIONAL
  129. );
  130. BOOL
  131. _SetupDiRegisterCoDeviceInstallers(
  132. IN HDEVINFO DeviceInfoSet,
  133. IN PSP_DEVINFO_DATA DeviceInfoData,
  134. IN BOOL DoFullInstall,
  135. IN HINF hDeviceInf, OPTIONAL
  136. IN HSPFILEQ UserFileQ OPTIONAL
  137. );
  138. BOOL
  139. RetrieveAllDevNodesSharingDriversWithDevice(
  140. IN PDEVINFO_ELEM DevInfoElem,
  141. OUT PTSTR *Drivers,
  142. OUT PDEVNODE *DevNodes,
  143. OUT ULONG *NumberOfDevNodes,
  144. IN HMACHINE hMachine
  145. );
  146. VOID
  147. RestartSingleDevice(
  148. IN PDEVINFO_ELEM DevInfoElem,
  149. IN PDEVICE_INFO_SET pDeviceInfoSet,
  150. IN BOOL NullDriverInstall,
  151. IN PSETUP_LOG_CONTEXT LogContext
  152. );
  153. VOID
  154. RestartAllDevicesUsingDrivers(
  155. IN PDEVINFO_ELEM DevInfoElem,
  156. IN PDEVICE_INFO_SET pDeviceInfoSet,
  157. IN BOOL NullDriverInstall,
  158. IN PSETUP_LOG_CONTEXT LogContext
  159. );
  160. DWORD
  161. GetNewInfName(
  162. IN HWND Owner, OPTIONAL
  163. IN PCTSTR OemInfName,
  164. IN PCTSTR OemInfOriginalName,
  165. IN PCTSTR OemInfCatName, OPTIONAL
  166. OUT PTSTR NewInfName,
  167. IN DWORD NewInfNameSize,
  168. OUT PDWORD RequiredSize,
  169. OUT PNEWINF_COPYTYPE CopyNeeded,
  170. IN BOOL ReplaceOnly,
  171. IN PCTSTR DeviceDesc, OPTIONAL
  172. IN DWORD DriverSigningPolicy,
  173. IN DWORD Flags,
  174. IN PCTSTR AltCatalogFile, OPTIONAL
  175. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
  176. OUT PDWORD DriverSigningError, OPTIONAL
  177. OUT PTSTR CatalogFilenameOnSystem,
  178. IN PSETUP_LOG_CONTEXT LogContext,
  179. IN OUT PVERIFY_CONTEXT VerifyContext, OPTIONAL
  180. OUT HANDLE *hWVTStateData OPTIONAL
  181. );
  182. VOID
  183. _WriteVetoLogEntry(
  184. IN PSETUP_LOG_CONTEXT LogContext,
  185. IN DWORD Level,
  186. IN DWORD MessageId,
  187. IN PCTSTR szDevID,
  188. IN PCTSTR szVetoName,
  189. IN PNP_VETO_TYPE dwVetoType
  190. )
  191. {
  192. static LPCTSTR VetoMap[] = {
  193. TEXT("PNP_VetoTypeUnknown"),
  194. TEXT("PNP_VetoLegacyDevice"),
  195. TEXT("PNP_VetoPendingClose"),
  196. TEXT("PNP_VetoWindowsApp"),
  197. TEXT("PNP_VetoWindowsService"),
  198. TEXT("PNP_VetoOutstandingOpen"),
  199. TEXT("PNP_VetoDevice"),
  200. TEXT("PNP_VetoDriver"),
  201. TEXT("PNP_VetoIllegalDeviceRequest"),
  202. TEXT("PNP_VetoInsufficientPower"),
  203. TEXT("PNP_VetoNonDisableable"),
  204. TEXT("PNP_VetoLegacyDriver"),
  205. TEXT("PNP_VetoInsufficientRights")
  206. };
  207. MYASSERT(dwVetoType < ARRAYSIZE(VetoMap));
  208. WriteLogEntry(
  209. LogContext,
  210. Level,
  211. MessageId,
  212. NULL,
  213. szDevID,
  214. szVetoName,
  215. dwVetoType,
  216. dwVetoType < ARRAYSIZE(VetoMap) ? VetoMap[dwVetoType] : TEXT("????")
  217. );
  218. }
  219. LPCTSTR
  220. _MapCmProbToString(
  221. IN DWORD prob
  222. )
  223. {
  224. #define PROBLEM_MAP_SIZE 0x33
  225. #if PROBLEM_MAP_SIZE != NUM_CM_PROB
  226. #error Add new problem code to ProbMap and update PROBLEM_MAP_SIZE.
  227. #endif
  228. static LPCTSTR ProbMap [PROBLEM_MAP_SIZE] = {
  229. NULL,
  230. TEXT("CM_PROB_NOT_CONFIGURED"),
  231. TEXT("CM_PROB_DEVLOADER_FAILED"),
  232. TEXT("CM_PROB_OUT_OF_MEMORY"),
  233. TEXT("CM_PROB_ENTRY_IS_WRONG_TYPE"),
  234. TEXT("CM_PROB_LACKED_ARBITRATOR"),
  235. TEXT("CM_PROB_BOOT_CONFIG_CONFLICT"),
  236. TEXT("CM_PROB_FAILED_FILTER"),
  237. TEXT("CM_PROB_DEVLOADER_NOT_FOUND"),
  238. TEXT("CM_PROB_INVALID_DATA"),
  239. TEXT("CM_PROB_FAILED_START"),
  240. TEXT("CM_PROB_LIAR"),
  241. TEXT("CM_PROB_NORMAL_CONFLICT"),
  242. TEXT("CM_PROB_NOT_VERIFIED"),
  243. TEXT("CM_PROB_NEED_RESTART"),
  244. TEXT("CM_PROB_REENUMERATION"),
  245. TEXT("CM_PROB_PARTIAL_LOG_CONF"),
  246. TEXT("CM_PROB_UNKNOWN_RESOURCE"),
  247. TEXT("CM_PROB_REINSTALL"),
  248. TEXT("CM_PROB_REGISTRY"),
  249. NULL,
  250. TEXT("CM_PROB_WILL_BE_REMOVED"),
  251. TEXT("CM_PROB_DISABLED"),
  252. TEXT("CM_PROB_DEVLOADER_NOT_READY"),
  253. TEXT("CM_PROB_DEVICE_NOT_THERE"),
  254. TEXT("CM_PROB_MOVED"),
  255. TEXT("CM_PROB_TOO_EARLY"),
  256. TEXT("CM_PROB_NO_VALID_LOG_CONF"),
  257. TEXT("CM_PROB_FAILED_INSTALL"),
  258. TEXT("CM_PROB_HARDWARE_DISABLED"),
  259. TEXT("CM_PROB_CANT_SHARE_IRQ"),
  260. TEXT("CM_PROB_FAILED_ADD"),
  261. TEXT("CM_PROB_DISABLED_SERVICE"),
  262. TEXT("CM_PROB_TRANSLATION_FAILED"),
  263. TEXT("CM_PROB_NO_SOFTCONFIG"),
  264. TEXT("CM_PROB_BIOS_TABLE"),
  265. TEXT("CM_PROB_IRQ_TRANSLATION_FAILED"),
  266. TEXT("CM_PROB_FAILED_DRIVER_ENTRY"),
  267. TEXT("CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD"),
  268. TEXT("CM_PROB_DRIVER_FAILED_LOAD"),
  269. TEXT("CM_PROB_DRIVER_SERVICE_KEY_INVALID"),
  270. TEXT("CM_PROB_LEGACY_SERVICE_NO_DEVICES"),
  271. TEXT("CM_PROB_DUPLICATE_DEVICE"),
  272. TEXT("CM_PROB_FAILED_POST_START"),
  273. TEXT("CM_PROB_HALTED"),
  274. TEXT("CM_PROB_PHANTOM"),
  275. TEXT("CM_PROB_SYSTEM_SHUTDOWN"),
  276. TEXT("CM_PROB_HELD_FOR_EJECT"),
  277. TEXT("CM_PROB_DRIVER_BLOCKED"),
  278. TEXT("CM_PROB_REGISTRY_TOO_LARGE"),
  279. TEXT("CM_PROB_SETPROPERTIES_FAILED")
  280. };
  281. LPCTSTR ProbText = NULL;
  282. MYASSERT(ARRAYSIZE(ProbMap)==NUM_CM_PROB);
  283. MYASSERT(prob<NUM_CM_PROB);
  284. if(prob < ARRAYSIZE(ProbMap)) {
  285. ProbText = ProbMap[prob];
  286. }
  287. if(!ProbText) {
  288. ProbText = TEXT("????");
  289. }
  290. return ProbText;
  291. }
  292. LPCTSTR
  293. _MapCmRetToString(
  294. IN DWORD cr
  295. )
  296. {
  297. LPCTSTR RetText = NULL;
  298. static LPCTSTR RetMap [] = {
  299. TEXT("CR_SUCCESS"),
  300. TEXT("CR_DEFAULT"),
  301. TEXT("CR_OUT_OF_MEMORY"),
  302. TEXT("CR_INVALID_POINTER"),
  303. TEXT("CR_INVALID_FLAG"),
  304. TEXT("CR_INVALID_DEVNODE"),
  305. TEXT("CR_INVALID_RES_DES"),
  306. TEXT("CR_INVALID_LOG_CONF"),
  307. TEXT("CR_INVALID_ARBITRATOR"),
  308. TEXT("CR_INVALID_NODELIST"),
  309. TEXT("CR_DEVNODE_HAS_REQS"),
  310. TEXT("CR_INVALID_RESOURCEID"),
  311. TEXT("CR_DLVXD_NOT_FOUND"),
  312. TEXT("CR_NO_SUCH_DEVNODE"),
  313. TEXT("CR_NO_MORE_LOG_CONF"),
  314. TEXT("CR_NO_MORE_RES_DES"),
  315. TEXT("CR_ALREADY_SUCH_DEVNODE"),
  316. TEXT("CR_INVALID_RANGE_LIST"),
  317. TEXT("CR_INVALID_RANGE"),
  318. TEXT("CR_FAILURE"),
  319. TEXT("CR_NO_SUCH_LOGICAL_DEV"),
  320. TEXT("CR_CREATE_BLOCKED"),
  321. TEXT("CR_NOT_SYSTEM_VM"),
  322. TEXT("CR_REMOVE_VETOED"),
  323. TEXT("CR_APM_VETOED"),
  324. TEXT("CR_INVALID_LOAD_TYPE"),
  325. TEXT("CR_BUFFER_SMALL"),
  326. TEXT("CR_NO_ARBITRATOR"),
  327. TEXT("CR_NO_REGISTRY_HANDLE"),
  328. TEXT("CR_REGISTRY_ERROR"),
  329. TEXT("CR_INVALID_DEVICE_ID"),
  330. TEXT("CR_INVALID_DATA"),
  331. TEXT("CR_INVALID_API"),
  332. TEXT("CR_DEVLOADER_NOT_READY"),
  333. TEXT("CR_NEED_RESTART"),
  334. TEXT("CR_NO_MORE_HW_PROFILES"),
  335. TEXT("CR_DEVICE_NOT_THERE"),
  336. TEXT("CR_NO_SUCH_VALUE"),
  337. TEXT("CR_WRONG_TYPE"),
  338. TEXT("CR_INVALID_PRIORITY"),
  339. TEXT("CR_NOT_DISABLEABLE"),
  340. TEXT("CR_FREE_RESOURCES"),
  341. TEXT("CR_QUERY_VETOED"),
  342. TEXT("CR_CANT_SHARE_IRQ"),
  343. TEXT("CR_NO_DEPENDENT"),
  344. TEXT("CR_SAME_RESOURCES"),
  345. TEXT("CR_NO_SUCH_REGISTRY_KEY"),
  346. TEXT("CR_INVALID_MACHINENAME"),
  347. TEXT("CR_REMOTE_COMM_FAILURE"),
  348. TEXT("CR_MACHINE_UNAVAILABLE"),
  349. TEXT("CR_NO_CM_SERVICES"),
  350. TEXT("CR_ACCESS_DENIED"),
  351. TEXT("CR_CALL_NOT_IMPLEMENTED"),
  352. TEXT("CR_INVALID_PROPERTY"),
  353. TEXT("CR_DEVICE_INTERFACE_ACTIVE"),
  354. TEXT("CR_NO_SUCH_DEVICE_INTERFACE"),
  355. TEXT("CR_INVALID_REFERENCE_STRING"),
  356. TEXT("CR_INVALID_CONFLICT_LIST"),
  357. TEXT("CR_INVALID_INDEX"),
  358. TEXT("CR_INVALID_STRUCTURE_SIZE")
  359. };
  360. MYASSERT(ARRAYSIZE(RetMap)==NUM_CR_RESULTS);
  361. MYASSERT(cr<NUM_CR_RESULTS);
  362. if(cr < ARRAYSIZE(RetMap)) {
  363. RetText = RetMap[cr];
  364. }
  365. if(!RetText) {
  366. RetText = TEXT("????");
  367. }
  368. return RetText;
  369. }
  370. BOOL
  371. WINAPI
  372. SetupDiInstallDevice(
  373. IN HDEVINFO DeviceInfoSet,
  374. IN OUT PSP_DEVINFO_DATA DeviceInfoData
  375. )
  376. /*++
  377. Routine Description:
  378. Default handler for DIF_INSTALLDEVICE
  379. This routine will install a device by performing a SetupInstallFromInfSection
  380. for the install section of the selected driver for the specified device
  381. information element. The device will then be started (if possible).
  382. NOTE: This API actually supports an OS/architecture-specific extension that
  383. may be used to specify multiple installation behaviors for a single device,
  384. based on the environment we're running under. The algorithm is as follows:
  385. We take the install section name, as specified in the driver node (for this
  386. example, it's "InstallSec"), and attempt to find one of the following INF
  387. sections (searched for in the order specified):
  388. If we're running under Windows 95:
  389. 1. InstallSec.Win
  390. 2. InstallSec
  391. If we're running under Windows NT:
  392. 1. InstallSec.NT<platform> (platform is "x86", "AMD64", or "IA64")
  393. 2. InstallSec.NT
  394. 3. InstallSec
  395. The first section that we find is the one we'll use to do the installation. This
  396. section name is also what we'll base our ".Hw" and ".Services" installation against.
  397. (E.g., if we match on "InstallSec.NTAmd64", then the service install section must be
  398. named "InstallSec.NTAmd64.Services".)
  399. The original install section name (i.e., the one specified in the driver node), will
  400. be written as-is to the driver key's "InfSection" value entry, just as it was in the
  401. past. The extension that we use (if any) will be stored in the device's driver key
  402. as the REG_SZ value, "InfSectionExt". E.g.,
  403. InfSection : REG_SZ : "InstallSec"
  404. InfSectionExt : REG_SZ : ".NTMIPS"
  405. If we successfully install the device, we'll kick off RunOnce. NOTE: We
  406. must do this _regardless_ of whether or not the device was dynamically
  407. brought on-line with its newly-installed driver/settings. This is because,
  408. for server-side device installations, the RunOnce processing is done by the
  409. user-mode PnP manager. We can't put this off until 'later'. Also, since
  410. anyone can kick off a RunOnce at any time, you really would have no
  411. assurance that the RunOnce would be postponed until after reboot anyway.
  412. Arguments:
  413. DeviceInfoSet - Supplies a handle to the device information set for which a
  414. driver is to be installed.
  415. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for which
  416. a driver is to be installed. This is an IN OUT parameter, since the
  417. DevInst field of the structure may be updated with a new handle value upon
  418. return.
  419. Return Value:
  420. If the function succeeds, the return value is TRUE.
  421. If the function fails, the return value is FALSE. To get extended error
  422. information, call GetLastError.
  423. Remarks:
  424. If no driver is selected for the specified device information element, then a
  425. NULL driver will be installed.
  426. Upon return, the install parameters Flags will indicate whether the system
  427. needs to be rebooted or restarted in order for the device to be started.
  428. During GUI-mode setup on Windows NT, quiet-install behavior is always
  429. employed in the absence of a user-supplied file queue, regardless of
  430. whether the device information element has the DI_QUIETINSTALL flag set.
  431. --*/
  432. {
  433. return _SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData, TRUE);
  434. }
  435. BOOL
  436. _SetupDiInstallDevice(
  437. IN HDEVINFO DeviceInfoSet,
  438. IN OUT PSP_DEVINFO_DATA DeviceInfoData,
  439. IN BOOL DoFullInstall
  440. )
  441. /*++
  442. Routine Description:
  443. Worker routine for both SetupDiInstallDevice and SetupDiInstallDriverFiles.
  444. See the description of SetupDiInstallDevice for more information.
  445. (jamiehun) If backups are enabled (DI_FLAGSEX_BACKUPOLDFILES or DI_FLAGSEX_BACKUPONREPLACE)
  446. then old inf file is backed up.
  447. Arguments:
  448. DeviceInfoSet - Supplies a handle to the device information set for which a
  449. driver is to be installed.
  450. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for which
  451. a driver is to be installed. This is an IN OUT parameter, since the
  452. DevInst field of the structure may be updated with a new handle value upon
  453. return.
  454. DoFullInstall - If TRUE, then an entire device installation is performed,
  455. otherwise, only the driver files are copied.
  456. Return Value:
  457. If the function succeeds, the return value is TRUE.
  458. If the function fails, the return value is FALSE. To get extended error
  459. information, call GetLastError.
  460. --*/
  461. {
  462. PDEVICE_INFO_SET pDeviceInfoSet;
  463. DWORD Err, ScanQueueResult;
  464. PDEVINFO_ELEM DevInfoElem = NULL;
  465. PTSTR szInfFileName, szInfSectionName;
  466. PTSTR szInfSectionExt = NULL;
  467. TCHAR InfSectionWithExt[MAX_PATH];
  468. DWORD InfSectionWithExtLength;
  469. HINF hDeviceInf = INVALID_HANDLE_VALUE;
  470. HKEY hkDrv = INVALID_HANDLE_VALUE;
  471. PSP_FILE_CALLBACK MsgHandler;
  472. PVOID MsgHandlerContext;
  473. BOOL MsgHandlerIsNativeCharWidth;
  474. HSPFILEQ UserFileQ;
  475. INFCONTEXT InfContext;
  476. DWORD dwConfigFlags=0;
  477. ULONG cbData;
  478. PTSTR DevIdBuffer = NULL;
  479. PCTSTR TempString;
  480. ULONG ulStatus, ulProblem;
  481. DEVINST dnReenum = 0;
  482. TCHAR szNewName[MAX_PATH];
  483. BOOL OemInfFileToCopy = FALSE;
  484. BOOL InfFromOemPath = FALSE;
  485. BOOL DeleteDevKey = FALSE;
  486. PSVCNAME_NODE DeleteServiceList = NULL;
  487. BOOL FreeMsgHandlerContext = FALSE;
  488. BOOL CloseUserFileQ = FALSE;
  489. HWND hwndParent;
  490. BOOL DoFileCopying;
  491. DWORD DevInstCapabilities;
  492. TCHAR DeviceFullID[MAX_DEVICE_ID_LEN];
  493. DWORD BackupFlags = 0;
  494. BOOL NullDriverInstall = FALSE;
  495. PINSTALLED_INF_CLEANUP InfsToCleanUp = NULL;
  496. INT FileQueueNeedsReboot;
  497. PSETUP_LOG_CONTEXT LogContext = NULL;
  498. DWORD slot_deviceID = 0;
  499. DWORD slot_section = 0;
  500. DWORD FileQueueFlags;
  501. BOOL NoProgressUI;
  502. TCHAR className[MAX_CLASS_NAME_LEN];
  503. PSP_ALTPLATFORM_INFO_V2 ValidationPlatform = NULL;
  504. #if MAX_SECT_NAME_LEN > MAX_PATH
  505. #error MAX_SECT_NAME_LEN is larger than MAX_PATH--fix InfSectionWithExt!
  506. #endif
  507. ASSERT_HEAP_IS_VALID();
  508. //
  509. // We can only install a device if a device was specified.
  510. //
  511. if(!DeviceInfoData) {
  512. SetLastError(ERROR_INVALID_PARAMETER);
  513. return FALSE;
  514. }
  515. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  516. SetLastError(ERROR_INVALID_HANDLE);
  517. return FALSE;
  518. }
  519. //
  520. // Make sure we're local
  521. //
  522. if(NULL != pDeviceInfoSet->hMachine ) { //&& !g_ReadOnlyRemote ??
  523. //
  524. // hDevInfo may be valid, but it's not for this machine
  525. //
  526. UnlockDeviceInfoSet(pDeviceInfoSet);
  527. SetLastError(ERROR_INVALID_HANDLE);
  528. return FALSE;
  529. }
  530. Err = NO_ERROR;
  531. try {
  532. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  533. DeviceInfoData,
  534. NULL))) {
  535. Err = ERROR_INVALID_PARAMETER;
  536. goto clean0;
  537. }
  538. //
  539. // This routine can't install a non-native driver
  540. //
  541. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  542. Err = ERROR_INVALID_FLAGS;
  543. goto clean0;
  544. }
  545. //
  546. // Make sure we only use the devinfo element's window if it's valid.
  547. //
  548. if(hwndParent = DevInfoElem->InstallParamBlock.hwndParent) {
  549. if(!IsWindow(hwndParent)) {
  550. hwndParent = NULL;
  551. }
  552. }
  553. //
  554. // set the local log context before it gets used.
  555. //
  556. LogContext = DevInfoElem->InstallParamBlock.LogContext;
  557. WriteLogEntry(
  558. LogContext,
  559. DRIVER_LOG_TIME,
  560. MSG_LOG_BEGIN_INSTALL_TIME,
  561. NULL); // text message
  562. //
  563. // obtain the full id of the device we are (re)installing
  564. //
  565. if( CM_Get_Device_ID(DevInfoElem->DevInst,
  566. DeviceFullID,
  567. SIZECHARS(DeviceFullID),
  568. 0
  569. ) != CR_SUCCESS ) {
  570. Err = ERROR_INVALID_HANDLE;
  571. goto clean0;
  572. }
  573. //
  574. // If we are installing a driver, then the selected driver pointer will be
  575. // non-NULL, otherwise we are actually removing the driver (i.e., installing the
  576. // NULL driver)
  577. //
  578. if(DevInfoElem->SelectedDriver) {
  579. if(DoFullInstall) {
  580. if(slot_deviceID == 0) {
  581. slot_deviceID = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_INFO,FALSE);
  582. }
  583. WriteLogEntry(
  584. LogContext,
  585. slot_deviceID,
  586. MSG_LOG_DO_FULL_INSTALL,
  587. NULL, // text message
  588. DeviceFullID);
  589. //
  590. // Create the Driver Reg Key.
  591. //
  592. if((hkDrv = SetupDiCreateDevRegKey(DeviceInfoSet,
  593. DeviceInfoData,
  594. DICS_FLAG_GLOBAL,
  595. 0,
  596. DIREG_DRV,
  597. NULL,
  598. NULL)) == INVALID_HANDLE_VALUE) {
  599. Err = GetLastError();
  600. goto clean0;
  601. }
  602. } else {
  603. DWORD slot = slot_deviceID;
  604. if(slot_deviceID == 0) {
  605. if(DevInfoElem->InstallParamBlock.Flags & DI_NOVCP) {
  606. slot = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_VERBOSE,TRUE); // may be being copied for someone else - keep this around
  607. } else {
  608. slot_deviceID = slot = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_INFO,FALSE); // we do copy ourselves
  609. }
  610. }
  611. WriteLogEntry(
  612. LogContext,
  613. slot,
  614. MSG_LOG_DO_COPY_INSTALL,
  615. NULL, // text message
  616. DeviceFullID);
  617. }
  618. szInfFileName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  619. DevInfoElem->SelectedDriver->InfFileName
  620. );
  621. szInfSectionName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  622. DevInfoElem->SelectedDriver->InfSectionName
  623. );
  624. if((hDeviceInf = SetupOpenInfFile(szInfFileName,
  625. NULL,
  626. INF_STYLE_WIN4,
  627. NULL)) == INVALID_HANDLE_VALUE) {
  628. Err = GetLastError();
  629. goto clean0;
  630. }
  631. //
  632. // Give the INF whatever the local log context is.
  633. //
  634. InheritLogContext(LogContext, &((PLOADED_INF) hDeviceInf)->LogContext);
  635. SetLogSectionName(LogContext, TEXT("Driver Install"));
  636. //
  637. // Figure out whether we need to copy files. (Ignore the DI_NOFILECOPY flag if we're
  638. // doing a copy-only installation--that's what setupx does.)
  639. //
  640. DoFileCopying = (!(DevInfoElem->InstallParamBlock.Flags & DI_NOFILECOPY) || !DoFullInstall);
  641. //
  642. // Find out the 'real' install section we should be using (i.e.,
  643. // the potentially OS/architecture-specific one.
  644. //
  645. if(!SetupDiGetActualSectionToInstall(hDeviceInf,
  646. szInfSectionName,
  647. InfSectionWithExt,
  648. SIZECHARS(InfSectionWithExt),
  649. &InfSectionWithExtLength,
  650. &szInfSectionExt
  651. )) {
  652. Err = GetLastError();
  653. goto clean0;
  654. }
  655. //
  656. // Append the layout INF, if necessary.
  657. //
  658. if(DoFileCopying) {
  659. SetupOpenAppendInfFile(NULL, hDeviceInf, NULL);
  660. }
  661. //
  662. // Append-load any included INFs specified in an "include=" line in our
  663. // install section.
  664. //
  665. AppendLoadIncludedInfs(hDeviceInf, szInfFileName, InfSectionWithExt, DoFileCopying);
  666. ASSERT_HEAP_IS_VALID();
  667. //
  668. // Now perform file installation activities...
  669. //
  670. if(!DoFileCopying) {
  671. //
  672. // We're not supposed to do any file copying, In this case, we
  673. // still need to have the INF copied to the INF directory
  674. // (along with its associated catalog, if any).
  675. //
  676. if(pSetupInfIsFromOemLocation(szInfFileName, TRUE)) {
  677. TCHAR CatalogName[MAX_PATH];
  678. TCHAR OriginalInfName[MAX_PATH];
  679. TCHAR CatalogFilenameOnSystem[MAX_PATH];
  680. BOOL DifferentOriginalName, UseOriginalInfName;
  681. DWORD PolicyToUse;
  682. //
  683. // Retrieve (potentially decorated) CatalogFile= entry, if
  684. // present, from [version] section.
  685. //
  686. // Note: We're safe in casting our INF handle straight to a
  687. // PLOADED_INF (without even locking it), since this INF
  688. // handle will never be seen outside of this routine.
  689. //
  690. Err = pGetInfOriginalNameAndCatalogFile(
  691. (PLOADED_INF)hDeviceInf,
  692. NULL,
  693. &DifferentOriginalName,
  694. OriginalInfName,
  695. SIZECHARS(OriginalInfName),
  696. CatalogName,
  697. SIZECHARS(CatalogName),
  698. NULL // always native OS/arch (ver doesn't matter for CatalogFile=)
  699. );
  700. if(Err == NO_ERROR) {
  701. if(*CatalogName) {
  702. TempString = CatalogName;
  703. } else {
  704. TempString = NULL;
  705. }
  706. } else {
  707. goto clean0;
  708. }
  709. PolicyToUse = GetCodeSigningPolicyForInf(LogContext,
  710. hDeviceInf,
  711. &ValidationPlatform,
  712. &UseOriginalInfName
  713. );
  714. //
  715. // An exception INF can't be used in a device installation!
  716. //
  717. if(UseOriginalInfName) {
  718. Err = ERROR_INVALID_CLASS;
  719. goto clean0;
  720. }
  721. //
  722. // We aren't supposed to be copying files here, hence we
  723. // want to fail if the INF doesn't already exist in the
  724. // Inf directory.
  725. //
  726. // NOTE: We should never see an issue where we need to
  727. // prompt user about their trust of an Authenticode
  728. // publisher, since the presence of the INF and CAT are
  729. // sufficient here (trust was confirmed when queue
  730. // committal occurred).
  731. //
  732. Err = GLE_FN_CALL(FALSE,
  733. _SetupCopyOEMInf(
  734. szInfFileName,
  735. NULL, // default source location to where INF presently is
  736. (DevInfoElem->SelectedDriver->Flags & DNF_INET_DRIVER)
  737. ? SPOST_URL : SPOST_PATH,
  738. SP_COPY_REPLACEONLY,
  739. szNewName,
  740. SIZECHARS(szNewName),
  741. NULL,
  742. NULL,
  743. (DifferentOriginalName
  744. ? OriginalInfName
  745. : pSetupGetFileTitle(szInfFileName)),
  746. TempString,
  747. hwndParent,
  748. pStringTableStringFromId(pDeviceInfoSet->StringTable,
  749. DevInfoElem->SelectedDriver->DrvDescription),
  750. PolicyToUse,
  751. SCOI_TRY_UPDATE_PNF // not fatal if existing PNF locked
  752. | SCOI_NO_UI_ON_SIGFAIL,
  753. NULL,
  754. ValidationPlatform,
  755. NULL,
  756. CatalogFilenameOnSystem,
  757. LogContext,
  758. NULL,
  759. NULL)
  760. );
  761. if(Err != NO_ERROR) {
  762. if(Err == ERROR_FILE_EXISTS) {
  763. //
  764. // We couldn't copy the legacy INF because it
  765. // already exists in the %windir%\Inf directory.
  766. // Since it probably has better source path
  767. // information than we do, it's best to leave the
  768. // PNF alone. We also need this information about
  769. // the INF's existence to that we know whether or
  770. // not to blow away the INF later in case we hit a
  771. // failure.
  772. //
  773. Err = NO_ERROR;
  774. } else {
  775. //
  776. // SetupCopyOEMInf failed for some reason other than
  777. // file-already-exists (most likely, because we were
  778. // dealing with a new-style device INF that didn't
  779. // already exist in the Inf directory). Bail now.
  780. //
  781. goto clean0;
  782. }
  783. }
  784. }
  785. } else {
  786. //
  787. // If the DI_NOVCP flag is set, then just queue up the file
  788. // copy/rename/delete operations. Otherwise, perform the
  789. // actions.
  790. //
  791. if(DevInfoElem->InstallParamBlock.Flags & DI_NOVCP) {
  792. //
  793. // We must have a user-supplied file queue.
  794. //
  795. MYASSERT(DevInfoElem->InstallParamBlock.UserFileQ);
  796. UserFileQ = DevInfoElem->InstallParamBlock.UserFileQ;
  797. } else {
  798. //
  799. // Since we may need to check the queued files to determine
  800. // whether file copy is necessary, we have to open our own
  801. // queue, and commit it ourselves.
  802. //
  803. if((UserFileQ = SetupOpenFileQueue()) != INVALID_HANDLE_VALUE) {
  804. CloseUserFileQ = TRUE;
  805. } else {
  806. //
  807. // SetupOpenFileQueue sets actual error
  808. //
  809. Err = GetLastError();
  810. goto clean0;
  811. }
  812. }
  813. //
  814. // Maybe replace the file queue's log context with the Inf's
  815. //
  816. if (LogContext) {
  817. InheritLogContext(LogContext,
  818. &((PSP_FILE_QUEUE) UserFileQ)->LogContext);
  819. }
  820. if(slot_section == 0) {
  821. //
  822. // we haven't done anything about logging section yet...
  823. //
  824. slot_section = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_VERBOSE,FALSE);
  825. //
  826. // Say what section is about to be installed.
  827. //
  828. WriteLogEntry(LogContext,
  829. slot_section,
  830. MSG_LOG_INSTALLING_SECTION_FROM,
  831. NULL,
  832. InfSectionWithExt,
  833. szInfFileName);
  834. }
  835. //
  836. // DI_FLAGSEX_PREINSTALLBACKUP has precedence over DI_FLAGSEX_BACKUPONREPLACE
  837. //
  838. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_PREINSTALLBACKUP) {
  839. BackupFlags |= SP_BKFLG_PREBACKUP | SP_BKFLG_CALLBACK;
  840. } else if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_BACKUPONREPLACE) {
  841. BackupFlags |= SP_BKFLG_LATEBACKUP | SP_BKFLG_CALLBACK;
  842. }
  843. if(BackupFlags != 0) {
  844. WriteLogEntry(
  845. LogContext,
  846. DRIVER_LOG_TIME,
  847. MSG_LOG_BEGIN_PREP_BACKUP_TIME,
  848. NULL); // text message
  849. pSetupGetBackupQueue(DeviceFullID, UserFileQ, BackupFlags);
  850. //
  851. // We don't care about errors here
  852. //
  853. }
  854. ASSERT_HEAP_IS_VALID();
  855. WriteLogEntry(
  856. LogContext,
  857. DRIVER_LOG_TIME,
  858. MSG_LOG_BEGIN_INSTALL_FROM_INF_TIME,
  859. NULL); // text message
  860. Err = InstallFromInfSectionAndNeededSections(NULL,
  861. hDeviceInf,
  862. InfSectionWithExt,
  863. SPINST_FILES,
  864. NULL,
  865. NULL,
  866. SP_COPY_NEWER_OR_SAME | SP_COPY_LANGUAGEAWARE |
  867. ((DevInfoElem->InstallParamBlock.Flags & DI_NOBROWSE) ? SP_COPY_NOBROWSE : 0),
  868. NULL,
  869. NULL,
  870. INVALID_HANDLE_VALUE,
  871. NULL,
  872. UserFileQ
  873. );
  874. //
  875. // If we're not doing a full install (i.e., file copy-only), then we also want to
  876. // queue up any file operations for co-installer registration and device interface
  877. // installation.
  878. //
  879. if(!DoFullInstall && (Err == NO_ERROR)) {
  880. WriteLogEntry(
  881. LogContext,
  882. DRIVER_LOG_TIME,
  883. MSG_LOG_BEGIN_CO_INSTALLER_COPY_TIME,
  884. NULL); // text message
  885. if(!_SetupDiRegisterCoDeviceInstallers(DeviceInfoSet, DeviceInfoData, FALSE, hDeviceInf, UserFileQ) ||
  886. !_SetupDiInstallDeviceInterfaces(DeviceInfoSet, DeviceInfoData, FALSE, hDeviceInf, UserFileQ)) {
  887. Err = GetLastError();
  888. }
  889. }
  890. //
  891. // Mark the queue as a device install queue (and make sure
  892. // there's a catalog node representing our device INF in the
  893. // queue).
  894. //
  895. Err = MarkQueueForDeviceInstall(UserFileQ,
  896. hDeviceInf,
  897. pStringTableStringFromId(
  898. pDeviceInfoSet->StringTable,
  899. DevInfoElem->SelectedDriver->DrvDescription)
  900. );
  901. if(CloseUserFileQ) {
  902. if(Err == NO_ERROR) {
  903. //
  904. // If the parameter block contains an install message handler, then use it,
  905. // otherwise, initialize our default one.
  906. //
  907. if(DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  908. MsgHandler = DevInfoElem->InstallParamBlock.InstallMsgHandler;
  909. MsgHandlerContext = DevInfoElem->InstallParamBlock.InstallMsgHandlerContext;
  910. MsgHandlerIsNativeCharWidth = DevInfoElem->InstallParamBlock.InstallMsgHandlerIsNativeCharWidth;
  911. } else {
  912. NoProgressUI = (GuiSetupInProgress || (DevInfoElem->InstallParamBlock.Flags & DI_QUIETINSTALL));
  913. MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  914. hwndParent,
  915. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  916. 0,
  917. 0,
  918. NULL
  919. );
  920. if(MsgHandlerContext) {
  921. FreeMsgHandlerContext = TRUE;
  922. MsgHandler = SetupDefaultQueueCallback;
  923. MsgHandlerIsNativeCharWidth = TRUE;
  924. } else {
  925. Err = ERROR_NOT_ENOUGH_MEMORY;
  926. }
  927. }
  928. //
  929. // Call _SetupVerifyQueuedCatalogs separately (i.e.,
  930. // don't let it happen automatically as a result of
  931. // scanning/committing the queue that happens below).
  932. // We do this beforehand so that we know what unique
  933. // name was generated when an OEM INF was installed into
  934. // %windir%\Inf (in case we need to delete the
  935. // INF/PNF/CAT files later if we encounter an error).
  936. //
  937. if(Err == NO_ERROR) {
  938. WriteLogEntry(
  939. LogContext,
  940. DRIVER_LOG_TIME,
  941. MSG_LOG_BEGIN_VERIFY_CAT_TIME,
  942. NULL); // text message
  943. Err = _SetupVerifyQueuedCatalogs(
  944. hwndParent,
  945. UserFileQ,
  946. (VERCAT_INSTALL_INF_AND_CAT |
  947. ((DevInfoElem->SelectedDriver->Flags & DNF_INET_DRIVER) ? VERCAT_PRIMARY_DEVICE_INF_FROM_INET : 0)),
  948. szNewName,
  949. &OemInfFileToCopy
  950. );
  951. WriteLogEntry(
  952. LogContext,
  953. DRIVER_LOG_TIME,
  954. MSG_LOG_END_VERIFY_CAT_TIME,
  955. NULL); // text message
  956. }
  957. ASSERT_HEAP_IS_VALID();
  958. if (Err == NO_ERROR) {
  959. //
  960. // We successfully queued up the file operations and
  961. // we have a message handler to use--now we need to
  962. // commit the queue. First off, though, we should
  963. // check to see if the files are already there.
  964. //
  965. // ScanQueueResult can have 1 of 3 values:
  966. //
  967. // 0: Some files were missing or not valid--must
  968. // commit queue.
  969. //
  970. // 1: All files to be copied are already present and
  971. // valid, and the queue is empty--skip committing
  972. // queue.
  973. //
  974. // 2: All files to be copied are present and valid,
  975. // but del/ren/backup queues not empty--must
  976. // commit queue. The copy queue will have been
  977. // emptied, so only del/ren/backup functions will
  978. // be performed.
  979. //
  980. // (jamiehun) If DI_FLAGSEX_PREINSTALLBACKUP is
  981. // specified and there are items to be backed up, it
  982. // is covered in (2) the inf file will have already
  983. // been backed up
  984. //
  985. WriteLogEntry(
  986. LogContext,
  987. DRIVER_LOG_TIME,
  988. MSG_LOG_BEGIN_PRESCAN_TIME,
  989. NULL); // text message
  990. if(!SetupScanFileQueue(UserFileQ,
  991. SPQ_SCAN_FILE_VALIDITY |
  992. SPQ_SCAN_PRUNE_COPY_QUEUE,
  993. hwndParent,
  994. NULL,
  995. NULL,
  996. &ScanQueueResult)) {
  997. //
  998. // SetupScanFileQueue should really never
  999. // fail when you don't ask it to call a
  1000. // callback routine, but if it does, just
  1001. // go ahead and commit the queue.
  1002. //
  1003. ScanQueueResult = 0;
  1004. }
  1005. if(ScanQueueResult != 1) {
  1006. //
  1007. // Copy enqueued files.
  1008. //
  1009. WriteLogEntry(
  1010. LogContext,
  1011. DRIVER_LOG_TIME,
  1012. MSG_LOG_BEGIN_COMMIT_TIME,
  1013. NULL); // text message
  1014. if(_SetupCommitFileQueue(hwndParent,
  1015. UserFileQ,
  1016. MsgHandler,
  1017. MsgHandlerContext,
  1018. MsgHandlerIsNativeCharWidth
  1019. )) {
  1020. //
  1021. // Check to see whether a reboot is required
  1022. // as a result of committing the queue (i.e.,
  1023. // because files were in use, or the INF
  1024. // requested a reboot).
  1025. //
  1026. FileQueueNeedsReboot = SetupPromptReboot(UserFileQ, NULL, TRUE);
  1027. //
  1028. // This should never fail...
  1029. //
  1030. MYASSERT(FileQueueNeedsReboot != -1);
  1031. if(FileQueueNeedsReboot) {
  1032. SetDevnodeNeedsRebootProblem(DevInfoElem, pDeviceInfoSet, MSG_LOG_REBOOT_REASON_INUSE);
  1033. }
  1034. } else {
  1035. Err = GetLastError();
  1036. }
  1037. }
  1038. //
  1039. // If no files were modified as a result of commiting
  1040. // the file queue, then set the DI_FLAGSEX_RESTART_DEVICE_ONLY
  1041. // flag so that we only restart this one device, as opposed
  1042. // to restarting this device and all other device that
  1043. // are sharing a driver or filter with this device.
  1044. //
  1045. if (SetupGetFileQueueFlags(UserFileQ, &FileQueueFlags) &&
  1046. !(FileQueueFlags & SPQ_FLAG_FILES_MODIFIED)) {
  1047. DevInfoElem->InstallParamBlock.FlagsEx |= DI_FLAGSEX_RESTART_DEVICE_ONLY;
  1048. }
  1049. //
  1050. // Terminate the default queue callback, if it was created.
  1051. //
  1052. if(FreeMsgHandlerContext) {
  1053. SetupTermDefaultQueueCallback(MsgHandlerContext);
  1054. FreeMsgHandlerContext = FALSE;
  1055. }
  1056. }
  1057. }
  1058. //
  1059. // Close our file queue handle.
  1060. //
  1061. SetupCloseFileQueue(UserFileQ);
  1062. CloseUserFileQ = FALSE;
  1063. }
  1064. if(Err != NO_ERROR) {
  1065. goto clean0;
  1066. }
  1067. }
  1068. //
  1069. // If the copy succeeded (or in setup's case was queued), then
  1070. // it's time to update the registry and ini files.
  1071. //
  1072. if(Err == NO_ERROR) {
  1073. //
  1074. // We've got some registry modifications to do, but we don't want to
  1075. // do them if this is a copy-only installation.
  1076. //
  1077. if(DoFullInstall) {
  1078. //
  1079. // Skip installation of basic log configs if this is an
  1080. // enumerated device.
  1081. //
  1082. if((CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine) != CR_SUCCESS) ||
  1083. (ulStatus & DN_ROOT_ENUMERATED)) {
  1084. LOG_CONF LogConf;
  1085. WriteLogEntry(
  1086. LogContext,
  1087. DRIVER_LOG_TIME,
  1088. MSG_LOG_BEGIN_WRITE_BASIC_CFGS_TIME,
  1089. NULL); // text message
  1090. //
  1091. // Clean out all existing BASIC_LOG_CONF LogConfigs before writing out new ones from
  1092. // the INF.
  1093. //
  1094. while(CM_Get_First_Log_Conf_Ex(&LogConf, DevInfoElem->DevInst, BASIC_LOG_CONF,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  1095. CM_Free_Log_Conf(LogConf, 0);
  1096. CM_Free_Log_Conf_Handle(LogConf);
  1097. }
  1098. //
  1099. // Now write out the new basic log configs.
  1100. //
  1101. Err = InstallFromInfSectionAndNeededSections(NULL,
  1102. hDeviceInf,
  1103. InfSectionWithExt,
  1104. SPINST_LOGCONFIG,
  1105. NULL,
  1106. NULL,
  1107. 0,
  1108. NULL,
  1109. NULL,
  1110. DeviceInfoSet,
  1111. DeviceInfoData,
  1112. NULL
  1113. );
  1114. } else {
  1115. //
  1116. // For non-root-enumerated devices, check to see if there's an [<InstallSec>.LogConfigOverride]
  1117. // section, and if so, run it.
  1118. //
  1119. if(MYVERIFY(SUCCEEDED(StringCchCopy(&(InfSectionWithExt[InfSectionWithExtLength - 1]),
  1120. SIZECHARS(InfSectionWithExt)-(InfSectionWithExtLength - 1),
  1121. pszLogConfigOverrideSectionSuffix)))) {
  1122. if(SetupFindFirstLine(hDeviceInf, InfSectionWithExt, NULL, &InfContext)) {
  1123. LOG_CONF LogConf;
  1124. WriteLogEntry(
  1125. LogContext,
  1126. DRIVER_LOG_TIME,
  1127. MSG_LOG_BEGIN_WRITE_OVERRIDE_CFGS_TIME,
  1128. NULL); // text message
  1129. //
  1130. // Clean out all existing OVERRIDE_LOG_CONF LogConfigs before writing out new ones from
  1131. // the INF.
  1132. //
  1133. while(CM_Get_First_Log_Conf_Ex(&LogConf, DevInfoElem->DevInst,
  1134. OVERRIDE_LOG_CONF,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  1135. CM_Free_Log_Conf(LogConf, 0);
  1136. CM_Free_Log_Conf_Handle(LogConf);
  1137. }
  1138. //
  1139. // Now write out the new override log configs.
  1140. //
  1141. Err = InstallFromInfSectionAndNeededSections(NULL,
  1142. hDeviceInf,
  1143. InfSectionWithExt,
  1144. SPINST_LOGCONFIG | SPINST_LOGCONFIGS_ARE_OVERRIDES,
  1145. NULL,
  1146. NULL,
  1147. 0,
  1148. NULL,
  1149. NULL,
  1150. DeviceInfoSet,
  1151. DeviceInfoData,
  1152. NULL
  1153. );
  1154. }
  1155. }
  1156. //
  1157. // Make sure we strip off the ".LogConfigOverride" we added above.
  1158. //
  1159. InfSectionWithExt[InfSectionWithExtLength - 1] = TEXT('\0');
  1160. }
  1161. if((Err == NO_ERROR) && !(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) {
  1162. //
  1163. // (Don't pass devinfo set and element here, because we're writing
  1164. // to the _driver_ key, not the _device_ key.)
  1165. //
  1166. WriteLogEntry(
  1167. LogContext,
  1168. DRIVER_LOG_TIME,
  1169. MSG_LOG_BEGIN_INSTALL_REG_TIME,
  1170. NULL); // text message
  1171. Err = InstallFromInfSectionAndNeededSections(NULL,
  1172. hDeviceInf,
  1173. InfSectionWithExt,
  1174. SPINST_INIFILES
  1175. | SPINST_REGISTRY
  1176. | SPINST_INI2REG
  1177. | SPINST_BITREG
  1178. | SPINST_REGSVR
  1179. | SPINST_UNREGSVR
  1180. | SPINST_PROFILEITEMS,
  1181. hkDrv,
  1182. NULL,
  1183. 0,
  1184. NULL,
  1185. NULL,
  1186. INVALID_HANDLE_VALUE,
  1187. NULL,
  1188. NULL
  1189. );
  1190. if(Err == NO_ERROR) {
  1191. //
  1192. // Install extra HardWare registry section (if any).
  1193. //
  1194. Err = InstallHW(DeviceInfoSet,
  1195. DeviceInfoData,
  1196. hDeviceInf,
  1197. InfSectionWithExt,
  1198. &DeleteDevKey
  1199. );
  1200. }
  1201. }
  1202. //
  1203. // Set appropriate flags if we need to reboot or restart after
  1204. // this installation.
  1205. //
  1206. if(SetupFindFirstLine(hDeviceInf, InfSectionWithExt, pszReboot, &InfContext)) {
  1207. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,pDeviceInfoSet,
  1208. MSG_LOG_REBOOT_REASON_KEY,
  1209. (ULONG_PTR)pszReboot,
  1210. (ULONG_PTR)InfSectionWithExt);
  1211. } else if(SetupFindFirstLine(hDeviceInf, InfSectionWithExt, pszRestart, &InfContext)) {
  1212. //
  1213. // NOTE: This behavior is taken from setupx. In both "Reboot"
  1214. // and "Restart" cases, it sets the DI_NEEDREBOOT flag.
  1215. //
  1216. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,pDeviceInfoSet,
  1217. MSG_LOG_REBOOT_REASON_KEY,
  1218. (ULONG_PTR)pszRestart,
  1219. (ULONG_PTR)InfSectionWithExt);
  1220. }
  1221. //
  1222. // Set the value to write for the config flags, only if there
  1223. // are no config flags yet. If they exist, i.e., we are updating
  1224. // an existing device, just clear the re-install flag.
  1225. //
  1226. dwConfigFlags = GetDevInstConfigFlags(
  1227. DevInfoElem->DevInst,
  1228. (DevInfoElem->InstallParamBlock.Flags & DI_INSTALLDISABLED)
  1229. ? CONFIGFLAG_DISABLED
  1230. : 0,
  1231. pDeviceInfoSet->hMachine
  1232. );
  1233. //
  1234. // Always clear the REINSTALL bit and the FAILEDINSTALL bit
  1235. // when installing a device.
  1236. // (Also, clear the CONFIGFLAG_FINISH_INSTALL bit, which is used for
  1237. // Raw and driver-detected devnodes.)
  1238. //
  1239. dwConfigFlags &= ~(CONFIGFLAG_REINSTALL | CONFIGFLAG_FAILEDINSTALL | CONFIGFLAG_FINISH_INSTALL);
  1240. }
  1241. //
  1242. // If we're doing a copy-only installation, then we're done.
  1243. //
  1244. if(!DoFullInstall) {
  1245. goto clean0;
  1246. }
  1247. WriteLogEntry(
  1248. LogContext,
  1249. DRIVER_LOG_TIME,
  1250. MSG_LOG_BEGIN_WRITE_REG_TIME,
  1251. NULL); // text message
  1252. //
  1253. // Insert Driver Specific strings into the registry.
  1254. //
  1255. if(InfFromOemPath = pSetupInfIsFromOemLocation(szInfFileName, TRUE)) {
  1256. TempString = pSetupGetFileTitle(szNewName);
  1257. } else {
  1258. TempString = pSetupGetFileTitle(szInfFileName);
  1259. }
  1260. RegSetValueEx(hkDrv,
  1261. pszInfPath,
  1262. 0,
  1263. REG_SZ,
  1264. (PBYTE)TempString,
  1265. (lstrlen(TempString) + 1) * sizeof(TCHAR)
  1266. );
  1267. RegSetValueEx(hkDrv,
  1268. pszInfSection,
  1269. 0,
  1270. REG_SZ,
  1271. (PBYTE)szInfSectionName,
  1272. (lstrlen(szInfSectionName) + 1) * sizeof(TCHAR)
  1273. );
  1274. if(szInfSectionExt) {
  1275. RegSetValueEx(hkDrv,
  1276. pszInfSectionExt,
  1277. 0,
  1278. REG_SZ,
  1279. (PBYTE)szInfSectionExt,
  1280. (lstrlen(szInfSectionExt) + 1) * sizeof(TCHAR)
  1281. );
  1282. } else {
  1283. //
  1284. // This wasn't an OS/architecture-specific install section, _or_ we are
  1285. // installing from a legacy INF. Make sure there's no value hanging
  1286. // around from a previous installation.
  1287. //
  1288. RegDeleteValue(hkDrv, pszInfSectionExt);
  1289. }
  1290. if(DevInfoElem->SelectedDriver->ProviderDisplayName == -1) {
  1291. //
  1292. // No provider specified--delete any previously existing value entry.
  1293. //
  1294. RegDeleteValue(hkDrv, pszProviderName);
  1295. } else {
  1296. //
  1297. // Retrieve the Provider name, and store it in the driver key.
  1298. //
  1299. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1300. DevInfoElem->SelectedDriver->ProviderDisplayName
  1301. );
  1302. RegSetValueEx(hkDrv,
  1303. pszProviderName,
  1304. 0,
  1305. REG_SZ,
  1306. (PBYTE)TempString,
  1307. (lstrlen(TempString) + 1) * sizeof(TCHAR)
  1308. );
  1309. }
  1310. if (DevInfoElem->SelectedDriver->DriverDate.dwLowDateTime != 0 ||
  1311. DevInfoElem->SelectedDriver->DriverDate.dwHighDateTime != 0) {
  1312. SYSTEMTIME SystemTime;
  1313. TCHAR Date[20];
  1314. //
  1315. // Save the driver date in binary (FILETIME) format in the registry
  1316. // so it can be localized by other components.
  1317. //
  1318. RegSetValueEx(hkDrv,
  1319. pszDriverDateData,
  1320. 0,
  1321. REG_BINARY,
  1322. (LPBYTE)&DevInfoElem->SelectedDriver->DriverDate,
  1323. sizeof(DevInfoElem->SelectedDriver->DriverDate)
  1324. );
  1325. //
  1326. // Save the driver date in string format for compatibility.
  1327. //
  1328. if (FileTimeToSystemTime(&(DevInfoElem->SelectedDriver->DriverDate), &SystemTime)) {
  1329. MYVERIFY(SUCCEEDED(StringCchPrintf(Date,
  1330. SIZECHARS(Date),
  1331. TEXT("%d-%d-%d"),
  1332. SystemTime.wMonth,
  1333. SystemTime.wDay,
  1334. SystemTime.wYear)));
  1335. RegSetValueEx(hkDrv,
  1336. pszDriverDate,
  1337. 0,
  1338. REG_SZ,
  1339. (PBYTE)Date,
  1340. (lstrlen(Date) + 1) * sizeof(TCHAR)
  1341. );
  1342. }
  1343. } else {
  1344. //
  1345. //No driver date for this driver--delete any previously existing value entry.
  1346. //
  1347. RegDeleteValue(hkDrv, pszDriverDateData);
  1348. RegDeleteValue(hkDrv, pszDriverDate);
  1349. }
  1350. if (DevInfoElem->SelectedDriver->DriverVersion != 0) {
  1351. ULARGE_INTEGER Version;
  1352. TCHAR VersionString[LINE_LEN];
  1353. Version.QuadPart = DevInfoElem->SelectedDriver->DriverVersion;
  1354. MYVERIFY(SUCCEEDED(StringCchPrintf(VersionString,
  1355. SIZECHARS(VersionString),
  1356. TEXT("%0d.%0d.%0d.%0d"),
  1357. HIWORD(Version.HighPart),
  1358. LOWORD(Version.HighPart),
  1359. HIWORD(Version.LowPart),
  1360. LOWORD(Version.LowPart))));
  1361. RegSetValueEx(hkDrv,
  1362. pszDriverVersion,
  1363. 0,
  1364. REG_SZ,
  1365. (PBYTE)VersionString,
  1366. (lstrlen(VersionString) + 1) * sizeof(TCHAR)
  1367. );
  1368. } else {
  1369. //
  1370. //No driver version for this driver--delete any previously existing value entry.
  1371. //
  1372. RegDeleteValue(hkDrv, pszDriverVersion);
  1373. }
  1374. //
  1375. // Set the Class property for this device.
  1376. //
  1377. SetupDiClassNameFromGuid(&DevInfoElem->ClassGuid, className, MAX_CLASS_NAME_LEN, NULL);
  1378. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1379. CM_DRP_CLASS,
  1380. className,
  1381. (lstrlen(className) + 1) * sizeof(TCHAR),
  1382. 0,
  1383. pDeviceInfoSet->hMachine);
  1384. //
  1385. // Set the MFG device registry property.
  1386. //
  1387. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1388. DevInfoElem->SelectedDriver->MfgDisplayName
  1389. );
  1390. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1391. CM_DRP_MFG,
  1392. TempString,
  1393. (lstrlen(TempString) + 1) * sizeof(TCHAR),
  1394. 0,
  1395. pDeviceInfoSet->hMachine);
  1396. //
  1397. // Add hardware and compatible IDs to the hardware key if they exist
  1398. // in the driver node and don't already exist in the registry. This
  1399. // sets up an ID for manually installed devices.
  1400. //
  1401. if(!(DevInfoElem->InstallParamBlock.Flags & DI_NOWRITE_IDS) && // Want IDs written?
  1402. (DevInfoElem->SelectedDriver->HardwareId != -1)) // ID in driver node?
  1403. {
  1404. //
  1405. // Don't write IDs if either Hardware or Compatible IDs already
  1406. // exist in the registry. Note that I use cbData as an IN/OUT parameter
  1407. // to both CM calls. This is OK, however, since cbSize will not be modified
  1408. // on a CR_NO_SUCH_VALUE return, and I won't try to re-use it otherwise.
  1409. //
  1410. cbData = 0;
  1411. if((DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALWAYSWRITEIDS) ||
  1412. ((CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1413. CM_DRP_HARDWAREID,
  1414. NULL,
  1415. NULL,
  1416. &cbData,
  1417. 0,
  1418. pDeviceInfoSet->hMachine) == CR_NO_SUCH_VALUE) &&
  1419. (CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1420. CM_DRP_COMPATIBLEIDS,
  1421. NULL,
  1422. NULL,
  1423. &cbData,
  1424. 0,
  1425. pDeviceInfoSet->hMachine) == CR_NO_SUCH_VALUE)))
  1426. {
  1427. DWORD CurStringLen, TotalStringLen, DevIdBufferLen, i;
  1428. //
  1429. // Compute the maximum buffer size needed to hold our REG_MULTI_SZ
  1430. // ID lists.
  1431. //
  1432. DevIdBufferLen = (((DevInfoElem->SelectedDriver->NumCompatIds) ?
  1433. DevInfoElem->SelectedDriver->NumCompatIds : 1)
  1434. * MAX_DEVICE_ID_LEN) + 1;
  1435. if(!(DevIdBuffer = MyMalloc(DevIdBufferLen * sizeof(TCHAR)))) {
  1436. Err = ERROR_NOT_ENOUGH_MEMORY;
  1437. goto clean0;
  1438. }
  1439. //
  1440. // Build a multi-sz list of the (single) HardwareID, and set it.
  1441. //
  1442. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1443. DevInfoElem->SelectedDriver->HardwareId
  1444. );
  1445. TotalStringLen = lstrlen(TempString) + 1;
  1446. MYVERIFY(SUCCEEDED(StringCchCopy(DevIdBuffer,
  1447. DevIdBufferLen,
  1448. TempString)));
  1449. DevIdBuffer[TotalStringLen++] = TEXT('\0'); // Add extra terminating NULL;
  1450. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1451. CM_DRP_HARDWAREID,
  1452. DevIdBuffer,
  1453. TotalStringLen * sizeof(TCHAR),
  1454. 0,
  1455. pDeviceInfoSet->hMachine );
  1456. //
  1457. // Build a multi-sz list of the zero or more CompatibleIDs, and set it
  1458. //
  1459. TotalStringLen = 0;
  1460. for(i = 0; i < DevInfoElem->SelectedDriver->NumCompatIds; i++) {
  1461. TempString = pStringTableStringFromId(
  1462. pDeviceInfoSet->StringTable,
  1463. DevInfoElem->SelectedDriver->CompatIdList[i]);
  1464. CurStringLen = lstrlen(TempString) + 1;
  1465. MYVERIFY(SUCCEEDED(StringCchCopy(DevIdBuffer+TotalStringLen,
  1466. DevIdBufferLen-TotalStringLen,
  1467. TempString)));
  1468. TotalStringLen += CurStringLen;
  1469. }
  1470. if(TotalStringLen) {
  1471. DevIdBuffer[TotalStringLen++] = TEXT('\0'); // Add extra terminating NULL;
  1472. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1473. CM_DRP_COMPATIBLEIDS,
  1474. DevIdBuffer,
  1475. TotalStringLen * sizeof(TCHAR),
  1476. 0,
  1477. pDeviceInfoSet->hMachine);
  1478. }
  1479. }
  1480. }
  1481. //
  1482. // Write out the 'MatchingDeviceId' value entry to the driver key that indicates which
  1483. // device ID (hardware or compatible) was used to pick this driver. For a compatible
  1484. // driver, this is the device ID that the compatible match was based on. For a class
  1485. // driver, this is the driver node's HardwareId (if present), or best CompatibleId. If
  1486. // the class driver node didn't specify a hardware or compatible IDs, then this value
  1487. // will not be written (we'll actually delete it to make sure it doesn't exist from a
  1488. // previous driver installation).
  1489. //
  1490. TempString = NULL;
  1491. if(DevInfoElem->SelectedDriverType == SPDIT_COMPATDRIVER) {
  1492. if(DevInfoElem->SelectedDriver->MatchingDeviceId == -1) {
  1493. //
  1494. // We have a HardwareID match.
  1495. //
  1496. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1497. DevInfoElem->SelectedDriver->HardwareId
  1498. );
  1499. } else {
  1500. //
  1501. // We have a CompatibleID match.
  1502. //
  1503. MYASSERT((DevInfoElem->SelectedDriver->MatchingDeviceId >= 0) &&
  1504. ((DWORD)(DevInfoElem->SelectedDriver->MatchingDeviceId) < DevInfoElem->SelectedDriver->NumCompatIds));
  1505. TempString = pStringTableStringFromId(
  1506. pDeviceInfoSet->StringTable,
  1507. DevInfoElem->SelectedDriver->CompatIdList[DevInfoElem->SelectedDriver->MatchingDeviceId]
  1508. );
  1509. }
  1510. } else if(DevInfoElem->SelectedDriver->HardwareId != -1) {
  1511. //
  1512. // There's no notion of compatibility for class drivers--pick the device ID with the
  1513. // highest order of preference.
  1514. //
  1515. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1516. DevInfoElem->SelectedDriver->HardwareId
  1517. );
  1518. if(!(*TempString)) {
  1519. //
  1520. // The HardwareID was an empty string--use the first CompatibleID.
  1521. //
  1522. if(DevInfoElem->SelectedDriver->NumCompatIds) {
  1523. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1524. DevInfoElem->SelectedDriver->CompatIdList[0]
  1525. );
  1526. } else {
  1527. TempString = NULL;
  1528. }
  1529. }
  1530. }
  1531. if(TempString) {
  1532. RegSetValueEx(hkDrv,
  1533. pszMatchingDeviceId,
  1534. 0,
  1535. REG_SZ,
  1536. (PBYTE)TempString,
  1537. (lstrlen(TempString) + 1) * sizeof(TCHAR)
  1538. );
  1539. } else {
  1540. //
  1541. // We have an override situation where the user picked a class driver that didn't
  1542. // specify any hardware or compatible IDs. Make sure there's no value hanging
  1543. // around from a previous installation.
  1544. //
  1545. RegDeleteValue(hkDrv, pszMatchingDeviceId);
  1546. }
  1547. //
  1548. // If we're running under Windows NT, and we've successfully installed the device instance,
  1549. // then we need to install any required services.
  1550. //
  1551. if((Err == NO_ERROR) && (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
  1552. PTSTR pServiceInstallSection;
  1553. WriteLogEntry(
  1554. LogContext,
  1555. DRIVER_LOG_TIME,
  1556. MSG_LOG_BEGIN_SERVICE_TIME,
  1557. NULL); // text message
  1558. //
  1559. // The install section name is of the form:
  1560. //
  1561. // <InfSectionWithExt>.Services
  1562. //
  1563. MYVERIFY(SUCCEEDED(StringCchCopy(&(InfSectionWithExt[InfSectionWithExtLength - 1]),
  1564. SIZECHARS(InfSectionWithExt)-(InfSectionWithExtLength - 1),
  1565. pszServicesSectionSuffix)));
  1566. pServiceInstallSection = InfSectionWithExt;
  1567. Err = InstallNtService(DevInfoElem,
  1568. hDeviceInf,
  1569. szInfFileName,
  1570. pServiceInstallSection,
  1571. &DeleteServiceList,
  1572. 0,
  1573. &NullDriverInstall
  1574. );
  1575. }
  1576. if((Err == NO_ERROR) && DoFullInstall) {
  1577. InfSectionWithExt[InfSectionWithExtLength - 1] = TEXT('\0');
  1578. pSetupCopyRelatedInfs(hDeviceInf,
  1579. szInfFileName,
  1580. InfSectionWithExt,
  1581. (DevInfoElem->SelectedDriver->Flags & DNF_INET_DRIVER)
  1582. ? SPOST_URL : SPOST_PATH,
  1583. LogContext);
  1584. if(SUCCEEDED(StringCchCopy(&(InfSectionWithExt[InfSectionWithExtLength - 1]),
  1585. SIZECHARS(InfSectionWithExt)-(InfSectionWithExtLength-1),
  1586. pszWmiSectionSuffix))) {
  1587. //
  1588. // InfSectionWithExt refers to DDInstall.WMI
  1589. //
  1590. if(!SetupConfigureWmiFromInfSection(hDeviceInf,
  1591. InfSectionWithExt,
  1592. 0)) {
  1593. Err = GetLastError();
  1594. }
  1595. }
  1596. }
  1597. }
  1598. } else {
  1599. //
  1600. // Installing the NULL driver.
  1601. // This means to set the Config flags, and nothing else.
  1602. // Config Flags get set to enabled in this case, so the device
  1603. // gets assigned the correct config. (Win95 bug 26320)
  1604. //
  1605. WriteLogEntry(
  1606. LogContext,
  1607. DRIVER_LOG_INFO,
  1608. MSG_LOG_INSTALL_NULL,
  1609. NULL, // text message
  1610. DeviceFullID);
  1611. NullDriverInstall = TRUE;
  1612. if(DoFullInstall) {
  1613. BOOL NullDrvInstallOK = FALSE;
  1614. //
  1615. // Check to see if the devnode is raw-capable, or if it already has a controlling
  1616. // service. If neither of those conditions are met, then we should fail this call
  1617. // unless the caller has explicitly passed us the DI_FLAGSEX_SETFAILEDINSTALL flag.
  1618. //
  1619. cbData = sizeof(DevInstCapabilities);
  1620. if(CR_SUCCESS == CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1621. CM_DRP_CAPABILITIES,
  1622. NULL,
  1623. &DevInstCapabilities,
  1624. &cbData,
  1625. 0,
  1626. pDeviceInfoSet->hMachine))
  1627. {
  1628. NullDrvInstallOK = (DevInstCapabilities & CM_DEVCAP_RAWDEVICEOK);
  1629. }
  1630. if(!NullDrvInstallOK) {
  1631. //
  1632. // The devnode isn't raw-capable. Check to see if it already has a
  1633. // controlling service (e.g., because it was created as a result of
  1634. // a driver's call to IoReportDetectedDevice).
  1635. //
  1636. cbData = 0;
  1637. if(CR_BUFFER_SMALL == CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1638. CM_DRP_SERVICE,
  1639. NULL,
  1640. NULL,
  1641. &cbData,
  1642. 0,
  1643. pDeviceInfoSet->hMachine))
  1644. {
  1645. NullDrvInstallOK = TRUE;
  1646. }
  1647. }
  1648. if(!NullDrvInstallOK &&
  1649. !(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)) {
  1650. Err = ERROR_NO_ASSOCIATED_SERVICE;
  1651. } else {
  1652. dwConfigFlags = GetDevInstConfigFlags(DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine) &
  1653. ~(CONFIGFLAG_DISABLED | CONFIGFLAG_REINSTALL | CONFIGFLAG_FINISH_INSTALL);
  1654. //
  1655. // Delete all driver (software) keys associated with the
  1656. // device (this will automatically reset the "Driver"
  1657. // registry property.
  1658. //
  1659. SetupDiDeleteDevRegKey(DeviceInfoSet,
  1660. DeviceInfoData,
  1661. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGGENERAL,
  1662. 0,
  1663. DIREG_DRV
  1664. );
  1665. //
  1666. // Delete the controlling (FDO) Service property, as well as the UpperFilters and
  1667. // LowerFilters properties. Only do this if the devnode is not root-enumerated,
  1668. // however, since NT can have root-enumerated devnodes reported by drivers via
  1669. // IoReportDetectedDevice for which there's no corresponding INF (hence, the user
  1670. // must do a null-driver install in order to silence the "New Hardware Found" popups
  1671. // for these devices.
  1672. //
  1673. if((CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevInfoElem->DevInst,
  1674. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  1675. !(ulStatus & DN_ROOT_ENUMERATED)) {
  1676. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst, CM_DRP_SERVICE,
  1677. NULL, 0, 0,pDeviceInfoSet->hMachine);
  1678. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst, CM_DRP_UPPERFILTERS,
  1679. NULL, 0, 0,pDeviceInfoSet->hMachine);
  1680. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst, CM_DRP_LOWERFILTERS,
  1681. NULL, 0, 0,pDeviceInfoSet->hMachine);
  1682. }
  1683. }
  1684. } else {
  1685. //
  1686. // It is an error to not have a selected driver in the copy-only case.
  1687. //
  1688. Err = ERROR_NO_DRIVER_SELECTED;
  1689. }
  1690. }
  1691. //
  1692. // If all went well above, then write some configflags, and re-enumerate
  1693. // the parent device instance if necessary
  1694. //
  1695. if(Err == NO_ERROR) {
  1696. //
  1697. // Write the Driver Description to the Registry, if there
  1698. // is an lpSelectedDriver, and the Device Description also
  1699. //
  1700. WriteLogEntry(
  1701. LogContext,
  1702. DRIVER_LOG_TIME,
  1703. MSG_LOG_BEGIN_WRITE_REG2_TIME,
  1704. NULL); // text message
  1705. if(DevInfoElem->SelectedDriver) {
  1706. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1707. DevInfoElem->SelectedDriver->DrvDescription
  1708. );
  1709. RegSetValueEx(hkDrv,
  1710. pszDrvDesc,
  1711. 0,
  1712. REG_SZ,
  1713. (PBYTE)TempString,
  1714. (lstrlen(TempString) + 1) * sizeof(TCHAR)
  1715. );
  1716. //
  1717. // (setupx BUG 12721) always update the DevDesc in the registry with the
  1718. // value from the INF (ie only do this if we have a SELECTED driver)
  1719. // The semantics are weird, but the SelectedDriver NODE contains the
  1720. // INF Device description, and DRV description
  1721. //
  1722. TempString = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  1723. DevInfoElem->SelectedDriver->DevDescriptionDisplayName
  1724. );
  1725. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1726. CM_DRP_DEVICEDESC,
  1727. TempString,
  1728. (lstrlen(TempString) + 1) * sizeof(TCHAR),
  1729. 0,
  1730. pDeviceInfoSet->hMachine);
  1731. } else {
  1732. //
  1733. // No driver is selected, so use the description stored with the device
  1734. // information element itself for the device description. However, only set this
  1735. // if it isn't already present.
  1736. //
  1737. cbData = 0;
  1738. if(CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1739. CM_DRP_DEVICEDESC,
  1740. NULL,
  1741. NULL,
  1742. &cbData,
  1743. 0,
  1744. pDeviceInfoSet->hMachine) == CR_NO_SUCH_VALUE) {
  1745. if(DevInfoElem->DeviceDescriptionDisplayName != -1) {
  1746. TempString = pStringTableStringFromId(
  1747. pDeviceInfoSet->StringTable,
  1748. DevInfoElem->DeviceDescriptionDisplayName
  1749. );
  1750. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1751. CM_DRP_DEVICEDESC,
  1752. TempString,
  1753. (lstrlen(TempString) + 1) * sizeof(TCHAR),
  1754. 0,
  1755. pDeviceInfoSet->hMachine);
  1756. }
  1757. }
  1758. }
  1759. //
  1760. // Unless the caller explicitly requested that this device be installed disabled, clear
  1761. // the CONFIGFLAG_DISABLED bit.
  1762. //
  1763. if(!(DevInfoElem->InstallParamBlock.Flags & DI_INSTALLDISABLED)) {
  1764. dwConfigFlags &= ~CONFIGFLAG_DISABLED;
  1765. }
  1766. //
  1767. // Write the config flags. If no selected driver means we should mark the install
  1768. // as a failure, then do so.
  1769. //
  1770. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL) {
  1771. dwConfigFlags |= CONFIGFLAG_FAILEDINSTALL;
  1772. }
  1773. //
  1774. // NTRAID#700056-2002/09/05-LonnyM check return codes from CM_Set_DevInst_Registry_Property.
  1775. //
  1776. // Only stop/start the device if we can set the ConfigFlags on the
  1777. // device. Otherwise we can get stuck in an infinite loop where
  1778. // the CONFIGFLAG_REINSTALL is not cleared and when the device is
  1779. // restarted we try to install it all over again.
  1780. // In the future we need to check all return codes from the
  1781. // CM_Set_DevInst_Registry_Property APIs and fail/exit appropriately.
  1782. //
  1783. if (CR_SUCCESS == CM_Set_DevInst_Registry_Property_Ex(
  1784. DevInfoElem->DevInst,
  1785. CM_DRP_CONFIGFLAGS,
  1786. &dwConfigFlags,
  1787. sizeof(dwConfigFlags),
  1788. 0,
  1789. pDeviceInfoSet->hMachine)) {
  1790. if(!(DevInfoElem->InstallParamBlock.Flags & (DI_DONOTCALLCONFIGMG | DI_NEEDREBOOT | DI_NEEDRESTART))) {
  1791. if (DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_RESTART_DEVICE_ONLY) {
  1792. //
  1793. // Restart this device only.
  1794. //
  1795. // This should only be done if no files were copied during
  1796. // DIF_INSTALLDEVICEFILES.
  1797. //
  1798. RestartSingleDevice(DevInfoElem,
  1799. pDeviceInfoSet,
  1800. NullDriverInstall,
  1801. LogContext);
  1802. } else {
  1803. //
  1804. // Restart this device as well as any other device that is
  1805. // using one of the same drivers as this device. This
  1806. // includes the function driver as well as the device and
  1807. // class upper and lower filter drivers.
  1808. //
  1809. // This only needs to be used if files were copied during
  1810. // DIF_INSTALLDEVICEFILES.
  1811. //
  1812. RestartAllDevicesUsingDrivers(DevInfoElem,
  1813. pDeviceInfoSet,
  1814. NullDriverInstall,
  1815. LogContext);
  1816. }
  1817. }
  1818. }
  1819. }
  1820. if((Err == NO_ERROR) && !GuiSetupInProgress) {
  1821. MYASSERT(DoFullInstall);
  1822. //
  1823. // Kick off RunOnce.
  1824. //
  1825. WriteLogEntry(
  1826. LogContext,
  1827. DRIVER_LOG_TIME,
  1828. MSG_LOG_BEGIN_INSTALLSTOP_TIME,
  1829. NULL); // text message
  1830. Err = pSetupInstallStopEx(TRUE, INSTALLSTOP_NO_GRPCONV, LogContext);
  1831. }
  1832. clean0: ; // nothing to do
  1833. } except(EXCEPTION_EXECUTE_HANDLER) {
  1834. //
  1835. // If our exception was an AV, then use Win32 invalid param error,
  1836. // otherwise, assume it was an inpage error dealing with a mapped-in
  1837. // file.
  1838. //
  1839. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  1840. if(FreeMsgHandlerContext) {
  1841. SetupTermDefaultQueueCallback(MsgHandlerContext);
  1842. }
  1843. if(CloseUserFileQ) {
  1844. SetupCloseFileQueue(UserFileQ);
  1845. }
  1846. //
  1847. // Access the following variables so that the compiler will respect our
  1848. // statement ordering w.r.t. these values. Otherwise, we may not be
  1849. // able to know with certainty whether or not we should release their
  1850. // corresponding resources.
  1851. //
  1852. DevInfoElem = DevInfoElem;
  1853. hDeviceInf = hDeviceInf;
  1854. hkDrv = hkDrv;
  1855. DevIdBuffer = DevIdBuffer;
  1856. DeleteServiceList = DeleteServiceList;
  1857. OemInfFileToCopy = OemInfFileToCopy;
  1858. }
  1859. //
  1860. // Clean up the registry if the install didn't go well. Along with other
  1861. // error paths, this handles the case where the user cancels the install
  1862. // while copying files
  1863. //
  1864. if(Err != NO_ERROR) {
  1865. WriteLogEntry(
  1866. LogContext,
  1867. DRIVER_LOG_TIME,
  1868. MSG_LOG_BEGIN_CLEANUP_TIME,
  1869. NULL); // text message
  1870. if(DevInfoElem && DoFullInstall) {
  1871. //
  1872. // Disable the device if the error wasn't a user cancel.
  1873. //
  1874. if(Err != ERROR_CANCELLED) {
  1875. DWORD dwConfigFlagsSize;
  1876. //
  1877. // The device is in an unknown state. Disable it by setting the
  1878. // CONFIGFLAG_DISABLED config flag.
  1879. //
  1880. dwConfigFlagsSize = sizeof(DWORD);
  1881. if(CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1882. CM_DRP_CONFIGFLAGS,
  1883. NULL,
  1884. &dwConfigFlags,
  1885. &dwConfigFlagsSize,
  1886. 0,
  1887. pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  1888. dwConfigFlags |= (CONFIGFLAG_DISABLED | CONFIGFLAG_REINSTALL);
  1889. //
  1890. // Also, make sure we clear the finish-install flag.
  1891. //
  1892. dwConfigFlags &= ~CONFIGFLAG_FINISH_INSTALL;
  1893. } else {
  1894. dwConfigFlags = CONFIGFLAG_DISABLED;
  1895. }
  1896. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  1897. CM_DRP_CONFIGFLAGS,
  1898. &dwConfigFlags,
  1899. sizeof(dwConfigFlags),
  1900. 0,
  1901. pDeviceInfoSet->hMachine);
  1902. //
  1903. // Delete the driver key (as well as the device key, if it
  1904. // didn't previously exist).
  1905. //
  1906. if(DevInfoElem->SelectedDriver) {
  1907. SetupDiDeleteDevRegKey(DeviceInfoSet,
  1908. DeviceInfoData,
  1909. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGGENERAL,
  1910. 0,
  1911. (DeleteDevKey ? DIREG_BOTH : DIREG_DRV)
  1912. );
  1913. }
  1914. //
  1915. // If necessary, delete any service entries created for this device instance.
  1916. //
  1917. if(DeleteServiceList) {
  1918. DeleteServicesInList(DeleteServiceList,LogContext);
  1919. }
  1920. }
  1921. }
  1922. //
  1923. // If we copied the OEM INF into the INF directory under a
  1924. // newly-generated name, delete it now.
  1925. //
  1926. if(OemInfFileToCopy) {
  1927. pSetupUninstallOEMInf(szNewName, LogContext, SUOI_FORCEDELETE, NULL);
  1928. }
  1929. }
  1930. UnlockDeviceInfoSet(pDeviceInfoSet);
  1931. if(hDeviceInf != INVALID_HANDLE_VALUE) {
  1932. SetupCloseInfFile(hDeviceInf);
  1933. }
  1934. if(hkDrv != INVALID_HANDLE_VALUE) {
  1935. RegCloseKey(hkDrv);
  1936. }
  1937. if(DevIdBuffer) {
  1938. MyFree(DevIdBuffer);
  1939. }
  1940. if(ValidationPlatform) {
  1941. MyFree(ValidationPlatform);
  1942. }
  1943. if(DeleteServiceList) {
  1944. PSVCNAME_NODE TmpSvcNode;
  1945. for(TmpSvcNode = DeleteServiceList; TmpSvcNode; TmpSvcNode = DeleteServiceList) {
  1946. DeleteServiceList = DeleteServiceList->Next;
  1947. MyFree(TmpSvcNode);
  1948. }
  1949. }
  1950. if (Err == NO_ERROR) {
  1951. //
  1952. // give a +ve affirmation of install
  1953. // if copy install, only do in Verbose-Logging, else do for standard Info-Logging
  1954. //
  1955. WriteLogEntry(
  1956. LogContext,
  1957. DoFullInstall?DRIVER_LOG_INFO:DRIVER_LOG_VERBOSE,
  1958. MSG_LOG_INSTALLED,
  1959. NULL,
  1960. DeviceFullID);
  1961. } else {
  1962. //
  1963. // indicate install failed, display error
  1964. //
  1965. WriteLogEntry(
  1966. LogContext,
  1967. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  1968. MSG_LOG_INSTALL_ERROR_ENCOUNTERED,
  1969. NULL);
  1970. WriteLogError(
  1971. LogContext,
  1972. DRIVER_LOG_ERROR,
  1973. Err);
  1974. }
  1975. if (slot_deviceID) {
  1976. ReleaseLogInfoSlot(LogContext,slot_deviceID);
  1977. }
  1978. if (slot_section) {
  1979. ReleaseLogInfoSlot(LogContext,slot_section);
  1980. }
  1981. WriteLogEntry(
  1982. LogContext,
  1983. DRIVER_LOG_TIME,
  1984. MSG_LOG_END_INSTALL_TIME,
  1985. NULL); // text message
  1986. SetLastError(Err);
  1987. return(Err == NO_ERROR);
  1988. }
  1989. BOOL
  1990. WINAPI
  1991. SetupDiInstallDriverFiles(
  1992. IN HDEVINFO DeviceInfoSet,
  1993. IN PSP_DEVINFO_DATA DeviceInfoData
  1994. )
  1995. /*++
  1996. Routine Description:
  1997. Default handler for DIF_INSTALLDEVICEFILES
  1998. This routine is similiar to a combination of SetupDiRegisterCoDeviceInstallers,
  1999. SetupDiInstallDeviceInterfaces, and SetupDiInstallDevice, but it only performs
  2000. the file copy commands in the install sections, and will not attempt to
  2001. configure the device in any way. This API is useful for pre-copying a device's
  2002. driver files.
  2003. Arguments:
  2004. DeviceInfoSet - Supplies a handle to the device information set containing
  2005. a device information element to be installed.
  2006. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for which
  2007. a driver is to be installed.
  2008. Return Value:
  2009. If the function succeeds, the return value is TRUE.
  2010. If the function fails, the return value is FALSE. To get extended error
  2011. information, call GetLastError.
  2012. Remarks:
  2013. A driver must be selected for the specified device information element before
  2014. calling this API.
  2015. --*/
  2016. {
  2017. return _SetupDiInstallDevice(DeviceInfoSet, DeviceInfoData, FALSE);
  2018. }
  2019. BOOL
  2020. WINAPI
  2021. SetupDiRemoveDevice(
  2022. IN HDEVINFO DeviceInfoSet,
  2023. IN OUT PSP_DEVINFO_DATA DeviceInfoData
  2024. )
  2025. /*++
  2026. Routine Description:
  2027. Default handler for DIF_REMOVE
  2028. This routine removes a device from the system.
  2029. Arguments:
  2030. DeviceInfoSet - Supplies a handle to the device information set for which a
  2031. device is to be removed.
  2032. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for
  2033. which a device is to be removed. This is an IN OUT parameter, since the
  2034. DevInst field of the structure may be updated with a new handle value upon
  2035. return. (If this is a global removal, or the last hardware profile-specific
  2036. removal, then all traces of the devinst are removed from the registry, and
  2037. the handle becomes NULL at that point.)
  2038. Return Value:
  2039. If the function succeeds, the return value is TRUE.
  2040. If the function fails, the return value is FALSE. To get extended error
  2041. information, call GetLastError.
  2042. Remarks:
  2043. This routine will remove the device from the system, deleting both of its
  2044. registry keys, and dynamically stopping the device if its DevInst is 'live'.
  2045. If the device cannot be dynamically stopped, then flags will be set in the
  2046. install parameter block that will eventually cause the user to be prompted
  2047. to shut the system down. The removal is either global to all hardware
  2048. profiles, or specific to one hardware profile depending on the contents of
  2049. the ClassInstallParams field.
  2050. ** This API cannot be called for a remote HDEVINFO set **
  2051. --*/
  2052. {
  2053. PDEVICE_INFO_SET pDeviceInfoSet;
  2054. DWORD Err, ConfigFlags;
  2055. PDEVINFO_ELEM DevInfoElem;
  2056. PDEVINSTALL_PARAM_BLOCK dipb;
  2057. TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
  2058. PSP_REMOVEDEVICE_PARAMS RemoveDevParams;
  2059. BOOL IsCurrentHwProfile = FALSE;
  2060. ULONG HwProfFlags;
  2061. DWORD HwProfileToRemove;
  2062. HWPROFILEINFO HwProfileInfo;
  2063. BOOL RemoveDevInst = FALSE, NukeDevInst = FALSE;
  2064. BOOL RemoveGlobally;
  2065. DEVINST DevNodeRemoved = 0;
  2066. DWORD i;
  2067. PDEVICE_INTERFACE_NODE DeviceInterfaceNode;
  2068. CONFIGRET cr;
  2069. ULONG ulStatus;
  2070. ULONG ulProblem;
  2071. PSETUP_LOG_CONTEXT LogContext = NULL;
  2072. DWORD slot_deviceID = 0;
  2073. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2074. Err = ERROR_INVALID_HANDLE;
  2075. goto clean1;
  2076. }
  2077. LogContext = pDeviceInfoSet->InstallParamBlock.LogContext;
  2078. Err = NO_ERROR;
  2079. try {
  2080. //
  2081. // This operation isn't supported for a remote HDEVINFO...
  2082. //
  2083. if(pDeviceInfoSet->hMachine) {
  2084. Err = ERROR_REMOTE_REQUEST_UNSUPPORTED;
  2085. goto clean0;
  2086. }
  2087. //
  2088. // Locate the devinfo element to be removed.
  2089. //
  2090. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  2091. DeviceInfoData,
  2092. NULL)) {
  2093. dipb = &(DevInfoElem->InstallParamBlock);
  2094. LogContext = dipb->LogContext;
  2095. } else {
  2096. Err = ERROR_INVALID_PARAMETER;
  2097. goto clean0;
  2098. }
  2099. //
  2100. // This routine can't be called if non-native drivers are involved.
  2101. // (Note: while presently this doesn't matter, it's possible that in
  2102. // the future uninstall will involve running one or more INF "uninstall"
  2103. // sections, and I don't want to limit that possibility by introducing
  2104. // the complication of non-native driver nodes.)
  2105. //
  2106. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  2107. Err = ERROR_INVALID_FLAGS;
  2108. goto clean0;
  2109. }
  2110. if(CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine) == CR_SUCCESS &&
  2111. (ulStatus & DN_ROOT_ENUMERATED) &&
  2112. !(ulStatus & DN_DISABLEABLE)) {
  2113. //
  2114. // we cannot remove a root enumerated non-disableable device
  2115. //
  2116. Err = ERROR_NOT_DISABLEABLE;
  2117. goto clean0;
  2118. }
  2119. //
  2120. // Retrieve the name of the device instance. This is necessary, because
  2121. // we're about to remove the DEVINST, but we need to be able to locate it
  2122. // again, as a phantom. This should never fail.
  2123. //
  2124. if(CM_Get_Device_ID_Ex(DevInfoElem->DevInst,
  2125. DeviceInstanceId,
  2126. SIZECHARS(DeviceInstanceId),
  2127. 0,
  2128. pDeviceInfoSet->hMachine) != CR_SUCCESS) {
  2129. MYASSERT(!CR_SUCCESS);
  2130. Err = ERROR_INVALID_DATA;
  2131. goto clean0;
  2132. }
  2133. if(slot_deviceID == 0) {
  2134. slot_deviceID = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_INFO,FALSE);
  2135. }
  2136. WriteLogEntry(
  2137. LogContext,
  2138. slot_deviceID,
  2139. MSG_LOG_DO_REMOVE,
  2140. NULL, // text message
  2141. DeviceInstanceId);
  2142. //
  2143. // See if there's a SP_REMOVEDEVICE_PARAMS structure we need to pay
  2144. // attention to.
  2145. //
  2146. if((dipb->Flags & DI_CLASSINSTALLPARAMS) &&
  2147. (dipb->ClassInstallHeader->InstallFunction == DIF_REMOVE)) {
  2148. RemoveDevParams = (PSP_REMOVEDEVICE_PARAMS)(dipb->ClassInstallHeader);
  2149. if(RemoveGlobally = (RemoveDevParams->Scope == DI_REMOVEDEVICE_GLOBAL)) {
  2150. //
  2151. // We are doing a global removal. We still want to set CSCONFIGFLAG_DO_NOT_CREATE
  2152. // for this device in the current hardware profile, so that someone else happening
  2153. // to do an enumeration won't turn this guy back on before we get a chance to
  2154. // remove it.
  2155. //
  2156. HwProfileToRemove = 0;
  2157. } else {
  2158. //
  2159. // Remove device from a particular hardware profile.
  2160. //
  2161. HwProfileToRemove = RemoveDevParams->HwProfile;
  2162. //
  2163. // Set the CSCONFIGFLAG_DO_NOT_CREATE flag for the specified hardware profile.
  2164. //
  2165. if(CM_Get_HW_Prof_Flags_Ex(DeviceInstanceId,
  2166. HwProfileToRemove,
  2167. &HwProfFlags,
  2168. 0,
  2169. pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2170. HwProfFlags |= CSCONFIGFLAG_DO_NOT_CREATE;
  2171. } else {
  2172. HwProfFlags = CSCONFIGFLAG_DO_NOT_CREATE;
  2173. }
  2174. Err = MapCrToSpError(
  2175. CM_Set_HW_Prof_Flags_Ex(DeviceInstanceId, HwProfileToRemove,
  2176. HwProfFlags, 0,pDeviceInfoSet->hMachine),
  2177. ERROR_INVALID_DATA
  2178. );
  2179. if(Err != NO_ERROR) {
  2180. goto clean0;
  2181. }
  2182. //
  2183. // Determine if we are deleting the device from the current hw profile.
  2184. //
  2185. if((HwProfileToRemove == 0) ||
  2186. ((CM_Get_Hardware_Profile_Info_Ex((ULONG)-1, &HwProfileInfo,
  2187. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  2188. (HwProfileInfo.HWPI_ulHWProfile == HwProfileToRemove))) {
  2189. IsCurrentHwProfile = TRUE;
  2190. }
  2191. }
  2192. //
  2193. // Is this the current hardware profile or a global removal AND
  2194. // is there a present device?
  2195. //
  2196. if((IsCurrentHwProfile || RemoveGlobally) &&
  2197. !(DevInfoElem->DiElemFlags & DIE_IS_PHANTOM) &&
  2198. !(dipb->Flags & DI_DONOTCALLCONFIGMG)) {
  2199. RemoveDevInst = TRUE;
  2200. }
  2201. } else {
  2202. //
  2203. // No device removal params given, so do a global removal.
  2204. //
  2205. RemoveGlobally = TRUE;
  2206. HwProfileToRemove = 0;
  2207. if(!(dipb->Flags & DI_DONOTCALLCONFIGMG)) {
  2208. RemoveDevInst = TRUE;
  2209. }
  2210. }
  2211. //
  2212. // If this is a global removal, or the last hardware profile-specific one, then clean up
  2213. // the registry.
  2214. //
  2215. if(RemoveGlobally || IsDevRemovedFromAllHwProfiles(DeviceInstanceId,pDeviceInfoSet->hMachine)) {
  2216. NukeDevInst = TRUE;
  2217. }
  2218. if(RemoveDevInst) {
  2219. TCHAR VetoName[MAX_PATH];
  2220. PNP_VETO_TYPE VetoType;
  2221. cr = CM_Query_And_Remove_SubTree_Ex(DevInfoElem->DevInst,
  2222. &VetoType,
  2223. VetoName,
  2224. SIZECHARS(VetoName),
  2225. CM_REMOVE_NO_RESTART |
  2226. ((DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NOUIONQUERYREMOVE)
  2227. ? CM_REMOVE_UI_NOT_OK
  2228. : CM_REMOVE_UI_OK),
  2229. pDeviceInfoSet->hMachine
  2230. );
  2231. if(cr == CR_SUCCESS) {
  2232. //
  2233. // Device instance successfully removed--now locate it as a phantom.
  2234. //
  2235. CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  2236. (DEVINSTID)DeviceInstanceId,
  2237. CM_LOCATE_DEVINST_PHANTOM,
  2238. pDeviceInfoSet->hMachine);
  2239. DevInfoElem->DiElemFlags |= DIE_IS_PHANTOM;
  2240. //
  2241. // Set the DevNodeRemoved DevNode so that we know we need to
  2242. // call CM_Setup_DevInst with the CM_SETUP_DEVNODE_RESET flag
  2243. // to allow this devnode to come back online on the next
  2244. // enumeration.
  2245. //
  2246. DevNodeRemoved = DevInfoElem->DevInst;
  2247. } else {
  2248. //
  2249. // If the failure was due to a veto, then log information about
  2250. // who vetoed us.
  2251. //
  2252. // SPLOG--write out an entry with real logging.
  2253. //
  2254. if(cr == CR_REMOVE_VETOED) {
  2255. //
  2256. // get the LogContext from dipb which should be a pointer
  2257. // to the appropriate DevInstallParamBlock
  2258. //
  2259. _WriteVetoLogEntry(
  2260. dipb->LogContext,
  2261. DRIVER_LOG_WARNING,
  2262. MSG_LOG_REMOVE_VETOED_IN_UNINSTALL,
  2263. DeviceInstanceId,
  2264. VetoName,
  2265. VetoType);
  2266. }
  2267. if (cr != CR_INVALID_DEVNODE) {
  2268. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,
  2269. pDeviceInfoSet,
  2270. MSG_LOG_REBOOT_REASON_QR_VETOED_UNINSTALL,
  2271. cr,
  2272. (ULONG_PTR)_MapCmRetToString(cr)
  2273. );
  2274. }
  2275. }
  2276. }
  2277. if(NukeDevInst) {
  2278. //
  2279. // Remove all traces of this device from the registry.
  2280. //
  2281. pSetupDeleteDevRegKeys(DevInfoElem->DevInst,
  2282. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGSPECIFIC,
  2283. (DWORD)-1,
  2284. DIREG_BOTH,
  2285. TRUE,
  2286. pDeviceInfoSet->hMachine // must be NULL
  2287. );
  2288. cr = CM_Uninstall_DevInst_Ex(DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine);
  2289. if (cr != CR_SUCCESS) {
  2290. //
  2291. // we try to catch this earlier
  2292. //
  2293. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2294. goto clean0;
  2295. }
  2296. //
  2297. // The above API will also remove all device interfaces associated with this
  2298. // device instance. Now we need to mark every device interface node that we
  2299. // are tracking for this devinfo element to indicate that they have been removed.
  2300. //
  2301. for(i = 0; i < DevInfoElem->InterfaceClassListSize; i++) {
  2302. for(DeviceInterfaceNode = DevInfoElem->InterfaceClassList[i].DeviceInterfaceNode;
  2303. DeviceInterfaceNode;
  2304. DeviceInterfaceNode = DeviceInterfaceNode->Next) {
  2305. DeviceInterfaceNode->Flags |= SPINT_REMOVED;
  2306. }
  2307. }
  2308. //
  2309. // Mark this device information element as unregistered, and set its
  2310. // devinst handle to NULL.
  2311. //
  2312. DevInfoElem->DiElemFlags &= ~DIE_IS_REGISTERED;
  2313. DevInfoElem->DevInst = (DEVINST)0;
  2314. }
  2315. //
  2316. // Now update the DevInst field of the DeviceInfoData structure with the new
  2317. // value of the devinst handle (possibly NULL).
  2318. //
  2319. DeviceInfoData->DevInst = DevInfoElem->DevInst;
  2320. clean0: ; // nothing to do.
  2321. //
  2322. // If the DevNode was really removed then we need to call CM_Setup_DevInst
  2323. // with the CM_SETUP_DEVNODE_RESET flag to allow the devnode to come back
  2324. // on the next enumeration.
  2325. //
  2326. if (DevNodeRemoved) {
  2327. CM_Setup_DevInst_Ex(DevNodeRemoved,
  2328. CM_SETUP_DEVNODE_RESET,
  2329. pDeviceInfoSet->hMachine
  2330. );
  2331. }
  2332. } except(EXCEPTION_EXECUTE_HANDLER) {
  2333. Err = ERROR_INVALID_PARAMETER;
  2334. }
  2335. UnlockDeviceInfoSet(pDeviceInfoSet);
  2336. clean1:
  2337. if (slot_deviceID) {
  2338. if (Err == NO_ERROR) {
  2339. //
  2340. // give a +ve affirmation of remove
  2341. //
  2342. WriteLogEntry(
  2343. LogContext,
  2344. DRIVER_LOG_INFO,
  2345. MSG_LOG_REMOVED,
  2346. NULL);
  2347. } else {
  2348. //
  2349. // indicate remove failed, display error
  2350. //
  2351. WriteLogEntry(
  2352. LogContext,
  2353. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  2354. MSG_LOG_REMOVE_ERROR,
  2355. NULL);
  2356. WriteLogError(
  2357. LogContext,
  2358. DRIVER_LOG_ERROR,
  2359. Err);
  2360. }
  2361. ReleaseLogInfoSlot(LogContext,slot_deviceID);
  2362. }
  2363. SetLastError(Err);
  2364. return(Err == NO_ERROR);
  2365. }
  2366. BOOL
  2367. WINAPI
  2368. SetupDiUnremoveDevice(
  2369. IN HDEVINFO DeviceInfoSet,
  2370. IN OUT PSP_DEVINFO_DATA DeviceInfoData
  2371. )
  2372. /*++
  2373. Routine Description:
  2374. Default handler for DIF_UNREMOVE
  2375. This routine unremoves a device from the system.
  2376. Arguments:
  2377. DeviceInfoSet - Supplies a handle to the device information set for which a
  2378. device is to be unremoved.
  2379. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for
  2380. which a device is to be unremoved. This is an IN OUT parameter, since the
  2381. DevInst field of the structure may be updated with a new handle value upon
  2382. return.
  2383. This device must contain class install parameters for DIF_UNREMOVE
  2384. or the API will fail with ERROR_NO_CLASSINSTALL_PARAMS.
  2385. Return Value:
  2386. If the function succeeds, the return value is TRUE.
  2387. If the function fails, the return value is FALSE. To get extended error
  2388. information, call GetLastError.
  2389. Remarks:
  2390. This function will unremove the the device on the system, dynamically starting
  2391. the device if possible. If the device cannot be dynamically started, then flags
  2392. will be set in the device install parameters that will eventually cause the user
  2393. to be prompted to shut the system down.
  2394. The unremoval is specific to one configuration, specified in the HwProfile field
  2395. of the SP_UNREMOVEDEVICE_PARAMS class install parameters associated with this
  2396. device information element. (The Scope field of this structure must be set to
  2397. DI_UNREMOVEDEVICE_CONFIGSPECIFIC.)
  2398. --*/
  2399. {
  2400. PDEVICE_INFO_SET pDeviceInfoSet;
  2401. DWORD Err;
  2402. PDEVINFO_ELEM DevInfoElem;
  2403. PDEVINSTALL_PARAM_BLOCK dipb;
  2404. PSP_UNREMOVEDEVICE_PARAMS UnremoveDevParams;
  2405. TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
  2406. ULONG HwProfFlags;
  2407. HWPROFILEINFO HwProfileInfo;
  2408. DEVINST dnRoot;
  2409. PSETUP_LOG_CONTEXT LogContext = NULL;
  2410. CONFIGRET cr;
  2411. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2412. Err = ERROR_INVALID_HANDLE;
  2413. goto clean1;
  2414. }
  2415. LogContext = pDeviceInfoSet->InstallParamBlock.LogContext;
  2416. Err = NO_ERROR;
  2417. try {
  2418. //
  2419. // Locate the devinfo element to be unremoved.
  2420. //
  2421. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  2422. DeviceInfoData,
  2423. NULL)) {
  2424. dipb = &(DevInfoElem->InstallParamBlock);
  2425. LogContext = dipb->LogContext;
  2426. } else {
  2427. Err = ERROR_INVALID_PARAMETER;
  2428. goto clean0;
  2429. }
  2430. //
  2431. // This routine can't be called if non-native drivers are involved.
  2432. // (Note: while presently this doesn't matter, it's possible that in
  2433. // the future this operation could involve running one or more INF
  2434. // sections, and I don't want to limit that possibility by introducing
  2435. // the complication of non-native driver nodes.)
  2436. //
  2437. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  2438. Err = ERROR_INVALID_FLAGS;
  2439. goto clean0;
  2440. }
  2441. //
  2442. // We'd better have DIF_UNREMOVE class install params
  2443. //
  2444. if(!(dipb->Flags & DI_CLASSINSTALLPARAMS) ||
  2445. (dipb->ClassInstallHeader->InstallFunction != DIF_UNREMOVE)) {
  2446. Err = ERROR_NO_CLASSINSTALL_PARAMS;
  2447. goto clean0;
  2448. }
  2449. UnremoveDevParams = (PSP_UNREMOVEDEVICE_PARAMS)(dipb->ClassInstallHeader);
  2450. //
  2451. // This only works in a hardware profile-specific manner.
  2452. //
  2453. MYASSERT(UnremoveDevParams->Scope == DI_UNREMOVEDEVICE_CONFIGSPECIFIC);
  2454. //
  2455. // Retrieve the name of the device instance. We need to do this because
  2456. // accessing hardware profile-specific config flags is done via name instead
  2457. // of devnode handle. (Also, we'll need this later after re-enumerating
  2458. // this device's parent.)
  2459. //
  2460. if((cr = CM_Get_Device_ID_Ex(DevInfoElem->DevInst,
  2461. DeviceInstanceId,
  2462. SIZECHARS(DeviceInstanceId),
  2463. 0,
  2464. pDeviceInfoSet->hMachine)) != CR_SUCCESS) {
  2465. Err = MapCrToSpError(cr,ERROR_INVALID_DATA);
  2466. goto clean0;
  2467. }
  2468. if(CM_Get_HW_Prof_Flags_Ex(DeviceInstanceId,
  2469. UnremoveDevParams->HwProfile,
  2470. &HwProfFlags,
  2471. 0,
  2472. pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2473. HwProfFlags &= ~CSCONFIGFLAG_DO_NOT_CREATE;
  2474. Err = MapCrToSpError(
  2475. CM_Set_HW_Prof_Flags_Ex(DeviceInstanceId, UnremoveDevParams->HwProfile,
  2476. HwProfFlags, 0,pDeviceInfoSet->hMachine),
  2477. ERROR_INVALID_DATA
  2478. );
  2479. if(Err != NO_ERROR) {
  2480. goto clean0;
  2481. }
  2482. }
  2483. //
  2484. // Determine if we are trying to un-remove the device in the current
  2485. // hardware profile.
  2486. //
  2487. if((UnremoveDevParams->HwProfile == 0) ||
  2488. ((CM_Get_Hardware_Profile_Info_Ex((ULONG)-1, &HwProfileInfo,
  2489. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  2490. (HwProfileInfo.HWPI_ulHWProfile == UnremoveDevParams->HwProfile))) {
  2491. //
  2492. // Make sure the device has started correctly.
  2493. //
  2494. if(CM_Locate_DevInst_Ex(&dnRoot, NULL, CM_LOCATE_DEVINST_NORMAL,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2495. //
  2496. // Try to get this device enumerated
  2497. //
  2498. CM_Reenumerate_DevInst_Ex(dnRoot, CM_REENUMERATE_SYNCHRONOUS,pDeviceInfoSet->hMachine);
  2499. if(CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  2500. (DEVINSTID)DeviceInstanceId,
  2501. CM_LOCATE_DEVINST_NORMAL,
  2502. pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2503. CheckIfDevStarted(DevInfoElem, pDeviceInfoSet);
  2504. } else {
  2505. //
  2506. // We couldn't locate the devnode. We don't need to
  2507. // request a reboot, because if the devnode ever shows up
  2508. // again, we should be able to bring it back on-line just
  2509. // fine.
  2510. //
  2511. // Retrieve the devnode as a phantom
  2512. //
  2513. CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  2514. (DEVINSTID)DeviceInstanceId,
  2515. CM_LOCATE_DEVINST_PHANTOM,
  2516. pDeviceInfoSet->hMachine
  2517. );
  2518. DevInfoElem->DiElemFlags |= DIE_IS_PHANTOM;
  2519. }
  2520. //
  2521. // Update the caller's buffer to reflect the new device instance handle
  2522. //
  2523. DeviceInfoData->DevInst = DevInfoElem->DevInst;
  2524. } else {
  2525. //
  2526. // We couldn't locate the root of the hardware tree! This should never happen...
  2527. //
  2528. Err = ERROR_INVALID_DATA;
  2529. }
  2530. }
  2531. clean0: ; // nothing to do.
  2532. } except(EXCEPTION_EXECUTE_HANDLER) {
  2533. Err = ERROR_INVALID_PARAMETER;
  2534. }
  2535. UnlockDeviceInfoSet(pDeviceInfoSet);
  2536. clean1:
  2537. if (Err == NO_ERROR) {
  2538. //
  2539. // give a +ve affirmation of unremove
  2540. //
  2541. WriteLogEntry(
  2542. LogContext,
  2543. DRIVER_LOG_INFO,
  2544. MSG_LOG_UNREMOVED,
  2545. NULL);
  2546. } else {
  2547. //
  2548. // indicate unremove failed, display error
  2549. //
  2550. WriteLogEntry(
  2551. LogContext,
  2552. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  2553. MSG_LOG_UNREMOVE_ERROR,
  2554. NULL);
  2555. WriteLogError(
  2556. LogContext,
  2557. DRIVER_LOG_ERROR,
  2558. Err);
  2559. }
  2560. SetLastError(Err);
  2561. return(Err == NO_ERROR);
  2562. }
  2563. BOOL
  2564. WINAPI
  2565. SetupDiMoveDuplicateDevice(
  2566. IN HDEVINFO DeviceInfoSet,
  2567. IN PSP_DEVINFO_DATA DestinationDeviceInfoData
  2568. )
  2569. /*++
  2570. Routine Description:
  2571. Default handler for DIF_MOVEDEVICE. This routine (and DIF code) has been
  2572. deprecated.
  2573. Arguments:
  2574. DeviceInfoSet - Supplied a handle to the device information set for which
  2575. a device was to be moved.
  2576. DestinationDeviceInfoData - Supplied the address of a SP_DEVINFO_DATA
  2577. structure for the device instance that was the destination of the move.
  2578. Return Value:
  2579. This function always returns FALSE, with GetLastError returning
  2580. ERROR_DI_FUNCTION_OBSOLETE.
  2581. --*/
  2582. {
  2583. UNREFERENCED_PARAMETER(DeviceInfoSet);
  2584. UNREFERENCED_PARAMETER(DestinationDeviceInfoData);
  2585. SetLastError(ERROR_DI_FUNCTION_OBSOLETE);
  2586. return FALSE;
  2587. }
  2588. BOOL
  2589. WINAPI
  2590. SetupDiChangeState(
  2591. IN HDEVINFO DeviceInfoSet,
  2592. IN OUT PSP_DEVINFO_DATA DeviceInfoData
  2593. )
  2594. /*++
  2595. Routine Description:
  2596. Default handler for DIF_PROPERTYCHANGE
  2597. This routine is used to change the state of an installed device.
  2598. Arguments:
  2599. DeviceInfoSet - Supplies a handle to the device information set for which a
  2600. device's state is to be changed.
  2601. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure identifying
  2602. the device whose state is to be changed. This is an IN OUT parameter, since
  2603. the DevInst field of the structure may be updated with a new handle value upon
  2604. return.
  2605. Return Value:
  2606. If the function succeeds, and there are files to be copied, the return value is TRUE.
  2607. If the function fails, the return value is FALSE, and GetLastError returns the cause
  2608. of failure.
  2609. --*/
  2610. {
  2611. PDEVICE_INFO_SET pDeviceInfoSet;
  2612. DWORD Err;
  2613. PDEVINFO_ELEM DevInfoElem;
  2614. PDEVINSTALL_PARAM_BLOCK dipb = NULL;
  2615. DWORD dwConfigFlags;
  2616. HKEY hk;
  2617. DEVINST dnToReenum;
  2618. DWORD dwStateChange = 0;
  2619. DWORD dwFlags = 0;
  2620. ULONG lParam = 0;
  2621. TCHAR szDevID[MAX_DEVICE_ID_LEN];
  2622. DWORD dwHWProfFlags;
  2623. HWPROFILEINFO HwProfileInfo;
  2624. CONFIGRET cr;
  2625. DWORD slot_deviceID = 0;
  2626. DWORD action = MSG_LOG_PROPERTYCHANGE_ERROR;
  2627. DWORD actionerr = MSG_LOG_PROPERTYCHANGE_ERROR;
  2628. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  2629. SetLastError(ERROR_INVALID_HANDLE);
  2630. return FALSE;
  2631. }
  2632. Err = NO_ERROR;
  2633. try {
  2634. //
  2635. // Locate the devinfo element whose state is to be changed.
  2636. //
  2637. if(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  2638. DeviceInfoData,
  2639. NULL)) {
  2640. dipb = &(DevInfoElem->InstallParamBlock);
  2641. } else {
  2642. Err = ERROR_INVALID_PARAMETER;
  2643. goto clean0;
  2644. }
  2645. if((cr = CM_Get_Device_ID_Ex(DevInfoElem->DevInst,
  2646. szDevID,
  2647. SIZECHARS(szDevID),
  2648. 0,
  2649. pDeviceInfoSet->hMachine)) != CR_SUCCESS) {
  2650. //
  2651. // this should never fail
  2652. //
  2653. MYASSERT(!CR_SUCCESS);
  2654. Err = ERROR_INVALID_PARAMETER;
  2655. goto clean0;
  2656. }
  2657. slot_deviceID = AllocLogInfoSlotOrLevel(dipb->LogContext,DRIVER_LOG_INFO,FALSE);
  2658. if(slot_deviceID) {
  2659. WriteLogEntry(
  2660. dipb->LogContext,
  2661. slot_deviceID,
  2662. MSG_LOG_DO_PROPERTYCHANGE,
  2663. NULL, // text message
  2664. szDevID);
  2665. }
  2666. //
  2667. // This routine can't be called if non-native drivers are involved.
  2668. // (Note: while presently this doesn't matter, it's possible that in
  2669. // the future this operation could involve running one or more INF
  2670. // sections, and I don't want to limit that possibility by introducing
  2671. // the complication of non-native driver nodes.)
  2672. //
  2673. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  2674. Err = ERROR_INVALID_FLAGS;
  2675. goto clean0;
  2676. }
  2677. if(!(dipb->Flags & DI_CLASSINSTALLPARAMS) ||
  2678. (dipb->ClassInstallHeader->InstallFunction != DIF_PROPERTYCHANGE)) {
  2679. //
  2680. // Don't have any class install parameters to tell us what needs to be done!
  2681. //
  2682. Err = ERROR_NO_CLASSINSTALL_PARAMS;
  2683. goto clean0;
  2684. }
  2685. if(!DevInfoElem->DevInst) {
  2686. Err = ERROR_NO_SUCH_DEVINST;
  2687. goto clean0;
  2688. }
  2689. dwStateChange = ((PSP_PROPCHANGE_PARAMS)(dipb->ClassInstallHeader))->StateChange;
  2690. dwFlags = ((PSP_PROPCHANGE_PARAMS)(dipb->ClassInstallHeader))->Scope;
  2691. lParam = ((PSP_PROPCHANGE_PARAMS)(dipb->ClassInstallHeader))->HwProfile;
  2692. //
  2693. // DICS_FLAG_CONFIGGENERAL is allowed below and is ignored
  2694. // people are relying on this broken behaviour
  2695. //
  2696. switch(dwStateChange) {
  2697. case DICS_ENABLE:
  2698. if(dwFlags == DICS_FLAG_GLOBAL) {
  2699. action = MSG_LOG_PROPERTYCHANGE_ENABLE_GLOBAL;
  2700. actionerr = MSG_LOG_PROPERTYCHANGE_ENABLE_GLOBAL_ERR;
  2701. //
  2702. // Clear the Disabled config flag, and attempt to enumerate the
  2703. // device. Presumably it has a device node, it is just dormant (ie
  2704. // prob 80000001).
  2705. //
  2706. dwConfigFlags = GetDevInstConfigFlags(DevInfoElem->DevInst,
  2707. 0,pDeviceInfoSet->hMachine) & ~CONFIGFLAG_DISABLED;
  2708. //
  2709. // Set the New config flags value
  2710. //
  2711. CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  2712. CM_DRP_CONFIGFLAGS,
  2713. &dwConfigFlags,
  2714. sizeof(dwConfigFlags),
  2715. 0,
  2716. pDeviceInfoSet->hMachine);
  2717. if(!(dipb->Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) {
  2718. if(CM_Enable_DevNode_Ex(DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2719. //
  2720. // Find the parent of this devnode and reenumerate it to bring this devnode online.
  2721. //
  2722. if (CM_Get_Parent_Ex(&dnToReenum, DevInfoElem->DevInst, 0, pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2723. //
  2724. // Process this devnode now.
  2725. //
  2726. CM_Reenumerate_DevNode_Ex(dnToReenum, CM_REENUMERATE_SYNCHRONOUS,pDeviceInfoSet->hMachine);
  2727. }
  2728. //
  2729. // See if we sucessfully started dynamically.
  2730. //
  2731. CheckIfDevStarted(DevInfoElem, pDeviceInfoSet);
  2732. } else {
  2733. //
  2734. // We could not enable so we should restart
  2735. //
  2736. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2737. MSG_LOG_REBOOT_REASON_ENABLE_FAILED);
  2738. }
  2739. }
  2740. } else {
  2741. action = MSG_LOG_PROPERTYCHANGE_ENABLE_PROFILE;
  2742. actionerr = MSG_LOG_PROPERTYCHANGE_ENABLE_PROFILE_ERR;
  2743. //
  2744. // Get the hardware profile-specific flags
  2745. //
  2746. if(CM_Get_HW_Prof_Flags_Ex(szDevID, lParam, &dwHWProfFlags, 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2747. //
  2748. // Clear the Disabled bit.
  2749. //
  2750. dwHWProfFlags &= ~CSCONFIGFLAG_DISABLED;
  2751. } else {
  2752. dwHWProfFlags = 0;
  2753. }
  2754. //
  2755. // Set the profile Flags for this device to Enabled. Setting the flags will
  2756. // also bring the devnode on-line, if we're modifying the current hardware
  2757. // profile.
  2758. //
  2759. cr = CM_Set_HW_Prof_Flags_Ex(szDevID, lParam, dwHWProfFlags, 0, pDeviceInfoSet->hMachine);
  2760. if(cr == CR_NEED_RESTART) {
  2761. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2762. MSG_LOG_REBOOT_REASON_HW_PROF_ENABLE_FAILED);
  2763. } else if(cr != CR_SUCCESS) {
  2764. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2765. goto clean0;
  2766. }
  2767. }
  2768. break;
  2769. case DICS_DISABLE:
  2770. if(dwFlags == DICS_FLAG_GLOBAL) {
  2771. BOOL disabled = FALSE;
  2772. action = MSG_LOG_PROPERTYCHANGE_DISABLE_GLOBAL;
  2773. actionerr = MSG_LOG_PROPERTYCHANGE_DISABLE_GLOBAL_ERR;
  2774. //
  2775. // we try to dynamically disable a device
  2776. // if it fails with anything but CR_NOT_DISABLEABLE
  2777. // then we set flag to try to disable it on reboot
  2778. //
  2779. if(!(dipb->Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) {
  2780. cr = CM_Disable_DevNode_Ex(DevInfoElem->DevInst,
  2781. CM_DISABLE_POLITE | CM_DISABLE_UI_NOT_OK,
  2782. pDeviceInfoSet->hMachine
  2783. );
  2784. if (cr == CR_SUCCESS) {
  2785. //
  2786. // we managed to disable it immediately
  2787. //
  2788. disabled = TRUE;
  2789. } else if (cr == CR_NOT_DISABLEABLE) {
  2790. //
  2791. // we couldn't and shouldn't try to disable it
  2792. //
  2793. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2794. goto clean0;
  2795. } else {
  2796. //
  2797. // set flag to indicate a reboot is required to disable this
  2798. //
  2799. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2800. MSG_LOG_REBOOT_REASON_DISABLE_FAILED);
  2801. }
  2802. }
  2803. //
  2804. // Note: There is a case where reboot-disabled device becomes non-disableable
  2805. // nothing we can do about this!
  2806. //
  2807. // Try and set the Disabled config flag if not already set, even if we managed to disable it
  2808. //
  2809. dwConfigFlags = GetDevInstConfigFlags(DevInfoElem->DevInst,
  2810. 0,pDeviceInfoSet->hMachine);
  2811. if ((dwConfigFlags & CONFIGFLAG_DISABLED) == 0) {
  2812. dwConfigFlags |= CONFIGFLAG_DISABLED;
  2813. //
  2814. // Set the New config flags value
  2815. //
  2816. cr = CM_Set_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  2817. CM_DRP_CONFIGFLAGS,
  2818. &dwConfigFlags,
  2819. sizeof(dwConfigFlags),
  2820. 0,
  2821. pDeviceInfoSet->hMachine);
  2822. if (cr != CR_SUCCESS) {
  2823. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2824. goto clean0;
  2825. }
  2826. }
  2827. if (disabled) {
  2828. //
  2829. // We don't want DICS_DISABLE to increment the disable
  2830. // ref count, so if we disabled the device then we
  2831. // always want to enable it. Note, however, that if we
  2832. // were successful in setting the CONFIGFLAG_DISABLED
  2833. // then the device won't come back when we enable it.
  2834. //
  2835. CM_Enable_DevNode_Ex(DevInfoElem->DevInst,
  2836. 0,
  2837. pDeviceInfoSet->hMachine);
  2838. }
  2839. } else {
  2840. action = MSG_LOG_PROPERTYCHANGE_DISABLE_PROFILE;
  2841. actionerr = MSG_LOG_PROPERTYCHANGE_DISABLE_PROFILE_ERR;
  2842. //
  2843. // Get the hardware profile-specific flags
  2844. //
  2845. if(CM_Get_HW_Prof_Flags_Ex(szDevID, lParam,
  2846. &dwHWProfFlags, 0,pDeviceInfoSet->hMachine) != CR_SUCCESS) {
  2847. dwHWProfFlags = 0;
  2848. }
  2849. //
  2850. // Set the Disabled bit.
  2851. //
  2852. dwHWProfFlags |= CSCONFIGFLAG_DISABLED;
  2853. //
  2854. // Set the profile Flags for this device to Disabled. Setting this
  2855. // flag will also take this device off-line, if we're modifying the
  2856. // current hardware profile.
  2857. //
  2858. cr = CM_Set_HW_Prof_Flags_Ex(szDevID,
  2859. lParam,
  2860. dwHWProfFlags,
  2861. CM_SET_HW_PROF_FLAGS_UI_NOT_OK,
  2862. pDeviceInfoSet->hMachine
  2863. );
  2864. if(cr == CR_NEED_RESTART) {
  2865. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2866. MSG_LOG_REBOOT_REASON_HW_PROF_DISABLE_FAILED);
  2867. } else if(cr != CR_SUCCESS) {
  2868. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2869. goto clean0;
  2870. }
  2871. }
  2872. break;
  2873. case DICS_PROPCHANGE:
  2874. //
  2875. // Properties have changed, so we need to remove the Devnode, and
  2876. // re-enumerate its parent.
  2877. //
  2878. // Don't remove/reenumerate if reboot/restart is required, or if DI_DONOTCALLCONFIGMG
  2879. // is set (the device may implement some form of 'non-stop' property change mechanism).
  2880. //
  2881. if(dipb->Flags & (DI_DONOTCALLCONFIGMG | DI_NEEDREBOOT | DI_NEEDRESTART)) {
  2882. action = MSG_LOG_PROPERTYCHANGE_NORESTART;
  2883. } else {
  2884. TCHAR VetoName[MAX_PATH];
  2885. PNP_VETO_TYPE VetoType;
  2886. action = MSG_LOG_PROPERTYCHANGE_RESTART;
  2887. actionerr = MSG_LOG_PROPERTYCHANGE_RESTART_ERR;
  2888. CM_Get_Parent_Ex(&dnToReenum, DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine);
  2889. cr = CM_Query_And_Remove_SubTree_Ex(DevInfoElem->DevInst,
  2890. &VetoType,
  2891. VetoName,
  2892. SIZECHARS(VetoName),
  2893. (DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NOUIONQUERYREMOVE)
  2894. ? CM_REMOVE_UI_NOT_OK
  2895. : CM_REMOVE_UI_OK,
  2896. pDeviceInfoSet->hMachine
  2897. );
  2898. if(cr == CR_SUCCESS) {
  2899. CM_Reenumerate_DevInst_Ex(dnToReenum, CM_REENUMERATE_SYNCHRONOUS,pDeviceInfoSet->hMachine);
  2900. DevInfoElem->DevInst = 0;
  2901. if(CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  2902. (DEVINSTID)szDevID,
  2903. CM_LOCATE_DEVINST_NORMAL,
  2904. pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2905. //
  2906. // Make sure the device instance started OK
  2907. //
  2908. if(!CheckIfDevStarted(DevInfoElem,pDeviceInfoSet)) {
  2909. action = MSG_LOG_PROPERTYCHANGE_RESTART_FAILED;
  2910. }
  2911. } else {
  2912. //
  2913. // We couldn't locate the devnode. We don't need
  2914. // to request a reboot, because if the devnode ever
  2915. // shows up again, we should be able to bring it
  2916. // back on-line just fine.
  2917. //
  2918. // Retrieve the devnode as a phantom
  2919. //
  2920. CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  2921. (DEVINSTID)szDevID,
  2922. CM_LOCATE_DEVINST_PHANTOM,
  2923. pDeviceInfoSet->hMachine
  2924. );
  2925. DevInfoElem->DiElemFlags |= DIE_IS_PHANTOM;
  2926. }
  2927. //
  2928. // Update the caller's buffer to reflect the new device instance handle
  2929. //
  2930. DeviceInfoData->DevInst = DevInfoElem->DevInst;
  2931. } else {
  2932. //
  2933. // If the failure was due to a veto, then log
  2934. // information about who vetoed us.
  2935. //
  2936. // SPLOG--write a log entry
  2937. //
  2938. if(cr == CR_REMOVE_VETOED) {
  2939. //
  2940. // get the LogContext from dipb which should be a pointer
  2941. // to the appropriate DevInstallParamBlock
  2942. //
  2943. _WriteVetoLogEntry(
  2944. dipb->LogContext,
  2945. DRIVER_LOG_WARNING,
  2946. MSG_LOG_REMOVE_VETOED_IN_PROPCHANGE,
  2947. szDevID,
  2948. VetoName,
  2949. VetoType);
  2950. }
  2951. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2952. MSG_LOG_REBOOT_VETOED_IN_PROPCHANGE);
  2953. action = MSG_LOG_PROPERTYCHANGE_RESTART_FAILED;
  2954. }
  2955. }
  2956. break;
  2957. case DICS_START:
  2958. action = MSG_LOG_PROPERTYCHANGE_START;
  2959. actionerr = MSG_LOG_PROPERTYCHANGE_START_ERR;
  2960. //
  2961. // DICS_START is always config specific (we enforce this in SetupDiSetClassInstallParams).
  2962. //
  2963. MYASSERT(dwFlags == DICS_FLAG_CONFIGSPECIFIC);
  2964. //
  2965. // Get the Profile Flags.
  2966. //
  2967. if(CM_Get_HW_Prof_Flags_Ex(szDevID, lParam, &dwHWProfFlags, 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  2968. //
  2969. // Clear the "don't start" bit.
  2970. //
  2971. dwHWProfFlags &= ~CSCONFIGFLAG_DO_NOT_START;
  2972. } else {
  2973. dwHWProfFlags = 0;
  2974. }
  2975. cr = CM_Set_HW_Prof_Flags_Ex(szDevID, lParam, dwHWProfFlags, 0, pDeviceInfoSet->hMachine);
  2976. if(cr == CR_NEED_RESTART) {
  2977. //
  2978. // Since setting/clearing the CSCONFIGFLAG_DO_NOT_START doesn't
  2979. // automatically effect a change, we should never get here.
  2980. //
  2981. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  2982. MSG_LOG_REBOOT_REASON_CLEAR_CSCONFIGFLAG_DO_NOT_START);
  2983. action = MSG_LOG_PROPERTYCHANGE_START_FAILED;
  2984. } else if(cr != CR_SUCCESS) {
  2985. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  2986. goto clean0;
  2987. }
  2988. //
  2989. // Start the device instance if this is for the current config (ie dwConfigID/lparam == 0)
  2990. //
  2991. if((lParam == 0) ||
  2992. ((CM_Get_Hardware_Profile_Info_Ex((ULONG)-1, &HwProfileInfo,
  2993. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  2994. (HwProfileInfo.HWPI_ulHWProfile == lParam)))
  2995. {
  2996. //
  2997. // Try to start the devnode.
  2998. //
  2999. if(!(dipb->Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) {
  3000. CM_Setup_DevNode_Ex(DevInfoElem->DevInst, CM_SETUP_DEVNODE_READY,pDeviceInfoSet->hMachine);
  3001. if(!CheckIfDevStarted(DevInfoElem, pDeviceInfoSet)) {
  3002. action = MSG_LOG_PROPERTYCHANGE_START_FAILED;
  3003. }
  3004. } else {
  3005. action = MSG_LOG_PROPERTYCHANGE_START_FAILED;
  3006. }
  3007. }
  3008. break;
  3009. case DICS_STOP:
  3010. action = MSG_LOG_PROPERTYCHANGE_STOP;
  3011. actionerr = MSG_LOG_PROPERTYCHANGE_STOP_ERR;
  3012. //
  3013. // DICS_STOP is always config specific (we enforce this in SetupDiSetClassInstallParams).
  3014. //
  3015. MYASSERT(dwFlags == DICS_FLAG_CONFIGSPECIFIC);
  3016. //
  3017. // Get the Profile Flags.
  3018. //
  3019. if(CM_Get_HW_Prof_Flags_Ex(szDevID, lParam, &dwHWProfFlags,
  3020. 0,pDeviceInfoSet->hMachine) != CR_SUCCESS) {
  3021. dwHWProfFlags = 0;
  3022. }
  3023. //
  3024. // Set the "don't start" bit.
  3025. //
  3026. dwHWProfFlags |= CSCONFIGFLAG_DO_NOT_START;
  3027. cr = CM_Set_HW_Prof_Flags_Ex(szDevID,
  3028. lParam,
  3029. dwHWProfFlags,
  3030. CM_SET_HW_PROF_FLAGS_UI_NOT_OK,
  3031. pDeviceInfoSet->hMachine
  3032. );
  3033. if(cr == CR_NEED_RESTART) {
  3034. //
  3035. // Since setting/clearing the CSCONFIGFLAG_DO_NOT_START doesn't
  3036. // automatically effect a change, we should never get here.
  3037. //
  3038. SetDevnodeNeedsRebootProblem(DevInfoElem,pDeviceInfoSet,
  3039. MSG_LOG_REBOOT_REASON_SET_CSCONFIGFLAG_DO_NOT_START);
  3040. action = MSG_LOG_PROPERTYCHANGE_STOP_FAILED;
  3041. } else if(cr != CR_SUCCESS) {
  3042. Err = MapCrToSpError(cr, ERROR_INVALID_DATA);
  3043. goto clean0;
  3044. }
  3045. //
  3046. // Stop the device instance if this is for the current config (ie dwConfigID/lparam == 0)
  3047. //
  3048. if((lParam == 0) ||
  3049. ((CM_Get_Hardware_Profile_Info_Ex((ULONG)-1, &HwProfileInfo,
  3050. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  3051. (HwProfileInfo.HWPI_ulHWProfile == lParam)))
  3052. {
  3053. //
  3054. // Try to stop the devnode.
  3055. //
  3056. if(!(dipb->Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))) {
  3057. TCHAR VetoName[MAX_PATH];
  3058. PNP_VETO_TYPE VetoType;
  3059. //
  3060. // Remove the device instance in order to stop the device.
  3061. //
  3062. cr = CM_Query_And_Remove_SubTree_Ex(DevInfoElem->DevInst,
  3063. &VetoType,
  3064. VetoName,
  3065. SIZECHARS(VetoName),
  3066. (DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NOUIONQUERYREMOVE)
  3067. ? CM_REMOVE_UI_NOT_OK
  3068. : CM_REMOVE_UI_OK,
  3069. pDeviceInfoSet->hMachine
  3070. );
  3071. if(cr == CR_SUCCESS) {
  3072. //
  3073. // Device instance successfully removed--now locate it as a phantom.
  3074. //
  3075. CM_Locate_DevInst_Ex(&(DevInfoElem->DevInst),
  3076. (DEVINSTID)szDevID,
  3077. CM_LOCATE_DEVINST_PHANTOM,
  3078. pDeviceInfoSet->hMachine);
  3079. DevInfoElem->DiElemFlags |= DIE_IS_PHANTOM;
  3080. //
  3081. // Update the caller's buffer to reflect the new device instance handle.
  3082. //
  3083. DeviceInfoData->DevInst = DevInfoElem->DevInst;
  3084. } else {
  3085. //
  3086. // If the failure was due to a veto, then log
  3087. // information about who vetoed us.
  3088. //
  3089. // SPLOG--write out a real log entry
  3090. //
  3091. if(cr == CR_REMOVE_VETOED) {
  3092. //
  3093. // get the LogContext from dipb which should be a pointer
  3094. // to the appropriate DevInstallParamBlock
  3095. //
  3096. _WriteVetoLogEntry(
  3097. dipb->LogContext,
  3098. DRIVER_LOG_WARNING,
  3099. MSG_LOG_REMOVE_VETOED_IN_STOP,
  3100. szDevID,
  3101. VetoName,
  3102. VetoType);
  3103. }
  3104. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,
  3105. pDeviceInfoSet,
  3106. MSG_LOG_REBOOT_QR_VETOED_IN_STOP,
  3107. cr,
  3108. (ULONG_PTR)_MapCmRetToString(cr)
  3109. );
  3110. }
  3111. } else {
  3112. action = MSG_LOG_PROPERTYCHANGE_STOP_FAILED;
  3113. }
  3114. }
  3115. break;
  3116. default:
  3117. action = actionerr = MSG_LOG_PROPERTYCHANGE_UNKNOWN;
  3118. Err = ERROR_DI_DO_DEFAULT;
  3119. }
  3120. clean0: ; // nothing to do.
  3121. } except(EXCEPTION_EXECUTE_HANDLER) {
  3122. Err = ERROR_INVALID_PARAMETER;
  3123. }
  3124. if(slot_deviceID) {
  3125. if ((Err == NO_ERROR) || (Err == ERROR_DI_DO_DEFAULT)) {
  3126. //
  3127. // give a +ve affirmation of property change
  3128. //
  3129. WriteLogEntry(
  3130. dipb->LogContext,
  3131. Err ? DRIVER_LOG_ERROR : DRIVER_LOG_INFO,
  3132. action,
  3133. NULL,
  3134. dwStateChange,
  3135. dwFlags,
  3136. lParam
  3137. );
  3138. } else {
  3139. //
  3140. // indicate property change failed, display error
  3141. //
  3142. WriteLogEntry(
  3143. dipb->LogContext,
  3144. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  3145. actionerr,
  3146. NULL,
  3147. dwStateChange,
  3148. dwFlags,
  3149. lParam
  3150. );
  3151. WriteLogError(
  3152. dipb->LogContext,
  3153. DRIVER_LOG_ERROR,
  3154. Err);
  3155. }
  3156. ReleaseLogInfoSlot(dipb->LogContext,slot_deviceID);
  3157. }
  3158. UnlockDeviceInfoSet(pDeviceInfoSet);
  3159. SetLastError(Err);
  3160. return(Err == NO_ERROR);
  3161. }
  3162. DWORD
  3163. GetNewInfName(
  3164. IN HWND Owner, OPTIONAL
  3165. IN PCTSTR OemInfName,
  3166. IN PCTSTR OemInfOriginalName,
  3167. IN PCTSTR OemInfCatName, OPTIONAL
  3168. OUT PTSTR NewInfName,
  3169. IN DWORD NewInfNameSize,
  3170. OUT PDWORD RequiredSize,
  3171. OUT PNEWINF_COPYTYPE CopyNeeded,
  3172. IN BOOL ReplaceOnly,
  3173. IN PCTSTR DeviceDesc, OPTIONAL
  3174. IN DWORD DriverSigningPolicy,
  3175. IN DWORD Flags,
  3176. IN PCTSTR AltCatalogFile, OPTIONAL
  3177. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
  3178. OUT PDWORD DriverSigningError, OPTIONAL
  3179. OUT PTSTR CatalogFilenameOnSystem,
  3180. IN PSETUP_LOG_CONTEXT LogContext,
  3181. IN OUT PVERIFY_CONTEXT VerifyContext, OPTIONAL
  3182. OUT HANDLE *hWVTStateData OPTIONAL
  3183. )
  3184. /*++
  3185. Routine Description:
  3186. This routine finds a unique INF name of the form "<systemroot>\Inf\OEM<n>.INF",
  3187. and returns it in the supplied buffer. It leaves an (empty) file of that
  3188. name in the INF directory, so that anyone else who attempts to generate a
  3189. unique filename won't pick the same name.
  3190. NOTE: We will search the INF directory to determine if the specified INF is
  3191. already present there based on the criteria outlined for SetupCopyOEMInf.
  3192. If so, then we will return the existing name. This name may be an
  3193. OEM<n>.INF form, or it may be the same name as the source INF.
  3194. Arguments:
  3195. Owner - supplies window to own any signature verification problem dialogs
  3196. that must be displayed.
  3197. OemInfName - Supplies the full pathname of the OEM INF that needs to be
  3198. copied into the Inf directory (under a unique name).
  3199. OemInfOriginalName - Supplies the original (simple) filename of the INF, to
  3200. be used for digital signature verification (i.e., the INF is only known
  3201. to the catalog under its original name).
  3202. OemInfCatName - Optionally, supplies the simple filename of the catalog file
  3203. specified by the OEM INF via a CatalogFile= entry in its [Version]
  3204. section.
  3205. NewInfName - supplies the address of a character buffer to store the unique
  3206. name in.
  3207. NewInfNameSize - Specifies the size, in characters, of the NewInfName buffer.
  3208. RequiredSize - supplies the address of a variable that receives the size, in
  3209. characters, required to store the full new filename.
  3210. CopyNeeded - Supplies the address of an enum variable that is set upon
  3211. successful return to indicate whether or not the OEM INF actually needs
  3212. to be copied (and whether or not the previously-existing INF, if found,
  3213. is zero-length. This variable will be set to one of the following
  3214. values:
  3215. NewInfCopyNo - no need to copy--INF already present in destination
  3216. NewInfCopyYes, - new INF placeholder created--need to copy real INF
  3217. NewInfCopyZeroLength - previously-existing zero-length INF match found
  3218. ReplaceOnly - If this flag is set, then this routine will fail if it doesn't
  3219. find that the INF/CAT is already installed.
  3220. DeviceDesc - Optionally, supplies the device description to be used in the
  3221. digital signature verification error dialogs that may be popped up.
  3222. DriverSigningPolicy - supplies the driver signing policy currently in
  3223. effect. Used when determining whether we can validate via an
  3224. Authenticode catalog, and to control behavior of
  3225. _HandleFailedVerification, if necessary.
  3226. Flags - supplies flags which alter the behavior of the routine. May be a
  3227. combination of the following values:
  3228. SCOI_NO_UI_ON_SIGFAIL - indicates whether user should be prompted (per
  3229. DriverSigningPolicy) if a digital signature
  3230. failure is encountered. Used when calling
  3231. _HandleFailedVerification, if necessary.
  3232. SCOI_NO_ERRLOG_ON_MISSING_CATALOG - if there's a signature verification
  3233. failure due to the INF lacking a
  3234. CatalogFile= entry, then that error
  3235. will be ignored if this flag is set
  3236. (no UI will be given, and no log
  3237. entry will be generated).
  3238. SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES - Install the INF and CAT under
  3239. their original (current) names
  3240. (i.e., don't generate a unique
  3241. oem<n>.inf/cat name). Used only
  3242. for exception INFs.
  3243. SCOI_ABORT_IF_UNSIGNED - If the INF is unsigned (and user wants to copy
  3244. it anyway, or policy is Ignore), then _don't_
  3245. copy the INF and instead return the error
  3246. ERROR_SET_SYSTEM_RESTORE_POINT. This gives
  3247. the caller a chance to set a system restore
  3248. point prior to installing the unsigned package.
  3249. SCOI_TRY_UPDATE_PNF - If an existing PNF cannot be updated, don't
  3250. consider it fatal.
  3251. AltCatalogFile - Optionally, supplies the full pathname of a catalog file to
  3252. be installed and used for verification of the INF in cases where the INF
  3253. doesn't specify a CatalogFile= entry (i.e., when the OemInfCatName
  3254. parameter is not specified.
  3255. If this parameter is specified (and OemInfCatName isn't specified), then
  3256. this catalog will be used to validate the INF, and if successful, the
  3257. catalog will be installed into the system using its current name (thus
  3258. overwriting any existing catalog having that name). Nothing more will
  3259. be done with the INF--we won't even create a zero-length placeholder for
  3260. it in this case.
  3261. AltPlatformInfo - Optionally, supplies alternate platform information to be
  3262. used in digital signature verification instead of the default (native)
  3263. platform info.
  3264. DriverSigningError - Optionally, supplies the address of a variable that
  3265. receives the error encountered when attempting to verify the digital
  3266. signature of either the INF or associated catalog. If no digital
  3267. signature problems were encountered, this is set to NO_ERROR. (Note
  3268. that this value can come back as NO_ERROR, yet GetNewInfName still
  3269. failed for some other reason).
  3270. CatalogFilenameOnSystem - receives the fully-qualified path of the catalog
  3271. file within the catalog store where this INF's catalog file was
  3272. installed to. This buffer should be at least MAX_PATH bytes (ANSI
  3273. version) or chars (Unicode version).
  3274. LogContext - supplies a LogContext to be used throughout the function.
  3275. VerifyContext - optionally, supplies the address of a structure that caches
  3276. various verification context handles. These handles may be NULL (if
  3277. not previously acquired, and they may be filled in upon return (in
  3278. either success or failure) if they were acquired during the processing
  3279. of this verification request. It is the caller's responsibility to
  3280. free these various context handles when they are no longer needed by
  3281. calling pSetupFreeVerifyContextMembers.
  3282. hWVTStateData - if supplied, this parameter points to a buffer that
  3283. receives a handle to WinVerifyTrust state data. This handle will be
  3284. returned only when validation was successfully performed using
  3285. Authenticode policy. This handle may be used, for example, to retrieve
  3286. signer info when prompting the user about whether they trust the
  3287. publisher. (The status code returned will indicate whether or not this
  3288. is necessary, see "Return Value" section below.)
  3289. This parameter *must* be supplied if the DRIVERSIGN_ALLOW_AUTHENTICODE
  3290. bit is set in the caller-specified DriverSigningPolicy. If the
  3291. routine fails, then this handle will be set to NULL.
  3292. It is the caller's responsibility to close this handle when they're
  3293. finished with it by calling pSetupCloseWVTStateData().
  3294. Return Value:
  3295. If the routine is successful, and the INF was successfully validated via
  3296. driver signing policy, then the return value is NO_ERROR.
  3297. If the routine is successful, the INF was successfully validated via
  3298. Authenticode policy, and the publisher was in the TrustedPublisher store,
  3299. then the return value is ERROR_AUTHENTICODE_TRUSTED_PUBLISHER.
  3300. If the routine was successful, the INF was successfully validated via
  3301. Authenticode policy, and the publisher was _not_ in the TrustedPublisher
  3302. store (hence we must prompt the user to establish their trust of the
  3303. publisher), then the return value is
  3304. ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED.
  3305. If a failure occurred, the return value is a Win32 error code indicating
  3306. the cause of the failure.
  3307. --*/
  3308. {
  3309. INT i;
  3310. HANDLE h;
  3311. DWORD Err, SavedErr;
  3312. DWORD AuthenticodeErr = NO_ERROR;
  3313. DWORD CpyErr;
  3314. TCHAR szNewName[MAX_PATH];
  3315. WIN32_FIND_DATA FindData;
  3316. HANDLE FindHandle;
  3317. PTSTR FilenamePart;
  3318. PTSTR FilenamePartCatFile;
  3319. DWORD OemInfFileSize, CatalogFileSize;
  3320. HANDLE OemInfFileHandle, OemInfMappingHandle;
  3321. HANDLE CatalogFileHandle, CatalogMappingHandle;
  3322. PVOID OemInfBaseAddress, CatalogBaseAddress;
  3323. DWORD CurInfFileSize;
  3324. HANDLE CurInfFileHandle, CurInfMappingHandle;
  3325. PVOID CurInfBaseAddress;
  3326. BOOL FileOfSameNameExists, MoreInfsToCheck;
  3327. WIN32_FILE_ATTRIBUTE_DATA FileAttribData;
  3328. BOOL FoundMatchingInf;
  3329. TCHAR PathBuffer[MAX_PATH];
  3330. TCHAR CatalogName[MAX_PATH];
  3331. SetupapiVerifyProblem Problem = SetupapiVerifyNoProblem;
  3332. PCTSTR ProblemFile;
  3333. DWORD NumCatalogsConsidered;
  3334. PTSTR LastResortInf;
  3335. BOOL FileNewlyCreated;
  3336. //
  3337. // Initially, assume that the specified INF isn't already present in the
  3338. // Inf directory.
  3339. //
  3340. *CopyNeeded = NewInfCopyYes;
  3341. //
  3342. // Initialize the driver signing error output parameter to success, and set
  3343. // the CatalogFilenameOnSystem character buffer to an empty string.
  3344. //
  3345. if(DriverSigningError) {
  3346. *DriverSigningError = NO_ERROR;
  3347. }
  3348. *CatalogFilenameOnSystem = TEXT('\0');
  3349. //
  3350. // This output parameter would get initialized if we ended up calling
  3351. // _VerifyFile, but we might not do that, so make sure it starts out as
  3352. // NULL (i.e., no user prompting for Authenticode publisher trust
  3353. // verification necessary)
  3354. //
  3355. if(hWVTStateData) {
  3356. *hWVTStateData = NULL;
  3357. }
  3358. //
  3359. // If the caller requested that we allow for verification via Authenticode
  3360. // policy, then they must also supply us with an output buffer in which to
  3361. // store the resultant handle for the WinVerifyTrust state data.
  3362. //
  3363. MYASSERT(!(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE) || hWVTStateData);
  3364. if(OemInfCatName || !AltCatalogFile) {
  3365. //
  3366. // The INF has a CatalogFile= entry, or we don't have an override. This
  3367. // means we want to do the 'normal' behavior of looking for an existing
  3368. // match in the INF directory, using default rules for which catalog
  3369. // files we'll consider during validation, etc.
  3370. //
  3371. // Examine all the existing OEM INFs in the Inf directory, to see if
  3372. // this INF already exists there. If so, we'll just return the name of
  3373. // the previously-existing file.
  3374. //
  3375. MYVERIFY(SUCCEEDED(StringCchCopy(szNewName,SIZECHARS(szNewName),InfDirectory)));
  3376. pSetupConcatenatePaths(szNewName, pszOemInfWildcard, SIZECHARS(szNewName), NULL);
  3377. //
  3378. // If we're supposed to install the INF and CAT under their original
  3379. // names, then we don't want to look at any of the oem<n>.inf files.
  3380. //
  3381. if(Flags & SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES) {
  3382. FindHandle = INVALID_HANDLE_VALUE;
  3383. //
  3384. // We'd better not have a policy that says it's acceptable to
  3385. // validate via Authenticode!
  3386. //
  3387. MYASSERT(!(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE));
  3388. } else {
  3389. FindHandle = FindFirstFile(szNewName, &FindData);
  3390. }
  3391. //
  3392. // Now reuse our buffer to look for an INF in the Inf directory having
  3393. // the same name as our OEM INF's original name.
  3394. //
  3395. FilenamePart = (PTSTR)pSetupGetFileTitle(szNewName);
  3396. MYVERIFY(SUCCEEDED(StringCchCopy(FilenamePart,
  3397. SIZECHARS(szNewName)-(FilenamePart-szNewName),
  3398. OemInfOriginalName)));
  3399. FileOfSameNameExists = GetFileAttributesEx(szNewName, GetFileExInfoStandard, &FileAttribData);
  3400. if(FileOfSameNameExists && !OemInfCatName) {
  3401. //
  3402. // We can try to match up an OEM INF with a system INF having the
  3403. // same name even if the INF doesn't specify a CatalogFile= entry,
  3404. // but _not_ if the system INF is zero-length!
  3405. //
  3406. if(!FileAttribData.nFileSizeLow) {
  3407. FileOfSameNameExists = FALSE;
  3408. }
  3409. }
  3410. if((FindHandle != INVALID_HANDLE_VALUE) || FileOfSameNameExists) {
  3411. //
  3412. // We have at least one INF to compare against, so open our source
  3413. // INF in preparation.
  3414. //
  3415. if(pSetupOpenAndMapFileForRead(OemInfName,
  3416. &OemInfFileSize,
  3417. &OemInfFileHandle,
  3418. &OemInfMappingHandle,
  3419. &OemInfBaseAddress) == NO_ERROR) {
  3420. if(OemInfCatName) {
  3421. //
  3422. // INF has an associated catalog--map it into memory for
  3423. // subsequent comparisons with existing installed catalogs.
  3424. //
  3425. MYVERIFY(SUCCEEDED(StringCchCopy(CatalogName,
  3426. SIZECHARS(CatalogName),
  3427. OemInfName)));
  3428. FilenamePartCatFile = (PTSTR)pSetupGetFileTitle(CatalogName);
  3429. MYVERIFY(SUCCEEDED(StringCchCopy(FilenamePartCatFile,
  3430. SIZECHARS(CatalogName)-(FilenamePartCatFile-CatalogName),
  3431. OemInfCatName)));
  3432. if(NO_ERROR != pSetupOpenAndMapFileForRead(
  3433. CatalogName,
  3434. &CatalogFileSize,
  3435. &CatalogFileHandle,
  3436. &CatalogMappingHandle,
  3437. &CatalogBaseAddress)) {
  3438. //
  3439. // Act as if the INF specified no CatalogFile. This
  3440. // will allow us to match up with any OEM<n>.INF that
  3441. // binary-compares with this one. We will consider
  3442. // this a digital signature verification failure,
  3443. // however. (Refer to code below that explicitly fails
  3444. // OEM<n>.INF files that don't have a CatalogFile
  3445. // entry.)
  3446. //
  3447. // Note, also, in this case we don't want to consider
  3448. // a previously-existing INF in the Inf directory that
  3449. // has this OEM INF's original name. That's because
  3450. // this would trip us up later because we'd believe we
  3451. // could do global validation on it (i.e., we'd think
  3452. // it was a system INF).
  3453. //
  3454. CatalogBaseAddress = NULL; // don't try to unmap and close later
  3455. if(FindHandle == INVALID_HANDLE_VALUE) {
  3456. //
  3457. // There are no OEM<n>.INF files to check--go ahead
  3458. // and bail.
  3459. //
  3460. goto FinishedCheckingOemInfs;
  3461. }
  3462. //
  3463. // There are some OEM<n>.INF files to check--make sure
  3464. // we _don't_ consider the originally-named file in
  3465. // %windir%\Inf, if it happens to exist.
  3466. //
  3467. FileOfSameNameExists = FALSE;
  3468. //
  3469. // Now make it look like the INF had no CatalogFile=
  3470. // entry in the first place.
  3471. //
  3472. OemInfCatName = NULL;
  3473. CatalogFileSize = 0;
  3474. }
  3475. } else {
  3476. //
  3477. // INF didn't have a CatalogFile= entry in its version
  3478. // section. This means we'll do global validation if we
  3479. // find an existing INF having this name that binary-compares
  3480. // identical. If the verification succeeds, then we'll consider
  3481. // this a match. Basically, this means you'll be able to
  3482. // re-install from system INFs, even if you point at them
  3483. // elsewhere (e.g., you point back at system.inf on the
  3484. // distribution media, but system.inf is already installed in
  3485. // your %windir%\Inf directory).
  3486. //
  3487. // If our INF doesn't specify a CatalogFile= entry, then
  3488. // we'll drop back to our pre-driver-signing behavior where
  3489. // we'll simply check to see if the INF's binary compare.
  3490. // If they do, then we know that there is no INF installed
  3491. // based on that matching INF's OEM name, thus we'll just
  3492. // drop out of the search loop and consider this a driver
  3493. // signing failure (which it is).
  3494. //
  3495. CatalogBaseAddress = NULL;
  3496. CatalogFileSize = 0;
  3497. }
  3498. LastResortInf = NULL;
  3499. do {
  3500. if(FileOfSameNameExists) {
  3501. if(FileAttribData.nFileSizeHigh) {
  3502. goto CheckNextOemInf;
  3503. }
  3504. if(FileAttribData.nFileSizeLow &&
  3505. (FileAttribData.nFileSizeLow != OemInfFileSize)) {
  3506. goto CheckNextOemInf;
  3507. }
  3508. //
  3509. // Note: We will consider a zero-length system INF
  3510. // that has the same name as our OEM INF, even if our
  3511. // OEM INF doesn't have a CatalogFile= entry in its
  3512. // version section. This allows us to re-use this name
  3513. // as long as we find our catalog is already installed.
  3514. //
  3515. CurInfFileSize = FileAttribData.nFileSizeLow;
  3516. } else {
  3517. if(FindData.nFileSizeHigh) {
  3518. goto CheckNextOemInf;
  3519. }
  3520. if(FindData.nFileSizeLow &&
  3521. (FindData.nFileSizeLow != OemInfFileSize)) {
  3522. goto CheckNextOemInf;
  3523. }
  3524. CurInfFileSize = FindData.nFileSizeLow;
  3525. //
  3526. // Build the fully-qualified path to the INF being
  3527. // compared.
  3528. //
  3529. MYVERIFY(SUCCEEDED(StringCchCopy(FilenamePart,
  3530. SIZECHARS(szNewName)-(FilenamePart-szNewName),
  3531. FindData.cFileName)));
  3532. }
  3533. //
  3534. // If the INF isn't zero-length, then map it into memory to
  3535. // see if it matches our OEM INF.
  3536. //
  3537. if(CurInfFileSize) {
  3538. if(NO_ERROR == pSetupOpenAndMapFileForRead(
  3539. szNewName,
  3540. &CurInfFileSize,
  3541. &CurInfFileHandle,
  3542. &CurInfMappingHandle,
  3543. &CurInfBaseAddress)) {
  3544. //
  3545. // Surround the following in try/except, in case we
  3546. // get an inpage error.
  3547. //
  3548. try {
  3549. //
  3550. // We've found a potential match.
  3551. //
  3552. FoundMatchingInf = !memcmp(OemInfBaseAddress,
  3553. CurInfBaseAddress,
  3554. OemInfFileSize
  3555. );
  3556. } except(EXCEPTION_EXECUTE_HANDLER) {
  3557. FoundMatchingInf = FALSE;
  3558. }
  3559. pSetupUnmapAndCloseFile(CurInfFileHandle,
  3560. CurInfMappingHandle,
  3561. CurInfBaseAddress
  3562. );
  3563. } else {
  3564. FoundMatchingInf = FALSE;
  3565. }
  3566. if(!FoundMatchingInf) {
  3567. goto CheckNextOemInf;
  3568. }
  3569. //
  3570. // If this is an OEM*.INF name and the INF has no
  3571. // CatalogFile= entry, then we've found our match. Set
  3572. // up our driver signing problem variables to indicate
  3573. // that there was an INF failure (since there was no
  3574. // catalog.
  3575. //
  3576. if(!OemInfCatName && !FileOfSameNameExists) {
  3577. *CopyNeeded = NewInfCopyNo;
  3578. Problem = SetupapiVerifyInfProblem;
  3579. ProblemFile = OemInfName;
  3580. Err = ERROR_NO_CATALOG_FOR_OEM_INF;
  3581. //
  3582. // go to end of loop (we'll drop out since we've
  3583. // found a match).
  3584. //
  3585. goto CheckNextOemInf;
  3586. }
  3587. } else {
  3588. //
  3589. // The current INF we're considering for a match is
  3590. // zero-length. This won't work for us if the INF
  3591. // we're searching for doesn't have a CatalogFile=
  3592. // entry, and this isn't an INF having the same name.
  3593. //
  3594. if(!OemInfCatName && !FileOfSameNameExists) {
  3595. goto CheckNextOemInf;
  3596. }
  3597. }
  3598. if(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED) {
  3599. //
  3600. // We aren't using crypto, so if the file we found
  3601. // isn't zero-length, we've found our match.
  3602. //
  3603. if(CurInfFileSize) {
  3604. Err = NO_ERROR;
  3605. } else {
  3606. //
  3607. // File is zero-length. Keep looking.
  3608. //
  3609. goto CheckNextOemInf;
  3610. }
  3611. } else {
  3612. //
  3613. // OK, the files binary compare OK (unless the one
  3614. // we're currently examining is zero length!), but
  3615. // we're not out of the woods yet! If the INF we're
  3616. // examining had a CatalogFile= entry, then generate
  3617. // the catalog name to be used for verification (based
  3618. // on the filename of the INF we're examining).
  3619. //
  3620. if(OemInfCatName) {
  3621. if(MYVERIFY(SUCCEEDED(StringCchCopy(
  3622. CatalogName,
  3623. SIZECHARS(CatalogName),
  3624. FilenamePart)))) {
  3625. PTSTR DotPart;
  3626. DotPart = _tcsrchr(CatalogName, TEXT('.'));
  3627. if(MYVERIFY(DotPart!=NULL)) {
  3628. MYVERIFY(SUCCEEDED(StringCchCopy(
  3629. DotPart,
  3630. SIZECHARS(CatalogName)-(DotPart-CatalogName),
  3631. pszCatSuffix)));
  3632. }
  3633. }
  3634. }
  3635. //
  3636. // Now verify the INF's signature against the specified
  3637. // catalog (or globally if the INF doesn't specify a
  3638. // catalog).
  3639. //
  3640. Err = _VerifyFile(LogContext,
  3641. VerifyContext,
  3642. (OemInfCatName ? CatalogName : NULL),
  3643. CatalogBaseAddress,
  3644. CatalogFileSize,
  3645. OemInfOriginalName,
  3646. OemInfName,
  3647. &Problem,
  3648. PathBuffer,
  3649. FALSE,
  3650. AltPlatformInfo,
  3651. (VERIFY_FILE_IGNORE_SELFSIGNED
  3652. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK),
  3653. CatalogFilenameOnSystem,
  3654. &NumCatalogsConsidered,
  3655. NULL,
  3656. NULL,
  3657. NULL
  3658. );
  3659. if((Err != NO_ERROR) && (Err != ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH) &&
  3660. OemInfCatName &&
  3661. (DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE)) {
  3662. //
  3663. // If we failed to validate via standard OS code-
  3664. // signing policy (for some reason other than an
  3665. // osattibute mismatch), and we're allowed to
  3666. // attempt validation via an Authenticode-signed
  3667. // catalog, then try again.
  3668. //
  3669. MYASSERT(!(*CatalogFilenameOnSystem));
  3670. AuthenticodeErr = _VerifyFile(
  3671. LogContext,
  3672. VerifyContext,
  3673. CatalogName,
  3674. CatalogBaseAddress,
  3675. CatalogFileSize,
  3676. OemInfOriginalName,
  3677. OemInfName,
  3678. &Problem,
  3679. PathBuffer,
  3680. FALSE,
  3681. AltPlatformInfo,
  3682. (VERIFY_FILE_IGNORE_SELFSIGNED
  3683. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK
  3684. | VERIFY_FILE_USE_AUTHENTICODE_CATALOG),
  3685. CatalogFilenameOnSystem,
  3686. &NumCatalogsConsidered,
  3687. NULL,
  3688. NULL,
  3689. hWVTStateData
  3690. );
  3691. if((AuthenticodeErr == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  3692. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  3693. //
  3694. // The catalog validated via Authenticode
  3695. // policy--reset the error (previously
  3696. // received during the failed attempt at
  3697. // validation via driversigning policy).
  3698. //
  3699. Err = NO_ERROR;
  3700. } else {
  3701. //
  3702. // Transfer Authenticode error over to be
  3703. // the "official" failure. We always want
  3704. // the Authenticode error to be NO_ERROR
  3705. // unless it's one of the two "special"
  3706. // values.
  3707. //
  3708. MYASSERT(AuthenticodeErr != NO_ERROR);
  3709. Err = AuthenticodeErr;
  3710. AuthenticodeErr = NO_ERROR;
  3711. }
  3712. }
  3713. }
  3714. if(Err == NO_ERROR) {
  3715. //
  3716. // We've found this INF/CAT combination already
  3717. // installed, and the signatures check out!
  3718. //
  3719. *CopyNeeded = CurInfFileSize ? NewInfCopyNo
  3720. : NewInfCopyZeroLength;
  3721. Problem = SetupapiVerifyNoProblem;
  3722. } else if(CurInfFileSize &&
  3723. (Err == ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH)) {
  3724. //
  3725. // We found this INF/CAT combination already installed,
  3726. // but it's no longer valid. This could happen, for
  3727. // example, if a driver WHQL-signed for a given version
  3728. // of the OS was installed on that version of the OS.
  3729. // Then, the OS was subsequently upgraded, and backward
  3730. // compatibility was not maintained for the device's
  3731. // class. Thus, while the INF and CAT were valid at
  3732. // the time of install, they no longer are valid (even
  3733. // though there's been no tampering with the INF/CAT).
  3734. //
  3735. // We still want to use this INF, but we also want to
  3736. // warn the user that it's not validly signed.
  3737. //
  3738. MYASSERT(Problem == SetupapiVerifyFileProblem);
  3739. MYASSERT(*CatalogFilenameOnSystem);
  3740. ProblemFile = PathBuffer;
  3741. *CopyNeeded = NewInfCopyNo;
  3742. } else {
  3743. //
  3744. // We should never see SetupapiVerifyCatalogProblem
  3745. // reported, since we're validating against a set of
  3746. // catalogs, and a match might be found in several
  3747. // (though, none turn out to successfully validate).
  3748. // It therefore makes no sense to "blame" any
  3749. // particular catalog.
  3750. //
  3751. MYASSERT(Problem != SetupapiVerifyCatalogProblem);
  3752. if((Problem == SetupapiVerifyFileProblem) &&
  3753. !(*CatalogFilenameOnSystem)) {
  3754. //
  3755. // We didn't find a catalog match--move on to the
  3756. // next INF (note: there still might be a match
  3757. // later on, because if the INF specified a
  3758. // CatalogFile= entry, we must match on _both_ the
  3759. // catalog filename _and_ the catalog's image.
  3760. //
  3761. // However, if the number of catalogs we considered
  3762. // when examining this INF/CAT combination was
  3763. // zero, that means that there is no installed
  3764. // catalog for this INF, thus we can use it if we
  3765. // don't find anything better. The reason why we'd
  3766. // rather not use this INF is that it obviously
  3767. // wasn't properly installed, hence the original
  3768. // source name and location info is almost
  3769. // certainly bogus. (One more thing--make sure the
  3770. // catalog isn't zero length. If it is, then that
  3771. // definitely implies that this was being used as a
  3772. // placeholder by setupapi, and we don't want to
  3773. // touch it!)
  3774. //
  3775. if(!NumCatalogsConsidered &&
  3776. !LastResortInf &&
  3777. CurInfFileSize)
  3778. {
  3779. LastResortInf = DuplicateString(szNewName);
  3780. SavedErr = Err;
  3781. }
  3782. goto CheckNextOemInf;
  3783. }
  3784. //
  3785. // We want to fall on through and proceed with
  3786. // examining other INFs for a potential match--this one
  3787. // ain't it!
  3788. //
  3789. }
  3790. CheckNextOemInf:
  3791. if(FileOfSameNameExists) {
  3792. FileOfSameNameExists = FALSE;
  3793. MoreInfsToCheck = (FindHandle != INVALID_HANDLE_VALUE);
  3794. } else {
  3795. MoreInfsToCheck = FindNextFile(FindHandle, &FindData);
  3796. }
  3797. } while((*CopyNeeded == NewInfCopyYes) && MoreInfsToCheck);
  3798. if(LastResortInf) {
  3799. if(*CopyNeeded == NewInfCopyYes) {
  3800. //
  3801. // We didn't find any better INF, so we'll try to use
  3802. // the incorrectly-installed INF.
  3803. //
  3804. // If this INF doesn't specify a CatalogFile= entry,
  3805. // then we'll just automatically set up the digital
  3806. // signature verification failure parameters, because
  3807. // that's the state we're in.
  3808. //
  3809. if(!OemInfCatName) {
  3810. Err = SavedErr;
  3811. Problem = SetupapiVerifyInfProblem;
  3812. MYVERIFY(SUCCEEDED(StringCchCopy(PathBuffer,
  3813. SIZECHARS(PathBuffer),
  3814. OemInfName)));
  3815. ProblemFile = PathBuffer;
  3816. } else {
  3817. //
  3818. // Attempt to verify our OEM INF's catalog, and if
  3819. // it verifies, then install it. We clear the
  3820. // problem set earlier, since we really don't have
  3821. // a problem (yet). If we do encounter a failure
  3822. // below, we'll set the failure as appropriate.
  3823. //
  3824. Problem = SetupapiVerifyNoProblem;
  3825. MYVERIFY(SUCCEEDED(StringCchCopy(CatalogName,
  3826. SIZECHARS(CatalogName),
  3827. OemInfName)));
  3828. *((PTSTR)pSetupGetFileTitle(CatalogName)) = TEXT('\0');
  3829. pSetupConcatenatePaths(CatalogName,
  3830. OemInfCatName,
  3831. SIZECHARS(CatalogName),
  3832. NULL
  3833. );
  3834. Err = _VerifyFile(LogContext,
  3835. VerifyContext,
  3836. CatalogName,
  3837. NULL,
  3838. 0,
  3839. OemInfOriginalName,
  3840. OemInfName,
  3841. &Problem,
  3842. PathBuffer,
  3843. FALSE,
  3844. AltPlatformInfo,
  3845. (VERIFY_FILE_IGNORE_SELFSIGNED
  3846. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK),
  3847. NULL,
  3848. NULL,
  3849. NULL,
  3850. NULL,
  3851. NULL
  3852. );
  3853. if((Err != NO_ERROR) &&
  3854. (Err != ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH) &&
  3855. (DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE)) {
  3856. //
  3857. // If we failed to validate via standard OS
  3858. // code-signing policy (due to some problem
  3859. // other than osattribute mismatch), and we're
  3860. // allowed to attempt validation via an
  3861. // Authenticode signed catalog, then try again.
  3862. //
  3863. AuthenticodeErr = _VerifyFile(
  3864. LogContext,
  3865. VerifyContext,
  3866. CatalogName,
  3867. NULL,
  3868. 0,
  3869. OemInfOriginalName,
  3870. OemInfName,
  3871. &Problem,
  3872. PathBuffer,
  3873. FALSE,
  3874. AltPlatformInfo,
  3875. (VERIFY_FILE_IGNORE_SELFSIGNED
  3876. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK
  3877. | VERIFY_FILE_USE_AUTHENTICODE_CATALOG),
  3878. NULL,
  3879. NULL,
  3880. NULL,
  3881. NULL,
  3882. hWVTStateData
  3883. );
  3884. if((AuthenticodeErr == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  3885. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  3886. //
  3887. // The catalog validated via
  3888. // Authenticode policy--reset the error
  3889. // (previously received during the
  3890. // failed attempt at validation via
  3891. // driversigning policy).
  3892. //
  3893. Err = NO_ERROR;
  3894. } else {
  3895. //
  3896. // Transfer Authenticode error over to
  3897. // be the "official" failure. We
  3898. // always want the Authenticode error
  3899. // to be NO_ERROR unless it's one of
  3900. // the two "special" values.
  3901. //
  3902. MYASSERT(AuthenticodeErr != NO_ERROR);
  3903. Err = AuthenticodeErr;
  3904. AuthenticodeErr = NO_ERROR;
  3905. }
  3906. }
  3907. if(Err != NO_ERROR) {
  3908. if(Problem != SetupapiVerifyCatalogProblem) {
  3909. MYASSERT(Problem != SetupapiVerifyNoProblem);
  3910. //
  3911. // If the problem was not a catalog problem,
  3912. // then it's an INF problem (the _VerifyFile
  3913. // routine doesn't know the file we passed
  3914. // it is an INF).
  3915. //
  3916. Problem = SetupapiVerifyInfProblem;
  3917. }
  3918. ProblemFile = PathBuffer;
  3919. } else {
  3920. //
  3921. // Make sure we aren't remembering any residual
  3922. // intermediate problems...
  3923. //
  3924. Problem = SetupapiVerifyNoProblem;
  3925. //
  3926. // Only attempt to install a catalog if we're
  3927. // not running in "minimal embedded" mode...
  3928. //
  3929. if(!(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED)) {
  3930. //
  3931. // Take the INF's new, unique name and
  3932. // generate a unique catalog filename under
  3933. // setupapi's namespace by simply replacing
  3934. // ".INF" with ".CAT".
  3935. //
  3936. if(MYVERIFY(SUCCEEDED(StringCchCopy(
  3937. PathBuffer,
  3938. SIZECHARS(PathBuffer),
  3939. pSetupGetFileTitle(LastResortInf))))) {
  3940. PTSTR DotPart = _tcsrchr(PathBuffer, TEXT('.'));
  3941. if(MYVERIFY(DotPart != NULL)) {
  3942. MYVERIFY(SUCCEEDED(StringCchCopy(
  3943. DotPart,
  3944. SIZECHARS(PathBuffer)-(DotPart-PathBuffer),
  3945. pszCatSuffix)));
  3946. }
  3947. }
  3948. //
  3949. // At this point, PathBuffer contains the
  3950. // basename to be used for the catalog on
  3951. // the system, and CatalogName is the
  3952. // fully-qualified path of the catalog file
  3953. // in the oem location.
  3954. //
  3955. Err = pSetupInstallCatalog(
  3956. CatalogName,
  3957. PathBuffer,
  3958. CatalogFilenameOnSystem
  3959. );
  3960. if(Err != NO_ERROR) {
  3961. Problem = SetupapiVerifyCatalogProblem;
  3962. ProblemFile = CatalogName;
  3963. }
  3964. }
  3965. }
  3966. }
  3967. MYVERIFY(SUCCEEDED(StringCchCopy(szNewName,
  3968. SIZECHARS(szNewName),
  3969. LastResortInf)));
  3970. //
  3971. // We will never consider a zero-length INF as a last-
  3972. // resort candidate, thus if we get here we know the
  3973. // previously-existing INF wasn't zero-length.
  3974. //
  3975. *CopyNeeded = NewInfCopyNo;
  3976. }
  3977. MyFree(LastResortInf);
  3978. }
  3979. FinishedCheckingOemInfs:
  3980. if(CatalogBaseAddress) {
  3981. pSetupUnmapAndCloseFile(CatalogFileHandle, CatalogMappingHandle, CatalogBaseAddress);
  3982. }
  3983. pSetupUnmapAndCloseFile(OemInfFileHandle, OemInfMappingHandle, OemInfBaseAddress);
  3984. }
  3985. if(FindHandle != INVALID_HANDLE_VALUE) {
  3986. FindClose(FindHandle);
  3987. }
  3988. }
  3989. } else {
  3990. //
  3991. // The INF has no CatalogFile= entry, and we have an alternate catalog
  3992. // to use. Validate our INF using the specified alternate catalog.
  3993. //
  3994. // We don't bother trying to "fall back" to an Authenticode signature,
  3995. // since it's invalid for an INF to validate via an Authenticode
  3996. // catalog unless that INF explicitly references the catalog.
  3997. //
  3998. Err = _VerifyFile(LogContext,
  3999. VerifyContext,
  4000. AltCatalogFile,
  4001. NULL,
  4002. 0,
  4003. OemInfOriginalName,
  4004. OemInfName,
  4005. &Problem,
  4006. PathBuffer,
  4007. FALSE,
  4008. AltPlatformInfo,
  4009. (VERIFY_FILE_IGNORE_SELFSIGNED
  4010. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK),
  4011. NULL,
  4012. NULL,
  4013. NULL,
  4014. NULL,
  4015. NULL
  4016. );
  4017. if(Err != NO_ERROR) {
  4018. if(Problem != SetupapiVerifyCatalogProblem) {
  4019. MYASSERT(Problem != SetupapiVerifyNoProblem);
  4020. //
  4021. // If the problem was not a catalog problem,
  4022. // then it's an INF problem (the _VerifyFile
  4023. // routine doesn't know the file we passed
  4024. // it is an INF).
  4025. //
  4026. Problem = SetupapiVerifyInfProblem;
  4027. }
  4028. ProblemFile = PathBuffer;
  4029. } else {
  4030. //
  4031. // Make sure we aren't remembering any residual intermediate
  4032. // problems...
  4033. //
  4034. Problem = SetupapiVerifyNoProblem;
  4035. //
  4036. // Only attempt to install a catalog if we're not running in
  4037. // "minimal embedded" mode...
  4038. //
  4039. if(!(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED)) {
  4040. Err = pSetupInstallCatalog(
  4041. AltCatalogFile,
  4042. pSetupGetFileTitle(AltCatalogFile),
  4043. CatalogFilenameOnSystem
  4044. );
  4045. if(Err != NO_ERROR) {
  4046. Problem = SetupapiVerifyCatalogProblem;
  4047. ProblemFile = AltCatalogFile;
  4048. }
  4049. }
  4050. }
  4051. //
  4052. // An INF copy is never needed when we're using an alternate catalog.
  4053. //
  4054. *CopyNeeded = NewInfCopyNo;
  4055. //
  4056. // Setup szNewName to be the same as the INF's present full pathname.
  4057. // Since we didn't copy this into the INF directory (or even create a
  4058. // zero-length placeholder), the only reasonable path to return is the
  4059. // INF's current full pathname.
  4060. //
  4061. MYVERIFY(SUCCEEDED(StringCchCopy(szNewName,
  4062. SIZECHARS(szNewName),
  4063. OemInfName)));
  4064. }
  4065. if(*CopyNeeded != NewInfCopyYes) {
  4066. MYASSERT(((Problem == SetupapiVerifyNoProblem) && (Err == NO_ERROR)) ||
  4067. ((Problem != SetupapiVerifyNoProblem) && (Err != NO_ERROR)));
  4068. //
  4069. // Then this INF already exists in the Inf directory (or at least its
  4070. // zero-length placeholder does), and its associated catalog (if it has
  4071. // one) is already installed, too. If either of these files had a
  4072. // signature verification problem (or we need to establish the user's
  4073. // trust of an Authenticode signature publisher), then inform the user
  4074. // now (based on policy).
  4075. //
  4076. if((Problem != SetupapiVerifyNoProblem) ||
  4077. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  4078. BOOL result;
  4079. MYASSERT((Err != NO_ERROR) || (hWVTStateData && *hWVTStateData));
  4080. //
  4081. // If we're here to ask the user whether they trust an Authenticode
  4082. // publisher, then we'd better not have encountered a verification
  4083. // error...
  4084. //
  4085. MYASSERT((AuthenticodeErr != ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED) ||
  4086. (Err == NO_ERROR));
  4087. if(DriverSigningError) {
  4088. *DriverSigningError = Err;
  4089. }
  4090. if(((Err == ERROR_NO_CATALOG_FOR_OEM_INF) && (Flags & SCOI_NO_ERRLOG_ON_MISSING_CATALOG)) ||
  4091. (Flags & SCOI_NO_ERRLOG_IF_INF_ALREADY_PRESENT)) {
  4092. //
  4093. // We shouldn't do any UI/logging because of one of the two
  4094. // following reasons:
  4095. //
  4096. // 1. This may be a valid INF after all (i.e., if it uses
  4097. // layout.inf for source media info, or doesn't copy any
  4098. // files at all).
  4099. //
  4100. // 2. We were asked not to. The public API, SetupCopyOEMInf
  4101. // doesn't want/need anything to happen here, because the
  4102. // INF is already present, and we haven't really done
  4103. // anything (except potentially update the source path
  4104. // information contained in the PNF), thus there's no
  4105. // reason to make noise about this.
  4106. //
  4107. result = TRUE;
  4108. } else {
  4109. result = _HandleFailedVerification(
  4110. Owner,
  4111. ((AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)
  4112. ? SetupapiVerifyCatalogProblem
  4113. : Problem),
  4114. ((AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)
  4115. ? CatalogName
  4116. : ProblemFile),
  4117. DeviceDesc,
  4118. DriverSigningPolicy,
  4119. (Flags & SCOI_NO_UI_ON_SIGFAIL),
  4120. ((Err == NO_ERROR) ? AuthenticodeErr : Err),
  4121. LogContext,
  4122. NULL,
  4123. NULL,
  4124. (hWVTStateData ? *hWVTStateData : NULL)
  4125. );
  4126. if(result) {
  4127. //
  4128. // The user wants to proceed with the unsigned/untrusted
  4129. // installation (or policy is Ignore, so they weren't even
  4130. // informed). If we were able to confirm with the user
  4131. // that they trust the Authenticode publisher, then set our
  4132. // error to indicate this.
  4133. //
  4134. if(AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED) {
  4135. MYASSERT(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE);
  4136. MYASSERT((DriverSigningPolicy & ~DRIVERSIGN_ALLOW_AUTHENTICODE)
  4137. != DRIVERSIGN_BLOCKING);
  4138. if((DriverSigningPolicy & ~DRIVERSIGN_ALLOW_AUTHENTICODE)
  4139. != DRIVERSIGN_NONE) {
  4140. AuthenticodeErr = ERROR_AUTHENTICODE_TRUSTED_PUBLISHER;
  4141. }
  4142. } else {
  4143. //
  4144. // If the caller wants a chance to set a system restore
  4145. // point prior to doing any unsigned installations, then we
  4146. // abort now with a "special" error code that tells them
  4147. // what to do...
  4148. //
  4149. if(Flags & SCOI_ABORT_IF_UNSIGNED) {
  4150. if(hWVTStateData && *hWVTStateData) {
  4151. pSetupCloseWVTStateData(*hWVTStateData);
  4152. *hWVTStateData = NULL;
  4153. }
  4154. return ERROR_SET_SYSTEM_RESTORE_POINT;
  4155. }
  4156. }
  4157. }
  4158. }
  4159. if(!result) {
  4160. if(hWVTStateData && *hWVTStateData) {
  4161. pSetupCloseWVTStateData(*hWVTStateData);
  4162. *hWVTStateData = NULL;
  4163. MYASSERT(Err == NO_ERROR);
  4164. //
  4165. // Need to report some error, since the user indicated they
  4166. // don't want to trust the publisher of this Authenticode-
  4167. // signed package (unless policy was block, in which case
  4168. // they didn't have a choice).
  4169. //
  4170. MYASSERT(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE);
  4171. Err = ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED;
  4172. }
  4173. return Err;
  4174. }
  4175. }
  4176. //
  4177. // There was no problem, or the user elected to install in spite of a
  4178. // problem, so return the INF name we found.
  4179. //
  4180. *RequiredSize = lstrlen(szNewName) + 1;
  4181. if(*RequiredSize < NewInfNameSize) {
  4182. MYVERIFY(SUCCEEDED(StringCchCopy(NewInfName, *RequiredSize, szNewName)));
  4183. //
  4184. // If Authenticode verification was done, then we'll return one of
  4185. // the two errors appropriate to that. Otherwise, we'll return
  4186. // NO_ERROR (that's what we initialized our AuthenticodeErr
  4187. // variable to at the beginning of this routine).
  4188. //
  4189. MYASSERT((AuthenticodeErr == NO_ERROR) ||
  4190. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  4191. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED));
  4192. return AuthenticodeErr;
  4193. } else {
  4194. //
  4195. // So close, yet so far. :-( Free the WinVerifyTrust state data,
  4196. // if any, since the caller won't be expecting it when a failure is
  4197. // encountered due to insufficient buffer.
  4198. //
  4199. if(hWVTStateData && *hWVTStateData) {
  4200. pSetupCloseWVTStateData(*hWVTStateData);
  4201. *hWVTStateData = NULL;
  4202. }
  4203. return ERROR_INSUFFICIENT_BUFFER;
  4204. }
  4205. }
  4206. //
  4207. // If we're in 'replace only' mode, then the fact that we didn't find the
  4208. // INF/CAT already installed above means we should fail with
  4209. // ERROR_FILE_NOT_FOUND.
  4210. //
  4211. if(ReplaceOnly) {
  4212. if(hWVTStateData && *hWVTStateData) {
  4213. pSetupCloseWVTStateData(*hWVTStateData);
  4214. *hWVTStateData = NULL;
  4215. }
  4216. return ERROR_FILE_NOT_FOUND;
  4217. }
  4218. //
  4219. // OK, so the INF isn't presently in the Inf directory--find a unique name
  4220. // for it. (Note: We'll go into the loop below even if we're meant to be
  4221. // installing the INF and CAT under their original names. We'll just skip
  4222. // the auto-generation part, and then we'll break out of the loop once
  4223. // we've made the attempt at INF/CAT installation.)
  4224. //
  4225. for(i = 0; i < 100000; i++) {
  4226. if(Flags & SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES) {
  4227. MYVERIFY(SUCCEEDED(StringCchCopy(szNewName,
  4228. SIZECHARS(szNewName),
  4229. InfDirectory)));
  4230. pSetupConcatenatePaths(szNewName, OemInfOriginalName, SIZECHARS(szNewName), NULL);
  4231. } else {
  4232. MYVERIFY(SUCCEEDED(StringCchPrintf(szNewName,
  4233. SIZECHARS(szNewName),
  4234. pszOemInfGenerate,
  4235. InfDirectory,
  4236. i)));
  4237. }
  4238. Err = GLE_FN_CALL(INVALID_HANDLE_VALUE,
  4239. h = CreateFile(szNewName,
  4240. GENERIC_READ | GENERIC_WRITE,
  4241. FILE_SHARE_READ,
  4242. NULL,
  4243. OPEN_ALWAYS,
  4244. FILE_ATTRIBUTE_NORMAL,
  4245. NULL)
  4246. );
  4247. if(Err == NO_ERROR) {
  4248. //
  4249. // We either opened an existing file (that we need to leave alone,
  4250. // unless we're replacing it with a new exception INF), or we
  4251. // created a new file (in which case, we've found our unique name).
  4252. //
  4253. // CreateFile actually sets last error upon success to indicate if
  4254. // the file was already in existence...
  4255. //
  4256. Err = GetLastError();
  4257. //
  4258. // Before we decide what to do, close the file handle.
  4259. //
  4260. CloseHandle(h);
  4261. FileNewlyCreated = (Err != ERROR_ALREADY_EXISTS);
  4262. if(FileNewlyCreated || (Flags & SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES)) {
  4263. //
  4264. // We've either (a) created a new file, or (b) found that we
  4265. // can replace an existing exception INF. Determine whether
  4266. // the filename fits in the caller-supplied buffer.
  4267. //
  4268. *RequiredSize = lstrlen(szNewName) + 1;
  4269. if(*RequiredSize < NewInfNameSize) {
  4270. //
  4271. // OK, we have a unique filename, and the caller-
  4272. // supplied buffer is large enough to hold that name.
  4273. //
  4274. // get LastKnownGood in on the loop
  4275. // if this is a newly created file, it will get deleted on revert
  4276. //
  4277. pSetupDoLastKnownGoodBackup(NULL,
  4278. szNewName,
  4279. SP_LKG_FLAG_FORCECOPY|SP_LKG_FLAG_DELETEIFNEW|(FileNewlyCreated?SP_LKG_FLAG_DELETEEXISTING:0),
  4280. LogContext);
  4281. //
  4282. // Now we need to verify the INF and its associated CAT.
  4283. //
  4284. if(!OemInfCatName) {
  4285. //
  4286. // An OEM INF without a CatalogFile= entry is
  4287. // automatically a digital signature failure!
  4288. //
  4289. Err = ERROR_NO_CATALOG_FOR_OEM_INF;
  4290. Problem = SetupapiVerifyInfProblem;
  4291. ProblemFile = OemInfName;
  4292. } else {
  4293. //
  4294. // Now verify the catalog file and INF, which must
  4295. // both be in the same directory.
  4296. //
  4297. MYVERIFY(SUCCEEDED(StringCchCopy(CatalogName,
  4298. SIZECHARS(CatalogName),
  4299. OemInfName)));
  4300. *((PTSTR)pSetupGetFileTitle(CatalogName)) = TEXT('\0');
  4301. pSetupConcatenatePaths(CatalogName, OemInfCatName, SIZECHARS(CatalogName), NULL);
  4302. Err = _VerifyFile(LogContext,
  4303. VerifyContext,
  4304. CatalogName,
  4305. NULL,
  4306. 0,
  4307. OemInfOriginalName,
  4308. OemInfName,
  4309. &Problem,
  4310. PathBuffer,
  4311. FALSE,
  4312. AltPlatformInfo,
  4313. (VERIFY_FILE_IGNORE_SELFSIGNED
  4314. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK),
  4315. NULL,
  4316. NULL,
  4317. NULL,
  4318. NULL,
  4319. NULL
  4320. );
  4321. if(Err != NO_ERROR) {
  4322. if(Problem != SetupapiVerifyCatalogProblem) {
  4323. MYASSERT(Problem != SetupapiVerifyNoProblem);
  4324. //
  4325. // If the problem was not a catalog problem,
  4326. // then it's an INF problem (the _VerifyFile
  4327. // routine doesn't know the file we passed
  4328. // it is an INF).
  4329. //
  4330. Problem = SetupapiVerifyInfProblem;
  4331. }
  4332. ProblemFile = PathBuffer;
  4333. if((Err != ERROR_SIGNATURE_OSATTRIBUTE_MISMATCH) &&
  4334. (DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE)) {
  4335. //
  4336. // If we failed to validate via standard OS
  4337. // code-signing policy (due to some reason
  4338. // other than osattribute mismatch), and we're
  4339. // allowed to attempt validation via an
  4340. // Authenticode-signed catalog, then try again.
  4341. //
  4342. AuthenticodeErr = _VerifyFile(
  4343. LogContext,
  4344. VerifyContext,
  4345. CatalogName,
  4346. NULL,
  4347. 0,
  4348. OemInfOriginalName,
  4349. OemInfName,
  4350. &Problem,
  4351. PathBuffer,
  4352. FALSE,
  4353. AltPlatformInfo,
  4354. (VERIFY_FILE_IGNORE_SELFSIGNED
  4355. | VERIFY_FILE_NO_DRIVERBLOCKED_CHECK
  4356. | VERIFY_FILE_USE_AUTHENTICODE_CATALOG),
  4357. NULL,
  4358. NULL,
  4359. NULL,
  4360. NULL,
  4361. hWVTStateData
  4362. );
  4363. if((AuthenticodeErr == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  4364. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  4365. //
  4366. // The catalog validated via
  4367. // Authenticode policy--reset the error
  4368. // (previously received during the
  4369. // failed attempt at validation via
  4370. // driversigning policy).
  4371. //
  4372. Err = NO_ERROR;
  4373. } else {
  4374. //
  4375. // Transfer Authenticode error over to
  4376. // be the "official" failure. We
  4377. // always want the Authenticode error
  4378. // to be NO_ERROR unless it's one of
  4379. // the two "special" values.
  4380. //
  4381. MYASSERT(AuthenticodeErr != NO_ERROR);
  4382. Err = AuthenticodeErr;
  4383. AuthenticodeErr = NO_ERROR;
  4384. }
  4385. }
  4386. }
  4387. if(Err == NO_ERROR) {
  4388. //
  4389. // Make sure we aren't remembering any residual
  4390. // intermediate problems...
  4391. //
  4392. Problem = SetupapiVerifyNoProblem;
  4393. //
  4394. // Only attempt to install a catalog if we're not
  4395. // running in "minimal embedded" mode...
  4396. //
  4397. if(!(GlobalSetupFlags & PSPGF_MINIMAL_EMBEDDED)) {
  4398. //
  4399. // Take the INF's new, unique name and generate
  4400. // a unique catalog filename under setupapi's
  4401. // namespace by simply replacing ".INF" with
  4402. // ".CAT".
  4403. //
  4404. if(MYVERIFY(SUCCEEDED(StringCchCopy(
  4405. PathBuffer,
  4406. SIZECHARS(PathBuffer),
  4407. pSetupGetFileTitle(szNewName))))) {
  4408. PTSTR DotPart = _tcsrchr(PathBuffer, TEXT('.'));
  4409. if(MYVERIFY(DotPart != NULL)) {
  4410. MYVERIFY(SUCCEEDED(StringCchCopy(
  4411. DotPart,
  4412. SIZECHARS(PathBuffer)-(DotPart-PathBuffer),
  4413. pszCatSuffix)));
  4414. }
  4415. }
  4416. //
  4417. // At this point, PathBuffer contains the
  4418. // basename to be used for the catalog on the
  4419. // system, and CatalogName is the fully-
  4420. // qualified path of the catalog file in the oem
  4421. // location.
  4422. //
  4423. Err = pSetupInstallCatalog(
  4424. CatalogName,
  4425. PathBuffer,
  4426. CatalogFilenameOnSystem
  4427. );
  4428. if(Err != NO_ERROR) {
  4429. Problem = SetupapiVerifyCatalogProblem;
  4430. ProblemFile = CatalogName;
  4431. //
  4432. // If this was au Authenticode-signed
  4433. // catalog that required user confirmation
  4434. // to establish publisher trust, then we
  4435. // need to free the WinVerifyTrust data
  4436. // now, since we've encountered an error.
  4437. //
  4438. if(hWVTStateData && *hWVTStateData) {
  4439. pSetupCloseWVTStateData(hWVTStateData);
  4440. *hWVTStateData = NULL;
  4441. }
  4442. }
  4443. }
  4444. }
  4445. }
  4446. MYASSERT(((Problem == SetupapiVerifyNoProblem) && (Err == NO_ERROR)) ||
  4447. ((Problem != SetupapiVerifyNoProblem) && (Err != NO_ERROR)));
  4448. //
  4449. // If we encountered a signature verification failure, were
  4450. // unable to install the catalog, or need to establish the
  4451. // user's trust for this Authenticode publisher, then
  4452. // prompt the user (based on policy) about what they want
  4453. // to do.
  4454. //
  4455. if((Problem != SetupapiVerifyNoProblem) ||
  4456. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  4457. MYASSERT((Err != NO_ERROR) || (hWVTStateData && *hWVTStateData));
  4458. //
  4459. // If we're here to ask the user whether they trust an
  4460. // Authenticode publisher, then we'd better not have
  4461. // encountered a verification error...
  4462. //
  4463. MYASSERT((AuthenticodeErr != ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED) ||
  4464. (Err == NO_ERROR));
  4465. if(DriverSigningError) {
  4466. *DriverSigningError = Err;
  4467. }
  4468. //
  4469. // Unless the error was due to missing CatalogFile=
  4470. // entry in the INF (and we were instructed to ignore
  4471. // such errors), then we need to handle the
  4472. // verification failure.
  4473. //
  4474. if((Err != ERROR_NO_CATALOG_FOR_OEM_INF) ||
  4475. !(Flags & SCOI_NO_ERRLOG_ON_MISSING_CATALOG)) {
  4476. if(_HandleFailedVerification(
  4477. Owner,
  4478. ((AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)
  4479. ? SetupapiVerifyCatalogProblem
  4480. : Problem),
  4481. ((AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)
  4482. ? CatalogName
  4483. : ProblemFile),
  4484. DeviceDesc,
  4485. DriverSigningPolicy,
  4486. (Flags & SCOI_NO_UI_ON_SIGFAIL),
  4487. ((Err == NO_ERROR) ? AuthenticodeErr
  4488. : Err),
  4489. LogContext,
  4490. NULL,
  4491. NULL,
  4492. (hWVTStateData ? *hWVTStateData : NULL))) {
  4493. //
  4494. // The user wants to proceed with the unsigned/
  4495. // untrusted installation (or policy is Ignore,
  4496. // so they weren't even informed). If we were
  4497. // able to confirm with the user that they
  4498. // trust the Authenticode publisher, then set
  4499. // our error to indicate this.
  4500. //
  4501. if(AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED) {
  4502. MYASSERT(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE);
  4503. MYASSERT((DriverSigningPolicy & ~DRIVERSIGN_ALLOW_AUTHENTICODE)
  4504. != DRIVERSIGN_BLOCKING);
  4505. if((DriverSigningPolicy & ~DRIVERSIGN_ALLOW_AUTHENTICODE)
  4506. != DRIVERSIGN_NONE) {
  4507. AuthenticodeErr = ERROR_AUTHENTICODE_TRUSTED_PUBLISHER;
  4508. }
  4509. }
  4510. } else {
  4511. //
  4512. // Failed verification should be treated as
  4513. // fatal.
  4514. //
  4515. if(FileNewlyCreated) {
  4516. //
  4517. // Delete the INF (and PNF and CAT, if they
  4518. // exist).
  4519. //
  4520. pSetupUninstallOEMInf(szNewName,
  4521. LogContext,
  4522. SUOI_FORCEDELETE,
  4523. NULL
  4524. );
  4525. }
  4526. if(hWVTStateData && *hWVTStateData) {
  4527. pSetupCloseWVTStateData(*hWVTStateData);
  4528. *hWVTStateData = NULL;
  4529. MYASSERT(Err == NO_ERROR);
  4530. //
  4531. // Need to report some error, since the
  4532. // user indicated they don't want to trust
  4533. // the publisher of this Authenticode-
  4534. // signed package (unless policy was block,
  4535. // in which case they didn't have a
  4536. // choice).
  4537. //
  4538. MYASSERT(DriverSigningPolicy & DRIVERSIGN_ALLOW_AUTHENTICODE);
  4539. Err = ERROR_AUTHENTICODE_PUBLISHER_NOT_TRUSTED;
  4540. }
  4541. return Err;
  4542. }
  4543. //
  4544. // The user wants to proceed with the installation
  4545. // (or policy is Ignore, so they weren't even
  4546. // informed). If the caller wants a chance to set
  4547. // a system restore point prior to doing any
  4548. // unsigned installations, then we abort now with a
  4549. // "special" error code that tells them what to
  4550. // do. (Note: if the user indicated that they
  4551. // trust the publisher of an Authenticode signed
  4552. // catalog, then we treat that as "signed", and
  4553. // thus don't bail out in this case.
  4554. //
  4555. if((Err != NO_ERROR) &&
  4556. (Flags & SCOI_ABORT_IF_UNSIGNED)) {
  4557. if(FileNewlyCreated) {
  4558. //
  4559. // Delete the INF (and PNF and CAT, if they
  4560. // exist)--we don't want these files to be
  4561. // present when the system restore point is
  4562. // created.
  4563. //
  4564. pSetupUninstallOEMInf(szNewName,
  4565. LogContext,
  4566. SUOI_FORCEDELETE,
  4567. NULL
  4568. );
  4569. }
  4570. if(hWVTStateData && *hWVTStateData) {
  4571. pSetupCloseWVTStateData(*hWVTStateData);
  4572. *hWVTStateData = NULL;
  4573. }
  4574. return ERROR_SET_SYSTEM_RESTORE_POINT;
  4575. }
  4576. }
  4577. }
  4578. MYVERIFY(SUCCEEDED(StringCchCopy(NewInfName, *RequiredSize, szNewName)));
  4579. //
  4580. // If we're installing an unsigned INF, then clean out any
  4581. // existing CAT that might've previously been installed.
  4582. //
  4583. if(Err != NO_ERROR) {
  4584. PTSTR DotPart = _tcsrchr(szNewName, TEXT('.'));
  4585. if(MYVERIFY(DotPart != NULL)) {
  4586. MYVERIFY(SUCCEEDED(StringCchCopy(DotPart,
  4587. SIZECHARS(szNewName)-(DotPart-szNewName),
  4588. pszCatSuffix)));
  4589. }
  4590. pSetupUninstallCatalog(pSetupGetFileTitle(szNewName));
  4591. }
  4592. //
  4593. // If Authenticode verification was done, then we'll return
  4594. // one of the two errors appropriate to that. Otherwise,
  4595. // we'll return NO_ERROR (that's what we initialized our
  4596. // AuthenticodeErr variable to at the beginning of this
  4597. // routine).
  4598. //
  4599. MYASSERT((AuthenticodeErr == NO_ERROR) ||
  4600. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  4601. (AuthenticodeErr == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED));
  4602. return AuthenticodeErr;
  4603. } else {
  4604. //
  4605. // The caller's buffer isn't large enough. We have to
  4606. // delete the file we created. We don't want to delete the
  4607. // file, however, if it already existed (i.e., for the
  4608. // exception INF case).
  4609. //
  4610. if(FileNewlyCreated) {
  4611. pSetupUninstallOEMInf(szNewName, LogContext, SUOI_FORCEDELETE, NULL);
  4612. }
  4613. //
  4614. // So close, yet so far. :-( Free the WinVerifyTrust state
  4615. // data, if any, since the caller won't be expecting it
  4616. // when a failure is encountered due to insufficient
  4617. // buffer.
  4618. //
  4619. if(hWVTStateData && *hWVTStateData) {
  4620. pSetupCloseWVTStateData(*hWVTStateData);
  4621. *hWVTStateData = NULL;
  4622. }
  4623. return ERROR_INSUFFICIENT_BUFFER;
  4624. }
  4625. }
  4626. } else {
  4627. MYASSERT(!hWVTStateData || !*hWVTStateData);
  4628. //
  4629. // We failed to open/create this oem inf. Check to see if the
  4630. // failure was access-denied. If so, then it's possible that the
  4631. // INF directory is ACL'ed such that we can't write to it. We want
  4632. // to bail in this case, otherwise we're going to spend a bunch of
  4633. // time trying all 100,000 oem<n>.inf filenames (with each one
  4634. // failing) before we give up.
  4635. //
  4636. // We check for this case by seeing if the file we were trying to
  4637. // create/open already exists. If so, then we want to keep going
  4638. // (e.g., maybe the individual file was ACL'ed, etc.). If, however,
  4639. // the file doesn't exist, then this indicates that we can't create
  4640. // files in the directory, and we should bail now.
  4641. //
  4642. if(Flags & SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES) {
  4643. //
  4644. // If we're installing an exception INF, we don't care what the
  4645. // error is--we gotta bail.
  4646. //
  4647. return Err;
  4648. } else if((Err == ERROR_ACCESS_DENIED) && !FileExists(szNewName, NULL)) {
  4649. return ERROR_ACCESS_DENIED;
  4650. }
  4651. }
  4652. }
  4653. //
  4654. // We didn't find a unique OEM INF name to use!
  4655. //
  4656. MYASSERT(!hWVTStateData || !*hWVTStateData);
  4657. return ERROR_FILE_NOT_FOUND;
  4658. }
  4659. DWORD
  4660. InstallHW(
  4661. IN HDEVINFO DeviceInfoSet,
  4662. IN PSP_DEVINFO_DATA DeviceInfoData,
  4663. IN HINF hDeviceInf,
  4664. IN PCTSTR szSectionName,
  4665. OUT PBOOL DeleteDevKey
  4666. )
  4667. /*++
  4668. Routine Description:
  4669. This routine appends a ".Hw" to the end of the install section name for the
  4670. specified device, and attempts to find that section name in the specified INF.
  4671. If found, it does a performs a registry installation against it.
  4672. Arguments:
  4673. DeviceInfoSet - Supplies a handle to the device information set to call
  4674. SetupInstallFromInfSection for.
  4675. DeviceInfoData - Supplies the address of a device information element structure
  4676. for which the installation action is to be performed.
  4677. hDeviceInf - Supplies a handle to the opened INF containing the device install
  4678. section.
  4679. szSectionName - Supplies the address of a string specifying the install section
  4680. name for this device. This string will be appended with ".Hw" to create
  4681. the corresponding hardware section name.
  4682. DeleteDevKey - Supplies the address of a variable that receives a boolean value
  4683. indicating whether or not a user-accessible device key was created as a
  4684. result of calling this routine. This output may be used to indicate whether
  4685. or not the key should be destroyed if the caller encounters some error later
  4686. on that requires clean-up.
  4687. Return Value:
  4688. If the function succeeds, the return value is NO_ERROR, otherwise it is an
  4689. ERROR_* code.
  4690. --*/
  4691. {
  4692. PDEVICE_INFO_SET pDeviceInfoSet;
  4693. PDEVINFO_ELEM DevInfoElem;
  4694. HKEY hKey;
  4695. DWORD Err;
  4696. TCHAR szHwSection[MAX_SECT_NAME_LEN];
  4697. INFCONTEXT InfContext;
  4698. PTSTR szInfFileName;
  4699. PTSTR NeedsSectionList, CurInstallSection;
  4700. BOOL b;
  4701. REGMOD_CONTEXT RegContext;
  4702. //
  4703. // Initially, assume the device key is already there, and therefore shouldn't be
  4704. // deleted during error clean-up.
  4705. //
  4706. *DeleteDevKey = FALSE;
  4707. //
  4708. // Form the hardware INF section name, and see if that section exists in the INF.
  4709. //
  4710. MYVERIFY(SUCCEEDED(StringCchPrintf(szHwSection,
  4711. SIZECHARS(szHwSection),
  4712. pszHwSectionFormat,
  4713. szSectionName)));
  4714. if(!SetupFindFirstLine(hDeviceInf, szHwSection, NULL, &InfContext)) {
  4715. return NO_ERROR;
  4716. }
  4717. if((hKey = SetupDiOpenDevRegKey(DeviceInfoSet,
  4718. DeviceInfoData,
  4719. DICS_FLAG_GLOBAL,
  4720. 0,
  4721. DIREG_DEV,
  4722. KEY_ALL_ACCESS)) == INVALID_HANDLE_VALUE) {
  4723. //
  4724. // Open failed--try create.
  4725. //
  4726. if((hKey = SetupDiCreateDevRegKey(DeviceInfoSet,
  4727. DeviceInfoData,
  4728. DICS_FLAG_GLOBAL,
  4729. 0,
  4730. DIREG_DEV,
  4731. NULL,
  4732. NULL)) == INVALID_HANDLE_VALUE) {
  4733. return GetLastError();
  4734. } else {
  4735. *DeleteDevKey = TRUE;
  4736. }
  4737. }
  4738. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  4739. MYASSERT(pDeviceInfoSet);
  4740. RegCloseKey(hKey);
  4741. SetLastError(ERROR_INVALID_HANDLE);
  4742. return FALSE;
  4743. }
  4744. Err = NO_ERROR;
  4745. NeedsSectionList = NULL;
  4746. try {
  4747. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  4748. DeviceInfoData,
  4749. NULL))) {
  4750. Err = ERROR_INVALID_PARAMETER;
  4751. goto clean0;
  4752. }
  4753. szInfFileName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  4754. DevInfoElem->SelectedDriver->InfFileName
  4755. );
  4756. //
  4757. // Append-load any included INFs specified in an "include=" line in our
  4758. // ".Hw" section.
  4759. //
  4760. AppendLoadIncludedInfs(hDeviceInf, szInfFileName, szHwSection, FALSE);
  4761. NeedsSectionList = GetMultiSzFromInf(hDeviceInf, szHwSection, TEXT("needs"), &b);
  4762. if(!NeedsSectionList && b) {
  4763. //
  4764. // Out of memory!
  4765. //
  4766. Err = ERROR_NOT_ENOUGH_MEMORY;
  4767. goto clean0;
  4768. }
  4769. ZeroMemory(&RegContext, sizeof(RegContext));
  4770. RegContext.Flags = INF_PFLAG_DEVPROP;
  4771. RegContext.UserRootKey = hKey;
  4772. RegContext.DevInst = DeviceInfoData->DevInst;
  4773. //
  4774. // Process the registry lines ("AddReg" and "DelReg") in this section, as well as
  4775. // those contained with any sections referenced in the "needs=" entry in this section.
  4776. //
  4777. for(CurInstallSection = szHwSection;
  4778. (CurInstallSection && *CurInstallSection);
  4779. CurInstallSection = (CurInstallSection == szHwSection)
  4780. ? NeedsSectionList
  4781. : (CurInstallSection + lstrlen(CurInstallSection) + 1))
  4782. {
  4783. if((Err = pSetupInstallRegistry(hDeviceInf, CurInstallSection, &RegContext)) != NO_ERROR) {
  4784. //
  4785. //Stop if we encounter an error while processing one of the section's registry entries
  4786. //
  4787. break;
  4788. }
  4789. }
  4790. clean0: ; // nothing to do.
  4791. } except(EXCEPTION_EXECUTE_HANDLER) {
  4792. //
  4793. // If our exception was an AV, then use Win32 invalid param error, otherwise, assume it was
  4794. // an inpage error dealing with a mapped-in file.
  4795. //
  4796. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  4797. }
  4798. UnlockDeviceInfoSet(pDeviceInfoSet);
  4799. RegCloseKey(hKey);
  4800. if(NeedsSectionList) {
  4801. MyFree(NeedsSectionList);
  4802. }
  4803. return Err;
  4804. }
  4805. BOOL
  4806. CheckIfDevStarted(
  4807. IN PDEVINFO_ELEM DevInfoElem,
  4808. IN PDEVICE_INFO_SET pDeviceInfoSet
  4809. )
  4810. /*++
  4811. Routine Description:
  4812. This routine calls CM_Get_DevInst_Status to see if the specified device
  4813. instance has been started. If the device hasn't been started, and it has
  4814. either the CM_PROB_NEED_RESTART or CM_PROB_NORMAL_CONFLICT problem codes,
  4815. the DI_NEEDREBOOT flag is set in the device information element. We also
  4816. set the CM_PROB_NEED_RESTART problem on the devnode.
  4817. Arguments:
  4818. DevInfoElem - Supplies the address of the device information element to
  4819. check.
  4820. pDeviceInfoSet - Supplies the address of the device info set
  4821. LogContext - Supplies a log context for logging the reason if a reboot is
  4822. needed.
  4823. Return Value:
  4824. None.
  4825. --*/
  4826. {
  4827. ULONG ulStatus, ulProblem;
  4828. BOOL restarted = FALSE;
  4829. if(CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevInfoElem->DevInst, 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) {
  4830. if(ulStatus & DN_STARTED) {
  4831. restarted = TRUE;
  4832. } else {
  4833. if (ulStatus & DN_HAS_PROBLEM) {
  4834. if((ulProblem == CM_PROB_NEED_RESTART) ||
  4835. (ulProblem == CM_PROB_NORMAL_CONFLICT) ||
  4836. (ulProblem == CM_PROB_DRIVER_FAILED_PRIOR_UNLOAD) ||
  4837. (ulProblem == CM_PROB_HELD_FOR_EJECT)) {
  4838. //
  4839. // The device either has the problem CM_PROB_NEED_RESTART or
  4840. // CM_PROB_NORMAL_CONFLICT. - change into need reboot
  4841. // and log what problem code was
  4842. //
  4843. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,
  4844. pDeviceInfoSet,
  4845. MSG_LOG_REBOOT_REASON_DEVHASPROBLEM,
  4846. (DWORD)ulProblem,
  4847. (ULONG_PTR)_MapCmProbToString((DWORD)ulProblem)
  4848. );
  4849. } else {
  4850. //
  4851. // The device has some other problem so we won't prompt for a reboot
  4852. // however these are interesting things to log
  4853. //
  4854. WriteLogEntry(
  4855. DevInfoElem->InstallParamBlock.LogContext,
  4856. DRIVER_LOG_INFO, // not worth a warning
  4857. MSG_LOG_NOTSTARTED_REASON_DEVHASPROBLEM,
  4858. NULL,
  4859. (DWORD)ulProblem,
  4860. _MapCmProbToString((DWORD)ulProblem)
  4861. );
  4862. }
  4863. } else if (ulStatus & DN_PRIVATE_PROBLEM) {
  4864. //
  4865. // some private problem, change into need reboot
  4866. // and log private problem
  4867. //
  4868. SetDevnodeNeedsRebootProblem(DevInfoElem, pDeviceInfoSet,
  4869. MSG_LOG_REBOOT_REASON_PRIVATEPROBLEM);
  4870. } else {
  4871. //
  4872. // not started for some other reason
  4873. // indicate reboot required and log this issue
  4874. //
  4875. SetDevnodeNeedsRebootProblem(DevInfoElem, pDeviceInfoSet,
  4876. MSG_LOG_REBOOT_REASON_NOTSTARTED);
  4877. }
  4878. }
  4879. }
  4880. return restarted;
  4881. }
  4882. DWORD
  4883. InstallNtService(
  4884. IN PDEVINFO_ELEM DevInfoElem, OPTIONAL
  4885. IN HINF hDeviceInf,
  4886. IN PCTSTR InfFileName, OPTIONAL
  4887. IN PCTSTR szSectionName, OPTIONAL
  4888. OUT PSVCNAME_NODE *ServicesToDelete, OPTIONAL
  4889. IN DWORD Flags,
  4890. OUT PBOOL NullDriverInstalled
  4891. )
  4892. /*++
  4893. Routine Description:
  4894. This routine looks for the specified INF section, and if found, it deletes
  4895. any services specified in "DelService" entries, then installs any services
  4896. specified in "AddService" entries. These entries have the following form:
  4897. AddService = [<ServiceName>], [<Flags>], <ServiceInstallSection>[, <EventLogInstallSection>[, [<EventLogType>] [, <EventName>]]]
  4898. DelService = <ServiceName>[, [<flags>] [, [<EventLogType>] [, <EventName>]]]
  4899. (<ServiceName> is only optional for an AddService entry if the
  4900. SPSVCINST_ASSOCSERVICE flag is set. This indicates that we're explicitly
  4901. installing a NULL driver for this device, even though the underlying bus
  4902. didn't report the device as being raw-capable. This is used for device such
  4903. as the BIOS-reported PIC, DMA controller, etc. devnodes that don't need a
  4904. driver (since the HAL runs them), yet need to have a NULL driver installed
  4905. so that they don't show up as yellow-banged in Device Manager.)
  4906. A linked list is built of newly-created services, and optionally returned to the
  4907. caller (in case a subsequent installation failure requires all modifications to
  4908. be undone).
  4909. After all service modifications are complete, this routine checks to see if we're
  4910. in the context of a device installation. If so, then it checks to see if the device
  4911. instance specifies a valid controlling service, and that the service is not disabled
  4912. (disabled services are assumed to be uninstalled). If the device's 'RawDeviceOK'
  4913. capability bit is set, then a device with no controlling service will be allowed.
  4914. Arguments:
  4915. DevInfoElem - Optionally, supplies the device information element for whom the
  4916. service installation is being performed. If this parameter is not specified,
  4917. then the service is not being installed in relation to a device instance.
  4918. hDeviceInf - Supplies a handle to the opened INF containing the service install
  4919. section.
  4920. InfFileName - Optionally, supplies the full path of the INF file containing the
  4921. service install section. If this parameter is NULL, the no Include= or Needs=
  4922. values will be processed in this section.
  4923. szSectionName - Optionally, supplies the name of the service install section in a
  4924. Win95-style device INF. If this parameter is NULL, then no AddService or
  4925. DelService lines will be processed.
  4926. ServicesToDelete - Optionally, supplies the address of a linked list head pointer,
  4927. that receives a list of services that were newly-created by this routine, and
  4928. as such, should be deleted if the installation fails later on. The caller must
  4929. free the memory allocated for the nodes in this list by calling MyFree() on each
  4930. one.
  4931. Flags - Supplies flags controlling how the services are to be installed. May be a
  4932. combination of the following values:
  4933. SPSVCINST_TAGTOFRONT - For every kernel or filesystem driver installed (that
  4934. has an associated LoadOrderGroup), always move this service's tag to the
  4935. front of the ordering list.
  4936. SPSVCINST_ASSOCSERVICE - This flag may only be specified if a device information
  4937. element is specified. If set, this flag specifies that the service being
  4938. installed is the owning service (i.e., function driver) for this device instance.
  4939. SPSVCINST_DELETEEVENTLOGENTRY - For every service specified in a DelService entry,
  4940. delete the associated event log entry (if there is one).
  4941. SPSVCINST_NOCLOBBER_DISPLAYNAME - If this flag is specified, then we will
  4942. not overwrite the service's display name, if it already exists.
  4943. SPSVCINST_NOCLOBBER_STARTTYPE - If this flag is specified, then we will
  4944. not overwrite the service's start type if the service already exists.
  4945. SPSVCINST_NOCLOBBER_ERRORCONTROL - If this flag is specified, then we
  4946. will not overwrite the service's error control value if the service
  4947. already exists.
  4948. SPSVCINST_NOCLOBBER_LOADORDERGROUP - If this flag is specified, then we
  4949. will not overwrite the service's load order group if it already
  4950. exists.
  4951. SPSVCINST_NOCLOBBER_DEPENDENCIES - If this flag is specified, then we
  4952. will not overwrite the service's dependencies list if it already
  4953. exists.
  4954. SPSVCINST_NO_DEVINST_CHECK - If this flag is specified, then we will not check
  4955. to ensure that a function driver is installed for the specified devinfo
  4956. element after running the service install section. This is a private flag
  4957. used only by SetupInstallServicesFromInfSection(Ex) and InstallHinfSection.
  4958. SPSVCINST_STOPSERVICE - If this flag is specified, then we will stop the service
  4959. before removing the service.
  4960. SPSVCINST_CLOBBER_SECURITY - If this flag is specified, security may be
  4961. overridden.
  4962. NullDriverInstalled - Supplies the address of a boolean variable that
  4963. indicates whether or not an explicit null driver installation was done
  4964. for this device.
  4965. Return Value:
  4966. If the function succeeds, the return value is NO_ERROR, otherwise it is an
  4967. ERROR_* code.
  4968. If NO_ERROR is returned, GetLastError may return ERROR_SUCCESS_REBOOT_REQUIRED
  4969. --*/
  4970. {
  4971. CONFIGRET cr;
  4972. TCHAR ServiceName[MAX_SERVICE_NAME_LEN];
  4973. ULONG ServiceNameSize;
  4974. DWORD Err = NO_ERROR, i;
  4975. SC_HANDLE SCMHandle, ServiceHandle, FilterServiceHandle;
  4976. LPQUERY_SERVICE_CONFIG ServiceConfig, FilterServiceConfig;
  4977. DWORD ServiceConfigSize;
  4978. PCTSTR Key;
  4979. INFCONTEXT LineContext;
  4980. PSVCNAME_NODE SvcListHead = NULL;
  4981. PSVCNAME_NODE TmpSvcNode;
  4982. SC_LOCK SCLock;
  4983. DWORD NewTag;
  4984. BOOL AssociatedService;
  4985. DWORD DevInstCapabilities;
  4986. ULONG DevInstCapabilitiesSize;
  4987. PTSTR FilterDrivers, CurFilterDriver;
  4988. BOOL FilterNeedsTag;
  4989. BOOL NullFunctionDriverAdded;
  4990. PTSTR NeedsSectionList, CurInstallSection;
  4991. BOOL b;
  4992. BOOL NeedsReboot;
  4993. DWORD slot_section = 0;
  4994. PSETUP_LOG_CONTEXT LogContext;
  4995. try {
  4996. LogContext = ((PLOADED_INF) hDeviceInf)->LogContext;
  4997. } except(EXCEPTION_EXECUTE_HANDLER) {
  4998. LogContext = NULL;
  4999. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  5000. goto FinalClean0;
  5001. }
  5002. //
  5003. // Initially, assume this is not a null driver install.
  5004. //
  5005. *NullDriverInstalled = FALSE;
  5006. NeedsReboot = FALSE;
  5007. if(szSectionName) {
  5008. //
  5009. // Surround the following in try/except, in case we get an inpage error.
  5010. //
  5011. try {
  5012. NeedsSectionList = NULL;
  5013. if (InfFileName) {
  5014. AppendLoadIncludedInfs(hDeviceInf, InfFileName, szSectionName, FALSE);
  5015. NeedsSectionList = GetMultiSzFromInf(hDeviceInf, szSectionName, TEXT("needs"), &b);
  5016. if(!NeedsSectionList && b) {
  5017. //
  5018. // Out of memory!
  5019. //
  5020. Err = ERROR_NOT_ENOUGH_MEMORY;
  5021. goto clean0;
  5022. }
  5023. }
  5024. if (slot_section == 0) {
  5025. slot_section = AllocLogInfoSlot(LogContext,FALSE);
  5026. }
  5027. //
  5028. // Make two passes through the section--once for deletions, and a
  5029. // second time for additions.
  5030. //
  5031. for(i = 0; i < 2; i++) {
  5032. //
  5033. // Find the relevent line (if there is one) in the given install section.
  5034. //
  5035. Key = (i) ? pszAddService : pszDelService;
  5036. //
  5037. // Process the service lines in this section, as well as
  5038. // those contained with any sections referenced in the "needs=" entry in this section.
  5039. //
  5040. for(CurInstallSection = (PTSTR)szSectionName;
  5041. (CurInstallSection && *CurInstallSection);
  5042. CurInstallSection = (CurInstallSection == szSectionName)
  5043. ? NeedsSectionList
  5044. : (CurInstallSection + lstrlen(CurInstallSection) + 1))
  5045. {
  5046. if(!SetupFindFirstLine(hDeviceInf, CurInstallSection, Key, &LineContext)) {
  5047. continue;
  5048. }
  5049. //
  5050. // Log which section we're installing if we log anything else
  5051. //
  5052. WriteLogEntry(
  5053. LogContext,
  5054. slot_section,
  5055. MSG_LOG_PROCESS_SERVICE_SECTION,
  5056. NULL,
  5057. CurInstallSection);
  5058. do {
  5059. //
  5060. // We have a line to act upon.
  5061. //
  5062. Err = (i) ? pSetupAddService(&LineContext,
  5063. &SvcListHead,
  5064. Flags,
  5065. (DevInfoElem ? DevInfoElem->DevInst : 0),
  5066. &NullFunctionDriverAdded,
  5067. LogContext)
  5068. : pSetupDeleteService(&LineContext,
  5069. Flags,
  5070. LogContext);
  5071. if(Err != NO_ERROR) {
  5072. //
  5073. // Log that an error occurred
  5074. //
  5075. WriteLogError(
  5076. LogContext,
  5077. // we don't know if it's a driver or not,
  5078. // so just allow both to work
  5079. SETUP_LOG_ERROR | DRIVER_LOG_ERROR,
  5080. Err);
  5081. goto clean0;
  5082. } else if(i) {
  5083. //
  5084. // We're processing AddService entries, so check to see
  5085. // if we just installed a null service (thus having no
  5086. // function driver on a non-raw-capable PDO should be
  5087. // allowed).
  5088. //
  5089. *NullDriverInstalled |= NullFunctionDriverAdded;
  5090. if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED) {
  5091. NeedsReboot |= TRUE;
  5092. }
  5093. }
  5094. } while(SetupFindNextMatchLine(&LineContext, Key, &LineContext));
  5095. }
  5096. }
  5097. clean0: ; // nothing to do
  5098. } except(EXCEPTION_EXECUTE_HANDLER) {
  5099. //
  5100. // If our exception was an AV, then use Win32 invalid param error, otherwise, assume it was
  5101. // an inpage error dealing with a mapped-in file.
  5102. //
  5103. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  5104. }
  5105. if (NeedsSectionList) {
  5106. MyFree(NeedsSectionList);
  5107. }
  5108. if((Err != NO_ERROR) || (Flags & SPSVCINST_NO_DEVINST_CHECK)) {
  5109. goto FinalClean0;
  5110. }
  5111. }
  5112. MYASSERT(DevInfoElem);
  5113. //
  5114. // Find out if the device instance already has an associated service.
  5115. //
  5116. ServiceNameSize = sizeof(ServiceName);
  5117. if(CR_SUCCESS == (cr = CM_Get_DevInst_Registry_Property(DevInfoElem->DevInst,
  5118. CM_DRP_SERVICE,
  5119. NULL,
  5120. ServiceName,
  5121. &ServiceNameSize,
  5122. 0)))
  5123. {
  5124. AssociatedService = TRUE;
  5125. //
  5126. // Make sure that the NullDriverInstalled output parameter is still FALSE.
  5127. // It typically would be, but might not be in the case where there are
  5128. // multiple AddService entries that specify SPSVCINST_ASSOCSERVICE (e.g.,
  5129. // when additional service install sections are pulled in via include=/needs=.
  5130. //
  5131. *NullDriverInstalled = FALSE;
  5132. } else {
  5133. //
  5134. // For the moment, there is no associated service.
  5135. //
  5136. AssociatedService = FALSE;
  5137. //
  5138. // Either the device instance has gone sour (in which case we return an error),
  5139. // or we couldn't retrieve an associated service name. In the latter case, we
  5140. // will make the association based on the default service for the class.
  5141. //
  5142. if(cr == CR_INVALID_DEVINST) {
  5143. Err = ERROR_NO_SUCH_DEVINST;
  5144. } else if(!*NullDriverInstalled) {
  5145. ServiceNameSize = sizeof(ServiceName);
  5146. AssociatedService = AssociateDevInstWithDefaultService(DevInfoElem,
  5147. ServiceName,
  5148. &ServiceNameSize
  5149. );
  5150. if(!AssociatedService) {
  5151. //
  5152. // If the device's capabilities report that it can be driven 'raw', then
  5153. // not having a function driver is OK. Otherwise, we have an error.
  5154. //
  5155. DevInstCapabilitiesSize = sizeof(DevInstCapabilities);
  5156. if(CR_SUCCESS != CM_Get_DevInst_Registry_Property(DevInfoElem->DevInst,
  5157. CM_DRP_CAPABILITIES,
  5158. NULL,
  5159. &DevInstCapabilities,
  5160. &DevInstCapabilitiesSize,
  5161. 0))
  5162. {
  5163. DevInstCapabilities = 0;
  5164. }
  5165. if(!(DevInstCapabilities & CM_DEVCAP_RAWDEVICEOK)) {
  5166. Err = ERROR_NO_ASSOCIATED_SERVICE;
  5167. }
  5168. }
  5169. }
  5170. if(!AssociatedService) {
  5171. //
  5172. // Either we hit an error, or the device can be driven 'raw'. In either case, we
  5173. // can skip the service controller checks that lie ahead.
  5174. //
  5175. goto FinalClean0;
  5176. }
  5177. }
  5178. //
  5179. // At this point, we have the name of the service with which the device instance is
  5180. // associated. Attempt to locate this service in the SCM database.
  5181. //
  5182. if(!(SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
  5183. Err = GetLastError();
  5184. WriteLogEntry(
  5185. LogContext,
  5186. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5187. MSG_LOG_INSTSERVSCM_ERROR,
  5188. NULL);
  5189. WriteLogError(
  5190. LogContext,
  5191. DRIVER_LOG_ERROR,
  5192. Err);
  5193. goto FinalClean0;
  5194. }
  5195. if(!(ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))) {
  5196. //
  5197. // We couldn't access the service--either because it doesn't exist, or because
  5198. // this is a detected device reported by a 'disembodied' driver object (e.g., the
  5199. // one the HAL creates for its driver object it got via IoCreateDriver).
  5200. //
  5201. // The former case is an error, the latter case is just fine.
  5202. //
  5203. Err = GetLastError();
  5204. if((lstrlen(ServiceName) > CSTRLEN(pszDriverObjectPathPrefix)) &&
  5205. CharUpper(ServiceName) &&
  5206. !memcmp(ServiceName, pszDriverObjectPathPrefix, CSTRLEN(pszDriverObjectPathPrefix)))
  5207. {
  5208. //
  5209. // The "service name" is actually a driver name (e.g., "\Driver\PCI_HAL"), so it's OK.
  5210. //
  5211. Err = NO_ERROR;
  5212. }
  5213. if(Err) {
  5214. WriteLogEntry(
  5215. LogContext,
  5216. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5217. MSG_LOG_INSTSERVOPEN_ERROR,
  5218. NULL,
  5219. ServiceName
  5220. );
  5221. WriteLogError(
  5222. LogContext,
  5223. DRIVER_LOG_ERROR,
  5224. Err);
  5225. }
  5226. goto FinalClean1;
  5227. }
  5228. //
  5229. // The service exists. Make sure that it's not disabled.
  5230. //
  5231. if((Err = pSetupRetrieveServiceConfig(ServiceHandle, &ServiceConfig)) == NO_ERROR) {
  5232. if(ServiceConfig->dwStartType == SERVICE_DISABLED) {
  5233. WriteLogEntry(
  5234. LogContext,
  5235. DRIVER_LOG_ERROR,
  5236. MSG_LOG_INSTSERV_DISABLED,
  5237. NULL,
  5238. ServiceName
  5239. );
  5240. Err = ERROR_SERVICE_DISABLED;
  5241. } else {
  5242. //
  5243. // If this service has a load order group, and is a kernel or filesystem
  5244. // driver, then make sure that it has a tag.
  5245. //
  5246. // NOTE: We have to do this here, even though we ensure that all new services we install
  5247. // have their tags set up properly in pSetupAddService(). The reason is that the device may
  5248. // using an existing service that wasn't installed via a Win95-style INF.
  5249. //
  5250. if(ServiceConfig->lpLoadOrderGroup && *(ServiceConfig->lpLoadOrderGroup) &&
  5251. (ServiceConfig->dwServiceType & (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER))) {
  5252. //
  5253. // This service needs a tag--does it have one???
  5254. //
  5255. if(!(NewTag = ServiceConfig->dwTagId)) {
  5256. //
  5257. // Attempt to lock the service database before generating a tag. We'll go ahead
  5258. // and make the change, even if this fails.
  5259. //
  5260. pAcquireSCMLock(SCMHandle, &SCLock, LogContext);
  5261. if(!ChangeServiceConfig(ServiceHandle,
  5262. SERVICE_NO_CHANGE,
  5263. SERVICE_NO_CHANGE,
  5264. SERVICE_NO_CHANGE,
  5265. NULL,
  5266. ServiceConfig->lpLoadOrderGroup, // have to specify this to generate new tag.
  5267. &NewTag,
  5268. NULL,
  5269. NULL,
  5270. NULL,
  5271. NULL)) {
  5272. DWORD LastErr = GetLastError();
  5273. WriteLogEntry(
  5274. LogContext,
  5275. DRIVER_LOG_WARNING | SETUP_LOG_BUFFER,
  5276. MSG_LOG_INSTSERVTAG_WARN,
  5277. NULL,
  5278. ServiceName
  5279. );
  5280. WriteLogError(
  5281. LogContext,
  5282. DRIVER_LOG_WARNING,
  5283. LastErr);
  5284. NewTag = 0;
  5285. }
  5286. if(SCLock) {
  5287. UnlockServiceDatabase(SCLock);
  5288. }
  5289. }
  5290. //
  5291. // Make sure that the tag exists in the service's corresponding GroupOrderList entry.
  5292. //
  5293. if(NewTag) {
  5294. pSetupAddTagToGroupOrderListEntry(ServiceConfig->lpLoadOrderGroup,
  5295. NewTag,
  5296. Flags & SPSVCINST_TAGTOFRONT
  5297. );
  5298. }
  5299. }
  5300. //
  5301. // If the function driver is marked as boot-start, then make sure that all
  5302. // associated upper- and lower-filters (both class- and device-specific) are
  5303. // also boot-start drivers.
  5304. //
  5305. if((ServiceConfig->dwStartType == SERVICE_BOOT_START) &&
  5306. RetrieveAllDriversForDevice(DevInfoElem, &FilterDrivers,RADFD_FLAG_ALL_FILTERS,NULL)) {
  5307. //
  5308. // If FilterDrivers is NULL, then we hit an out-of-memory error.
  5309. //
  5310. if(!FilterDrivers) {
  5311. Err = ERROR_NOT_ENOUGH_MEMORY;
  5312. } else {
  5313. WriteLogEntry(
  5314. LogContext,
  5315. DRIVER_LOG_VERBOSE,
  5316. MSG_LOG_INSTSERV_BOOT,
  5317. NULL,
  5318. ServiceName
  5319. );
  5320. //
  5321. // Check each filter driver.
  5322. //
  5323. for(CurFilterDriver = FilterDrivers;
  5324. *CurFilterDriver;
  5325. CurFilterDriver += (lstrlen(CurFilterDriver) + 1)) {
  5326. if(!(FilterServiceHandle = OpenService(SCMHandle, CurFilterDriver, SERVICE_ALL_ACCESS))) {
  5327. //
  5328. // We couldn't access the service--probably because it doesn't exist.
  5329. // Bail now.
  5330. //
  5331. Err = GetLastError();
  5332. WriteLogEntry(
  5333. LogContext,
  5334. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5335. MSG_LOG_BOOTFILTSERVOPEN_ERROR,
  5336. NULL,
  5337. CurFilterDriver);
  5338. WriteLogError(
  5339. LogContext,
  5340. DRIVER_LOG_ERROR,
  5341. Err);
  5342. break;
  5343. }
  5344. //
  5345. // The service exists. Make sure that it's not disabled.
  5346. //
  5347. Err = pSetupRetrieveServiceConfig(FilterServiceHandle, &FilterServiceConfig);
  5348. if(Err != NO_ERROR) {
  5349. WriteLogEntry(
  5350. LogContext,
  5351. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5352. MSG_LOG_BOOTFILTSERVCONFIG_ERROR,
  5353. NULL,
  5354. CurFilterDriver);
  5355. WriteLogError(
  5356. LogContext,
  5357. DRIVER_LOG_ERROR,
  5358. Err);
  5359. goto CloseFilterSvcAndContinue;
  5360. }
  5361. if(FilterServiceConfig->dwStartType == SERVICE_DISABLED) {
  5362. WriteLogEntry(
  5363. LogContext,
  5364. DRIVER_LOG_ERROR,
  5365. MSG_LOG_BOOTFILTSERV_DISABLED,
  5366. NULL,
  5367. CurFilterDriver);
  5368. Err = ERROR_SERVICE_DISABLED;
  5369. } else {
  5370. //
  5371. // Ensure that this service is a boot-start kernel driver, and that it has
  5372. // a tag if necessary.
  5373. //
  5374. if(FilterServiceConfig->dwServiceType & SERVICE_KERNEL_DRIVER) {
  5375. if(FilterServiceConfig->lpLoadOrderGroup &&
  5376. *(FilterServiceConfig->lpLoadOrderGroup)) {
  5377. FilterNeedsTag = TRUE;
  5378. NewTag = FilterServiceConfig->dwTagId;
  5379. }
  5380. if((FilterNeedsTag && !NewTag) ||
  5381. (FilterServiceConfig->dwStartType != SERVICE_BOOT_START)) {
  5382. //
  5383. // Lock the service database before modifying this service.
  5384. //
  5385. Err = pAcquireSCMLock(SCMHandle, &SCLock, LogContext);
  5386. if(Err == NO_ERROR) {
  5387. //
  5388. // Make the modifications to the service (NOTE: Because the
  5389. // service controller is really bad when it comes to driver paths,
  5390. // we must explicitly pass the lpBinaryPathName in, even though we
  5391. // aren't changing it. Otherwise, the service controller will complain
  5392. // because it thinks all paths have to begin with \SystemRoot\.)
  5393. //
  5394. if(!ChangeServiceConfig(FilterServiceHandle,
  5395. SERVICE_NO_CHANGE,
  5396. (FilterServiceConfig->dwStartType != SERVICE_BOOT_START)
  5397. ? SERVICE_BOOT_START
  5398. : SERVICE_NO_CHANGE,
  5399. SERVICE_NO_CHANGE,
  5400. (FilterServiceConfig->dwStartType != SERVICE_BOOT_START)
  5401. ? FilterServiceConfig->lpBinaryPathName
  5402. : NULL,
  5403. (FilterNeedsTag && !NewTag)
  5404. ? FilterServiceConfig->lpLoadOrderGroup
  5405. : NULL,
  5406. (FilterNeedsTag && !NewTag)
  5407. ? &NewTag
  5408. : NULL,
  5409. NULL,
  5410. NULL,
  5411. NULL,
  5412. NULL)) {
  5413. Err = GetLastError();
  5414. WriteLogEntry(
  5415. LogContext,
  5416. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5417. MSG_LOG_BOOTFILTSERVCHANGE_ERROR,
  5418. NULL,
  5419. CurFilterDriver);
  5420. WriteLogError(
  5421. LogContext,
  5422. DRIVER_LOG_ERROR,
  5423. Err);
  5424. } else {
  5425. WriteLogEntry(
  5426. LogContext,
  5427. DRIVER_LOG_VERBOSE,
  5428. MSG_LOG_BOOTFILTSERVCHANGE_OK,
  5429. NULL,
  5430. CurFilterDriver);
  5431. }
  5432. UnlockServiceDatabase(SCLock);
  5433. } else {
  5434. WriteLogEntry(
  5435. LogContext,
  5436. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5437. MSG_LOG_BOOTFILTSERVSCM_ERROR,
  5438. NULL,
  5439. CurFilterDriver);
  5440. WriteLogError(
  5441. LogContext,
  5442. DRIVER_LOG_ERROR,
  5443. Err);
  5444. }
  5445. if((Err == NO_ERROR) && FilterNeedsTag) {
  5446. //
  5447. // Make sure that the tag exists in the service's corresponding GroupOrderList entry.
  5448. //
  5449. MYASSERT(NewTag);
  5450. pSetupAddTagToGroupOrderListEntry(FilterServiceConfig->lpLoadOrderGroup,
  5451. NewTag,
  5452. FALSE
  5453. );
  5454. }
  5455. }
  5456. } else {
  5457. //
  5458. // This is not a kernel driver. This is an error.
  5459. //
  5460. WriteLogEntry(
  5461. LogContext,
  5462. DRIVER_LOG_ERROR,
  5463. MSG_LOG_BOOTFILTSERV_KERN,
  5464. NULL,
  5465. CurFilterDriver);
  5466. Err = ERROR_INVALID_FILTER_DRIVER;
  5467. }
  5468. }
  5469. MyFree(FilterServiceConfig);
  5470. CloseFilterSvcAndContinue:
  5471. CloseServiceHandle(FilterServiceHandle);
  5472. if(Err) {
  5473. break;
  5474. }
  5475. }
  5476. MyFree(FilterDrivers);
  5477. }
  5478. }
  5479. }
  5480. MyFree(ServiceConfig);
  5481. } else {
  5482. WriteLogEntry(
  5483. LogContext,
  5484. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5485. MSG_LOG_INSTSERVCONFIG_ERROR,
  5486. NULL,
  5487. ServiceName
  5488. );
  5489. WriteLogError(
  5490. LogContext,
  5491. DRIVER_LOG_ERROR,
  5492. Err);
  5493. }
  5494. CloseServiceHandle(ServiceHandle);
  5495. FinalClean1:
  5496. CloseServiceHandle(SCMHandle);
  5497. FinalClean0:
  5498. if(Err == NO_ERROR) {
  5499. //
  5500. // If requested, store the linked-list of newly-created service nodes in the output
  5501. // parameter, otherwise, delete the list.
  5502. //
  5503. if(ServicesToDelete) {
  5504. *ServicesToDelete = SvcListHead;
  5505. } else {
  5506. for(TmpSvcNode = SvcListHead; TmpSvcNode; TmpSvcNode = SvcListHead) {
  5507. SvcListHead = SvcListHead->Next;
  5508. MyFree(TmpSvcNode);
  5509. }
  5510. }
  5511. if (NeedsReboot) {
  5512. //
  5513. // this is intentional - return NO_ERROR but GetLastError = ERROR_SUCCESS_REBOOT_REQUIRED
  5514. //
  5515. SetLastError(ERROR_SUCCESS_REBOOT_REQUIRED);
  5516. }
  5517. } else {
  5518. //
  5519. // Something failed along the way, so we need to clean up any newly-created
  5520. // services.
  5521. //
  5522. if(Err && LogContext) {
  5523. WriteLogEntry(
  5524. LogContext,
  5525. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5526. MSG_LOG_INSTSERV_ERROR,
  5527. NULL
  5528. );
  5529. WriteLogError(
  5530. LogContext,
  5531. DRIVER_LOG_ERROR,
  5532. Err);
  5533. }
  5534. if(SvcListHead) {
  5535. DeleteServicesInList(SvcListHead,LogContext);
  5536. for(TmpSvcNode = SvcListHead; TmpSvcNode; TmpSvcNode = SvcListHead) {
  5537. SvcListHead = SvcListHead->Next;
  5538. MyFree(TmpSvcNode);
  5539. }
  5540. }
  5541. }
  5542. if (slot_section != 0) {
  5543. ReleaseLogInfoSlot(LogContext,slot_section);
  5544. }
  5545. return Err;
  5546. }
  5547. BOOL
  5548. AssociateDevInstWithDefaultService(
  5549. IN PDEVINFO_ELEM DevInfoElem,
  5550. OUT PTSTR ServiceName,
  5551. IN OUT PDWORD ServiceNameSize
  5552. )
  5553. /*++
  5554. Routine Description:
  5555. This routine attempts to find out the default service with which to associate
  5556. the specified device. The default service (if there is one) is associated with
  5557. the device's class. If a default is found, the device instance is associated
  5558. with that service.
  5559. Arguments:
  5560. DeviceInfoData - Specifies the device information element to create a default
  5561. service association for.
  5562. ServiceName - Supplies the address of a character buffer that receives the name
  5563. of the service with which the device instance was associated (if this routine
  5564. is successful).
  5565. ServiceNameSize - Supplies the address of a variable containing the size, in bytes,
  5566. of the ServiceName buffer. On output, this variable receives the number of
  5567. bytes actually stored in ServiceName.
  5568. Return Value:
  5569. If the function succeeds, the return value is TRUE, otherwise it is FALSE.
  5570. --*/
  5571. {
  5572. HKEY hClassKey;
  5573. DWORD RegDataType;
  5574. BOOL Success;
  5575. //
  5576. // Open up the class key for this device's class.
  5577. //
  5578. if((hClassKey = SetupDiOpenClassRegKey(&(DevInfoElem->ClassGuid),
  5579. KEY_READ)) == INVALID_HANDLE_VALUE) {
  5580. return FALSE;
  5581. }
  5582. Success = FALSE; // assume failure
  5583. try {
  5584. //
  5585. // Retrieve the "Default Service" value from the class key. If present, this value entry
  5586. // indicates what service to associate the device with, when one isn't specified during
  5587. // installation.
  5588. //
  5589. if (RegQueryValueEx(hClassKey,
  5590. pszDefaultService,
  5591. NULL,
  5592. &RegDataType,
  5593. (PBYTE)ServiceName,
  5594. ServiceNameSize) != ERROR_SUCCESS) {
  5595. goto clean0;
  5596. }
  5597. *ServiceNameSize = (lstrlen(ServiceName) + 1) * sizeof(TCHAR);
  5598. if((RegDataType != REG_SZ) || (*ServiceNameSize < sizeof(TCHAR)) || !(*ServiceName)) {
  5599. goto clean0;
  5600. }
  5601. //
  5602. // We have successfully retrieved the default service name to be associated with this
  5603. // device instance. Perform the association now by setting the Service device registry
  5604. // property.
  5605. //
  5606. if(CM_Set_DevInst_Registry_Property(DevInfoElem->DevInst,
  5607. CM_DRP_SERVICE,
  5608. ServiceName,
  5609. *ServiceNameSize,
  5610. 0) == CR_SUCCESS) {
  5611. Success = TRUE;
  5612. }
  5613. clean0: ; // nothing to do
  5614. } except(EXCEPTION_EXECUTE_HANDLER) {
  5615. Success = FALSE;
  5616. }
  5617. RegCloseKey(hClassKey);
  5618. return Success;
  5619. }
  5620. DWORD
  5621. DeleteServicesInList(
  5622. IN PSVCNAME_NODE ServicesToDelete,
  5623. IN PSETUP_LOG_CONTEXT LogContext
  5624. )
  5625. /*++
  5626. Routine Description:
  5627. This routine deletes each service entry in the supplied linked list. This is
  5628. typically called to clean up if something goes wrong during a device's installation.
  5629. If the 'DeleteEventLog' flag for a particular node is TRUE, then the corresponding
  5630. event log entry under HKLM\System\CurrentControlSet\Services\EventLog\<EventLogType> is
  5631. also deleted.
  5632. Arguments:
  5633. ServicesToDelete - supplies a pointer to the head of a linked list of service names
  5634. to be deleted.
  5635. LogContext - context for logging failures
  5636. Return Value:
  5637. Error if we could not open service manager or acquire lock.
  5638. Note that we do not return error for individual services.
  5639. --*/
  5640. {
  5641. SC_HANDLE SCMHandle, ServiceHandle;
  5642. SC_LOCK SCLock;
  5643. HKEY hKeyEventLog = NULL, hKeyEventLogType;
  5644. TCHAR RegistryPath[SIZECHARS(REGSTR_PATH_SERVICES) + SIZECHARS(DISTR_EVENTLOG) + (2 * 256)];
  5645. DWORD Result = NO_ERROR;
  5646. DWORD LastErr;
  5647. if(SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) {
  5648. Result = pAcquireSCMLock(SCMHandle, &SCLock, LogContext);
  5649. if(Result == NO_ERROR) {
  5650. for(; ServicesToDelete; ServicesToDelete = ServicesToDelete->Next) {
  5651. LastErr = NO_ERROR;
  5652. if(ServiceHandle = OpenService(SCMHandle,
  5653. ServicesToDelete->Name,
  5654. SERVICE_ALL_ACCESS)) {
  5655. //
  5656. // stop the service first if we're supposed to
  5657. // wait awhile for the service to stop before deleting the
  5658. // service, since we don't want the service to be in use when
  5659. // delete the service or the service binaries
  5660. if (ServicesToDelete->Flags & SPSVCINST_STOPSERVICE) {
  5661. SERVICE_STATUS ssStatus;
  5662. if (ControlService( ServiceHandle,
  5663. SERVICE_CONTROL_STOP ,
  5664. &ssStatus)
  5665. || (LastErr = GetLastError()) == ERROR_SERVICE_NOT_ACTIVE) {
  5666. #define SLEEP_TIME 4000
  5667. #define LOOP_COUNT 30
  5668. DWORD loopCount = 0;
  5669. do {
  5670. BOOL b;
  5671. b = QueryServiceStatus( ServiceHandle, &ssStatus);
  5672. if ( !b ) {
  5673. LastErr = GetLastError();
  5674. //
  5675. // query failed for some reason, but let's
  5676. // just delete the service anyway
  5677. //
  5678. WriteLogEntry(
  5679. LogContext,
  5680. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5681. MSG_LOG_DELSERVSTAT_ERROR,
  5682. NULL,
  5683. ServicesToDelete->Name
  5684. );
  5685. WriteLogError(
  5686. LogContext,
  5687. DRIVER_LOG_ERROR,
  5688. LastErr);
  5689. break;
  5690. }
  5691. if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
  5692. if ( loopCount++ == LOOP_COUNT ) {
  5693. // still pending after LOOP_COUNT iterations...
  5694. // just delete the service anyway
  5695. //
  5696. WriteLogEntry(
  5697. LogContext,
  5698. DRIVER_LOG_ERROR,
  5699. MSG_LOG_DELSERVPEND_ERROR,
  5700. NULL,
  5701. ServicesToDelete->Name
  5702. );
  5703. break;
  5704. }
  5705. Sleep( SLEEP_TIME );
  5706. } else {
  5707. loopCount++;
  5708. }
  5709. } while ( ssStatus.dwCurrentState != SERVICE_STOPPED
  5710. && loopCount < LOOP_COUNT );
  5711. } else {
  5712. // control service failed for some reason...
  5713. // let's just continue on and try to delete the
  5714. // service anyway
  5715. //
  5716. WriteLogEntry(
  5717. LogContext,
  5718. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5719. MSG_LOG_DELSERVCTRL_ERROR,
  5720. NULL,
  5721. ServicesToDelete->Name
  5722. );
  5723. WriteLogError(
  5724. LogContext,
  5725. DRIVER_LOG_ERROR,
  5726. LastErr);
  5727. }
  5728. }
  5729. if(DeleteService(ServiceHandle) ||
  5730. ((LastErr = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)) {
  5731. //
  5732. // Delete succeeded, or we don't care
  5733. //
  5734. WriteLogEntry(
  5735. LogContext,
  5736. DRIVER_LOG_VERBOSE,
  5737. MSG_LOG_DELSERV_OK,
  5738. NULL,
  5739. ServicesToDelete->Name
  5740. );
  5741. } else {
  5742. // delete service failed for some reason...
  5743. //
  5744. WriteLogEntry(
  5745. LogContext,
  5746. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5747. MSG_LOG_DELSERV_ERROR,
  5748. NULL,
  5749. ServicesToDelete->Name
  5750. );
  5751. WriteLogError(
  5752. LogContext,
  5753. DRIVER_LOG_ERROR,
  5754. LastErr);
  5755. }
  5756. CloseServiceHandle(ServiceHandle);
  5757. } else {
  5758. LastErr = GetLastError();
  5759. if(LastErr == ERROR_SERVICE_DOES_NOT_EXIST) {
  5760. WriteLogEntry(
  5761. LogContext,
  5762. DRIVER_LOG_VERBOSE,
  5763. MSG_LOG_DELSERVNOSERV,
  5764. NULL,
  5765. ServicesToDelete->Name
  5766. );
  5767. } else {
  5768. //
  5769. // open service failed for some reason
  5770. //
  5771. WriteLogEntry(
  5772. LogContext,
  5773. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5774. MSG_LOG_DELSERVOPEN_ERROR,
  5775. NULL,
  5776. ServicesToDelete->Name
  5777. );
  5778. WriteLogError(
  5779. LogContext,
  5780. DRIVER_LOG_ERROR,
  5781. LastErr);
  5782. }
  5783. }
  5784. //
  5785. // Delete the event log entry (if required) if either (a) we succeeded in deleting
  5786. // the service, or (b) the service didn't exist.
  5787. //
  5788. if(ServicesToDelete->DeleteEventLog) {
  5789. if(ServiceHandle || (LastErr == ERROR_SERVICE_DOES_NOT_EXIST)) {
  5790. //
  5791. // We need to delete the associated event log for this service.
  5792. //
  5793. if(!hKeyEventLog) {
  5794. //
  5795. // We haven't opened up the EventLog registry key yet, so do that now.
  5796. //
  5797. PTSTR EndPtr;
  5798. size_t EndCount;
  5799. if(MYVERIFY(SUCCEEDED(StringCchCopyEx(RegistryPath,
  5800. SIZECHARS(RegistryPath),
  5801. pszServicesRegPath,
  5802. &EndPtr,
  5803. &EndCount,
  5804. 0)))) {
  5805. MYVERIFY(SUCCEEDED(StringCchCopy(EndPtr,
  5806. EndCount,
  5807. pszEventLog)));
  5808. }
  5809. if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  5810. RegistryPath,
  5811. 0,
  5812. KEY_READ,
  5813. &hKeyEventLog) != ERROR_SUCCESS) {
  5814. hKeyEventLog = NULL; // make sure this value is still NULL!
  5815. continue;
  5816. }
  5817. }
  5818. //
  5819. // Now open up the event log type key.
  5820. //
  5821. if(RegOpenKeyEx(hKeyEventLog,
  5822. ServicesToDelete->EventLogType,
  5823. 0,
  5824. KEY_READ | KEY_WRITE,
  5825. &hKeyEventLogType) == ERROR_SUCCESS) {
  5826. pSetupRegistryDelnode(hKeyEventLogType, ServicesToDelete->EventLogName);
  5827. RegCloseKey(hKeyEventLogType);
  5828. }
  5829. }
  5830. }
  5831. }
  5832. if(hKeyEventLog) {
  5833. RegCloseKey(hKeyEventLog);
  5834. }
  5835. UnlockServiceDatabase(SCLock);
  5836. }
  5837. CloseServiceHandle(SCMHandle);
  5838. } else {
  5839. Result = GetLastError();
  5840. }
  5841. if (Result != NO_ERROR) {
  5842. WriteLogEntry(
  5843. LogContext,
  5844. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  5845. MSG_LOG_DELSERVSCM_ERROR,
  5846. NULL);
  5847. WriteLogError(
  5848. LogContext,
  5849. DRIVER_LOG_ERROR,
  5850. Result);
  5851. }
  5852. return Result;
  5853. }
  5854. BOOL
  5855. IsDevRemovedFromAllHwProfiles(
  5856. IN PCTSTR DeviceInstanceId,
  5857. IN HMACHINE hMachine
  5858. )
  5859. /*++
  5860. Routine Description:
  5861. This routine determines whether the specified device instance has been removed from
  5862. every hardware profile. The device has been removed from a particular profile if
  5863. its corresponding CsConfigFlags has the CSCONFIGFLAG_DO_NOT_CREATE bit set.
  5864. Arguments:
  5865. DeviceInstanceId - Supplies the name of the device instance to check.
  5866. Return Value:
  5867. If the device exists in only the specified profile, the return value is TRUE,
  5868. otherwise, it is FALSE.
  5869. --*/
  5870. {
  5871. CONFIGRET cr;
  5872. ULONG i = 0;
  5873. HWPROFILEINFO HwProfileInfo;
  5874. ULONG HwProfFlags;
  5875. //
  5876. // Enumerate all the hardware profiles.
  5877. //
  5878. do {
  5879. if((cr = CM_Get_Hardware_Profile_Info_Ex(i, &HwProfileInfo, 0,hMachine)) == CR_SUCCESS) {
  5880. if((CM_Get_HW_Prof_Flags_Ex((DEVINSTID)DeviceInstanceId,
  5881. HwProfileInfo.HWPI_ulHWProfile,
  5882. &HwProfFlags,
  5883. 0,
  5884. hMachine) != CR_SUCCESS) ||
  5885. !(HwProfFlags & CSCONFIGFLAG_DO_NOT_CREATE))
  5886. {
  5887. //
  5888. // If we couldn't retrieve the CSConfigFlags, or if the
  5889. // CSCONFIGFLAG_DO_NOT_CREATE bit was not set, then we've found
  5890. // a profile where the device still exists, so we can bail here.
  5891. //
  5892. return FALSE;
  5893. }
  5894. }
  5895. i++;
  5896. } while(cr != CR_NO_MORE_HW_PROFILES);
  5897. //
  5898. // We didn't find any hardware profile where the device wasn't removed.
  5899. //
  5900. return TRUE;
  5901. }
  5902. DWORD
  5903. GetDevInstConfigFlags(
  5904. IN DEVINST DevInst,
  5905. IN DWORD Default,
  5906. IN HMACHINE hMachine
  5907. )
  5908. /*++
  5909. Routine Description:
  5910. This routine retrieves the ConfigFlags for the specified device instance. If the
  5911. value can not be retrieved, the specified default is returned.
  5912. Arguments:
  5913. DevInst - Supplies the handle of the device instance for which the ConfigFlags value
  5914. is to be retrieved.
  5915. Default - Supplies the default value that should be returned if for some reason the
  5916. ConfigFlags cannot be retrieved.
  5917. Return Value:
  5918. The ConfigFlags value for the specified device instance.
  5919. Notes:
  5920. This is used for device install, and doesn't need to be remotable for 5.0
  5921. --*/
  5922. {
  5923. DWORD ConfigFlags;
  5924. ULONG ConfigFlagsSize = sizeof(ConfigFlags);
  5925. if(CM_Get_DevInst_Registry_Property_Ex(DevInst,
  5926. CM_DRP_CONFIGFLAGS,
  5927. NULL,
  5928. &ConfigFlags,
  5929. &ConfigFlagsSize,
  5930. 0,
  5931. hMachine) != CR_SUCCESS) {
  5932. ConfigFlags = Default;
  5933. }
  5934. return ConfigFlags;
  5935. }
  5936. DWORD
  5937. pSetupDeleteService(
  5938. IN PINFCONTEXT LineContext,
  5939. IN DWORD Flags,
  5940. IN PSETUP_LOG_CONTEXT LogContext
  5941. )
  5942. /*++
  5943. Routine Description:
  5944. This routine processes the specified DelService line in an INF's Service
  5945. install section. The line has the form:
  5946. DelService = <ServiceName>[, [<flags>] [, [<EventLogType>] [, <EventName>]]]
  5947. Flags :
  5948. SPSVCINST_DELETEEVENTLOGENTRY - delete the associated event log entry
  5949. for this service (if there is one).
  5950. If the EventLogType field isn't specified,
  5951. then it is assumed to be "System". If
  5952. the EventName field isn't specified, then
  5953. it is assumed to be the same as the service
  5954. name.
  5955. SPSVCINST_DELETEEVENTLOGENTRY - stop the service before deleting it
  5956. Arguments:
  5957. LineContext - Supplies the context of the DelService line to be processed.
  5958. Flags - specifies one or more SPSVCINST_* flags
  5959. LogContext - Supplies a pointer to a log context to be used for logging.
  5960. Return Value:
  5961. If field 1 on the specified line could not be retrieved, then an error
  5962. is returned. Otherwise, the routine returns NO_ERROR (i.e., the routine
  5963. is considered successful regardless of whether the service to delete
  5964. actually existed).
  5965. --*/
  5966. {
  5967. SVCNAME_NODE TempSvcNode;
  5968. DWORD DelServiceFlags;
  5969. PCTSTR EventLogType, EventLogName;
  5970. BOOL DeleteEventLogEntry;
  5971. DWORD Result = NO_ERROR;
  5972. //
  5973. // Initialize a service name node for a call to DeleteServicesInList.
  5974. //
  5975. if(!SetupGetStringField(LineContext,
  5976. 1,
  5977. TempSvcNode.Name,
  5978. SIZECHARS(TempSvcNode.Name),
  5979. NULL)) {
  5980. return GetLastError();
  5981. }
  5982. //
  5983. // Get the flags field.
  5984. //
  5985. if(!SetupGetIntField(LineContext, 2, (PINT)&DelServiceFlags)) {
  5986. DelServiceFlags = 0;
  5987. }
  5988. DeleteEventLogEntry = (Flags & SPSVCINST_DELETEEVENTLOGENTRY);
  5989. //
  5990. // If the caller specified that the associated event log entry should be
  5991. // deleted, then make sure that flag is set.
  5992. //
  5993. if(DeleteEventLogEntry) {
  5994. DelServiceFlags |= SPSVCINST_DELETEEVENTLOGENTRY;
  5995. }
  5996. if(TempSvcNode.DeleteEventLog = (DelServiceFlags & SPSVCINST_DELETEEVENTLOGENTRY)) {
  5997. //
  5998. // Retrieve the event log type (default is "System") and the event log name
  5999. // (default is the service name).
  6000. //
  6001. if(!(EventLogType = pSetupGetField(LineContext, 3)) || !(*EventLogType)) {
  6002. EventLogType = pszSystem;
  6003. }
  6004. if(!(EventLogName = pSetupGetField(LineContext, 4)) || !(*EventLogName)) {
  6005. EventLogName = TempSvcNode.Name;
  6006. }
  6007. MYVERIFY(SUCCEEDED(StringCchCopy(TempSvcNode.EventLogType,
  6008. SIZECHARS(TempSvcNode.EventLogType),
  6009. EventLogType)));
  6010. MYVERIFY(SUCCEEDED(StringCchCopy(TempSvcNode.EventLogName,
  6011. SIZECHARS(TempSvcNode.EventLogName),
  6012. EventLogName)));
  6013. }
  6014. TempSvcNode.Next = NULL;
  6015. TempSvcNode.Flags = DelServiceFlags | Flags;
  6016. Result = DeleteServicesInList(&TempSvcNode,LogContext);
  6017. return Result;
  6018. }
  6019. BOOL
  6020. IsNativeDriver(
  6021. PCTSTR FullPath
  6022. )
  6023. /*++
  6024. Routine Description:
  6025. determines if a kernel-mode driver binary is valid
  6026. helps avoid bugchecks and catch problems earlier
  6027. Arguments:
  6028. FullPath - Fully qualified path to the binary to be processed
  6029. Return Value:
  6030. TRUE indicates that the file is a native driver
  6031. --*/
  6032. {
  6033. LOADED_IMAGE LoadedImage;
  6034. BOOL RetVal = FALSE;
  6035. PSTR FullPathCopy;
  6036. WORD WantedImage;
  6037. BOOL locked = FALSE;
  6038. #if defined(_IA64_)
  6039. WantedImage = IMAGE_FILE_MACHINE_IA64;
  6040. #elif defined(_AMD64_)
  6041. WantedImage = IMAGE_FILE_MACHINE_AMD64;
  6042. #elif defined(_X86_)
  6043. if(IsWow64) {
  6044. //
  6045. // we don't support installing drivers if in Wow64
  6046. //
  6047. return FALSE;
  6048. }
  6049. WantedImage = IMAGE_FILE_MACHINE_I386;
  6050. #else
  6051. #error Unknown platform
  6052. #endif
  6053. //
  6054. // imagehlp takes a non-const ANSI string, so convert it.
  6055. //
  6056. FullPathCopy = pSetupUnicodeToMultiByte(FullPath, CP_ACP);
  6057. if (!FullPathCopy) {
  6058. return(FALSE);
  6059. }
  6060. ZeroMemory(&LoadedImage,sizeof(LoadedImage));
  6061. //
  6062. // get the image headers
  6063. //
  6064. try {
  6065. EnterCriticalSection(&ImageHlpMutex);
  6066. locked = TRUE;
  6067. } except(EXCEPTION_EXECUTE_HANDLER) {
  6068. }
  6069. if(!locked) {
  6070. MyFree(FullPathCopy);
  6071. return FALSE;
  6072. }
  6073. if (MapAndLoad(
  6074. FullPathCopy,
  6075. NULL,
  6076. &LoadedImage,
  6077. FALSE, // assume it's an exe if there isn't any file extension
  6078. TRUE /* read only */ )) {
  6079. if ((LoadedImage.FileHeader->Signature == IMAGE_NT_SIGNATURE)
  6080. && (LoadedImage.FileHeader->FileHeader.Machine == WantedImage)
  6081. && (LoadedImage.FileHeader->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) {
  6082. RetVal = TRUE;
  6083. }
  6084. UnMapAndLoad(&LoadedImage);
  6085. }
  6086. LeaveCriticalSection(&ImageHlpMutex);
  6087. MyFree(FullPathCopy);
  6088. return(RetVal);
  6089. }
  6090. DWORD
  6091. pSetupAddService(
  6092. IN PINFCONTEXT LineContext,
  6093. OUT PSVCNAME_NODE *SvcListHead,
  6094. IN DWORD Flags,
  6095. IN DEVINST DevInst, OPTIONAL
  6096. OUT PBOOL NullDriverInstalled,
  6097. IN PSETUP_LOG_CONTEXT LogContext
  6098. )
  6099. /*++
  6100. Routine Description:
  6101. This routine processes the specified AddService line in an INF's Service
  6102. install section. The line has the form:
  6103. AddService = <ServiceName>, [<Flags>], <ServiceInstallSection>[, <EventLogInstallSection>[, [<EventLogType>] [, <EventName>]]]
  6104. Currently, the following flags are defined:
  6105. SPSVCINST_TAGTOFRONT (0x1) - Move the tag for this service to the front of its
  6106. group order list
  6107. SPSVCINST_ASSOCSERVICE (0x2) - Associate this service with the device instance
  6108. being installed (only used if DevInst is non-zero)
  6109. SPSVCINST_NOCLOBBER_DISPLAYNAME (0x8) - If this flag is specified, then
  6110. we will not overwrite the service's
  6111. display name, if it already exists.
  6112. SPSVCINST_NOCLOBBER_STARTTYPE (0x10) - If this flag is specified, then
  6113. we will not overwrite the service's
  6114. start type if the service already exists.
  6115. SPSVCINST_NOCLOBBER_ERRORCONTROL (0x20) - If this flag is specified, then
  6116. we will not overwrite the service's
  6117. error control value if the service
  6118. already exists.
  6119. SPSVCINST_NOCLOBBER_LOADORDERGROUP (0x40) - If this flag is specified, then
  6120. we will not overwrite the service's
  6121. load order group if it already
  6122. exists.
  6123. SPSVCINST_NOCLOBBER_DEPENDENCIES (0x80) - If this flag is specified, then
  6124. we will not overwrite the service's
  6125. dependencies list if it already
  6126. exists.
  6127. SPSVCINST_CLOBBER_SECURITY (0x400) - If this flag is specified, then
  6128. security may be overridden.
  6129. A service with the name <ServiceName> is created. The parameters used in the
  6130. call to CreateService are retrieved from the <ServiceInstallSection>, and are
  6131. in the following format (lines not marked as optional must be present or the
  6132. routine will fail):
  6133. DisplayName = <string> ; (optional) 'Friendly name' for the service
  6134. ServiceType = <number> ; one of the SERVICE_* type codes
  6135. StartType = <number> ; one of the SERVICE_* start codes
  6136. ErrorControl = <number> ; one of the SERVICE_ERROR_* error control codes
  6137. ServiceBinary = <string> ; path to binary
  6138. LoadOrderGroup = <string> ; (optional) group to which this service belongs
  6139. Dependencies = <string>[[, <string>]...] ; (optional) list of groups (prefixed with '+')
  6140. ; and services this service depends on
  6141. StartName = <string> ; (optional) driver object name used to load the
  6142. ; driver--only used for drivers & filesystems
  6143. Security = <string> ; (optional) SDS specifying security
  6144. SetupInstallFromInfSection is then called for the <ServiceInstallSection>, which may
  6145. also contain registry modifications (SPINST_REGISTRY is the only flag used). HKR is
  6146. the service entry key.
  6147. Finally, if <EventLogInstallSection> is specified, then a key for this service is
  6148. created under HKLM\System\CurrentControlSet\Services\EventLog, and SetupInstallFromInfSection
  6149. is invoked to do registry modifications specified in that section, with HKR being the event log
  6150. entry (again, only SPINST_REGISTRY is used). By default, the event log type is "System" and the
  6151. event log name is the same as the service name.
  6152. Arguments:
  6153. LineContext - Supplies the context of the AddService line to be processed.
  6154. SvcListHead - Supplies the address of the linked-list head containing a list of
  6155. all services newly created as a result of the current installation. This
  6156. routine first checks for the presence of the service, and if it already exists,
  6157. then it simply modifies the existing one. If the service doesn't already exist,
  6158. then this routine creates a new SVCNAME_NODE, and fills it in with the name of
  6159. the newly-created service. Likewise, if an EventLog entry is given, then the
  6160. presence of an existing one is checked first, and the service node's
  6161. 'DeleteEventLog' field is set to TRUE only if the event log entry didn't
  6162. previously exist. This list is kept to allow for proper clean-up in case
  6163. of a later failure.
  6164. Flags - Specifies how the service should be installed. These flags are basically
  6165. overrides of what the AddService flags field specifies, as described above.
  6166. DevInst - If specified (i.e., non-zero), and if the SPSVCINST_ASSOCSERVICE flag is
  6167. set in either the Flags parameter or the AddService flags INF field, then we will
  6168. store this service name in the device instance's 'Service' registry property.
  6169. NullDriverInstalled - Supplies a pointer to a boolean variable that is set
  6170. upon successful return to indicate whether or not the service install
  6171. specified a null service (i.e., the service name field in the INF AddService
  6172. entry was empty).
  6173. LogContext - Supplies a pointer to a log context so that info may be logged.
  6174. Return Value:
  6175. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error code.
  6176. Remarks:
  6177. Note that we don't do anything special for SERVICE_ADAPTER and SERVICE_RECOGNIZER_DRIVER
  6178. service types. These types are invalid as far as the service contoller is concerned, so
  6179. we just let the create/change service APIs do the validation on them.
  6180. --*/
  6181. {
  6182. PCTSTR ServiceName, InstallSection, EventLogType, EventLogName;
  6183. HINF hInf;
  6184. INFCONTEXT InstallSectionContext;
  6185. DWORD ServiceType, StartType, ErrorControl, ServiceInstallFlags;
  6186. PCTSTR ServiceBinary;
  6187. PCTSTR ActualBinary = NULL;
  6188. TCHAR ServiceBinaryBuffer[MAX_PATH];
  6189. PCTSTR DisplayName = NULL, LoadOrderGroup = NULL,
  6190. StartName = NULL, Security = NULL, Description = NULL;
  6191. PTSTR DependenciesBuffer;
  6192. DWORD TagId;
  6193. PDWORD NewTag;
  6194. DWORD Err;
  6195. SC_HANDLE SCMHandle, ServiceHandle;
  6196. SC_LOCK SCLock;
  6197. HKEY hKeyService, hKeyEventLog;
  6198. TCHAR RegistryPath[SIZECHARS(REGSTR_PATH_SERVICES) + SIZECHARS(DISTR_EVENTLOG) + (2 * 256)];
  6199. DWORD EventLogKeyDisposition;
  6200. SVCNAME_NODE NewSvcNameNode;
  6201. PSVCNAME_NODE TmpNode;
  6202. BOOL NewService;
  6203. INT PathLen;
  6204. BOOL b, BinaryInSysRoot, ServiceHasTag;
  6205. LPQUERY_SERVICE_CONFIG ServiceConfig;
  6206. REGMOD_CONTEXT RegContext;
  6207. BOOL NeedsReboot;
  6208. //
  6209. // Initially, assume we're not doing a null service install.
  6210. //
  6211. *NullDriverInstalled = FALSE;
  6212. NeedsReboot = FALSE;
  6213. //
  6214. // Get the AddService flags.
  6215. //
  6216. if(!SetupGetIntField(LineContext, 2, (PINT)&ServiceInstallFlags)) {
  6217. ServiceInstallFlags = 0;
  6218. }
  6219. //
  6220. // Allow the caller-supplied flags to override the INF.
  6221. //
  6222. ServiceInstallFlags |= Flags;
  6223. //
  6224. // Now get the service name.
  6225. //
  6226. if(!(ServiceName = pSetupGetField(LineContext, 1)) || !(*ServiceName)) {
  6227. //
  6228. // This is only allowed if the SPSVCINST_ASSOCSERVICE flag is set. That
  6229. // indicates to PnP that a null driver installation is allowed, even
  6230. // though the underlying bus didn't report the device as raw-capable.
  6231. //
  6232. if(ServiceInstallFlags & SPSVCINST_ASSOCSERVICE) {
  6233. if(DevInst) {
  6234. CM_Set_DevInst_Registry_Property(DevInst,
  6235. CM_DRP_SERVICE,
  6236. NULL,
  6237. 0,
  6238. 0
  6239. );
  6240. }
  6241. *NullDriverInstalled = TRUE;
  6242. WriteLogEntry(
  6243. LogContext,
  6244. DRIVER_LOG_VERBOSE,
  6245. MSG_LOG_ADDSERV_NULL,
  6246. NULL);
  6247. return NO_ERROR;
  6248. } else {
  6249. return GetLastError();
  6250. }
  6251. }
  6252. //
  6253. // Next, get the name of the install section.
  6254. //
  6255. if(!(InstallSection = pSetupGetField(LineContext, 3))) {
  6256. return GetLastError();
  6257. }
  6258. //
  6259. // Locate the service install section.
  6260. //
  6261. hInf = LineContext->Inf;
  6262. //
  6263. // Retrieve the required values from this section. Don't do validation on them--leave
  6264. // that up to the Service Control Manager.
  6265. //
  6266. if(!SetupFindFirstLine(hInf, InstallSection, pszServiceType, &InstallSectionContext) ||
  6267. !SetupGetIntField(&InstallSectionContext, 1, (PINT)&ServiceType)) {
  6268. return ERROR_BAD_SERVICE_INSTALLSECT;
  6269. }
  6270. if(!SetupFindFirstLine(hInf, InstallSection, pszStartType, &InstallSectionContext) ||
  6271. !SetupGetIntField(&InstallSectionContext, 1, (PINT)&StartType)) {
  6272. return ERROR_BAD_SERVICE_INSTALLSECT;
  6273. }
  6274. if(!SetupFindFirstLine(hInf, InstallSection, pszErrorControl, &InstallSectionContext) ||
  6275. !SetupGetIntField(&InstallSectionContext, 1, (PINT)&ErrorControl)) {
  6276. return ERROR_BAD_SERVICE_INSTALLSECT;
  6277. }
  6278. BinaryInSysRoot = FALSE;
  6279. if(SetupFindFirstLine(hInf, InstallSection, pszServiceBinary, &InstallSectionContext) &&
  6280. (ServiceBinary = pSetupGetField(&InstallSectionContext, 1)) && *ServiceBinary) {
  6281. //
  6282. // Compare the initial part of this path with the WindowsDirectory path. If they're
  6283. // the same, then we strip off that part (including the dividing backslash), and use
  6284. // the rest of the path for the subsequent calls to SCM. This allows SCM to assign
  6285. // the special path to the binary, that is accessible, at any time (i.e, boot-loader on).
  6286. //
  6287. ActualBinary = ServiceBinary;
  6288. PathLen = lstrlen(WindowsDirectory);
  6289. MYASSERT(PathLen);
  6290. //
  6291. // Make sure that the it is possible for the WindowsDirectory to fit in the ServiceBinary
  6292. // path string.
  6293. //
  6294. if(PathLen < lstrlen(ServiceBinary)) {
  6295. //
  6296. // There will never be a trailing backslash in the WindowsDirectory path, unless the
  6297. // installation is at the root of a drive (e.g., C:\). Check this, just to be
  6298. // on the safe side.
  6299. //
  6300. // DBCS-unfriendly code ahead. This isn't a problem in the ANSI version of
  6301. // setupapi presently, because there's no such thing as service installation on Win9x.
  6302. //
  6303. b = (WindowsDirectory[PathLen - 1] == TEXT('\\'));
  6304. if(b || (ServiceBinary[PathLen] == TEXT('\\'))) {
  6305. //
  6306. // The path prefix is in the right format--now we need to see if the two
  6307. // paths actually match. Copy just the prefix part to another buffer, so
  6308. // that we can do the comparison.
  6309. //
  6310. MYVERIFY(SUCCEEDED(StringCchCopy(ServiceBinaryBuffer,
  6311. SIZECHARS(ServiceBinaryBuffer),
  6312. ServiceBinary)));
  6313. ServiceBinaryBuffer[PathLen] = TEXT('\0');
  6314. if(!lstrcmpi(WindowsDirectory, ServiceBinaryBuffer)) {
  6315. //
  6316. // We have a match--take the relative part of the path (relative to SystemRoot),
  6317. // and do one of the following:
  6318. //
  6319. // 1. If it's a driver, simply use the relative part (no preceding backslash).
  6320. // This tells the bootloader/NtLoadDriver that the path is relative to the
  6321. // SystemRoot, so the driver can be loaded no matter what phase it's loaded in.
  6322. //
  6323. // 2. If it's a Win32 service, prepend a %SystemRoot%, so that the service will
  6324. // still be able to start if the drive letter mappings change.
  6325. //
  6326. ServiceBinary += PathLen;
  6327. if(!b) {
  6328. ServiceBinary++;
  6329. }
  6330. if(ServiceType & SERVICE_WIN32) {
  6331. PTSTR EndPtr;
  6332. size_t EndCount;
  6333. if(MYVERIFY(SUCCEEDED(StringCchCopyEx(ServiceBinaryBuffer,
  6334. SIZECHARS(ServiceBinaryBuffer),
  6335. pszSystemRoot,
  6336. &EndPtr,
  6337. &EndCount,
  6338. 0)))) {
  6339. MYVERIFY(SUCCEEDED(StringCchCopy(EndPtr,EndCount,ServiceBinary)));
  6340. }
  6341. ServiceBinary = ServiceBinaryBuffer;
  6342. }
  6343. BinaryInSysRoot = TRUE;
  6344. }
  6345. }
  6346. }
  6347. } else {
  6348. return ERROR_BAD_SERVICE_INSTALLSECT;
  6349. }
  6350. //
  6351. // If this is a driver, then it has to be located under SystemRoot.
  6352. //
  6353. if(ServiceType & (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER)) {
  6354. if(!BinaryInSysRoot) {
  6355. //
  6356. // service install section is wrong, driver path is bad
  6357. //
  6358. return ERROR_BAD_SERVICE_INSTALLSECT;
  6359. }
  6360. if(DevInst) {
  6361. if(!FileExists(ActualBinary,NULL)) {
  6362. //
  6363. // service install section is wrong, it doesn't point to existing
  6364. // binary
  6365. //
  6366. WriteLogEntry(
  6367. LogContext,
  6368. DRIVER_LOG_ERROR,
  6369. MSG_LOG_MISSING_DRIVER,
  6370. NULL,
  6371. ServiceName,
  6372. ActualBinary
  6373. );
  6374. return ERROR_BAD_SERVICE_INSTALLSECT;
  6375. }
  6376. if(!IsNativeDriver(ActualBinary)) {
  6377. //
  6378. // oh oh, we've come this far, only to find that we're going to try and use
  6379. // a non-native or bad driver
  6380. //
  6381. // we might be able to revert original binary if there was one
  6382. //
  6383. if(pSetupRestoreLastKnownGoodFile(ActualBinary,0,LogContext)
  6384. && IsNativeDriver(ActualBinary)) {
  6385. WriteLogEntry(
  6386. LogContext,
  6387. DRIVER_LOG_ERROR,
  6388. MSG_LOG_REVERTED_BAD_DRIVER,
  6389. NULL,
  6390. ServiceName,
  6391. ActualBinary
  6392. );
  6393. } else {
  6394. WriteLogEntry(
  6395. LogContext,
  6396. DRIVER_LOG_ERROR,
  6397. MSG_LOG_HAVE_BAD_DRIVER,
  6398. NULL,
  6399. ServiceName,
  6400. ActualBinary
  6401. );
  6402. }
  6403. return ERROR_DRIVER_NONNATIVE;
  6404. }
  6405. }
  6406. }
  6407. //
  6408. // if this is a boot start driver, we need a reboot for it to start running
  6409. //
  6410. if (StartType == SERVICE_BOOT_START) {
  6411. NeedsReboot = TRUE;
  6412. }
  6413. //
  6414. // Now check for the other, optional, parameters.
  6415. //
  6416. if(SetupFindFirstLine(hInf, InstallSection, pszDisplayName, &InstallSectionContext)) {
  6417. if((DisplayName = pSetupGetField(&InstallSectionContext, 1)) && !(*DisplayName)) {
  6418. DisplayName = NULL;
  6419. }
  6420. }
  6421. if(SetupFindFirstLine(hInf, InstallSection, pszLoadOrderGroup, &InstallSectionContext)) {
  6422. if((LoadOrderGroup = pSetupGetField(&InstallSectionContext, 1)) && !(*LoadOrderGroup)) {
  6423. LoadOrderGroup = NULL;
  6424. }
  6425. }
  6426. if(SetupFindFirstLine(hInf, InstallSection, pszSecurity, &InstallSectionContext)) {
  6427. if((Security = pSetupGetField(&InstallSectionContext, 1)) && !(*Security)) {
  6428. Security = NULL;
  6429. }
  6430. }
  6431. if(SetupFindFirstLine(hInf, InstallSection, pszDescription, &InstallSectionContext)) {
  6432. if((Description = pSetupGetField(&InstallSectionContext, 1)) && !(*Description)) {
  6433. Description = NULL;
  6434. }
  6435. }
  6436. //
  6437. // Only retrieve the StartName parameter for kernel-mode drivers and win32 services.
  6438. //
  6439. if(ServiceType & (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_WIN32)) {
  6440. if(SetupFindFirstLine(hInf, InstallSection, pszStartName, &InstallSectionContext)) {
  6441. if((StartName = pSetupGetField(&InstallSectionContext, 1)) &&
  6442. !(*StartName)) {
  6443. StartName = NULL;
  6444. }
  6445. }
  6446. }
  6447. //
  6448. // We now need to retrieve the multi-sz list of dependencies. This requires memory allocation,
  6449. // so we include everything from here on out in try/except, so that we can do proper clean-up
  6450. // in case we encounter an inpage error.
  6451. //
  6452. DependenciesBuffer = NULL;
  6453. SCMHandle = ServiceHandle = NULL;
  6454. SCLock = NULL;
  6455. hKeyService = hKeyEventLog = NULL;
  6456. Err = NO_ERROR;
  6457. NewService = FALSE;
  6458. ServiceConfig = NULL;
  6459. try {
  6460. if(!(DependenciesBuffer = GetMultiSzFromInf(hInf, InstallSection, pszDependencies, &b)) && b) {
  6461. //
  6462. // Then we failed to retrieve a dependencies list because of an out-of-memory error.
  6463. //
  6464. Err = ERROR_NOT_ENOUGH_MEMORY;
  6465. goto clean0;
  6466. }
  6467. //
  6468. // We've now retrieved all parameters necessary to create a service.
  6469. //
  6470. if(!(SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) {
  6471. Err = GetLastError();
  6472. WriteLogEntry(
  6473. LogContext,
  6474. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6475. MSG_LOG_ADDSERVSCM_ERROR,
  6476. NULL);
  6477. WriteLogError(
  6478. LogContext,
  6479. DRIVER_LOG_ERROR,
  6480. Err);
  6481. goto clean0;
  6482. }
  6483. //
  6484. // Only generate a tag for this service if it has a load order group, and is a kernel or
  6485. // filesystem driver.
  6486. //
  6487. ServiceHasTag = (LoadOrderGroup &&
  6488. (ServiceType & (SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER)));
  6489. NewTag = ServiceHasTag ? &TagId : NULL;
  6490. ServiceHandle = CreateService(SCMHandle,
  6491. ServiceName,
  6492. DisplayName,
  6493. SERVICE_CHANGE_CONFIG,
  6494. ServiceType,
  6495. StartType,
  6496. ErrorControl,
  6497. ServiceBinary,
  6498. LoadOrderGroup,
  6499. NewTag,
  6500. DependenciesBuffer,
  6501. StartName,
  6502. NULL
  6503. );
  6504. if(ServiceHandle) {
  6505. NewService = TRUE;
  6506. NewSvcNameNode.Next = NULL;
  6507. NewSvcNameNode.DeleteEventLog = FALSE;
  6508. MYVERIFY(SUCCEEDED(StringCchCopy(NewSvcNameNode.Name,
  6509. SIZECHARS(NewSvcNameNode.Name),
  6510. ServiceName)));
  6511. if( Security ){
  6512. //
  6513. // Log security being set.
  6514. //
  6515. if( NO_ERROR != (Err = pSetupCallSCE( ST_SCE_SERVICES, ServiceName, NULL, Security, StartType, NULL )) ) {
  6516. WriteLogEntry(
  6517. LogContext,
  6518. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6519. MSG_LOG_ADDSERVSECURE_ERROR,
  6520. NULL,
  6521. ServiceName
  6522. );
  6523. WriteLogError(
  6524. LogContext,
  6525. DRIVER_LOG_ERROR,
  6526. Err);
  6527. goto clean0;
  6528. }
  6529. }
  6530. WriteLogEntry(
  6531. LogContext,
  6532. DRIVER_LOG_VERBOSE,
  6533. MSG_LOG_ADDSERVCREATE_OK,
  6534. NULL,
  6535. ServiceName
  6536. );
  6537. } else {
  6538. //
  6539. // If we were unable to create the service, then check to see if the service already
  6540. // exists. If so, all we need to do is change the configuration parameters in the
  6541. // service.
  6542. //
  6543. if((Err = GetLastError()) != ERROR_SERVICE_EXISTS) {
  6544. WriteLogEntry(
  6545. LogContext,
  6546. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6547. MSG_LOG_ADDSERVCREATE_ERROR,
  6548. NULL,
  6549. ServiceName
  6550. );
  6551. WriteLogError(
  6552. LogContext,
  6553. DRIVER_LOG_ERROR,
  6554. Err);
  6555. goto clean0;
  6556. }
  6557. //
  6558. // Lock the service database.
  6559. //
  6560. if(NO_ERROR != (Err = pAcquireSCMLock(SCMHandle, &SCLock, LogContext))) {
  6561. WriteLogEntry(
  6562. LogContext,
  6563. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6564. MSG_LOG_ADDSERVLOCK_ERROR,
  6565. NULL
  6566. );
  6567. WriteLogError(
  6568. LogContext,
  6569. DRIVER_LOG_ERROR,
  6570. Err);
  6571. goto clean0;
  6572. }
  6573. if(!(ServiceHandle = OpenService(SCMHandle, ServiceName, SERVICE_ALL_ACCESS))) {
  6574. Err = GetLastError();
  6575. WriteLogEntry(
  6576. LogContext,
  6577. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6578. MSG_LOG_ADDSERVOPEN_ERROR,
  6579. NULL,
  6580. ServiceName
  6581. );
  6582. WriteLogError(
  6583. LogContext,
  6584. DRIVER_LOG_ERROR,
  6585. Err);
  6586. goto clean0;
  6587. }
  6588. if((Err = pSetupRetrieveServiceConfig(ServiceHandle, &ServiceConfig)) != NO_ERROR) {
  6589. WriteLogEntry(
  6590. LogContext,
  6591. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6592. MSG_LOG_ADDSERVCONFIG_ERROR,
  6593. NULL,
  6594. ServiceName
  6595. );
  6596. WriteLogError(
  6597. LogContext,
  6598. DRIVER_LOG_ERROR,
  6599. Err);
  6600. //
  6601. // Make sure our ServiceConfig pointer is still NULL.
  6602. //
  6603. ServiceConfig = NULL;
  6604. goto clean0;
  6605. }
  6606. //
  6607. // Since this is an existing driver, then it may already have a perfectly good tag. If
  6608. // so, we don't want to disturb it.
  6609. //
  6610. if(ServiceHasTag) {
  6611. if(ServiceConfig->lpLoadOrderGroup && *(ServiceConfig->lpLoadOrderGroup)) {
  6612. //
  6613. // The service already has a load order group specified.
  6614. // Check to see whether the load order group 'noclobber'
  6615. // flag is set.
  6616. //
  6617. if(ServiceInstallFlags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) {
  6618. //
  6619. // We should leave the existing load order group as-is.
  6620. // We do this by replacing the INF-specified one with the
  6621. // previously-existing one. That way, our code below will
  6622. // still generate a tag if necessary.
  6623. //
  6624. LoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
  6625. }
  6626. if(!lstrcmpi(ServiceConfig->lpLoadOrderGroup, LoadOrderGroup) && ServiceConfig->dwTagId) {
  6627. //
  6628. // The load order group hasn't changed, and there's already a tag assigned, so
  6629. // leave it alone.
  6630. //
  6631. NewTag = NULL;
  6632. TagId = ServiceConfig->dwTagId;
  6633. }
  6634. }
  6635. }
  6636. if(ServiceInstallFlags & SPSVCINST_NOCLOBBER_DISPLAYNAME) {
  6637. //
  6638. // If the service already has a display name, then we don't want
  6639. // to overwrite it.
  6640. //
  6641. if(ServiceConfig->lpDisplayName && *(ServiceConfig->lpDisplayName)) {
  6642. DisplayName = NULL;
  6643. }
  6644. }
  6645. if(ServiceInstallFlags & SPSVCINST_NOCLOBBER_DEPENDENCIES) {
  6646. //
  6647. // If the service already has a dependencies list, then we don't
  6648. // want to overwrite it.
  6649. //
  6650. if(ServiceConfig->lpDependencies && *(ServiceConfig->lpDependencies)) {
  6651. MyFree(DependenciesBuffer);
  6652. DependenciesBuffer = NULL;
  6653. }
  6654. }
  6655. if(!ChangeServiceConfig(ServiceHandle,
  6656. ServiceType,
  6657. (ServiceInstallFlags & SPSVCINST_NOCLOBBER_STARTTYPE)
  6658. ? SERVICE_NO_CHANGE : StartType,
  6659. (ServiceInstallFlags & SPSVCINST_NOCLOBBER_ERRORCONTROL)
  6660. ? SERVICE_NO_CHANGE : ErrorControl,
  6661. ServiceBinary,
  6662. LoadOrderGroup,
  6663. NewTag,
  6664. DependenciesBuffer,
  6665. StartName,
  6666. TEXT(""),
  6667. DisplayName)) {
  6668. Err = GetLastError();
  6669. WriteLogEntry(
  6670. LogContext,
  6671. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6672. MSG_LOG_ADDSERVCHANGE_ERROR,
  6673. NULL,
  6674. ServiceName
  6675. );
  6676. WriteLogError(
  6677. LogContext,
  6678. DRIVER_LOG_ERROR,
  6679. Err);
  6680. goto clean0;
  6681. } else {
  6682. WriteLogEntry(
  6683. LogContext,
  6684. DRIVER_LOG_VERBOSE,
  6685. MSG_LOG_ADDSERVCHANGE_OK,
  6686. NULL,
  6687. ServiceName
  6688. );
  6689. }
  6690. if( Security && (ServiceInstallFlags & SPSVCINST_CLOBBER_SECURITY)){
  6691. //
  6692. // Set/log security
  6693. // in this scenario, service was already running
  6694. // so don't fail if we can't change security
  6695. //
  6696. if( NO_ERROR != (Err = pSetupCallSCE( ST_SCE_SERVICES,
  6697. ServiceName,
  6698. NULL,
  6699. Security,
  6700. (ServiceInstallFlags & SPSVCINST_NOCLOBBER_STARTTYPE)
  6701. ? ServiceConfig->dwStartType
  6702. : StartType,
  6703. NULL )) ) {
  6704. WriteLogEntry(
  6705. LogContext,
  6706. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  6707. MSG_LOG_ADDSERVSECURE_ERROR,
  6708. NULL,
  6709. ServiceName
  6710. );
  6711. WriteLogError(
  6712. LogContext,
  6713. DRIVER_LOG_ERROR,
  6714. Err);
  6715. //goto clean0;
  6716. }
  6717. }
  6718. }
  6719. //
  6720. // we've added/updated the service, now handle the description, which is an oddball
  6721. // parameter since it's a new parameter and isn't present in the prior calls.
  6722. //
  6723. //
  6724. // we ignore failure at this point since this won't effect operation of the service.
  6725. //
  6726. if ((NewService && Description) || ((ServiceInstallFlags & SPSVCINST_NOCLOBBER_DESCRIPTION) == 0)) {
  6727. SERVICE_DESCRIPTION ServiceDescription;
  6728. ServiceDescription.lpDescription = (LPTSTR)Description;
  6729. ChangeServiceConfig2(ServiceHandle, SERVICE_CONFIG_DESCRIPTION,&ServiceDescription);
  6730. }
  6731. //
  6732. // We've successfully created/updated the service. If this service has a load order group
  6733. // tag, then make sure it's in the appropriate GroupOrderList entry.
  6734. //
  6735. // (We ignore failure here, since the service should still work just fine without this.)
  6736. //
  6737. if(ServiceHasTag) {
  6738. pSetupAddTagToGroupOrderListEntry(LoadOrderGroup,
  6739. TagId,
  6740. ServiceInstallFlags & SPSVCINST_TAGTOFRONT);
  6741. }
  6742. //
  6743. // Now process any AddReg and DelReg entries found in this service install section.
  6744. //
  6745. MYVERIFY(SUCCEEDED(StringCchCopy(RegistryPath,
  6746. SIZECHARS(RegistryPath),
  6747. pszServicesRegPath)));
  6748. MYVERIFY(pSetupConcatenatePaths(RegistryPath,
  6749. ServiceName,
  6750. SIZECHARS(RegistryPath),
  6751. NULL
  6752. ));
  6753. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  6754. RegistryPath,
  6755. 0,
  6756. KEY_READ | KEY_WRITE,
  6757. &hKeyService)) != ERROR_SUCCESS) {
  6758. goto clean0;
  6759. }
  6760. ZeroMemory(&RegContext, sizeof(RegContext));
  6761. RegContext.UserRootKey = hKeyService;
  6762. if((Err = pSetupInstallRegistry(hInf, InstallSection, &RegContext)) != NO_ERROR) {
  6763. goto clean0;
  6764. }
  6765. //
  6766. // Now, see if the INF also specifies an EventLog installation section. If so, create a
  6767. // key under HKLM\System\CurrentControlSet\Services\EventLog\System for that service, and
  6768. // run the registry modification lines in the specified install section.
  6769. //
  6770. if((InstallSection = pSetupGetField(LineContext, 4)) && *InstallSection) {
  6771. //
  6772. // Get the (optional) event log type and event log name strings.
  6773. //
  6774. if(!(EventLogType = pSetupGetField(LineContext, 5)) || !(*EventLogType)) {
  6775. EventLogType = pszSystem;
  6776. }
  6777. if(!(EventLogName = pSetupGetField(LineContext, 6)) || !(*EventLogName)) {
  6778. EventLogName = ServiceName;
  6779. }
  6780. //
  6781. // We already have the services database registry path in our registry path buffer. All
  6782. // we need to do is add the \EventLog\<EventLogType>\<EventLogName> part.
  6783. //
  6784. MYVERIFY(SUCCEEDED(StringCchCopy(RegistryPath + CSTRLEN(REGSTR_PATH_SERVICES),
  6785. SIZECHARS(RegistryPath)-CSTRLEN(REGSTR_PATH_SERVICES),
  6786. pszEventLog)));
  6787. MYVERIFY(pSetupConcatenatePaths(RegistryPath,
  6788. EventLogType,
  6789. SIZECHARS(RegistryPath),
  6790. NULL
  6791. ));
  6792. MYVERIFY(pSetupConcatenatePaths(RegistryPath,
  6793. EventLogName,
  6794. SIZECHARS(RegistryPath),
  6795. NULL
  6796. ));
  6797. if((Err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  6798. RegistryPath,
  6799. 0,
  6800. NULL,
  6801. REG_OPTION_NON_VOLATILE,
  6802. KEY_READ | KEY_WRITE,
  6803. NULL,
  6804. &hKeyEventLog,
  6805. &EventLogKeyDisposition)) != ERROR_SUCCESS) {
  6806. goto clean0;
  6807. }
  6808. if(EventLogKeyDisposition == REG_CREATED_NEW_KEY) {
  6809. NewSvcNameNode.DeleteEventLog = TRUE;
  6810. MYVERIFY(SUCCEEDED(StringCchCopy(NewSvcNameNode.EventLogType,
  6811. SIZECHARS(NewSvcNameNode.EventLogType),
  6812. EventLogType)));
  6813. MYVERIFY(SUCCEEDED(StringCchCopy(NewSvcNameNode.EventLogName,
  6814. SIZECHARS(NewSvcNameNode.EventLogName),
  6815. EventLogName)));
  6816. }
  6817. ZeroMemory(&RegContext, sizeof(RegContext));
  6818. RegContext.UserRootKey = hKeyEventLog;
  6819. if((Err = pSetupInstallRegistry(hInf, InstallSection, &RegContext)) != NO_ERROR) {
  6820. goto clean0;
  6821. }
  6822. }
  6823. //
  6824. // Service entry (and optional EventLog entry) were successfully installed. If the
  6825. // AddService flags field in the INF included the SPSVCINST_ASSOCSERVICE flag, _and_
  6826. // the caller supplied us with a non-zero DevInst handle, then we need to set the
  6827. // device instance's 'Service' property to indicate that it is associated with this
  6828. // service.
  6829. //
  6830. if(DevInst && (ServiceInstallFlags & SPSVCINST_ASSOCSERVICE)) {
  6831. CM_Set_DevInst_Registry_Property(DevInst,
  6832. CM_DRP_SERVICE,
  6833. ServiceName,
  6834. (lstrlen(ServiceName) + 1) * sizeof(TCHAR),
  6835. 0
  6836. );
  6837. }
  6838. //
  6839. // If a new service was created, then link a new service name node into the list we
  6840. // were passed in. Don't fret about the case where we can't allocate a node--it just
  6841. // means we won't know about this new service in case clean-up is required later.
  6842. //
  6843. if(NewService) {
  6844. if(TmpNode = MyMalloc(sizeof(SVCNAME_NODE))) {
  6845. MYVERIFY(SUCCEEDED(StringCchCopy(TmpNode->Name,
  6846. SIZECHARS(TmpNode->Name),
  6847. NewSvcNameNode.Name)));
  6848. if(TmpNode->DeleteEventLog = NewSvcNameNode.DeleteEventLog) {
  6849. MYVERIFY(SUCCEEDED(StringCchCopy(TmpNode->EventLogType,
  6850. SIZECHARS(TmpNode->EventLogType),
  6851. NewSvcNameNode.EventLogType)));
  6852. MYVERIFY(SUCCEEDED(StringCchCopy(TmpNode->EventLogName,
  6853. SIZECHARS(TmpNode->EventLogName),
  6854. NewSvcNameNode.EventLogName)));
  6855. }
  6856. TmpNode->Next = *SvcListHead;
  6857. *SvcListHead = TmpNode;
  6858. }
  6859. }
  6860. clean0: ; // nothing to do.
  6861. } except(EXCEPTION_EXECUTE_HANDLER) {
  6862. //
  6863. // If our exception was an AV, then use Win32 invalid param error, otherwise, assume it was
  6864. // an inpage error dealing with a mapped-in file.
  6865. //
  6866. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  6867. //
  6868. // Access the following variables so that the compiler will respect our statement ordering
  6869. // w.r.t. these values. Otherwise, we can't be sure that we know whether or not their
  6870. // corresponding resources should be freed.
  6871. //
  6872. DependenciesBuffer = DependenciesBuffer;
  6873. hKeyService = hKeyService;
  6874. hKeyEventLog = hKeyEventLog;
  6875. ServiceHandle = ServiceHandle;
  6876. SCLock = SCLock;
  6877. SCMHandle = SCMHandle;
  6878. NewService = NewService;
  6879. ServiceConfig = ServiceConfig;
  6880. }
  6881. if(ServiceConfig) {
  6882. MyFree(ServiceConfig);
  6883. }
  6884. if(DependenciesBuffer) {
  6885. MyFree(DependenciesBuffer);
  6886. }
  6887. if(hKeyService) {
  6888. RegCloseKey(hKeyService);
  6889. }
  6890. if(hKeyEventLog) {
  6891. RegCloseKey(hKeyEventLog);
  6892. }
  6893. if(ServiceHandle) {
  6894. CloseServiceHandle(ServiceHandle);
  6895. }
  6896. if(SCLock) {
  6897. UnlockServiceDatabase(SCLock);
  6898. }
  6899. if(SCMHandle) {
  6900. CloseServiceHandle(SCMHandle);
  6901. }
  6902. if (Err != NO_ERROR) {
  6903. if (NewService) {
  6904. //
  6905. // Then we failed part-way through, and need to clean up the service (and
  6906. // possibly event log entry) we created.
  6907. //
  6908. DeleteServicesInList(&NewSvcNameNode,LogContext);
  6909. }
  6910. } else {
  6911. if (NeedsReboot) {
  6912. SetLastError(ERROR_SUCCESS_REBOOT_REQUIRED);
  6913. }
  6914. }
  6915. return Err;
  6916. }
  6917. DWORD
  6918. pSetupRetrieveServiceConfig(
  6919. IN SC_HANDLE ServiceHandle,
  6920. OUT LPQUERY_SERVICE_CONFIG *ServiceConfig
  6921. )
  6922. /*++
  6923. Routine Description:
  6924. This routine allocates a buffer for the specified service's configuration parameters,
  6925. and retrieves those parameters into the buffer. The caller is responsible for freeing
  6926. the buffer.
  6927. Arguments:
  6928. ServiceHandle - supplies a handle to the service being queried
  6929. ServiceConfig - supplies the address of a QUERY_SERVICE_CONFIG pointer that receives
  6930. the address of the allocated buffer containing the requested information.
  6931. Return Value:
  6932. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error code.
  6933. Remarks:
  6934. The pointer whose address is contained in ServiceConfig is guaranteed to be NULL upon
  6935. return if any error occurred.
  6936. --*/
  6937. {
  6938. DWORD ServiceConfigSize = 0, Err;
  6939. MYASSERT(ServiceConfig);
  6940. *ServiceConfig = NULL;
  6941. while(TRUE) {
  6942. if(QueryServiceConfig(ServiceHandle, *ServiceConfig, ServiceConfigSize, &ServiceConfigSize)) {
  6943. MYASSERT(*ServiceConfig);
  6944. return NO_ERROR;
  6945. } else {
  6946. Err = GetLastError();
  6947. if(*ServiceConfig) {
  6948. MyFree(*ServiceConfig);
  6949. }
  6950. if(Err == ERROR_INSUFFICIENT_BUFFER) {
  6951. //
  6952. // Allocate a larger buffer, and try again.
  6953. //
  6954. if(!(*ServiceConfig = MyMalloc(ServiceConfigSize))) {
  6955. return ERROR_NOT_ENOUGH_MEMORY;
  6956. }
  6957. } else {
  6958. *ServiceConfig = NULL;
  6959. return Err;
  6960. }
  6961. }
  6962. }
  6963. }
  6964. DWORD
  6965. RetrieveServiceConfig2(
  6966. IN SC_HANDLE ServiceHandle,
  6967. IN DWORD Level,
  6968. OUT LPBYTE *Buffer
  6969. )
  6970. /*++
  6971. Routine Description:
  6972. This routine allocates a buffer for the specified service's configuration parameters,
  6973. and retrieves those parameters into the buffer. The caller is responsible for freeing
  6974. the buffer.
  6975. Arguments:
  6976. ServiceHandle - supplies a handle to the service being queried
  6977. Level - specifies the information to query
  6978. Buffer - supplies the address of an opaque address to the buffer containing the info.
  6979. Return Value:
  6980. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error code.
  6981. Remarks:
  6982. The pointer whose address is contained in Buffer is guaranteed to be NULL upon
  6983. return if any error occurred.
  6984. --*/
  6985. {
  6986. DWORD ServiceConfigSize = 0, Err;
  6987. *Buffer = NULL;
  6988. while(TRUE) {
  6989. if(QueryServiceConfig2(ServiceHandle, Level, *Buffer, ServiceConfigSize, &ServiceConfigSize)) {
  6990. MYASSERT(*Buffer);
  6991. return NO_ERROR;
  6992. } else {
  6993. Err = GetLastError();
  6994. if(*Buffer) {
  6995. MyFree(*Buffer);
  6996. }
  6997. if(Err == ERROR_INSUFFICIENT_BUFFER) {
  6998. //
  6999. // Allocate a larger buffer, and try again.
  7000. //
  7001. if(!(*Buffer = MyMalloc(ServiceConfigSize))) {
  7002. return ERROR_NOT_ENOUGH_MEMORY;
  7003. }
  7004. } else {
  7005. *Buffer = NULL;
  7006. return Err;
  7007. }
  7008. }
  7009. }
  7010. }
  7011. DWORD
  7012. pSetupAddTagToGroupOrderListEntry(
  7013. IN PCTSTR LoadOrderGroup,
  7014. IN DWORD TagId,
  7015. IN BOOL MoveToFront
  7016. )
  7017. /*++
  7018. Routine Description:
  7019. This routine first creates the specified LoadOrderGroup value entry under
  7020. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\GroupOrderList
  7021. if the value doesn't already exist. The routine then inserts the specified
  7022. tag into the list. If MoveToFront is TRUE, the tag is inserted at the front
  7023. of the list (or moved to the front of the list if it was already present in
  7024. the list). If MoveToFront is FALSE, then the new tag is inserted at the end
  7025. of the list, or left where it is if it already exists in the list.
  7026. Arguments:
  7027. LoadOrderGroup - Specifies the name of the LoadOrderGroup to insert this new
  7028. tag into.
  7029. TagId - Specifies the tag ID to be inserted into the list.
  7030. MoveToFront - If TRUE, place the tag at the front of the list. If FALSE, then
  7031. append the tag to the end of the list, unless it was already there, in which
  7032. case it is left where it was.
  7033. Return Value:
  7034. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error code.
  7035. --*/
  7036. {
  7037. DWORD Err;
  7038. HKEY hKey;
  7039. PDWORD GroupOrderList, p;
  7040. DWORD GroupOrderListSize, DataType, ExtraBytes, i, NumElements;
  7041. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  7042. pszGroupOrderListPath,
  7043. 0,
  7044. KEY_ALL_ACCESS,
  7045. &hKey)) != ERROR_SUCCESS) {
  7046. return Err;
  7047. }
  7048. Err = QueryRegistryValue(hKey,
  7049. LoadOrderGroup,
  7050. (PVOID)(&GroupOrderList),
  7051. &DataType,
  7052. &GroupOrderListSize
  7053. );
  7054. if(Err == NO_ERROR) {
  7055. //
  7056. // Validate the list, and fix it if it's broken.
  7057. //
  7058. if(GroupOrderListSize < sizeof(DWORD)) {
  7059. if(GroupOrderList) {
  7060. MyFree(GroupOrderList);
  7061. }
  7062. if(GroupOrderList = MyMalloc(sizeof(DWORD))) {
  7063. *GroupOrderList = 0;
  7064. GroupOrderListSize = sizeof(DWORD);
  7065. } else {
  7066. Err = ERROR_NOT_ENOUGH_MEMORY;
  7067. goto clean0;
  7068. }
  7069. } else {
  7070. if(ExtraBytes = GroupOrderListSize % sizeof(DWORD)) {
  7071. if(p = MyRealloc(GroupOrderList, GroupOrderListSize + (sizeof(DWORD) - ExtraBytes))) {
  7072. GroupOrderList = p;
  7073. ZeroMemory((PBYTE)GroupOrderList + GroupOrderListSize, ExtraBytes);
  7074. GroupOrderListSize += ExtraBytes;
  7075. } else {
  7076. Err = ERROR_NOT_ENOUGH_MEMORY;
  7077. goto clean1;
  7078. }
  7079. }
  7080. }
  7081. MYASSERT(!(GroupOrderListSize % sizeof(DWORD)));
  7082. //
  7083. // We now have a list that's at least in the correct format. Now validate the list count,
  7084. // and adjust if necessary.
  7085. //
  7086. NumElements = (GroupOrderListSize / sizeof(DWORD)) - 1;
  7087. if(*GroupOrderList != NumElements) {
  7088. if(*GroupOrderList > NumElements) {
  7089. *GroupOrderList = NumElements;
  7090. } else {
  7091. NumElements = *GroupOrderList;
  7092. GroupOrderListSize = (NumElements + 1) * sizeof(DWORD);
  7093. }
  7094. }
  7095. } else {
  7096. //
  7097. // If we ran out of memory, then bail, otherwise, just assume
  7098. // there wasn't a list to retrieve.
  7099. //
  7100. if(Err == ERROR_NOT_ENOUGH_MEMORY) {
  7101. goto clean0;
  7102. } else {
  7103. //
  7104. // Allocate a list containing no tags.
  7105. //
  7106. if(GroupOrderList = MyMalloc(sizeof(DWORD))) {
  7107. *GroupOrderList = 0;
  7108. GroupOrderListSize = sizeof(DWORD);
  7109. } else {
  7110. Err = ERROR_NOT_ENOUGH_MEMORY;
  7111. goto clean0;
  7112. }
  7113. }
  7114. }
  7115. //
  7116. // Now we have a valid group order list to manipulate.
  7117. //
  7118. for(i = 0; i < *GroupOrderList; i++) {
  7119. if(GroupOrderList[i + 1] == TagId) {
  7120. //
  7121. // Tag already exists in the list.
  7122. //
  7123. break;
  7124. }
  7125. }
  7126. if(i == *GroupOrderList) {
  7127. //
  7128. // Then we didn't find the tag in the list. Add it either to the front, or
  7129. // the end, depending on the 'MoveToFront' flag.
  7130. //
  7131. if(p = MyRealloc(GroupOrderList, GroupOrderListSize + sizeof(DWORD))) {
  7132. GroupOrderList = p;
  7133. GroupOrderListSize += sizeof(DWORD);
  7134. } else {
  7135. Err = ERROR_NOT_ENOUGH_MEMORY;
  7136. goto clean1;
  7137. }
  7138. if(MoveToFront) {
  7139. MoveMemory(&(GroupOrderList[2]), &(GroupOrderList[1]), *GroupOrderList * sizeof(DWORD));
  7140. GroupOrderList[1] = TagId;
  7141. } else {
  7142. GroupOrderList[*GroupOrderList + 1] = TagId;
  7143. }
  7144. (*GroupOrderList)++;
  7145. } else if(MoveToFront && i) {
  7146. MoveMemory(&(GroupOrderList[2]), &(GroupOrderList[1]), i * sizeof(DWORD));
  7147. GroupOrderList[1] = TagId;
  7148. }
  7149. //
  7150. // Now write the value back to the registry.
  7151. //
  7152. Err = RegSetValueEx(hKey,
  7153. LoadOrderGroup,
  7154. 0,
  7155. REG_BINARY,
  7156. (PBYTE)GroupOrderList,
  7157. GroupOrderListSize
  7158. );
  7159. clean1:
  7160. MyFree(GroupOrderList);
  7161. clean0:
  7162. RegCloseKey(hKey);
  7163. return Err;
  7164. }
  7165. PTSTR
  7166. pSetupCmdLineAppendString(
  7167. IN OUT PTSTR CmdLine,
  7168. IN PCTSTR Key,
  7169. IN PCTSTR Value, OPTIONAL
  7170. IN OUT PUINT StrLen,
  7171. IN OUT PUINT BufSize
  7172. )
  7173. /*++
  7174. Routine Description:
  7175. Forms a new (multi-sz) command line by appending a list of arguments to
  7176. the current command line. For example:
  7177. CmdLine = SpSetupCmdLineAppendString(
  7178. CmdLine,
  7179. "STF_PRODUCT",
  7180. "NTWKSTA"
  7181. );
  7182. would append "STF_PRODUCT\0NTWKSTA\0\0" to CmdLine.
  7183. Arguments:
  7184. CmdLine - Original CmdLine, to be appended to. THIS BUFFER MUST CONTAIN
  7185. AT LEAST A SINGLE NULL CHARACTER!
  7186. Key - Key identifier
  7187. Value - Value of Key
  7188. StrLen - How long the current string in -- save on strlens
  7189. BufSize - Size of Current Buffer
  7190. Returns:
  7191. Pointer to the new string, or NULL if out-of-memory (in that case, the
  7192. original CmdLine buffer is freed).
  7193. --*/
  7194. {
  7195. PTSTR Ptr;
  7196. UINT NewLen;
  7197. //
  7198. // Handle special cases so we don't end up with empty strings.
  7199. //
  7200. if(!Value || !(*Value)) {
  7201. Value = TEXT("\"\"");
  7202. }
  7203. //
  7204. // "\0" -> 1 chars
  7205. // "\0\0" -> 2 char
  7206. // but we have to back up 1 character...
  7207. //
  7208. NewLen = (*StrLen + 2 + lstrlen(Key) + lstrlen(Value));
  7209. //
  7210. // Allocate more space if necessary.
  7211. //
  7212. if(NewLen >= *BufSize) {
  7213. //
  7214. // Grow the current buffer
  7215. //
  7216. *BufSize += 1024;
  7217. if(Ptr = MyRealloc(CmdLine, (*BufSize) * sizeof(TCHAR))) {
  7218. CmdLine = Ptr;
  7219. } else {
  7220. //
  7221. // Free the memory here so the caller doesn't have to worry about it.
  7222. //
  7223. MyFree(CmdLine);
  7224. return NULL;
  7225. }
  7226. }
  7227. Ptr = &(CmdLine[*StrLen-1]);
  7228. MYVERIFY(SUCCEEDED(StringCchCopy(Ptr,
  7229. *BufSize-(Ptr-CmdLine),
  7230. Key)));
  7231. Ptr = &(CmdLine[*StrLen+lstrlen(Key)]);
  7232. MYVERIFY(SUCCEEDED(StringCchCopy(Ptr,
  7233. *BufSize-(Ptr-CmdLine),
  7234. Value)));
  7235. CmdLine[NewLen-1] = TEXT('\0');
  7236. //
  7237. // Update the length of the buffer that we are using
  7238. //
  7239. *StrLen = NewLen;
  7240. return CmdLine;
  7241. }
  7242. //
  7243. // ANSI version
  7244. //
  7245. BOOL
  7246. WINAPI
  7247. SetupDiGetActualSectionToInstallA(
  7248. IN HINF InfHandle,
  7249. IN PCSTR InfSectionName,
  7250. OUT PSTR InfSectionWithExt, OPTIONAL
  7251. IN DWORD InfSectionWithExtSize,
  7252. OUT PDWORD RequiredSize, OPTIONAL
  7253. OUT PSTR *Extension OPTIONAL
  7254. )
  7255. {
  7256. return SetupDiGetActualSectionToInstallExA(InfHandle,
  7257. InfSectionName,
  7258. NULL,
  7259. InfSectionWithExt,
  7260. InfSectionWithExtSize,
  7261. RequiredSize,
  7262. Extension,
  7263. NULL
  7264. );
  7265. }
  7266. BOOL
  7267. WINAPI
  7268. SetupDiGetActualSectionToInstall(
  7269. IN HINF InfHandle,
  7270. IN PCTSTR InfSectionName,
  7271. OUT PTSTR InfSectionWithExt, OPTIONAL
  7272. IN DWORD InfSectionWithExtSize,
  7273. OUT PDWORD RequiredSize, OPTIONAL
  7274. OUT PTSTR *Extension OPTIONAL
  7275. )
  7276. /*++
  7277. Routine Description:
  7278. (See description of SetupDiGetActualSectionToInstallEx)
  7279. --*/
  7280. {
  7281. return SetupDiGetActualSectionToInstallEx(InfHandle,
  7282. InfSectionName,
  7283. NULL,
  7284. InfSectionWithExt,
  7285. InfSectionWithExtSize,
  7286. RequiredSize,
  7287. Extension,
  7288. NULL
  7289. );
  7290. }
  7291. //
  7292. // ANSI version
  7293. //
  7294. BOOL
  7295. WINAPI
  7296. SetupDiGetActualSectionToInstallExA(
  7297. IN HINF InfHandle,
  7298. IN PCSTR InfSectionName,
  7299. IN PSP_ALTPLATFORM_INFO_V2 AlternatePlatformInfo, OPTIONAL
  7300. OUT PSTR InfSectionWithExt, OPTIONAL
  7301. IN DWORD InfSectionWithExtSize,
  7302. OUT PDWORD RequiredSize, OPTIONAL
  7303. OUT PSTR *Extension, OPTIONAL
  7304. IN PVOID Reserved
  7305. )
  7306. {
  7307. PWSTR infsectionname;
  7308. DWORD rc;
  7309. BOOL b;
  7310. PWSTR extension;
  7311. UINT CharOffset,i;
  7312. PSTR p;
  7313. DWORD requiredsize;
  7314. WCHAR newsection[MAX_SECT_NAME_LEN];
  7315. PSTR ansi;
  7316. rc = pSetupCaptureAndConvertAnsiArg(InfSectionName,&infsectionname);
  7317. if(rc != NO_ERROR) {
  7318. SetLastError(rc);
  7319. return(FALSE);
  7320. }
  7321. b = SetupDiGetActualSectionToInstallExW(
  7322. InfHandle,
  7323. infsectionname,
  7324. AlternatePlatformInfo,
  7325. newsection,
  7326. MAX_SECT_NAME_LEN,
  7327. &requiredsize,
  7328. &extension,
  7329. Reserved
  7330. );
  7331. rc = GetLastError();
  7332. if(b) {
  7333. if(ansi = pSetupUnicodeToAnsi(newsection)) {
  7334. requiredsize = lstrlenA(ansi)+1;
  7335. if(RequiredSize) {
  7336. try {
  7337. *RequiredSize = requiredsize;
  7338. } except(EXCEPTION_EXECUTE_HANDLER) {
  7339. rc = ERROR_INVALID_PARAMETER;
  7340. b = FALSE;
  7341. }
  7342. }
  7343. if(b && InfSectionWithExt) {
  7344. if(requiredsize <= InfSectionWithExtSize) {
  7345. if(FAILED(StringCchCopyA(InfSectionWithExt,
  7346. InfSectionWithExtSize,
  7347. ansi))) {
  7348. //
  7349. // lstrcpy faulted, so InfSectionWithExt must be bad
  7350. //
  7351. rc = ERROR_INVALID_PARAMETER;
  7352. b = FALSE;
  7353. }
  7354. } else {
  7355. rc = ERROR_INSUFFICIENT_BUFFER;
  7356. b = FALSE;
  7357. }
  7358. }
  7359. if(b && Extension) {
  7360. if(extension && InfSectionWithExt) {
  7361. //
  7362. // We need to figure out where the extension is
  7363. // in the converted string. To be DBCS safe we will
  7364. // count characters forward to find it.
  7365. //
  7366. CharOffset = (UINT)(extension - newsection);
  7367. p = InfSectionWithExt;
  7368. for(i=0; i<CharOffset; i++) {
  7369. p = CharNextA(p);
  7370. }
  7371. } else {
  7372. p = NULL;
  7373. }
  7374. try {
  7375. *Extension = p;
  7376. } except(EXCEPTION_EXECUTE_HANDLER) {
  7377. b = FALSE;
  7378. rc = ERROR_INVALID_PARAMETER;
  7379. }
  7380. }
  7381. MyFree(ansi);
  7382. } else {
  7383. rc = ERROR_NOT_ENOUGH_MEMORY;
  7384. b = FALSE;
  7385. }
  7386. }
  7387. MyFree(infsectionname);
  7388. SetLastError(rc);
  7389. return(b);
  7390. }
  7391. BOOL
  7392. WINAPI
  7393. SetupDiGetActualSectionToInstallEx(
  7394. IN HINF InfHandle,
  7395. IN PCTSTR InfSectionName,
  7396. IN PSP_ALTPLATFORM_INFO_V2 AlternatePlatformInfo, OPTIONAL
  7397. OUT PTSTR InfSectionWithExt, OPTIONAL
  7398. IN DWORD InfSectionWithExtSize,
  7399. OUT PDWORD RequiredSize, OPTIONAL
  7400. OUT PTSTR *Extension, OPTIONAL
  7401. IN PVOID Reserved
  7402. )
  7403. /*++
  7404. Routine Description:
  7405. This API finds the appropriate install section to be used when installing
  7406. a device from a Win95-style device INF. Refer to the documentation for
  7407. SetupDiInstallDevice for details on how this determination is made.
  7408. Arguments:
  7409. InfHandle - Supplies the handle of the INF to be installed from.
  7410. InfSectionName - Supplies the name of the install section, as specified by
  7411. the driver node being installed.
  7412. AlternatePlatformInfo - Optionally, supplies alternate platform information
  7413. to be used in selecting the section. Presently, only the Platform and
  7414. ProcessorArchitecture fields are used in formulating the section
  7415. decoration. (NOTE: caller may actually pass in a V1 struct instead--
  7416. this is fine, as the fields we care about are shared in common between
  7417. the V1 and V2 structs.)
  7418. InfSectionWithExt - Optionally, supplies the address of a character buffer
  7419. that receives the actual install section name that should be used
  7420. during installation. If this parameter is NULL, then
  7421. InfSectionWithExtSize must be zero. In that case, the caller is only
  7422. interested in retrieving the required buffer size, so the API will
  7423. return TRUE, and RequiredSize (if supplied), will be set to the size,
  7424. in characters, necessary to store the actual install section name.
  7425. InfSectionWithExtSize - Supplies the size, in characters, of the
  7426. InfSectionWithExt buffer.
  7427. RequiredSize - Optionally, supplies the address of a variable that receives
  7428. the size, in characters, required to store the actual install section
  7429. name (including terminating NULL).
  7430. Extension - Optionally, supplies the address of a variable that receives a
  7431. pointer to the extension (including '.'), or NULL if no extension is to
  7432. be used. The pointer points to the extension within the caller-
  7433. supplied buffer. If the InfSectionWithExt buffer is not supplied, then
  7434. this variable will not be filled in.
  7435. Reserved - Must be NULL.
  7436. Returns:
  7437. If the function succeeds, the return value is TRUE.
  7438. If the function fails, the return value is FALSE. To get extended error
  7439. information, call GetLastError.
  7440. Remarks:
  7441. Presently, the only possible failures are ERROR_INVALID_PARAMETER
  7442. (bad caller-supplied pointers), and ERROR_INSUFFICIENT_BUFFER (if the
  7443. caller-supplied buffer isn't large enough). If we fall back to the
  7444. baseline (i.e., non-decorated) section name, then we simply return it,
  7445. without verifying that the section actually exists.
  7446. --*/
  7447. {
  7448. TCHAR TempInfSectionName[MAX_SECT_NAME_LEN];
  7449. DWORD SectionNameLen = (DWORD)lstrlen(InfSectionName);
  7450. DWORD ExtBufferLen;
  7451. BOOL ExtFound = TRUE;
  7452. DWORD Err = NO_ERROR;
  7453. DWORD Platform;
  7454. PCTSTR NtArchSuffix;
  7455. DWORD NtArchSuffixSize;
  7456. if(Reserved) {
  7457. SetLastError(ERROR_INVALID_PARAMETER);
  7458. return FALSE;
  7459. }
  7460. if(SectionNameLen >= MAX_SECT_NAME_LEN) {
  7461. SetLastError(ERROR_SECTION_NAME_TOO_LONG);
  7462. return FALSE;
  7463. }
  7464. //
  7465. // Both V1 and V2 SP_ALTPLATFORM_INFO structures share a common layout for
  7466. // the first 6 fields (including Platform and ProcessorArchitecture, which
  7467. // are the ones we're interested in here). Thus, all we need to do is
  7468. // verify that the cbSize field is one of the two valid values.
  7469. //
  7470. if(AlternatePlatformInfo) {
  7471. if((AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO_V2)) &&
  7472. (AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO_V1))) {
  7473. SetLastError(ERROR_INVALID_PARAMETER);
  7474. return FALSE;
  7475. }
  7476. }
  7477. MYVERIFY(SUCCEEDED(StringCchCopy(TempInfSectionName,
  7478. SIZECHARS(TempInfSectionName),
  7479. InfSectionName)));
  7480. Platform = AlternatePlatformInfo ? AlternatePlatformInfo->Platform
  7481. : OSVersionInfo.dwPlatformId;
  7482. if(Platform == VER_PLATFORM_WIN32_NT) {
  7483. //
  7484. // We're running on NT, so first try the NT architecture-specific
  7485. // extension, then the generic NT extension.
  7486. //
  7487. if(AlternatePlatformInfo) {
  7488. switch(AlternatePlatformInfo->ProcessorArchitecture) {
  7489. case PROCESSOR_ARCHITECTURE_INTEL :
  7490. NtArchSuffix = pszNtX86Suffix;
  7491. NtArchSuffixSize = sizeof(pszNtX86Suffix);
  7492. break;
  7493. case PROCESSOR_ARCHITECTURE_IA64 :
  7494. NtArchSuffix = pszNtIA64Suffix;
  7495. NtArchSuffixSize = sizeof(pszNtIA64Suffix);
  7496. break;
  7497. case PROCESSOR_ARCHITECTURE_AMD64 :
  7498. NtArchSuffix = pszNtAMD64Suffix;
  7499. NtArchSuffixSize = sizeof(pszNtAMD64Suffix);
  7500. break;
  7501. default:
  7502. //
  7503. // Unknown/invalid architecture
  7504. //
  7505. SetLastError(ERROR_INVALID_PARAMETER);
  7506. return FALSE;
  7507. }
  7508. } else {
  7509. NtArchSuffix = pszNtPlatformSuffix;
  7510. NtArchSuffixSize = sizeof(pszNtPlatformSuffix);
  7511. }
  7512. if(NtArchSuffixSize <=
  7513. sizeof(TempInfSectionName) - (SectionNameLen * sizeof(TCHAR))) {
  7514. MYVERIFY(SUCCEEDED(StringCchCopy(&(TempInfSectionName[SectionNameLen]),
  7515. SIZECHARS(TempInfSectionName)-SectionNameLen,
  7516. NtArchSuffix)));
  7517. if(SetupGetLineCount(InfHandle, TempInfSectionName) != -1) {
  7518. goto clean0;
  7519. }
  7520. //
  7521. // We know the ".NT" suffix is always guaranteed to be shorter than
  7522. // any of the ".NT<architecture>" suffixes, thus we know this will
  7523. // fit in our MAX_SECT_NAME_LEN buffer. (Note: if the OS/arch.
  7524. // decoration is too big, then we won't even try the simple OS
  7525. // decoration. To do otherwise might be misleading, as we'd select
  7526. // a "<reallylongsectionname>.NT" section, even though the INF
  7527. // (erroneously) contains a "<reallylongsectionname>.NTx86" section
  7528. // that doesn't fit.)
  7529. //
  7530. MYVERIFY(SUCCEEDED(StringCchCopy(&(TempInfSectionName[SectionNameLen]),
  7531. SIZECHARS(TempInfSectionName)-SectionNameLen,
  7532. pszNtSuffix)));
  7533. if(SetupGetLineCount(InfHandle, TempInfSectionName) != -1) {
  7534. goto clean0;
  7535. }
  7536. }
  7537. } else {
  7538. //
  7539. // We're running on Windows 95, so try the Windows-specific extension
  7540. //
  7541. if(sizeof(pszWinSuffix) <=
  7542. sizeof(TempInfSectionName) - (SectionNameLen * sizeof(TCHAR))) {
  7543. MYVERIFY(SUCCEEDED(StringCchCopy(&(TempInfSectionName[SectionNameLen]),
  7544. SIZECHARS(TempInfSectionName)-SectionNameLen,
  7545. pszWinSuffix)));
  7546. if(SetupGetLineCount(InfHandle, TempInfSectionName) != -1) {
  7547. goto clean0;
  7548. }
  7549. }
  7550. }
  7551. //
  7552. // If we get to here, then we found no applicable extensions. We'll just use
  7553. // the install section specified.
  7554. //
  7555. TempInfSectionName[SectionNameLen] = TEXT('\0');
  7556. ExtFound = FALSE;
  7557. clean0:
  7558. //
  7559. // Now, determine whether the caller-supplied buffer is large enough to contain
  7560. // the section name.
  7561. //
  7562. ExtBufferLen = lstrlen(TempInfSectionName) + 1;
  7563. //
  7564. // Guard the rest of the routine in try/except, since we're dealing with caller-supplied
  7565. // memory.
  7566. //
  7567. try {
  7568. if(RequiredSize) {
  7569. *RequiredSize = ExtBufferLen;
  7570. }
  7571. if(InfSectionWithExt) {
  7572. if(ExtBufferLen > InfSectionWithExtSize) {
  7573. Err = ERROR_INSUFFICIENT_BUFFER;
  7574. } else {
  7575. MYVERIFY(SUCCEEDED(StringCchCopy(InfSectionWithExt,
  7576. InfSectionWithExtSize,
  7577. TempInfSectionName)));
  7578. if(Extension) {
  7579. *Extension = ExtFound ? InfSectionWithExt + SectionNameLen : NULL;
  7580. }
  7581. }
  7582. }
  7583. } except(EXCEPTION_EXECUTE_HANDLER) {
  7584. Err = ERROR_INVALID_PARAMETER;
  7585. }
  7586. SetLastError(Err);
  7587. return (Err == NO_ERROR);
  7588. }
  7589. BOOL
  7590. pSetupInfIsFromOemLocation(
  7591. IN PCTSTR InfFileName,
  7592. IN BOOL InfDirectoryOnly
  7593. )
  7594. /*++
  7595. Routine Description:
  7596. This routine determines whether the specified INF came from one of the directories
  7597. in our INF search path list. This list can also be limited to just the %windir%\Inf
  7598. directory.
  7599. Arguments:
  7600. InfFileName - Supplies the fully-qualified path of the INF file.
  7601. InfDirectoryOnly - If TRUE, then consider the INF to be from an OEM location if it is
  7602. not in the %windir%\Inf directory (i.e., ignore any other directories in the INF
  7603. search path).
  7604. Returns:
  7605. If the file is from an OEM location (i.e., _not_ in our INF search path list), then
  7606. the return value is TRUE. Otherwise, it is FALSE.
  7607. --*/
  7608. {
  7609. PCTSTR CharPos, DirTruncPos;
  7610. INT DirectoryPathLen, CurSearchPathLen;
  7611. //
  7612. // First, retrieve just the directory path part of the specified filename.
  7613. //
  7614. CharPos = pSetupGetFileTitle(InfFileName);
  7615. DirTruncPos = CharPrev(InfFileName, CharPos);
  7616. //
  7617. // (We know pSetupGetFileTitle will never return a pointer to a path separator character,
  7618. // so the following check is valid.)
  7619. //
  7620. if(*DirTruncPos == TEXT('\\')) {
  7621. //
  7622. // If this is in a root directory (e.g., "A:\"), then we don't want to strip off
  7623. // the trailing backslash.
  7624. //
  7625. if(((DirTruncPos - InfFileName) != 2) || (*CharNext(InfFileName) != TEXT(':'))) {
  7626. CharPos = DirTruncPos;
  7627. }
  7628. }
  7629. DirectoryPathLen = (int)(CharPos - InfFileName);
  7630. //
  7631. // Now, see if this directory matches any of the ones in our search path list.
  7632. //
  7633. if(InfDirectoryOnly) {
  7634. CharPos = InfDirectory;
  7635. } else {
  7636. CharPos = InfSearchPaths;
  7637. }
  7638. do {
  7639. //
  7640. // If the current search path ends in a backslash, we want to strip it off.
  7641. //
  7642. CurSearchPathLen = lstrlen(CharPos);
  7643. if((DirectoryPathLen == CurSearchPathLen) &&
  7644. !_tcsnicmp(CharPos, InfFileName, CurSearchPathLen)) {
  7645. //
  7646. // We've found this directory in our list--we can return.
  7647. //
  7648. return FALSE;
  7649. }
  7650. if(InfDirectoryOnly) {
  7651. //
  7652. // We're only supposed to consider the %windir%\Inf directory--that failed,
  7653. // so we're done.
  7654. //
  7655. break;
  7656. } else {
  7657. //
  7658. // Move on to next component of INF search path.
  7659. //
  7660. CharPos += (CurSearchPathLen + 1);
  7661. }
  7662. } while(*CharPos);
  7663. //
  7664. // If we get to here, then we didn't find the directory in our search path list.
  7665. // Therefore, it's from an OEM location.
  7666. //
  7667. return TRUE;
  7668. }
  7669. BOOL
  7670. WINAPI
  7671. SetupDiInstallDeviceInterfaces(
  7672. IN HDEVINFO DeviceInfoSet,
  7673. IN PSP_DEVINFO_DATA DeviceInfoData
  7674. )
  7675. /*++
  7676. Routine Description:
  7677. Default handler for DIF_INSTALLINTERFACES.
  7678. This routine will install any device interface specified in an
  7679. [<InstallSec>.Interfaces] section, where <InstallSec> is the install
  7680. section name for the selected driver node, potentially decorated with
  7681. an OS/architecture-specific extension (e.g., "InstallSec.NTAmd64.Interfaces").
  7682. Presently, only "AddInterface" lines in this section are processed. Their
  7683. format is as follows:
  7684. AddInterface = <InterfaceClassGuid> [, [<RefString>] [, [<InstallSection>] [, <Flags>]]]
  7685. (There are currently no flags defined for the <Flags> field--must be zero.)
  7686. If the interface class specified by <InterfaceClassGuid> is not already
  7687. installed in the system, we will install it. An INF can optionally specify
  7688. installation actions to be done when this interface class is installed (just
  7689. like it can do for class installers via a [ClassInstall32] section. It does
  7690. this by including an [InterfaceInstall32] section with an entry for the
  7691. interface class to be installed. This section name does not allow os/architecture-
  7692. specific decoration. Instead, the install sections referenced by lines within
  7693. this section are processed with decoration rules. Thus, it is possible to have
  7694. an install entry for interface class <x> that applies to both Win9x and NT, and
  7695. have another install entry for interface class <y> that behaves differently
  7696. depending on whether we're running on Win9x or NT.
  7697. The format of an entry in the [InterfaceInstall32] section is as follows:
  7698. <InterfaceClassGuid> = <InstallSection> [, <Flags>]
  7699. (There are currently no flags defined for the <Flags> field--must be zero.)
  7700. Arguments:
  7701. DeviceInfoSet - Supplies a handle to the device information set containing
  7702. a device information element whose device interfaces are to be installed.
  7703. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for which
  7704. device interfaces are to be installed.
  7705. Return Value:
  7706. If the function succeeds, the return value is TRUE.
  7707. If the function fails, the return value is FALSE. To get extended error
  7708. information, call GetLastError.
  7709. Remarks:
  7710. If no driver is selected (i.e., this is a null-driver installation), then
  7711. this routine does nothing.
  7712. --*/
  7713. {
  7714. return _SetupDiInstallDeviceInterfaces(DeviceInfoSet,
  7715. DeviceInfoData,
  7716. TRUE,
  7717. INVALID_HANDLE_VALUE,
  7718. INVALID_HANDLE_VALUE
  7719. );
  7720. }
  7721. BOOL
  7722. _SetupDiInstallDeviceInterfaces(
  7723. IN HDEVINFO DeviceInfoSet,
  7724. IN PSP_DEVINFO_DATA DeviceInfoData,
  7725. IN BOOL DoFullInstall,
  7726. IN HINF hDeviceInf, OPTIONAL
  7727. IN HSPFILEQ UserFileQ OPTIONAL
  7728. )
  7729. /*++
  7730. Routine Description:
  7731. Worker routine for both SetupDiInstallDeviceInterfaces and SetupDiInstallDriverFiles.
  7732. See the description of SetupDiInstallDeviceInterfaces for more information.
  7733. Arguments:
  7734. DeviceInfoSet - Supplies a handle to the device information set containing
  7735. a device information element whose device interfaces are to be installed.
  7736. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for which
  7737. device interfaces are to be installed.
  7738. DoFullInstall - If TRUE, then the device interfaces will be fully installed.
  7739. Otherwise, only the required files are copied.
  7740. hDeviceInf - Optionally, supplies a handle to the INF for which installation
  7741. is being performed. If this handle is not supplied, the INF specified in
  7742. the selected driver node will be opened. If this handle is not supplied,
  7743. this parameter must be set to INVALID_HANDLE_VALUE.
  7744. UserFileQ - Optionally, supplies a file queue where file operations should be added.
  7745. If this handle is not supplied, then the queue associated with this devinfo
  7746. element will be used (if the DI_NOVCP flag is set), or one will be automatically
  7747. generated and committed. If this handle is not supplied, this parameter must
  7748. be set to INVALID_HANDLE_VALUE.
  7749. Return Value:
  7750. If the function succeeds, the return value is TRUE.
  7751. If the function fails, the return value is FALSE. To get extended error
  7752. information, call GetLastError.
  7753. Remarks:
  7754. During GUI-mode setup on Windows NT, quiet-install behavior is always
  7755. employed in the absence of a user-supplied file queue, regardless of
  7756. whether the device information element has the DI_QUIETINSTALL flag set.
  7757. --*/
  7758. {
  7759. PDEVICE_INFO_SET pDeviceInfoSet;
  7760. DWORD Err, ScanQueueResult;
  7761. PDEVINFO_ELEM DevInfoElem;
  7762. HWND hwndParent;
  7763. PTSTR szInfFileName, szInfSectionName;
  7764. TCHAR InfSectionWithExt[MAX_SECT_NAME_LEN];
  7765. DWORD InfSectionWithExtLength;
  7766. INFCONTEXT DeviceInterfaceInstallLine, InterfaceClassInstallLine;
  7767. TCHAR InterfaceGuidString[GUID_STRING_LEN];
  7768. DWORD InstallFlags;
  7769. GUID InterfaceGuid;
  7770. HKEY hKeyInterfaceClass, hKeyDeviceClassesRoot, hKeyDeviceInterface;
  7771. PINTERFACE_CLASS_TO_INSTALL InterfacesToInstall, InterfaceInstallNode, CurInterfaceInstallNode;
  7772. DWORD RegDisposition;
  7773. BOOL NeedToInstallInterfaceClass;
  7774. TCHAR InterfaceInstallSection[MAX_SECT_NAME_LEN];
  7775. BOOL DoFileCopying;
  7776. BOOL CloseUserFileQ;
  7777. BOOL FreeMsgHandlerContext;
  7778. PSP_FILE_CALLBACK MsgHandler;
  7779. PVOID MsgHandlerContext;
  7780. BOOL MsgHandlerIsNativeCharWidth;
  7781. TCHAR RefString[MAX_PATH];
  7782. SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
  7783. PCTSTR UndecoratedInstallSection;
  7784. BOOL CloseInfHandle;
  7785. PTSTR NeedsSectionList, CurInstallSection;
  7786. BOOL b;
  7787. INT FileQueueNeedsReboot;
  7788. PSETUP_LOG_CONTEXT LogContext = NULL;
  7789. BOOL NoProgressUI;
  7790. DWORD slot_section = 0;
  7791. TCHAR szNewName[MAX_PATH];
  7792. BOOL OemInfFileToCopy = FALSE;
  7793. //
  7794. // A device information element must be specified.
  7795. //
  7796. if(!DeviceInfoData) {
  7797. Err = ERROR_INVALID_PARAMETER;
  7798. goto clean1;
  7799. }
  7800. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  7801. Err = ERROR_INVALID_HANDLE;
  7802. goto clean1;
  7803. }
  7804. LogContext = pDeviceInfoSet->InstallParamBlock.LogContext;
  7805. Err = NO_ERROR;
  7806. hKeyDeviceClassesRoot = hKeyInterfaceClass = hKeyDeviceInterface = INVALID_HANDLE_VALUE;
  7807. InterfacesToInstall = InterfaceInstallNode = NULL;
  7808. CloseUserFileQ = FALSE;
  7809. FreeMsgHandlerContext = FALSE;
  7810. CloseInfHandle = FALSE;
  7811. NeedsSectionList = NULL;
  7812. try {
  7813. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  7814. DeviceInfoData,
  7815. NULL))) {
  7816. Err = ERROR_INVALID_PARAMETER;
  7817. goto clean0;
  7818. }
  7819. //
  7820. // This routine can't install a non-native driver
  7821. //
  7822. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  7823. Err = ERROR_INVALID_FLAGS;
  7824. goto clean0;
  7825. }
  7826. //
  7827. // set the LogContext for this function
  7828. //
  7829. LogContext = DevInfoElem->InstallParamBlock.LogContext;
  7830. //
  7831. // If there's no driver selected (i.e., this is a null driver install)
  7832. // then there's nothing for us to do.
  7833. //
  7834. if(!DevInfoElem->SelectedDriver) {
  7835. goto clean0;
  7836. }
  7837. //
  7838. // Make sure we only use the devinfo element's window if it's valid.
  7839. //
  7840. if(hwndParent = DevInfoElem->InstallParamBlock.hwndParent) {
  7841. if(!IsWindow(hwndParent)) {
  7842. hwndParent = NULL;
  7843. }
  7844. }
  7845. //
  7846. // Ignore the DI_NOFILECOPY flag if we're doing a copy-only installation--that's
  7847. // what setupx does.
  7848. //
  7849. if(DoFileCopying = (!(DevInfoElem->InstallParamBlock.Flags & DI_NOFILECOPY) || !DoFullInstall)) {
  7850. if(UserFileQ == INVALID_HANDLE_VALUE) {
  7851. if(DevInfoElem->InstallParamBlock.Flags & DI_NOVCP) {
  7852. //
  7853. // We must have a user-supplied file queue.
  7854. //
  7855. MYASSERT(DevInfoElem->InstallParamBlock.UserFileQ);
  7856. UserFileQ = DevInfoElem->InstallParamBlock.UserFileQ;
  7857. } else {
  7858. //
  7859. // Create our own queue.
  7860. //
  7861. if((UserFileQ = SetupOpenFileQueue()) != INVALID_HANDLE_VALUE) {
  7862. CloseUserFileQ = TRUE;
  7863. } else {
  7864. //
  7865. // SetupOpenFileQueue sets actual error
  7866. //
  7867. Err = GetLastError();
  7868. goto clean0;
  7869. }
  7870. }
  7871. //
  7872. // Maybe replace the file queue's log context with the DevInfoElem's
  7873. //
  7874. InheritLogContext(LogContext,
  7875. &((PSP_FILE_QUEUE) UserFileQ)->LogContext);
  7876. }
  7877. }
  7878. szInfFileName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  7879. DevInfoElem->SelectedDriver->InfFileName
  7880. );
  7881. szInfSectionName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  7882. DevInfoElem->SelectedDriver->InfSectionName
  7883. );
  7884. if(hDeviceInf == INVALID_HANDLE_VALUE) {
  7885. if((hDeviceInf = SetupOpenInfFile(szInfFileName,
  7886. NULL,
  7887. INF_STYLE_WIN4,
  7888. NULL)) == INVALID_HANDLE_VALUE) {
  7889. Err = GetLastError();
  7890. goto clean0;
  7891. }
  7892. CloseInfHandle = TRUE;
  7893. }
  7894. //
  7895. // Find out the 'real' install section we should be using (i.e., the potentially
  7896. // OS/architecture-specific one.
  7897. //
  7898. if(!SetupDiGetActualSectionToInstall(hDeviceInf,
  7899. szInfSectionName,
  7900. InfSectionWithExt,
  7901. SIZECHARS(InfSectionWithExt),
  7902. &InfSectionWithExtLength,
  7903. NULL
  7904. )) {
  7905. Err = GetLastError();
  7906. goto clean0;
  7907. }
  7908. //
  7909. // Now append the ".Interfaces" extension to the install section name to find
  7910. // the interface install section to run.
  7911. //
  7912. MYVERIFY(SUCCEEDED(StringCchCopy(&(InfSectionWithExt[InfSectionWithExtLength - 1]),
  7913. SIZECHARS(InfSectionWithExt)-(InfSectionWithExtLength - 1),
  7914. pszInterfacesSectionSuffix)));
  7915. if(slot_section == 0) {
  7916. //
  7917. // we haven't done anything about logging section yet...
  7918. //
  7919. slot_section = AllocLogInfoSlotOrLevel(LogContext,DRIVER_LOG_VERBOSE,FALSE);
  7920. //
  7921. // Say what section is about to be installed.
  7922. //
  7923. WriteLogEntry(LogContext,
  7924. slot_section,
  7925. MSG_LOG_INSTALLING_SECTION_FROM,
  7926. NULL,
  7927. InfSectionWithExt,
  7928. szInfFileName);
  7929. }
  7930. //
  7931. // Append the layout INF, if necessary.
  7932. //
  7933. if(DoFileCopying) {
  7934. SetupOpenAppendInfFile(NULL, hDeviceInf, NULL);
  7935. }
  7936. //
  7937. // Append-load any included INFs specified in an "include=" line in our
  7938. // install section.
  7939. //
  7940. AppendLoadIncludedInfs(hDeviceInf, szInfFileName, InfSectionWithExt, DoFileCopying);
  7941. NeedsSectionList = GetMultiSzFromInf(hDeviceInf, InfSectionWithExt, TEXT("needs"), &b);
  7942. if(!NeedsSectionList && b) {
  7943. //
  7944. // Out of memory!
  7945. //
  7946. Err = ERROR_NOT_ENOUGH_MEMORY;
  7947. goto clean0;
  7948. }
  7949. //
  7950. // Process the "AddInterface" lines in this section, as well as those contained with any
  7951. // sections referenced in the "needs=" entry in this section.
  7952. //
  7953. for(CurInstallSection = InfSectionWithExt;
  7954. (CurInstallSection && *CurInstallSection);
  7955. CurInstallSection = (CurInstallSection == InfSectionWithExt)
  7956. ? NeedsSectionList
  7957. : (CurInstallSection + lstrlen(CurInstallSection) + 1))
  7958. {
  7959. if(SetupFindFirstLine(hDeviceInf, CurInstallSection, pszAddInterface, &DeviceInterfaceInstallLine)) {
  7960. do {
  7961. //
  7962. // Retrieve the interface class GUID for this device interface.
  7963. //
  7964. if(!SetupGetStringField(&DeviceInterfaceInstallLine,
  7965. 1,
  7966. InterfaceGuidString,
  7967. SIZECHARS(InterfaceGuidString),
  7968. NULL))
  7969. {
  7970. Err = ERROR_BAD_INTERFACE_INSTALLSECT;
  7971. goto clean0;
  7972. }
  7973. if(NO_ERROR != pSetupGuidFromString(InterfaceGuidString, &InterfaceGuid)) {
  7974. Err = ERROR_BAD_INTERFACE_INSTALLSECT;
  7975. goto clean0;
  7976. }
  7977. //
  7978. // Next, we need to check and see if the specified interface class is already present.
  7979. // If not, we'll need to install it, too.
  7980. //
  7981. NeedToInstallInterfaceClass = FALSE;
  7982. hKeyInterfaceClass = SetupDiOpenClassRegKeyEx(&InterfaceGuid,
  7983. KEY_READ,
  7984. DIOCR_INTERFACE,
  7985. NULL,
  7986. NULL
  7987. );
  7988. if(hKeyInterfaceClass != INVALID_HANDLE_VALUE) {
  7989. //
  7990. // OK, this interface class already exists. We don't need to install it.
  7991. //
  7992. RegCloseKey(hKeyInterfaceClass);
  7993. hKeyInterfaceClass = INVALID_HANDLE_VALUE;
  7994. } else {
  7995. //
  7996. // This interface class isn't currently installed. Check to see if we've
  7997. // already encountered this class (and added it to our list of interface
  7998. // classes to install).
  7999. //
  8000. for(CurInterfaceInstallNode = InterfacesToInstall;
  8001. CurInterfaceInstallNode;
  8002. CurInterfaceInstallNode = CurInterfaceInstallNode->Next)
  8003. {
  8004. if(IsEqualGUID(&InterfaceGuid, &(CurInterfaceInstallNode->InterfaceGuid))) {
  8005. //
  8006. // The installation of this interface class is already in our
  8007. // 'to do' list.
  8008. //
  8009. break;
  8010. }
  8011. }
  8012. if(!CurInterfaceInstallNode) {
  8013. NeedToInstallInterfaceClass = TRUE;
  8014. }
  8015. }
  8016. if(NeedToInstallInterfaceClass) {
  8017. //
  8018. // Look for this interface class GUID in the INF's [InterfaceInstall32] section
  8019. // (if present).
  8020. //
  8021. if(SetupFindFirstLine(hDeviceInf,
  8022. pszInterfaceInstall32,
  8023. InterfaceGuidString,
  8024. &InterfaceClassInstallLine)) {
  8025. //
  8026. // Get the name of the install section for this interface class.
  8027. //
  8028. if((UndecoratedInstallSection = pSetupGetField(&InterfaceClassInstallLine, 1))
  8029. && !(*UndecoratedInstallSection))
  8030. {
  8031. UndecoratedInstallSection = NULL;
  8032. }
  8033. if(!UndecoratedInstallSection) {
  8034. *InterfaceInstallSection = TEXT('\0');
  8035. } else {
  8036. //
  8037. // Get the (potentially) os/architecture-specific install section.
  8038. //
  8039. PTSTR SectionExtension;
  8040. if(!SetupDiGetActualSectionToInstall(hDeviceInf,
  8041. UndecoratedInstallSection,
  8042. InterfaceInstallSection,
  8043. SIZECHARS(InterfaceInstallSection),
  8044. NULL,
  8045. &SectionExtension
  8046. )) {
  8047. Err = GetLastError();
  8048. goto clean0;
  8049. }
  8050. //
  8051. // If this is the undecorated name, then make sure that the section actually exists.
  8052. //
  8053. if(!SectionExtension && (SetupGetLineCount(hDeviceInf, InterfaceInstallSection) == -1)) {
  8054. WriteLogEntry(LogContext,
  8055. DRIVER_LOG_ERROR,
  8056. MSG_LOG_NOSECTION,
  8057. NULL,
  8058. InterfaceInstallSection);
  8059. Err = ERROR_SECTION_NOT_FOUND;
  8060. goto clean0;
  8061. }
  8062. }
  8063. if(!SetupGetIntField(&InterfaceClassInstallLine, 2, (PINT)&InstallFlags)) {
  8064. InstallFlags = 0;
  8065. }
  8066. } else {
  8067. *InterfaceInstallSection = TEXT('\0');
  8068. InstallFlags = 0;
  8069. }
  8070. //
  8071. // At this point, we just want to queue up any file operations required.
  8072. //
  8073. if(DoFileCopying && *InterfaceInstallSection) {
  8074. Err = pSetupInstallFiles(hDeviceInf,
  8075. NULL,
  8076. InterfaceInstallSection,
  8077. NULL,
  8078. NULL,
  8079. NULL,
  8080. SP_COPY_NEWER_OR_SAME | SP_COPY_LANGUAGEAWARE |
  8081. ((DevInfoElem->InstallParamBlock.Flags & DI_NOBROWSE) ? SP_COPY_NOBROWSE : 0),
  8082. NULL,
  8083. UserFileQ,
  8084. TRUE
  8085. );
  8086. if(Err != NO_ERROR) {
  8087. goto clean0;
  8088. }
  8089. }
  8090. //
  8091. // Now add a node onto our 'to do' list of interface classes to install.
  8092. //
  8093. if(InterfaceInstallNode = MyMalloc(sizeof(INTERFACE_CLASS_TO_INSTALL))) {
  8094. InterfaceInstallNode->InterfaceGuid = InterfaceGuid;
  8095. MYVERIFY(SUCCEEDED(StringCchCopy(InterfaceInstallNode->InstallSection,
  8096. SIZECHARS(InterfaceInstallNode->InstallSection),
  8097. InterfaceInstallSection)));
  8098. InterfaceInstallNode->Flags = InstallFlags;
  8099. InterfaceInstallNode->Next = InterfacesToInstall;
  8100. InterfacesToInstall = InterfaceInstallNode;
  8101. //
  8102. // Now set newly allocated node pointer to NULL, so we won't try
  8103. // to free it if we hit an exception.
  8104. //
  8105. InterfaceInstallNode = NULL;
  8106. } else {
  8107. Err = ERROR_NOT_ENOUGH_MEMORY;
  8108. goto clean0;
  8109. }
  8110. }
  8111. //
  8112. // Now queue up any file operations for this particular device interface.
  8113. //
  8114. if(DoFileCopying
  8115. && SetupGetStringField(&DeviceInterfaceInstallLine,
  8116. 3,
  8117. InterfaceInstallSection,
  8118. SIZECHARS(InterfaceInstallSection),
  8119. NULL)
  8120. && *InterfaceInstallSection)
  8121. {
  8122. Err = pSetupInstallFiles(hDeviceInf,
  8123. NULL,
  8124. InterfaceInstallSection,
  8125. NULL,
  8126. NULL,
  8127. NULL,
  8128. SP_COPY_NEWER_OR_SAME | SP_COPY_LANGUAGEAWARE |
  8129. ((DevInfoElem->InstallParamBlock.Flags & DI_NOBROWSE)? SP_COPY_NOBROWSE : 0),
  8130. NULL,
  8131. UserFileQ,
  8132. TRUE
  8133. );
  8134. if(Err != NO_ERROR) {
  8135. goto clean0;
  8136. }
  8137. }
  8138. } while(SetupFindNextMatchLine(&DeviceInterfaceInstallLine, pszAddInterface, &DeviceInterfaceInstallLine));
  8139. }
  8140. }
  8141. //
  8142. // Mark the queue as a device install queue (and make sure there's a
  8143. // catalog node representing our device INF in the queue).
  8144. //
  8145. if(DoFileCopying) {
  8146. MYASSERT(UserFileQ && (UserFileQ != INVALID_HANDLE_VALUE));
  8147. Err = MarkQueueForDeviceInstall(UserFileQ,
  8148. hDeviceInf,
  8149. pStringTableStringFromId(
  8150. pDeviceInfoSet->StringTable,
  8151. DevInfoElem->SelectedDriver->DrvDescription)
  8152. );
  8153. }
  8154. //
  8155. // At this point, we have queued up all the files that need to be
  8156. // copied. If we weren't given a user-supplied queue, then commit our
  8157. // queue now.
  8158. //
  8159. if(CloseUserFileQ) {
  8160. if(Err == NO_ERROR) {
  8161. //
  8162. // Determine whether the queue actually needs to be committed.
  8163. //
  8164. // ScanQueueResult can have 1 of 3 values:
  8165. //
  8166. // 0: Some files were missing--must commit queue.
  8167. //
  8168. // 1: All files to be copied are already present and valid,
  8169. // and the queue is empty--skip committing queue.
  8170. //
  8171. // 2: All files to be copied are present/valid, but
  8172. // del/ren/backup queues not empty--must commit queue.
  8173. // The copy queue will have been emptied, so only
  8174. // del/ren/backup functions will be performed.
  8175. //
  8176. // (jamiehun) see previous case of SetupScanFileQueue for a
  8177. // discussion of DI_FLAGSEX_PREINSTALLBACKUP handling.
  8178. //
  8179. if(!SetupScanFileQueue(UserFileQ,
  8180. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  8181. hwndParent,
  8182. NULL,
  8183. NULL,
  8184. &ScanQueueResult)) {
  8185. //
  8186. // SetupScanFileQueue should really never fail when you
  8187. // don't ask it to call a callback routine, but if it does,
  8188. // just go ahead and commit the queue.
  8189. //
  8190. ScanQueueResult = 0;
  8191. }
  8192. }
  8193. if((Err == NO_ERROR) && (ScanQueueResult != 1)) {
  8194. //
  8195. // We need to commit this file queue. Figure out what message
  8196. // handler to use.
  8197. //
  8198. if(DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  8199. MsgHandler = DevInfoElem->InstallParamBlock.InstallMsgHandler;
  8200. MsgHandlerContext = DevInfoElem->InstallParamBlock.InstallMsgHandlerContext;
  8201. MsgHandlerIsNativeCharWidth = DevInfoElem->InstallParamBlock.InstallMsgHandlerIsNativeCharWidth;
  8202. } else {
  8203. NoProgressUI = (GuiSetupInProgress || (DevInfoElem->InstallParamBlock.Flags & DI_QUIETINSTALL));
  8204. if(MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  8205. hwndParent,
  8206. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  8207. 0,
  8208. 0,
  8209. NULL))
  8210. {
  8211. FreeMsgHandlerContext = TRUE;
  8212. MsgHandler = SetupDefaultQueueCallback;
  8213. MsgHandlerIsNativeCharWidth = TRUE;
  8214. } else {
  8215. Err = ERROR_NOT_ENOUGH_MEMORY;
  8216. }
  8217. }
  8218. //
  8219. // Copy enqueued files.
  8220. //
  8221. if(Err == NO_ERROR) {
  8222. //
  8223. // Call _SetupVerifyQueuedCatalogs separately (i.e., don't
  8224. // let it happen automatically as a result of committing
  8225. // the queue that happens below). We do this beforehand so
  8226. // that we know what unique name was generated when an OEM
  8227. // INF was installed into %windir%\Inf (in case we need to
  8228. // delete the INF/PNF/CAT files later if we encounter an
  8229. // error).
  8230. //
  8231. WriteLogEntry(
  8232. LogContext,
  8233. DRIVER_LOG_TIME,
  8234. MSG_LOG_BEGIN_INTFC_VERIFY_CAT_TIME,
  8235. NULL); // text message
  8236. Err = _SetupVerifyQueuedCatalogs(
  8237. hwndParent,
  8238. UserFileQ,
  8239. (VERCAT_INSTALL_INF_AND_CAT |
  8240. ((DevInfoElem->SelectedDriver->Flags & DNF_INET_DRIVER)
  8241. ? VERCAT_PRIMARY_DEVICE_INF_FROM_INET : 0)),
  8242. szNewName,
  8243. &OemInfFileToCopy
  8244. );
  8245. WriteLogEntry(
  8246. LogContext,
  8247. DRIVER_LOG_TIME,
  8248. MSG_LOG_END_INTFC_VERIFY_CAT_TIME,
  8249. NULL); // text message
  8250. if(Err == NO_ERROR) {
  8251. if(_SetupCommitFileQueue(hwndParent,
  8252. UserFileQ,
  8253. MsgHandler,
  8254. MsgHandlerContext,
  8255. MsgHandlerIsNativeCharWidth
  8256. )) {
  8257. //
  8258. // Check to see whether a reboot is required as a
  8259. // result of committing the queue (i.e., because files
  8260. // were in use, or the INF requested a reboot).
  8261. //
  8262. FileQueueNeedsReboot = SetupPromptReboot(UserFileQ, NULL, TRUE);
  8263. //
  8264. // This should never fail...
  8265. //
  8266. MYASSERT(FileQueueNeedsReboot != -1);
  8267. if(FileQueueNeedsReboot) {
  8268. SetDevnodeNeedsRebootProblem(DevInfoElem, pDeviceInfoSet,
  8269. MSG_LOG_REBOOT_REASON_INUSE);
  8270. }
  8271. } else {
  8272. Err = GetLastError();
  8273. }
  8274. }
  8275. }
  8276. }
  8277. //
  8278. // Close our file queue handle.
  8279. //
  8280. SetupCloseFileQueue(UserFileQ);
  8281. CloseUserFileQ = FALSE;
  8282. //
  8283. // Terminate the default queue callback, if it was created.
  8284. //
  8285. if(FreeMsgHandlerContext) {
  8286. SetupTermDefaultQueueCallback(MsgHandlerContext);
  8287. FreeMsgHandlerContext = FALSE;
  8288. }
  8289. if(Err != NO_ERROR) {
  8290. goto clean0;
  8291. }
  8292. }
  8293. //
  8294. // If all we were asked to do was copy files, then we're done.
  8295. //
  8296. if(!DoFullInstall) {
  8297. goto clean0;
  8298. }
  8299. //
  8300. // Now go through our list of interface classes to install, and install
  8301. // each one.
  8302. //
  8303. if(CurInterfaceInstallNode = InterfacesToInstall) {
  8304. //
  8305. // Open a handle to the root of the DeviceClasses registry branch.
  8306. //
  8307. hKeyDeviceClassesRoot = SetupDiOpenClassRegKeyEx(NULL,
  8308. KEY_ALL_ACCESS,
  8309. DIOCR_INTERFACE,
  8310. NULL,
  8311. NULL
  8312. );
  8313. if(hKeyDeviceClassesRoot == INVALID_HANDLE_VALUE) {
  8314. Err = GetLastError();
  8315. goto clean0;
  8316. }
  8317. do {
  8318. //
  8319. // Presently, the flags field, if present, must be zero.
  8320. //
  8321. if(CurInterfaceInstallNode->Flags) {
  8322. Err = ERROR_INVALID_FLAGS;
  8323. goto clean0;
  8324. }
  8325. pSetupStringFromGuid(&(CurInterfaceInstallNode->InterfaceGuid),
  8326. InterfaceGuidString,
  8327. SIZECHARS(InterfaceGuidString)
  8328. );
  8329. Err = RegCreateKeyEx(hKeyDeviceClassesRoot,
  8330. InterfaceGuidString,
  8331. 0,
  8332. NULL,
  8333. REG_OPTION_NON_VOLATILE,
  8334. KEY_ALL_ACCESS,
  8335. NULL,
  8336. &hKeyInterfaceClass,
  8337. &RegDisposition
  8338. );
  8339. if(Err != ERROR_SUCCESS) {
  8340. //
  8341. // Ensure that the registry handle is still invalid, so we won't try
  8342. // to close it.
  8343. //
  8344. hKeyInterfaceClass = INVALID_HANDLE_VALUE;
  8345. goto clean0;
  8346. }
  8347. //
  8348. // Now run the INF section for this newly-created key.
  8349. //
  8350. if(!SetupInstallFromInfSection(NULL,
  8351. hDeviceInf,
  8352. CurInterfaceInstallNode->InstallSection,
  8353. SPINST_INIFILES
  8354. | SPINST_REGISTRY
  8355. | SPINST_INI2REG
  8356. | SPINST_BITREG
  8357. | SPINST_REGSVR
  8358. | SPINST_UNREGSVR
  8359. | SPINST_PROFILEITEMS,
  8360. hKeyInterfaceClass,
  8361. NULL,
  8362. 0,
  8363. NULL,
  8364. NULL,
  8365. INVALID_HANDLE_VALUE,
  8366. NULL))
  8367. {
  8368. Err = GetLastError();
  8369. //
  8370. // Normally, we would want to clean up this newly-created key.
  8371. // However, the kernel-mode IoRegisterDeviceClassAssociation API
  8372. // will quite happily create the class key if it doesn't exist.
  8373. // Thus, a driver might have registered a device while we were
  8374. // trying to run the INF, and if we deleted the key that might
  8375. // really mess things up. Thus, we'll leave this alone. Since
  8376. // we should never see a failure with this call, this isn't a big
  8377. // deal anyway.
  8378. //
  8379. }
  8380. RegCloseKey(hKeyInterfaceClass);
  8381. hKeyInterfaceClass = INVALID_HANDLE_VALUE;
  8382. if(Err != NO_ERROR) {
  8383. goto clean0;
  8384. }
  8385. CurInterfaceInstallNode = CurInterfaceInstallNode->Next;
  8386. } while(CurInterfaceInstallNode);
  8387. }
  8388. //
  8389. // At this point, we've done everything except for actually registering the
  8390. // device interfaces and (potentially) running INFs against their registry keys.
  8391. // Do that now...
  8392. //
  8393. DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  8394. for(CurInstallSection = InfSectionWithExt;
  8395. (CurInstallSection && *CurInstallSection);
  8396. CurInstallSection = (CurInstallSection == InfSectionWithExt)
  8397. ? NeedsSectionList
  8398. : (CurInstallSection + lstrlen(CurInstallSection) + 1))
  8399. {
  8400. if(SetupFindFirstLine(hDeviceInf, CurInstallSection, pszAddInterface, &DeviceInterfaceInstallLine)) {
  8401. do {
  8402. //
  8403. // Retrieve the interface class GUID for this device interface. (There's
  8404. // no need to check the return status of these two calls, since we've already
  8405. // done this once, and they were fine.
  8406. //
  8407. SetupGetStringField(&DeviceInterfaceInstallLine,
  8408. 1,
  8409. InterfaceGuidString,
  8410. SIZECHARS(InterfaceGuidString),
  8411. NULL
  8412. );
  8413. pSetupGuidFromString(InterfaceGuidString, &InterfaceGuid);
  8414. if(!SetupGetStringField(&DeviceInterfaceInstallLine,
  8415. 2,
  8416. RefString,
  8417. SIZECHARS(RefString),
  8418. NULL))
  8419. {
  8420. *RefString = TEXT('\0');
  8421. }
  8422. if(!SetupGetStringField(&DeviceInterfaceInstallLine,
  8423. 3,
  8424. InterfaceInstallSection,
  8425. SIZECHARS(InterfaceInstallSection),
  8426. NULL))
  8427. {
  8428. *InterfaceInstallSection = TEXT('\0');
  8429. }
  8430. if(!SetupGetIntField(&DeviceInterfaceInstallLine, 4, (PINT)&InstallFlags)) {
  8431. InstallFlags = 0;
  8432. }
  8433. //
  8434. // (Presently, no flags are defined--field, if present, must be zero.
  8435. //
  8436. if(InstallFlags) {
  8437. Err = ERROR_INVALID_FLAGS;
  8438. goto clean0;
  8439. }
  8440. //
  8441. // OK, we have all the information we need to create this device interface.
  8442. //
  8443. if(!SetupDiCreateDeviceInterface(DeviceInfoSet,
  8444. DeviceInfoData,
  8445. &InterfaceGuid,
  8446. (*RefString) ? RefString : NULL,
  8447. 0,
  8448. &DeviceInterfaceData)) {
  8449. Err = GetLastError();
  8450. goto clean0;
  8451. }
  8452. if(*InterfaceInstallSection) {
  8453. //
  8454. // Run the INF against this device interface's registry key.
  8455. //
  8456. hKeyDeviceInterface = SetupDiCreateDeviceInterfaceRegKey(DeviceInfoSet,
  8457. &DeviceInterfaceData,
  8458. 0,
  8459. KEY_ALL_ACCESS,
  8460. INVALID_HANDLE_VALUE,
  8461. NULL
  8462. );
  8463. if(hKeyDeviceInterface == INVALID_HANDLE_VALUE) {
  8464. Err = GetLastError();
  8465. goto clean0;
  8466. }
  8467. //
  8468. // Now run the INF section for this newly-created key.
  8469. //
  8470. if(!SetupInstallFromInfSection(NULL,
  8471. hDeviceInf,
  8472. InterfaceInstallSection,
  8473. SPINST_INIFILES
  8474. | SPINST_REGISTRY
  8475. | SPINST_INI2REG
  8476. | SPINST_BITREG
  8477. | SPINST_REGSVR
  8478. | SPINST_UNREGSVR
  8479. | SPINST_PROFILEITEMS,
  8480. hKeyDeviceInterface,
  8481. NULL,
  8482. 0,
  8483. NULL,
  8484. NULL,
  8485. INVALID_HANDLE_VALUE,
  8486. NULL))
  8487. {
  8488. Err = GetLastError();
  8489. }
  8490. RegCloseKey(hKeyDeviceInterface);
  8491. hKeyDeviceInterface = INVALID_HANDLE_VALUE;
  8492. if(Err != NO_ERROR) {
  8493. goto clean0;
  8494. }
  8495. }
  8496. } while(SetupFindNextMatchLine(&DeviceInterfaceInstallLine, pszAddInterface, &DeviceInterfaceInstallLine));
  8497. }
  8498. }
  8499. clean0: ; // nothing to do.
  8500. } except(EXCEPTION_EXECUTE_HANDLER) {
  8501. Err = ERROR_INVALID_PARAMETER;
  8502. if(hKeyInterfaceClass != INVALID_HANDLE_VALUE) {
  8503. RegCloseKey(hKeyInterfaceClass);
  8504. }
  8505. if(hKeyDeviceInterface != INVALID_HANDLE_VALUE) {
  8506. RegCloseKey(hKeyDeviceInterface);
  8507. }
  8508. if(InterfaceInstallNode) {
  8509. MyFree(InterfaceInstallNode);
  8510. }
  8511. if(FreeMsgHandlerContext) {
  8512. SetupTermDefaultQueueCallback(MsgHandlerContext);
  8513. }
  8514. if(CloseUserFileQ) {
  8515. SetupCloseFileQueue(UserFileQ);
  8516. }
  8517. //
  8518. // Reference the following variables so the compiler will respect statement
  8519. // ordering w.r.t. assignment.
  8520. //
  8521. InterfacesToInstall = InterfacesToInstall;
  8522. CloseInfHandle = CloseInfHandle;
  8523. NeedsSectionList = NeedsSectionList;
  8524. OemInfFileToCopy = OemInfFileToCopy;
  8525. }
  8526. UnlockDeviceInfoSet(pDeviceInfoSet);
  8527. for(CurInterfaceInstallNode = InterfacesToInstall;
  8528. CurInterfaceInstallNode;
  8529. CurInterfaceInstallNode = InterfacesToInstall) {
  8530. InterfacesToInstall = CurInterfaceInstallNode->Next;
  8531. MyFree(CurInterfaceInstallNode);
  8532. }
  8533. if(hKeyDeviceClassesRoot != INVALID_HANDLE_VALUE) {
  8534. RegCloseKey(hKeyDeviceClassesRoot);
  8535. }
  8536. if(CloseInfHandle) {
  8537. MYASSERT(hDeviceInf != INVALID_HANDLE_VALUE);
  8538. SetupCloseInfFile(hDeviceInf);
  8539. }
  8540. if(NeedsSectionList) {
  8541. MyFree(NeedsSectionList);
  8542. }
  8543. clean1:
  8544. if (Err == NO_ERROR) {
  8545. //
  8546. // give a +ve affirmation of Success
  8547. //
  8548. WriteLogEntry(
  8549. LogContext,
  8550. DoFullInstall ? DRIVER_LOG_INFO : DRIVER_LOG_VERBOSE,
  8551. MSG_LOG_INSTALLEDINTERFACES,
  8552. NULL);
  8553. } else {
  8554. //
  8555. // indicate failed, display error
  8556. //
  8557. WriteLogEntry(
  8558. LogContext,
  8559. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  8560. MSG_LOG_INSTALLINTERFACES_ERROR,
  8561. NULL);
  8562. WriteLogError(
  8563. LogContext,
  8564. DRIVER_LOG_ERROR,
  8565. Err);
  8566. //
  8567. // If we copied the OEM INF into the INF directory under a newly-
  8568. // generated name, delete it now.
  8569. //
  8570. if(OemInfFileToCopy) {
  8571. pSetupUninstallOEMInf(szNewName, LogContext, SUOI_FORCEDELETE, NULL);
  8572. }
  8573. }
  8574. if (slot_section) {
  8575. ReleaseLogInfoSlot(LogContext,slot_section);
  8576. }
  8577. SetLastError(Err);
  8578. return(Err == NO_ERROR);
  8579. }
  8580. BOOL
  8581. pSetupGetSourceMediaTypeFromPnf(
  8582. PCTSTR InfName,
  8583. PDWORD SourceMediaType
  8584. )
  8585. /*++
  8586. Routine Description:
  8587. This function will get the Source Media Type from the PNF for a given INF
  8588. file. If the INF does not have a PNF file then the API will fail.
  8589. Arguments:
  8590. InfFileName - Supplies the full path of the INF that we will get the source
  8591. media type from it's PNF.
  8592. SourceMediaType - Supplies a pointer that will be filled in the the source
  8593. media type from the PNF.
  8594. Return Value:
  8595. TRUE if the INF has a PNF and we are able to get a valid source media type
  8596. FALSE if their is no PNF for this INF.
  8597. Remarks:
  8598. --*/
  8599. {
  8600. PLOADED_INF Inf;
  8601. BOOL PnfWasUsed;
  8602. WIN32_FIND_DATA InfFileData;
  8603. UINT ErrorLineNumber;
  8604. BOOL bReturn = FALSE;
  8605. if (FileExists(InfName, &InfFileData)) {
  8606. if(LoadInfFile(InfName,
  8607. &InfFileData,
  8608. INF_STYLE_WIN4,
  8609. LDINF_FLAG_IGNORE_VOLATILE_DIRIDS,
  8610. NULL,
  8611. NULL,
  8612. NULL,
  8613. NULL,
  8614. NULL,
  8615. &Inf,
  8616. &ErrorLineNumber,
  8617. &PnfWasUsed) == NO_ERROR) {
  8618. if (PnfWasUsed) {
  8619. //
  8620. // We were able to open the INF with a PNF. Now get the
  8621. // InfSourceMediaType.
  8622. //
  8623. LockInf(Inf);
  8624. *SourceMediaType = Inf->InfSourceMediaType;
  8625. UnlockInf(Inf);
  8626. bReturn = TRUE;
  8627. }
  8628. FreeInfFile(Inf);
  8629. }
  8630. }
  8631. return bReturn;
  8632. }
  8633. //
  8634. // ANSI version
  8635. //
  8636. BOOL
  8637. WINAPI
  8638. SetupCopyOEMInfA(
  8639. IN PCSTR SourceInfFileName,
  8640. IN PCSTR OEMSourceMediaLocation, OPTIONAL
  8641. IN DWORD OEMSourceMediaType,
  8642. IN DWORD CopyStyle,
  8643. OUT PSTR DestinationInfFileName, OPTIONAL
  8644. IN DWORD DestinationInfFileNameSize,
  8645. OUT PDWORD RequiredSize, OPTIONAL
  8646. OUT PSTR *DestinationInfFileNameComponent OPTIONAL
  8647. )
  8648. {
  8649. PWSTR UnicodeSourceInfFileName, UnicodeOEMSourceMediaLocation, UnicodeFileNameComponent;
  8650. WCHAR UnicodeDestinationInfFileName[MAX_PATH];
  8651. PSTR AnsiDestinationInfFileName;
  8652. DWORD AnsiRequiredSize;
  8653. DWORD rc;
  8654. DWORD CharOffset, i;
  8655. PSTR p;
  8656. WCHAR SourceInfCatalogName[MAX_PATH];
  8657. WCHAR CatalogFilenameOnSystem[MAX_PATH];
  8658. BOOL DifferentOriginalName;
  8659. TCHAR OriginalInfName[MAX_PATH];
  8660. HINF hInf;
  8661. DWORD CodeSigningPolicy;
  8662. BOOL UseOriginalInfName;
  8663. PSETUP_LOG_CONTEXT LogContext = NULL;
  8664. PSP_ALTPLATFORM_INFO_V2 ValidationPlatform;
  8665. rc = pSetupCaptureAndConvertAnsiArg(SourceInfFileName,
  8666. &UnicodeSourceInfFileName
  8667. );
  8668. if(rc != NO_ERROR) {
  8669. SetLastError(rc);
  8670. return FALSE;
  8671. }
  8672. //
  8673. // Open the specified INF.
  8674. //
  8675. hInf = SetupOpenInfFile(UnicodeSourceInfFileName,
  8676. NULL,
  8677. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  8678. NULL
  8679. );
  8680. if(hInf == INVALID_HANDLE_VALUE) {
  8681. rc = GetLastError();
  8682. MyFree(UnicodeSourceInfFileName);
  8683. SetLastError(rc);
  8684. return FALSE;
  8685. }
  8686. ValidationPlatform = NULL;
  8687. //
  8688. // GetCodeSigningPolicyForInf() presently can generate an unhandled
  8689. // exception, so guard the code below in try/except to protect ourselves...
  8690. //
  8691. try {
  8692. if(NO_ERROR != InheritLogContext(((PLOADED_INF)hInf)->LogContext,
  8693. &LogContext)) {
  8694. LogContext = NULL;
  8695. }
  8696. //
  8697. // Retrieve the CatalogFile entry (if present) from this INF's version
  8698. // section.
  8699. //
  8700. rc = pGetInfOriginalNameAndCatalogFile(
  8701. (PLOADED_INF)hInf,
  8702. NULL,
  8703. &DifferentOriginalName,
  8704. OriginalInfName,
  8705. SIZECHARS(OriginalInfName),
  8706. SourceInfCatalogName,
  8707. SIZECHARS(SourceInfCatalogName),
  8708. NULL // always native OS/arch (ver doesn't matter for CatalogFile=)
  8709. );
  8710. if(rc == NO_ERROR) {
  8711. CodeSigningPolicy = GetCodeSigningPolicyForInf(LogContext,
  8712. hInf,
  8713. &ValidationPlatform,
  8714. &UseOriginalInfName
  8715. );
  8716. if(UseOriginalInfName) {
  8717. //
  8718. // If we're looking at an exception INF, make sure it's under its
  8719. // original name.
  8720. //
  8721. if(DifferentOriginalName) {
  8722. rc = ERROR_INVALID_CLASS;
  8723. }
  8724. }
  8725. }
  8726. } except(EXCEPTION_EXECUTE_HANDLER) {
  8727. //
  8728. // If we hit an AV, then use invalid parameter error, otherwise, assume
  8729. // an inpage error when dealing with a mapped-in file (e.g., in the
  8730. // call to GetCodeSigningPolicyForInf).
  8731. //
  8732. rc = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  8733. }
  8734. //
  8735. // We're done with the INF handle
  8736. //
  8737. SetupCloseInfFile(hInf);
  8738. if(rc == NO_ERROR) {
  8739. if(OEMSourceMediaLocation) {
  8740. rc = pSetupCaptureAndConvertAnsiArg(OEMSourceMediaLocation,
  8741. &UnicodeOEMSourceMediaLocation
  8742. );
  8743. } else {
  8744. UnicodeOEMSourceMediaLocation = NULL;
  8745. }
  8746. }
  8747. if(rc != NO_ERROR) {
  8748. MyFree(UnicodeSourceInfFileName);
  8749. if(ValidationPlatform) {
  8750. MyFree(ValidationPlatform);
  8751. }
  8752. SetLastError(rc);
  8753. return FALSE;
  8754. }
  8755. rc = GLE_FN_CALL(FALSE,
  8756. _SetupCopyOEMInf(
  8757. UnicodeSourceInfFileName,
  8758. UnicodeOEMSourceMediaLocation,
  8759. OEMSourceMediaType,
  8760. CopyStyle,
  8761. UnicodeDestinationInfFileName,
  8762. SIZECHARS(UnicodeDestinationInfFileName),
  8763. NULL,
  8764. &UnicodeFileNameComponent,
  8765. (DifferentOriginalName ? OriginalInfName
  8766. : pSetupGetFileTitle(UnicodeSourceInfFileName)),
  8767. (*SourceInfCatalogName ? SourceInfCatalogName : NULL),
  8768. NULL, // no HWND for UI!
  8769. NULL,
  8770. CodeSigningPolicy,
  8771. SCOI_NO_ERRLOG_IF_INF_ALREADY_PRESENT |
  8772. (UseOriginalInfName ? SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES : 0),
  8773. NULL,
  8774. ValidationPlatform,
  8775. NULL,
  8776. CatalogFilenameOnSystem,
  8777. LogContext, // either made-up or thread log context
  8778. NULL,
  8779. NULL)
  8780. );
  8781. if((rc == NO_ERROR) || (rc == ERROR_FILE_EXISTS)) {
  8782. if(DestinationInfFileName || RequiredSize) {
  8783. if(AnsiDestinationInfFileName = pSetupUnicodeToAnsi(UnicodeDestinationInfFileName)) {
  8784. AnsiRequiredSize = lstrlenA(AnsiDestinationInfFileName) + 1;
  8785. if(RequiredSize) {
  8786. try {
  8787. *RequiredSize = AnsiRequiredSize;
  8788. } except(EXCEPTION_EXECUTE_HANDLER) {
  8789. rc = ERROR_INVALID_PARAMETER;
  8790. }
  8791. }
  8792. if(((rc == NO_ERROR) || (rc == ERROR_FILE_EXISTS))
  8793. && DestinationInfFileName) {
  8794. if(AnsiRequiredSize <= DestinationInfFileNameSize) {
  8795. if(FAILED(StringCchCopyA(DestinationInfFileName,
  8796. DestinationInfFileNameSize,
  8797. AnsiDestinationInfFileName))) {
  8798. rc = ERROR_INVALID_PARAMETER;
  8799. } else if(DestinationInfFileNameComponent) {
  8800. //
  8801. // We need to figure out where the extension is
  8802. // in the converted string. To be DBCS safe we will
  8803. // count characters forward to find it.
  8804. //
  8805. CharOffset = (DWORD)(UnicodeFileNameComponent - UnicodeDestinationInfFileName);
  8806. p = DestinationInfFileName;
  8807. for(i = 0; i < CharOffset; i++) {
  8808. p = CharNextA(p);
  8809. }
  8810. try {
  8811. *DestinationInfFileNameComponent = p;
  8812. } except(EXCEPTION_EXECUTE_HANDLER) {
  8813. rc = ERROR_INVALID_PARAMETER;
  8814. }
  8815. }
  8816. } else {
  8817. rc = ERROR_INSUFFICIENT_BUFFER;
  8818. }
  8819. }
  8820. MyFree(AnsiDestinationInfFileName);
  8821. } else {
  8822. rc = ERROR_NOT_ENOUGH_MEMORY;
  8823. }
  8824. } else {
  8825. //
  8826. // It would be dumb to request the filename part of the destination
  8827. // INF path when the path itself wasn't requested, but let's make
  8828. // sure we set this to NULL if that happens.
  8829. //
  8830. if(DestinationInfFileNameComponent) {
  8831. try {
  8832. *DestinationInfFileNameComponent = NULL;
  8833. } except(EXCEPTION_EXECUTE_HANDLER) {
  8834. rc = ERROR_INVALID_PARAMETER;
  8835. }
  8836. }
  8837. }
  8838. }
  8839. MyFree(UnicodeSourceInfFileName);
  8840. if(UnicodeOEMSourceMediaLocation) {
  8841. MyFree(UnicodeOEMSourceMediaLocation);
  8842. }
  8843. if(ValidationPlatform) {
  8844. MyFree(ValidationPlatform);
  8845. }
  8846. DeleteLogContext(LogContext);
  8847. SetLastError(rc);
  8848. return (rc == NO_ERROR);
  8849. }
  8850. BOOL
  8851. WINAPI
  8852. SetupCopyOEMInf(
  8853. IN PCTSTR SourceInfFileName,
  8854. IN PCTSTR OEMSourceMediaLocation, OPTIONAL
  8855. IN DWORD OEMSourceMediaType,
  8856. IN DWORD CopyStyle,
  8857. OUT PTSTR DestinationInfFileName, OPTIONAL
  8858. IN DWORD DestinationInfFileNameSize,
  8859. OUT PDWORD RequiredSize, OPTIONAL
  8860. OUT PTSTR *DestinationInfFileNameComponent OPTIONAL
  8861. )
  8862. /*++
  8863. Routine Description:
  8864. This API copies an INF into %windir%\Inf, giving it a unique name if it
  8865. doesn't already exist there. We determine whether the INF already exists
  8866. in the INF directory as follows:
  8867. 1. All INFs of the form "OEM*.INF" are enumerated, and any that have the
  8868. same file size as that of our INF are binary-compared with it.
  8869. 2. We also look for the INF using its source filename. If a file of the
  8870. same name exists, and is the same size as that of our INF, we
  8871. binary-compare the two to see if they are identical.
  8872. If the INF already exists (by either of the two criteria described above),
  8873. then we will further check to see if the INF specifies a CatalogFile= entry
  8874. in its version section. If so, we will see if that catalog is already
  8875. installed (using the INF's %windir%\Inf primary filename with a ".CAT"
  8876. extension). If there is a catalog installed, but it isn't the same as the
  8877. catalog associated with the source INF, then we won't consider that INF to
  8878. be a match, and we'll keep enumerating looking for a match. This means
  8879. it's possible to have multiple identical INFs contained in %windir%\Inf,
  8880. each having its own unique catalog. (In general, this shouldn't happen,
  8881. since driver package updates should also update the DriverVer information
  8882. in the INF, thus you wouldn't get identical INFs in the first place.) If
  8883. we don't find an existing match (i.e., both INF and CAT), then we'll
  8884. install the INF and CAT under a new, unique name.
  8885. OEM INFs that don't specify a CatalogFile= entry are considered invalid
  8886. w.r.t. digital signature verification.
  8887. In cases where the INF must be copied to %windir%\Inf (i.e., it wasn't
  8888. already there), we'll report any digital signature verification failures
  8889. (based on applicable policy).
  8890. If we decide that the INF/CAT files already exist, then we will use that
  8891. name, and our replacement behavior is based on the caller-specified
  8892. CopyStyle flags. (NOTE: Replacement behavior here refers solely to the
  8893. source media information stored in the PNF. We will not blow away existing
  8894. INFs/PNFs/CATs under any circumstances.)
  8895. Arguments:
  8896. SourceInfFileName - Specifies the full path to the INF to be copied.
  8897. OEMSourceMediaLocation - Specifies source location information to be stored
  8898. in the precompiled INF (.PNF), thus allowing the system to go to the
  8899. correct location for files when installing from this INF. This location
  8900. information is specific to the source media type specified.
  8901. OEMSourceMediaType - Specifies the type of source media that the location
  8902. information references. May be one of the following values:
  8903. SPOST_NONE - No source media information should be stored in the PNF
  8904. file. (OEMSourceMediaLocation is ignored in this case.)
  8905. SPOST_PATH - OEMSourceMediaLocation contains a path to the source media.
  8906. For example, if the media is on a floppy, this path might
  8907. be "A:\". If OEMSourceMediaLocation is NULL, then the path
  8908. is assumed to be the path where the INF is located (unless
  8909. the INF has a corresponding PNF in that location, in which
  8910. case that PNF's source media information will be
  8911. transferred to the destination PNF).
  8912. SPOST_URL - OEMSourceMediaLocation contains a URL indicating the
  8913. internet location where the INF/driver files were retrieved
  8914. from. If OEMSourceMediaLocation is NULL, then it is
  8915. assumed that the default Code Download Manager location was
  8916. used.
  8917. CopyStyle - Specifies flags that control how the INF is copied into the INF
  8918. directory. May be a combination of the following flags (all other
  8919. SP_COPY_* flags are ignored).
  8920. SP_COPY_DELETESOURCE - Delete source file on successful copy.
  8921. SP_COPY_REPLACEONLY - Copy only if this file already exists in the INF
  8922. directory. This could be used to update the
  8923. source location information for an existing INF.
  8924. SP_COPY_NOOVERWRITE - Copy only if this files doesn't already exist in
  8925. the INF directory. If the INF _does_ already
  8926. exist, this API will fail with GetLastError
  8927. returning ERROR_FILE_EXISTS. In this case, the
  8928. destination INF file information output buffers
  8929. will be filled in for the existing INF's filename.
  8930. SP_COPY_OEMINF_CATALOG_ONLY - Don't copy the INF into %windir%\Inf--just
  8931. install its corresponding catalog file.
  8932. If this flag is specified, then the
  8933. destination filename information will only
  8934. be filled out upon successful return if
  8935. the INF is already in the Inf directory.
  8936. SP_COPY_OEM_F6_INF - The Inf was installed by the user during textmode
  8937. setup using F6.
  8938. DestinationInfFileName - Optionally, supplies a character buffer that
  8939. receives the name that the INF was assigned when it was copied into the
  8940. INF directory. If the SP_COPY_NOOVERWRITE flag is specified, and the
  8941. API fails with ERROR_FILE_EXISTS, then this buffer will contain the name
  8942. of the existing INF.
  8943. If the SP_COPY_OEMINF_CATALOG_ONLY flag was specified, then this buffer
  8944. will only be filled in with a destination INF filename if the INF is
  8945. already in the INF directory. Otherwise, this buffer will be set to the
  8946. empty string.
  8947. DestinationInfFileNameSize - Specifies the size, in characters, of the
  8948. DestinationInfFileName buffer, or zero if the buffer is not specified.
  8949. If DestinationInfFileName is specified, and this buffer size is less
  8950. than the size required to return the destination INF name (including
  8951. full path), then this API will fail, and GetLastError will return
  8952. ERROR_INSUFFICIENT_BUFFER.
  8953. RequiredSize - Optionally, supplies the address of a variable that receives
  8954. the size (in characters) required to store the destination INF file name
  8955. (including terminating NULL.
  8956. If the SP_COPY_OEMINF_CATALOG_ONLY flag was specified, then this
  8957. variable will only receive a string length if the INF is already in the
  8958. INF directory. Otherwise, this variable will be set to zero.
  8959. DestinationInfFileNameComponent - Optionally, supplies the address of a
  8960. character pointer that is set, upon successful return (or
  8961. ERROR_FILE_EXISTS), to point to the beginning of the filename component
  8962. of the path stored in DestinationInfFileName.
  8963. If the SP_COPY_OEMINF_CATALOG_ONLY flag was specified, then the
  8964. DestinationInfFileName may be an empty string (see above). In that case
  8965. this character pointer will be set to NULL upon successful return.
  8966. Return Value:
  8967. If the function succeeds, the return value is TRUE.
  8968. If the function fails, the return value is FALSE. To get extended error
  8969. information, call GetLastError.
  8970. --*/
  8971. {
  8972. TCHAR SourceInfCatalogName[MAX_PATH];
  8973. TCHAR CatalogFilenameOnSystem[MAX_PATH];
  8974. DWORD rc;
  8975. BOOL DifferentOriginalName;
  8976. TCHAR OriginalInfName[MAX_PATH];
  8977. HINF hInf;
  8978. DWORD CodeSigningPolicy;
  8979. BOOL UseOriginalInfName;
  8980. PSETUP_LOG_CONTEXT LogContext = NULL;
  8981. PSP_ALTPLATFORM_INFO_V2 ValidationPlatform;
  8982. //
  8983. // Open the specified INF.
  8984. //
  8985. hInf = SetupOpenInfFile(SourceInfFileName,
  8986. NULL,
  8987. INF_STYLE_OLDNT | INF_STYLE_WIN4,
  8988. NULL
  8989. );
  8990. if(hInf == INVALID_HANDLE_VALUE) {
  8991. //
  8992. // last error already set.
  8993. //
  8994. return FALSE;
  8995. }
  8996. ValidationPlatform = NULL;
  8997. //
  8998. // GetCodeSigningPolicyForInf() presently can generate an unhandled
  8999. // exception, so guard the code below in try/except to protect ourselves...
  9000. //
  9001. try {
  9002. if(NO_ERROR != InheritLogContext(((PLOADED_INF)hInf)->LogContext,
  9003. &LogContext)) {
  9004. LogContext = NULL;
  9005. }
  9006. //
  9007. // Retrieve the CatalogFile entry (if present) from this INF's version
  9008. // section.
  9009. //
  9010. rc = pGetInfOriginalNameAndCatalogFile(
  9011. NULL,
  9012. SourceInfFileName,
  9013. &DifferentOriginalName,
  9014. OriginalInfName,
  9015. SIZECHARS(OriginalInfName),
  9016. SourceInfCatalogName,
  9017. SIZECHARS(SourceInfCatalogName),
  9018. NULL // always native OS/arch (ver doesn't matter for CatalogFile=)
  9019. );
  9020. if(rc == NO_ERROR) {
  9021. CodeSigningPolicy = GetCodeSigningPolicyForInf(LogContext,
  9022. hInf,
  9023. &ValidationPlatform,
  9024. &UseOriginalInfName
  9025. );
  9026. if(UseOriginalInfName) {
  9027. //
  9028. // If we're looking at an exception INF, make sure it's under its
  9029. // original name.
  9030. //
  9031. if(DifferentOriginalName) {
  9032. rc = ERROR_INVALID_CLASS;
  9033. }
  9034. }
  9035. }
  9036. } except(EXCEPTION_EXECUTE_HANDLER) {
  9037. //
  9038. // If we hit an AV, then use invalid parameter error, otherwise, assume
  9039. // an inpage error when dealing with a mapped-in file (e.g., in the
  9040. // call to GetCodeSigningPolicyForInf).
  9041. //
  9042. rc = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? ERROR_INVALID_PARAMETER : ERROR_READ_FAULT;
  9043. }
  9044. //
  9045. // We're done with the INF handle
  9046. //
  9047. SetupCloseInfFile(hInf);
  9048. if(rc != NO_ERROR) {
  9049. goto final;
  9050. }
  9051. rc = GLE_FN_CALL(FALSE,
  9052. _SetupCopyOEMInf(
  9053. SourceInfFileName,
  9054. OEMSourceMediaLocation,
  9055. OEMSourceMediaType,
  9056. CopyStyle,
  9057. DestinationInfFileName,
  9058. DestinationInfFileNameSize,
  9059. RequiredSize,
  9060. DestinationInfFileNameComponent,
  9061. (DifferentOriginalName ? OriginalInfName
  9062. : pSetupGetFileTitle(SourceInfFileName)),
  9063. (*SourceInfCatalogName ? SourceInfCatalogName : NULL),
  9064. NULL, // no HWND for UI!
  9065. NULL,
  9066. CodeSigningPolicy,
  9067. SCOI_NO_ERRLOG_IF_INF_ALREADY_PRESENT |
  9068. (UseOriginalInfName ? SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES : 0),
  9069. NULL,
  9070. ValidationPlatform,
  9071. NULL,
  9072. CatalogFilenameOnSystem,
  9073. LogContext, // either made-up or thread log context
  9074. NULL,
  9075. NULL)
  9076. );
  9077. final:
  9078. if(ValidationPlatform) {
  9079. MyFree(ValidationPlatform);
  9080. }
  9081. DeleteLogContext(LogContext);
  9082. SetLastError(rc);
  9083. return (rc == NO_ERROR);
  9084. }
  9085. BOOL
  9086. _SetupCopyOEMInf(
  9087. IN PCTSTR SourceInfFileName,
  9088. IN PCTSTR OEMSourceMediaLocation, OPTIONAL
  9089. IN DWORD OEMSourceMediaType,
  9090. IN DWORD CopyStyle,
  9091. OUT PTSTR DestinationInfFileName, OPTIONAL
  9092. IN DWORD DestinationInfFileNameSize,
  9093. OUT PDWORD RequiredSize, OPTIONAL
  9094. OUT PTSTR *DestinationInfFileNameComponent, OPTIONAL
  9095. IN PCTSTR SourceInfOriginalName,
  9096. IN PCTSTR SourceInfCatalogName, OPTIONAL
  9097. IN HWND Owner,
  9098. IN PCTSTR DeviceDesc, OPTIONAL
  9099. IN DWORD DriverSigningPolicy,
  9100. IN DWORD Flags,
  9101. IN PCTSTR AltCatalogFile, OPTIONAL
  9102. IN PSP_ALTPLATFORM_INFO_V2 AltPlatformInfo, OPTIONAL
  9103. OUT PDWORD DriverSigningError, OPTIONAL
  9104. OUT PTSTR CatalogFilenameOnSystem,
  9105. IN PSETUP_LOG_CONTEXT LogContext,
  9106. IN OUT PVERIFY_CONTEXT VerifyContext, OPTIONAL
  9107. OUT HANDLE *hWVTStateData OPTIONAL
  9108. )
  9109. /*++
  9110. Routine Description:
  9111. (See SetupCopyOEMInf)
  9112. Arguments:
  9113. (See SetupCopyOEMInf)
  9114. SourceInfOriginalName - supplies the simple filename (no path) that this INF
  9115. originally had. This will typically be the same as its current name,
  9116. except in cases where there's a valid PNF for that INF, and the PNF
  9117. specifies a different original name.
  9118. SourceInfCatalogName - Optionally, supplies the simple filename of the
  9119. catalog file specified by the OEM INF via a CatalogFile= entry in its
  9120. [Version] section. If this parameter is not specified, then the INF
  9121. doesn't specify an associated catalog. (NOTE: One may still be used if
  9122. the AltCatalogFile parameter is specified.
  9123. Owner - supplies window handle to be used for any UI related to digital
  9124. signature verification failures.
  9125. DeviceDesc - Optionally, supplies the device description to be used in the
  9126. digital signature verification error dialogs that may be popped up.
  9127. DriverSigningPolicy - supplies the driver signing policy currently in
  9128. effect. Used when determining whether we can validate via an
  9129. Authenticode catalog, and to control behavior of
  9130. _HandleFailedVerification, if necessary.
  9131. Flags - supplies flags which alter the behavior of the routine. May be a
  9132. combination of the following values:
  9133. SCOI_NO_UI_ON_SIGFAIL - indicates whether user should be prompted (per
  9134. DriverSigningPolicy) if a digital signature
  9135. failure is encountered. Used when calling
  9136. _HandleFailedVerification, if necessary.
  9137. SCOI_NO_ERRLOG_ON_MISSING_CATALOG - if there's a signature verification
  9138. failure due to the INF lacking a
  9139. CatalogFile= entry, then that error
  9140. will be ignored if this flag is set
  9141. (no UI will be given, and no log
  9142. entry will be generated).
  9143. SCOI_NO_ERRLOG_IF_INF_ALREADY_PRESENT - If we discover that the INF
  9144. already exists in %windir%\Inf,
  9145. then don't popup any UI and
  9146. don't even generate an error
  9147. log entry.
  9148. SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES - Install the INF and CAT under
  9149. their original (current) names
  9150. (i.e., don't generate a unique
  9151. oem<n>.inf/cat name). Used only
  9152. for exception INFs.
  9153. SCOI_ABORT_IF_UNSIGNED - If the INF is unsigned (and user wants to copy
  9154. it anyway, or policy is Ignore), then _don't_
  9155. copy the INF and instead return the error
  9156. ERROR_SET_SYSTEM_RESTORE_POINT. This gives
  9157. the caller a chance to set a system restore
  9158. point prior to installing the unsigned package.
  9159. SCOI_TRY_UPDATE_PNF - If an existing PNF cannot be updated, don't
  9160. consider it fatal.
  9161. AltCatalogFile - Optionally, supplies the name of a catalog file to be
  9162. installed and used for verification of the INF in cases where the INF
  9163. doesn't specify a CatalogFile= entry (i.e., when the
  9164. SourceInfCatalogName parameter is not specified.
  9165. AltPlatformInfo - Optionally, supplies alternate platform information to be
  9166. used in digital signature verification instead of the default (native)
  9167. platform info.
  9168. DriverSigningError - Optionally, supplies the address of a variable that
  9169. receives the error encountered when attempting to verify the digital
  9170. signature of either the INF or associated catalog. If no digital
  9171. signature problems were encountered, this is set to NO_ERROR. (Note
  9172. that this value can come back as NO_ERROR, yet _SetupCopyOEMInf still
  9173. failed for some other reason).
  9174. If the INF was successfully validated via Authenticode policy, and the
  9175. publisher was in the TrustedPublisher store, then this value will be
  9176. set to ERROR_AUTHENTICODE_TRUSTED_PUBLISHER upon return.
  9177. If the INF was successfully validated via Authenticode policy, and the
  9178. publisher was not in the TrustedPublisher store (hence we must prompt
  9179. the user to establish their trust of the publisher), then this value
  9180. will be set to ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED upon return.
  9181. CatalogFilenameOnSystem - Receives the fully-qualified path of the catalog
  9182. file within the catalog store where this INF's catalog file was
  9183. installed to. This buffer should be at least MAX_PATH bytes (ANSI
  9184. version) or chars (Unicode version).
  9185. LogContext - supplies a LogContext to be passed to GetNewInfName.
  9186. VerifyContext - optionally, supplies the address of a structure that caches
  9187. various verification context handles. These handles may be NULL (if
  9188. not previously acquired, and they may be filled in upon return (in
  9189. either success or failure) if they were acquired during the processing
  9190. of this verification request. It is the caller's responsibility to
  9191. free these various context handles when they are no longer needed by
  9192. calling pSetupFreeVerifyContextMembers.
  9193. hWVTStateData - if supplied, this parameter points to a buffer that
  9194. receives a handle to WinVerifyTrust state data. This handle will be
  9195. returned only when validation was successfully performed using
  9196. Authenticode policy. This handle may be used, for example, to retrieve
  9197. signer info when prompting the user about whether they trust the
  9198. publisher. (The status code returned in the DriverSigningError output
  9199. parameter will indicate whether or not this is necessary.)
  9200. This parameter should only be supplied if the
  9201. DRIVERSIGN_ALLOW_AUTHENTICODE bit is set in the caller-specified
  9202. DriverSigningPolicy. If the routine fails, then this handle will be
  9203. set to NULL.
  9204. It is the caller's responsibility to close this handle when they're
  9205. finished with it by calling pSetupCloseWVTStateData().
  9206. Return Value:
  9207. If the function succeeds, the return value is TRUE.
  9208. If the function fails, the return value is FALSE. To get extended error
  9209. information, call GetLastError.
  9210. --*/
  9211. {
  9212. TCHAR NewName[MAX_PATH];
  9213. DWORD TempRequiredSize, Err;
  9214. NEWINF_COPYTYPE CopyNeeded;
  9215. WIN32_FIND_DATA FindData;
  9216. PLOADED_INF PrecompiledNewInf;
  9217. UINT ErrorLineNumber;
  9218. TCHAR TempOemSourceMediaLocation[MAX_PATH];
  9219. PTSTR TempCharPtr;
  9220. BOOL AlternateCatInstalled;
  9221. DWORD TempDriverSigningError;
  9222. DWORD DefaultSourceMediaType;
  9223. HINF hInf;
  9224. HANDLE LocalhWVTStateData = NULL;
  9225. if(DriverSigningError) {
  9226. *DriverSigningError = NO_ERROR;
  9227. }
  9228. //
  9229. // Initialize the output handle for WinVerifyTrust state data.
  9230. //
  9231. if(hWVTStateData) {
  9232. *hWVTStateData = NULL;
  9233. }
  9234. //
  9235. // If the DestinationInfFileName buffer is NULL, the size had better be
  9236. // zero. Also, make sure the caller passed us a valid OEMSourceMediaType.
  9237. //
  9238. if((!DestinationInfFileName && DestinationInfFileNameSize) ||
  9239. (OEMSourceMediaType >= SPOST_MAX))
  9240. {
  9241. MYASSERT(!DriverSigningError);
  9242. SetLastError(ERROR_INVALID_PARAMETER);
  9243. return FALSE;
  9244. }
  9245. //
  9246. // If we're installing an exception INF, it's illegal to request that we
  9247. // not copy the INF.
  9248. //
  9249. if((Flags & SCOI_KEEP_INF_AND_CAT_ORIGINAL_NAMES) &&
  9250. (CopyStyle & SP_COPY_OEMINF_CATALOG_ONLY))
  9251. {
  9252. SetLastError(ERROR_INVALID_PARAMETER);
  9253. return FALSE;
  9254. }
  9255. Err = NO_ERROR;
  9256. CopyNeeded = NewInfCopyNo;
  9257. AlternateCatInstalled = FALSE;
  9258. TempCharPtr = NULL;
  9259. hInf = INVALID_HANDLE_VALUE;
  9260. try {
  9261. //
  9262. // Check to see if the INF is already in the %windir%\Inf directory,
  9263. // and create a uniquely-named, zero-length placeholder file if it
  9264. // isn't.
  9265. //
  9266. Err = GetNewInfName(Owner,
  9267. SourceInfFileName,
  9268. SourceInfOriginalName,
  9269. SourceInfCatalogName,
  9270. NewName,
  9271. SIZECHARS(NewName),
  9272. &TempRequiredSize,
  9273. &CopyNeeded,
  9274. CopyStyle & SP_COPY_REPLACEONLY,
  9275. DeviceDesc,
  9276. DriverSigningPolicy,
  9277. Flags,
  9278. AltCatalogFile,
  9279. AltPlatformInfo,
  9280. &TempDriverSigningError,
  9281. CatalogFilenameOnSystem,
  9282. LogContext,
  9283. VerifyContext,
  9284. &LocalhWVTStateData
  9285. );
  9286. if((Err == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  9287. (Err == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
  9288. MYASSERT(TempDriverSigningError == NO_ERROR);
  9289. MYASSERT(LocalhWVTStateData);
  9290. if(hWVTStateData) {
  9291. *hWVTStateData = LocalhWVTStateData;
  9292. } else {
  9293. pSetupCloseWVTStateData(LocalhWVTStateData);
  9294. }
  9295. //
  9296. // We want to return Authenticode signature status to the caller
  9297. // via the DriverSigningError output parameter. We can't use a
  9298. // return of FALSE (with GetLastError), since we also need to
  9299. // report ERROR_FILE_EXISTS (which isn't really an error, and needs
  9300. // to be communicated in tandem with the Authenticode status).
  9301. //
  9302. TempDriverSigningError = Err;
  9303. Err = NO_ERROR;
  9304. } else {
  9305. MYASSERT(!LocalhWVTStateData);
  9306. }
  9307. if(DriverSigningError) {
  9308. *DriverSigningError = TempDriverSigningError;
  9309. }
  9310. if(Err != NO_ERROR) {
  9311. //
  9312. // Value of CopyNeeded parameter is undefined upon error, but we do
  9313. // know that no clean-up will be necessary if GetNewInfName fails.
  9314. //
  9315. CopyNeeded = NewInfCopyNo;
  9316. //
  9317. // If we were only trying to get the catalog installed, and the
  9318. // failure was for some reason _other_ than a digital signature
  9319. // verification failure (e.g., we couldn't create the placeholder
  9320. // INF in %windir%\Inf), then we want to treat this as if it were
  9321. // a signature verification failure. Since we aren't trying to
  9322. // install the full INF, this implies that we aren't doing a device
  9323. // install, thus the policy is going to be non-driver-signing
  9324. // policy. This has the default of "Ignore", which is fortunate,
  9325. // since the dialog complains about an unsigned driver package when
  9326. // in fact we don't really know whether or not the package is
  9327. // unsigned--all we know is that we couldn't install its catalog,
  9328. // even if it had one.
  9329. //
  9330. // Note: if the user clicks the "More Info..." button, we will tell
  9331. // them that the catalog installation failed, and what a possible
  9332. // cause might be (e.g., no write access to Windows directory).
  9333. //
  9334. if((CopyStyle & SP_COPY_OEMINF_CATALOG_ONLY) &&
  9335. (TempDriverSigningError == NO_ERROR)) {
  9336. if(SourceInfCatalogName) {
  9337. //
  9338. // Typical case (INF specified a catalog), give the user
  9339. // some indication (via codesigning popup based on policy)
  9340. // about what went wrong...
  9341. //
  9342. if(_HandleFailedVerification(
  9343. Owner,
  9344. SetupapiVerifyCatalogInstallProblem,
  9345. SourceInfCatalogName,
  9346. DeviceDesc,
  9347. DriverSigningPolicy,
  9348. (Flags & SCOI_NO_UI_ON_SIGFAIL),
  9349. Err,
  9350. LogContext,
  9351. NULL,
  9352. NULL,
  9353. NULL)) {
  9354. TempDriverSigningError = Err;
  9355. if(DriverSigningError) {
  9356. *DriverSigningError = TempDriverSigningError;
  9357. }
  9358. //
  9359. // The user wants to proceed with the unsigned
  9360. // installation (or policy is Ignore, so they weren't
  9361. // even informed). If the caller wants a chance to set
  9362. // a system restore point prior to doing any unsigned
  9363. // installations, then we abort now with a "special"
  9364. // error code that tells them what to do...
  9365. //
  9366. if(Flags & SCOI_ABORT_IF_UNSIGNED) {
  9367. Err = ERROR_SET_SYSTEM_RESTORE_POINT;
  9368. } else {
  9369. //
  9370. // We should consider the operation a success, even
  9371. // though we couldn't install the catalog.
  9372. //
  9373. Err = NO_ERROR;
  9374. }
  9375. }
  9376. } else {
  9377. //
  9378. // Unlikely scenario (INF didn't specify a catalog, yet we
  9379. // were called with SP_COPY_OEMINF_CATALOG_ONLY???), just
  9380. // ignore the issue, generate a setupapi.log entry, and
  9381. // proceed...
  9382. //
  9383. WriteLogEntry(LogContext,
  9384. SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
  9385. MSG_LOG_FAILED_INF_INSTALL,
  9386. NULL,
  9387. SourceInfFileName
  9388. );
  9389. WriteLogError(LogContext,
  9390. SETUP_LOG_ERROR,
  9391. Err
  9392. );
  9393. TempDriverSigningError = Err;
  9394. if(DriverSigningError) {
  9395. *DriverSigningError = TempDriverSigningError;
  9396. }
  9397. Err = NO_ERROR;
  9398. }
  9399. if(Err == NO_ERROR) {
  9400. //
  9401. // In this case, we don't have a filename to return to the
  9402. // caller.
  9403. //
  9404. if(RequiredSize) {
  9405. *RequiredSize = 0;
  9406. }
  9407. if(DestinationInfFileName && DestinationInfFileNameSize) {
  9408. *DestinationInfFileName = TEXT('\0');
  9409. }
  9410. if(DestinationInfFileNameComponent) {
  9411. *DestinationInfFileNameComponent = NULL;
  9412. }
  9413. }
  9414. }
  9415. leave;
  9416. }
  9417. //
  9418. // OK, we have a filename to copy to, now copy the file (if necessary),
  9419. // unless the caller doesn't want to overwrite the existing file.
  9420. //
  9421. if(CopyNeeded != NewInfCopyNo) {
  9422. //
  9423. // We either created a new zero-length placeholder file ourselves,
  9424. // or we found an existing placeholder that we could use.
  9425. //
  9426. // Copy our INF over the top of this placeholder file, unless the
  9427. // caller specified the SP_COPY_OEMINF_CATALOG_ONLY flag, in which
  9428. // case we want to leave the zero-length file as-is (and mark it
  9429. // hidden), so that no other OEM INFs can subsequently get this name
  9430. // (hence causing namespace collisions for the catalog files).
  9431. //
  9432. if(!(CopyStyle & SP_COPY_OEMINF_CATALOG_ONLY)) {
  9433. SetFileAttributes(NewName, FILE_ATTRIBUTE_NORMAL);
  9434. Err = GLE_FN_CALL(FALSE,
  9435. InfCacheAwareCopyFile(SourceInfFileName, NewName)
  9436. );
  9437. if(Err != NO_ERROR) {
  9438. //
  9439. // Hopefully, this didn't return ERROR_FILE_EXISTS, as that
  9440. // return code means something special for SetupCopyOEMInf.
  9441. //
  9442. MYASSERT(Err != ERROR_FILE_EXISTS);
  9443. if(Err == ERROR_FILE_EXISTS) {
  9444. Err = ERROR_INVALID_DATA; // just pick something else!
  9445. }
  9446. leave;
  9447. }
  9448. } else {
  9449. //
  9450. // If we didn't encounter a driver signing error, or if the
  9451. // zero-length file was already present, then just make sure
  9452. // it's marked as hidden.
  9453. //
  9454. if((TempDriverSigningError == NO_ERROR) ||
  9455. (TempDriverSigningError == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
  9456. (TempDriverSigningError == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED) ||
  9457. (CopyNeeded == NewInfCopyZeroLength)) {
  9458. //
  9459. // Mark the zero-length file as hidden.
  9460. //
  9461. SetFileAttributes(NewName, FILE_ATTRIBUTE_HIDDEN);
  9462. } else {
  9463. //
  9464. // Delete the newly-created zero-length placeholder INF,
  9465. // because it serves no purpose.
  9466. //
  9467. SetFileAttributes(NewName, FILE_ATTRIBUTE_NORMAL);
  9468. DeleteFile(NewName);
  9469. }
  9470. //
  9471. // Since we only have a zero-length placeholder (or possibly,
  9472. // no placeholder at all if catalog installation failed), we
  9473. // shouldn't return a filename to the caller.
  9474. //
  9475. if(RequiredSize) {
  9476. *RequiredSize = 0;
  9477. }
  9478. if(DestinationInfFileName && DestinationInfFileNameSize) {
  9479. *DestinationInfFileName = TEXT('\0');
  9480. }
  9481. if(DestinationInfFileNameComponent) {
  9482. *DestinationInfFileNameComponent = NULL;
  9483. }
  9484. //
  9485. // We're done!
  9486. //
  9487. leave;
  9488. }
  9489. } else {
  9490. //
  9491. // If the original INF name and the new INF name are different,
  9492. // then we know this wasn't an alternate catalog-only install.
  9493. //
  9494. AlternateCatInstalled = !lstrcmpi(SourceInfFileName, NewName);
  9495. if((CopyStyle & SP_COPY_NOOVERWRITE) && !AlternateCatInstalled) {
  9496. //
  9497. // OK, the INF already exists in the INF directory, and the
  9498. // caller has specified that they _do not_ want to wipe out the
  9499. // existing PNF. We may need to return back the name of the
  9500. // existing INF if they requested it, however.
  9501. //
  9502. // NOTE: It's OK to return the WinVerifyTrust state data handle
  9503. // in this case, since this isn't "really" an error (and both
  9504. // pieces of info need to be returned to caller).
  9505. //
  9506. Err = ERROR_FILE_EXISTS;
  9507. }
  9508. }
  9509. //
  9510. // If we get to here, then the INF exists in %windir%\Inf, and we
  9511. // either have no error, or ERROR_FILE_EXISTS. Next, we need to store
  9512. // the name of the INF in the caller's buffer (if supplied).
  9513. //
  9514. if(RequiredSize) {
  9515. *RequiredSize = TempRequiredSize;
  9516. }
  9517. if(DestinationInfFileName) {
  9518. if(DestinationInfFileNameSize >= TempRequiredSize) {
  9519. MYVERIFY(SUCCEEDED(StringCchCopy(DestinationInfFileName,
  9520. DestinationInfFileNameSize,
  9521. NewName)));
  9522. //
  9523. // If requested by the caller, return a pointer to the filename
  9524. // part of this path.
  9525. //
  9526. if(DestinationInfFileNameComponent) {
  9527. *DestinationInfFileNameComponent = (PTSTR)pSetupGetFileTitle(DestinationInfFileName);
  9528. }
  9529. } else {
  9530. Err = ERROR_INSUFFICIENT_BUFFER;
  9531. }
  9532. } else {
  9533. //
  9534. // Nobody should be requesting a pointer to the filename component
  9535. // of the path when they don't supply us a buffer to store the full
  9536. // path. If anyone does do this, make sure we set the pointer to
  9537. // NULL.
  9538. //
  9539. if(DestinationInfFileNameComponent) {
  9540. *DestinationInfFileNameComponent = NULL;
  9541. }
  9542. }
  9543. if((Err != NO_ERROR) || AlternateCatInstalled) {
  9544. leave;
  9545. }
  9546. //
  9547. // If the code calling this API claims that this INF is from the
  9548. // Internet we first want to check if there is a PNF for this INF and
  9549. // that the PNF agrees that this INF is from the Internet. If the PNF
  9550. // says the INF is from a location other than the Internet then we will
  9551. // change the OEMSourceMediaType to this other media type. We will
  9552. // also set the OEMSourceMediaLocation to NULL. This has the desired
  9553. // affect of us falling through the next if statement which will read
  9554. // the SourceMediaLocation from the PNF instead of the current INF
  9555. // location. If there is no PNF for the given INF then we just leave
  9556. // OEMSourceMediaType alone.
  9557. //
  9558. if(OEMSourceMediaType == SPOST_URL) {
  9559. if(pSetupGetSourceMediaTypeFromPnf(SourceInfFileName, &DefaultSourceMediaType) &&
  9560. (DefaultSourceMediaType != SPOST_URL)) {
  9561. OEMSourceMediaType = DefaultSourceMediaType;
  9562. OEMSourceMediaLocation = NULL;
  9563. }
  9564. }
  9565. if(!OEMSourceMediaLocation && (OEMSourceMediaType == SPOST_PATH)) {
  9566. //
  9567. // The caller wants to store the OEM source path, but they didn't
  9568. // provide us with one to use. Thus, we'll use the path where the
  9569. // INF existed (unless there's a valid PNF there, in which case
  9570. // we'll use its SPOST_PATH information, if it has any).
  9571. // pSetupGetDefaultSourcePath() does just what we want.
  9572. //
  9573. Err = GLE_FN_CALL(INVALID_HANDLE_VALUE,
  9574. hInf = SetupOpenInfFile(SourceInfFileName,
  9575. NULL,
  9576. INF_STYLE_WIN4 | INF_STYLE_OLDNT,
  9577. NULL)
  9578. );
  9579. if(Err != NO_ERROR) {
  9580. //
  9581. // Hopefully, this didn't return ERROR_FILE_EXISTS, as that
  9582. // return code means something special for SetupCopyOEMInf.
  9583. //
  9584. MYASSERT(Err != ERROR_FILE_EXISTS);
  9585. if(Err == ERROR_FILE_EXISTS) {
  9586. Err = ERROR_INVALID_DATA; // just pick something else!
  9587. }
  9588. leave;
  9589. }
  9590. Err = GLE_FN_CALL(NULL,
  9591. TempCharPtr = pSetupGetDefaultSourcePath(
  9592. hInf,
  9593. SRCPATH_USEINFLOCATION,
  9594. &DefaultSourceMediaType)
  9595. );
  9596. //
  9597. // We don't need the INF handle anymore.
  9598. //
  9599. SetupCloseInfFile(hInf);
  9600. hInf = INVALID_HANDLE_VALUE;
  9601. MYASSERT(DefaultSourceMediaType == SPOST_PATH);
  9602. if(Err != NO_ERROR) {
  9603. //
  9604. // Hopefully, this didn't return ERROR_FILE_EXISTS, as that
  9605. // return code means something special for SetupCopyOEMInf.
  9606. //
  9607. MYASSERT(Err != ERROR_FILE_EXISTS);
  9608. if(Err == ERROR_FILE_EXISTS) {
  9609. Err = ERROR_INVALID_DATA; // just pick something else!
  9610. }
  9611. leave;
  9612. }
  9613. MYVERIFY(SUCCEEDED(StringCchCopy(TempOemSourceMediaLocation,
  9614. SIZECHARS(TempOemSourceMediaLocation),
  9615. TempCharPtr)));
  9616. OEMSourceMediaLocation = TempOemSourceMediaLocation;
  9617. //
  9618. // We no longer need the buffer allocated for us by
  9619. // pSetupGetDefaultSourcePath.
  9620. //
  9621. MyFree(TempCharPtr);
  9622. //
  9623. // Reset this pointer so we won't try to free it should we
  9624. // subsequently encounter an exception.
  9625. //
  9626. TempCharPtr = NULL;
  9627. }
  9628. Err = GLE_FN_CALL(FALSE, FileExists(NewName, &FindData));
  9629. if(Err != NO_ERROR) {
  9630. //
  9631. // Hopefully, this didn't return ERROR_FILE_EXISTS, as that
  9632. // return code means something special for SetupCopyOEMInf.
  9633. //
  9634. MYASSERT(Err != ERROR_FILE_EXISTS);
  9635. if(Err == ERROR_FILE_EXISTS) {
  9636. Err = ERROR_INVALID_DATA; // just pick something else!
  9637. }
  9638. leave;
  9639. }
  9640. Err = LoadInfFile(NewName,
  9641. &FindData,
  9642. INF_STYLE_WIN4 | INF_STYLE_OLDNT,
  9643. LDINF_FLAG_ALWAYS_TRY_PNF
  9644. | LDINF_FLAG_REGENERATE_PNF
  9645. | ((Flags & SCOI_TRY_UPDATE_PNF) ? LDINF_FLAG_ALLOW_PNF_SHARING_LOCK : 0)
  9646. | ((OEMSourceMediaType == SPOST_URL) ? LDINF_FLAG_SRCPATH_IS_URL : 0)
  9647. | ((CopyStyle & SP_COPY_OEM_F6_INF) ? LDINF_FLAG_OEM_F6_INF : 0),
  9648. NULL,
  9649. (OEMSourceMediaType == SPOST_NONE) ? NULL : OEMSourceMediaLocation,
  9650. (lstrcmpi(SourceInfOriginalName, pSetupGetFileTitle(NewName))
  9651. ? SourceInfOriginalName
  9652. : NULL),
  9653. NULL,
  9654. LogContext,
  9655. &PrecompiledNewInf,
  9656. &ErrorLineNumber,
  9657. NULL
  9658. );
  9659. if(Err != NO_ERROR) {
  9660. //
  9661. // Hopefully, this didn't return ERROR_FILE_EXISTS, as that
  9662. // return code means something special for SetupCopyOEMInf.
  9663. //
  9664. MYASSERT(Err != ERROR_FILE_EXISTS);
  9665. if(Err == ERROR_FILE_EXISTS) {
  9666. Err = ERROR_INVALID_DATA; // just pick something else!
  9667. }
  9668. leave;
  9669. }
  9670. //
  9671. // The INF was successfully precompiled.
  9672. //
  9673. FreeInfFile(PrecompiledNewInf);
  9674. //
  9675. // Finally, delete the source INF file if the caller requested it.
  9676. //
  9677. if(CopyStyle & SP_COPY_DELETESOURCE) {
  9678. DeleteFile(SourceInfFileName);
  9679. }
  9680. } except(pSetupExceptionFilter(GetExceptionCode())) {
  9681. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Err);
  9682. MYASSERT(Err != ERROR_FILE_EXISTS);
  9683. if(TempCharPtr) {
  9684. MyFree(TempCharPtr);
  9685. }
  9686. if(hInf != INVALID_HANDLE_VALUE) {
  9687. SetupCloseInfFile(hInf);
  9688. }
  9689. }
  9690. if(Err != NO_ERROR) {
  9691. //
  9692. // For any error other than ERROR_FILE_EXISTS (which doesn't really
  9693. // indicate a problem), we need to ensure that no WinVerifyTrust state
  9694. // data is being returned to the caller.
  9695. //
  9696. if((Err != ERROR_FILE_EXISTS) && hWVTStateData && *hWVTStateData) {
  9697. pSetupCloseWVTStateData(*hWVTStateData);
  9698. *hWVTStateData = NULL;
  9699. }
  9700. if(CopyNeeded == NewInfCopyYes) {
  9701. //
  9702. // We encountered an error, after GetNewInfName created a new,
  9703. // unique INF for us. Delete it now.
  9704. //
  9705. // (Note: we don't do clean-up when GetNewInfName found an
  9706. // existing, zero-length file for us to use, even if we may have
  9707. // subsequently copied the 'real' INF over the top of it. Since we
  9708. // believed the existing file to be a duplicate of our OEM INF,
  9709. // this should be OK--the worst that's going to happen is that an
  9710. // INF that was once zero-length is now a full-blown INF after
  9711. // SetupCopyOEMInf encountered an error.)
  9712. //
  9713. pSetupUninstallOEMInf(NewName, LogContext, SUOI_FORCEDELETE, NULL);
  9714. //
  9715. // NTRAID#256075-2000/08/18-JamieHun Handle Rollback of INF/PNF/CAT files
  9716. //
  9717. // If we were installing an exception INF and encountered an error,
  9718. // we may have already blown away a previous INF/CAT. In the
  9719. // future, we might want to look into doing a backup on the old
  9720. // INF/CAT before installing the new INF/CAT over the top of them.
  9721. //
  9722. }
  9723. }
  9724. SetLastError(Err);
  9725. return (Err == NO_ERROR);
  9726. }
  9727. //
  9728. // ANSI version
  9729. //
  9730. BOOL
  9731. WINAPI
  9732. SetupUninstallOEMInfA(
  9733. IN PCSTR InfFileName,
  9734. IN DWORD Flags,
  9735. IN PVOID Reserved
  9736. )
  9737. {
  9738. DWORD Err;
  9739. PCWSTR UnicodeInfFileName;
  9740. BOOL b;
  9741. Err = pSetupCaptureAndConvertAnsiArg(InfFileName, &UnicodeInfFileName);
  9742. if(Err != NO_ERROR) {
  9743. SetLastError(Err);
  9744. return FALSE;
  9745. }
  9746. b = SetupUninstallOEMInfW(UnicodeInfFileName, Flags, Reserved);
  9747. Err = GetLastError();
  9748. MyFree(UnicodeInfFileName);
  9749. SetLastError(Err);
  9750. return b;
  9751. }
  9752. BOOL
  9753. WINAPI
  9754. SetupUninstallOEMInf(
  9755. IN PCTSTR InfFileName,
  9756. IN DWORD Flags,
  9757. IN PVOID Reserved
  9758. )
  9759. /*++
  9760. Routine Description:
  9761. This API uninstalls the specified INF file, and deletes the associated
  9762. .PNF and .CAT files, if they exist.
  9763. The default behavior of this API is to first verify that there are no
  9764. other devices, live or phantom, that are using this INF. If another
  9765. device is using this INF then it will not be uninstalled. This behavior
  9766. can be overwritten by the SUOI_FORCEDELETE flag.
  9767. Arguments:
  9768. InfFileName - Supplies the simple filename (no path) of the INF to be
  9769. uninstalled.
  9770. Flags - Supplies flags that alter the behavior of this API.
  9771. SUOI_FORCEDELETE - forces the INF, PNF, and CAT to be uninstalled, even
  9772. if another device is using this INF.
  9773. Reserved - Reserved for future use. Must be NULL.
  9774. Return Value:
  9775. If the function succeeds, the return value is TRUE.
  9776. If the function fails, the return value is FALSE. To get extended error
  9777. information, call GetLastError.
  9778. --*/
  9779. {
  9780. DWORD Err;
  9781. TCHAR InfFullPath[MAX_PATH];
  9782. if(Flags & ~(SUOI_FORCEDELETE)) {
  9783. SetLastError(ERROR_INVALID_FLAGS);
  9784. return FALSE;
  9785. }
  9786. if(Reserved) {
  9787. SetLastError(ERROR_INVALID_PARAMETER);
  9788. return FALSE;
  9789. }
  9790. try {
  9791. //
  9792. // INF filename must not contain path
  9793. //
  9794. if(InfFileName != pSetupGetFileTitle(InfFileName)) {
  9795. Err = ERROR_INVALID_PARAMETER;
  9796. goto clean0;
  9797. }
  9798. //
  9799. // Look for specified INF in %windir%\Inf...
  9800. //
  9801. if(MYVERIFY(SUCCEEDED(StringCchCopy(InfFullPath,
  9802. SIZECHARS(InfFullPath),
  9803. InfDirectory)))) {
  9804. MYVERIFY(pSetupConcatenatePaths(InfFullPath,
  9805. InfFileName,
  9806. SIZECHARS(InfFullPath),
  9807. NULL
  9808. ));
  9809. }
  9810. if(!FileExists(InfFullPath, NULL)) {
  9811. Err = GetLastError();
  9812. goto clean0;
  9813. }
  9814. pSetupUninstallOEMInf(InfFullPath, NULL, Flags, &Err);
  9815. clean0:
  9816. ; // nothing to do
  9817. } except(EXCEPTION_EXECUTE_HANDLER) {
  9818. Err = ERROR_INVALID_PARAMETER;
  9819. }
  9820. SetLastError(Err);
  9821. return(Err == NO_ERROR);
  9822. }
  9823. BOOL
  9824. WINAPI
  9825. SetupDiRegisterCoDeviceInstallers(
  9826. IN HDEVINFO DeviceInfoSet,
  9827. IN PSP_DEVINFO_DATA DeviceInfoData
  9828. )
  9829. /*++
  9830. Routine Description:
  9831. Default handler for DIF_REGISTER_COINSTALLERS
  9832. This routine will install any (device-specific) co-installers specified
  9833. in an [<InstallSec>.CoInstallers] section, where <InstallSec> is the install
  9834. section name for the selected driver node, potentially decorated with
  9835. an OS/architecture-specific extension (e.g., "InstallSec.NTAmd64.CoInstallers").
  9836. AddReg entries listed in a CoInstallers section use the device's driver key
  9837. for their HKR. To register a device-specific co-installer, a REG_MULTI_SZ entry
  9838. titled "CoInstallers32" must be written to the driver key. Each entry in this list
  9839. has the following format:
  9840. dll[,procname]
  9841. where dll is the name of the module to load and procname is an optional entry
  9842. point name. If procname is not specified, then the entry point name
  9843. "CoDeviceInstall" will be used.
  9844. Arguments:
  9845. DeviceInfoSet - Supplies a handle to the device information set containing
  9846. a device information element for whom co-installers are to be registered.
  9847. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for whom
  9848. co-installers are to be registered.
  9849. Return Value:
  9850. If the function succeeds, the return value is TRUE.
  9851. If the function fails, the return value is FALSE. To get extended error
  9852. information, call GetLastError.
  9853. Remarks:
  9854. If no driver is selected (i.e., this is a null-driver installation), then
  9855. this routine does nothing.
  9856. --*/
  9857. {
  9858. return _SetupDiRegisterCoDeviceInstallers(DeviceInfoSet,
  9859. DeviceInfoData,
  9860. TRUE,
  9861. INVALID_HANDLE_VALUE,
  9862. INVALID_HANDLE_VALUE
  9863. );
  9864. }
  9865. BOOL
  9866. _SetupDiRegisterCoDeviceInstallers(
  9867. IN HDEVINFO DeviceInfoSet,
  9868. IN PSP_DEVINFO_DATA DeviceInfoData,
  9869. IN BOOL DoFullInstall,
  9870. IN HINF hDeviceInf, OPTIONAL
  9871. IN HSPFILEQ UserFileQ OPTIONAL
  9872. )
  9873. /*++
  9874. Routine Description:
  9875. Worker routine for both SetupDiRegisterCoDeviceInstallers and SetupDiInstallDriverFiles.
  9876. See the description of SetupDiRegisterCoDeviceInstallers for more information.
  9877. Arguments:
  9878. DeviceInfoSet - Supplies a handle to the device information set containing
  9879. a device information element for whom co-installers are to be registered.
  9880. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for whom
  9881. co-installers are to be registered.
  9882. DoFullInstall - If TRUE (non-zero), then the co-installers are completely registered,
  9883. otherwise, only files are copied.
  9884. hDeviceInf - Optionally, supplies a handle to the INF for which installation
  9885. is being performed. If this handle is not supplied, the INF specified in
  9886. the selected driver node will be opened. If this handle is not supplied,
  9887. this parameter must be set to INVALID_HANDLE_VALUE.
  9888. UserFileQ - Optionally, supplies a file queue where file operations should be added.
  9889. If this handle is not supplied, then the queue associated with this devinfo
  9890. element will be used (if the DI_NOVCP flag is set), or one will be automatically
  9891. generated and committed. If this handle is not supplied, this parameter must
  9892. be set to INVALID_HANDLE_VALUE.
  9893. Return Value:
  9894. If the function succeeds, the return value is TRUE.
  9895. If the function fails, the return value is FALSE. To get extended error
  9896. information, call GetLastError.
  9897. Remarks:
  9898. During GUI-mode setup on Windows NT, quiet-install behavior is always
  9899. employed in the absence of a user-supplied file queue, regardless of
  9900. whether the device information element has the DI_QUIETINSTALL flag set.
  9901. --*/
  9902. {
  9903. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  9904. DWORD Err, ScanQueueResult;
  9905. PDEVINFO_ELEM DevInfoElem;
  9906. HWND hwndParent;
  9907. BOOL CloseUserFileQ;
  9908. PTSTR szInfFileName, szInfSectionName;
  9909. TCHAR InfSectionWithExt[MAX_SECT_NAME_LEN];
  9910. DWORD InfSectionWithExtLength;
  9911. BOOL FreeMsgHandlerContext;
  9912. PSP_FILE_CALLBACK MsgHandler;
  9913. PVOID MsgHandlerContext;
  9914. BOOL MsgHandlerIsNativeCharWidth, DeleteDrvRegKey;
  9915. HKEY hkDrv;
  9916. BOOL CloseInfHandle;
  9917. BOOL DoFileCopying;
  9918. INT FileQueueNeedsReboot;
  9919. PSETUP_LOG_CONTEXT LogContext = NULL;
  9920. DWORD slot_section = 0;
  9921. BOOL NoProgressUI;
  9922. TCHAR szNewName[MAX_PATH];
  9923. BOOL OemInfFileToCopy = FALSE;
  9924. //
  9925. // A device information element must be specified.
  9926. //
  9927. if(!DeviceInfoData) {
  9928. Err = ERROR_INVALID_PARAMETER;
  9929. goto clean1;
  9930. }
  9931. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  9932. Err = ERROR_INVALID_HANDLE;
  9933. goto clean1;
  9934. }
  9935. LogContext = pDeviceInfoSet->InstallParamBlock.LogContext;
  9936. Err = NO_ERROR;
  9937. hDeviceInf = INVALID_HANDLE_VALUE;
  9938. CloseUserFileQ = FALSE;
  9939. FreeMsgHandlerContext = FALSE;
  9940. hkDrv = INVALID_HANDLE_VALUE;
  9941. DeleteDrvRegKey = FALSE;
  9942. CloseInfHandle = FALSE;
  9943. try {
  9944. if(!(DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  9945. DeviceInfoData,
  9946. NULL))) {
  9947. Err = ERROR_INVALID_PARAMETER;
  9948. goto clean0;
  9949. }
  9950. //
  9951. // This routine can't install a non-native driver
  9952. //
  9953. if(DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_ALTPLATFORM_DRVSEARCH) {
  9954. Err = ERROR_INVALID_FLAGS;
  9955. goto clean0;
  9956. }
  9957. //
  9958. // set the LogContext for this function
  9959. //
  9960. LogContext = DevInfoElem->InstallParamBlock.LogContext;
  9961. //
  9962. // If there's no driver selected (i.e., this is a null driver install)
  9963. // then there's nothing for us to do.
  9964. //
  9965. if(!DevInfoElem->SelectedDriver) {
  9966. goto clean0;
  9967. }
  9968. //
  9969. // Make sure we only use the devinfo element's window if it's valid.
  9970. //
  9971. if(hwndParent = DevInfoElem->InstallParamBlock.hwndParent) {
  9972. if(!IsWindow(hwndParent)) {
  9973. hwndParent = NULL;
  9974. }
  9975. }
  9976. szInfFileName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  9977. DevInfoElem->SelectedDriver->InfFileName
  9978. );
  9979. szInfSectionName = pStringTableStringFromId(pDeviceInfoSet->StringTable,
  9980. DevInfoElem->SelectedDriver->InfSectionName
  9981. );
  9982. if(hDeviceInf == INVALID_HANDLE_VALUE) {
  9983. if((hDeviceInf = SetupOpenInfFile(szInfFileName,
  9984. NULL,
  9985. INF_STYLE_WIN4,
  9986. NULL)) == INVALID_HANDLE_VALUE) {
  9987. Err = GetLastError();
  9988. goto clean0;
  9989. }
  9990. CloseInfHandle = TRUE;
  9991. }
  9992. //
  9993. // see if we should give the INF the same LogContext as the DevInfoElem
  9994. //
  9995. InheritLogContext(LogContext,
  9996. &((PLOADED_INF) hDeviceInf)->LogContext);
  9997. slot_section = AllocLogInfoSlot(LogContext,FALSE);
  9998. //
  9999. // Find out the 'real' install section we should be using (i.e., the potentially
  10000. // OS/architecture-specific one.
  10001. //
  10002. if(!SetupDiGetActualSectionToInstall(hDeviceInf,
  10003. szInfSectionName,
  10004. InfSectionWithExt,
  10005. SIZECHARS(InfSectionWithExt),
  10006. &InfSectionWithExtLength,
  10007. NULL
  10008. )) {
  10009. Err = GetLastError();
  10010. goto clean0;
  10011. }
  10012. //
  10013. // Now append the ".CoInstallers" extension to the install section name to find
  10014. // the co-installer INF section to run.
  10015. //
  10016. MYVERIFY(SUCCEEDED(StringCchCopy(&(InfSectionWithExt[InfSectionWithExtLength - 1]),
  10017. SIZECHARS(InfSectionWithExt)-(InfSectionWithExtLength - 1),
  10018. pszCoInstallersSectionSuffix)));
  10019. //
  10020. // Figure out whether we need to do file copying. (Ignore the DI_NOFILECOPY
  10021. // flag if we're doing a copy-only installation--that's what setupx does.)
  10022. //
  10023. DoFileCopying = (!(DevInfoElem->InstallParamBlock.Flags & DI_NOFILECOPY) || !DoFullInstall);
  10024. //
  10025. // Append the layout INF, if necessary.
  10026. //
  10027. if(DoFileCopying) {
  10028. SetupOpenAppendInfFile(NULL, hDeviceInf, NULL);
  10029. }
  10030. //
  10031. // Append-load any included INFs specified in an "include=" line in our
  10032. // install section.
  10033. //
  10034. AppendLoadIncludedInfs(hDeviceInf, szInfFileName, InfSectionWithExt, DoFileCopying);
  10035. //
  10036. // Now copy the files, if necessary.
  10037. //
  10038. if(DoFileCopying) {
  10039. if(UserFileQ == INVALID_HANDLE_VALUE) {
  10040. //
  10041. // If the DI_NOVCP flag is set, then just queue up the file
  10042. // copy/rename/delete operations. Otherwise, perform the
  10043. // actions.
  10044. //
  10045. if(DevInfoElem->InstallParamBlock.Flags & DI_NOVCP) {
  10046. //
  10047. // We must have a user-supplied file queue.
  10048. //
  10049. MYASSERT(DevInfoElem->InstallParamBlock.UserFileQ);
  10050. UserFileQ = DevInfoElem->InstallParamBlock.UserFileQ;
  10051. } else {
  10052. //
  10053. // Since we may need to check the queued files to determine whether file copy
  10054. // is necessary, we have to open our own queue, and commit it ourselves.
  10055. //
  10056. if((UserFileQ = SetupOpenFileQueue()) != INVALID_HANDLE_VALUE) {
  10057. CloseUserFileQ = TRUE;
  10058. } else {
  10059. //
  10060. // SetupOpenFileQueue sets actual error
  10061. //
  10062. Err = GetLastError();
  10063. goto clean0;
  10064. }
  10065. }
  10066. }
  10067. //
  10068. // See if we should replace the file queue's log context with the
  10069. // DevInfoElem's
  10070. //
  10071. InheritLogContext(LogContext,
  10072. &((PSP_FILE_QUEUE) UserFileQ)->LogContext);
  10073. WriteLogEntry(LogContext,
  10074. slot_section,
  10075. MSG_LOG_COINSTALLER_REGISTRATION,
  10076. NULL,
  10077. InfSectionWithExt);
  10078. Err = InstallFromInfSectionAndNeededSections(NULL,
  10079. hDeviceInf,
  10080. InfSectionWithExt,
  10081. SPINST_FILES,
  10082. NULL,
  10083. NULL,
  10084. SP_COPY_NEWER_OR_SAME | SP_COPY_LANGUAGEAWARE |
  10085. ((DevInfoElem->InstallParamBlock.Flags & DI_NOBROWSE) ? SP_COPY_NOBROWSE : 0),
  10086. NULL,
  10087. NULL,
  10088. INVALID_HANDLE_VALUE,
  10089. NULL,
  10090. UserFileQ
  10091. );
  10092. //
  10093. // Mark the queue as a device install queue (and make sure there's a
  10094. // catalog node representing our device INF in the queue).
  10095. //
  10096. Err = MarkQueueForDeviceInstall(UserFileQ,
  10097. hDeviceInf,
  10098. pStringTableStringFromId(
  10099. pDeviceInfoSet->StringTable,
  10100. DevInfoElem->SelectedDriver->DrvDescription)
  10101. );
  10102. //
  10103. // At this point, we have queued up all the files that need to be copied. If
  10104. // we weren't given a user-supplied queue, then commit our queue now.
  10105. //
  10106. if(CloseUserFileQ) {
  10107. if(Err == NO_ERROR) {
  10108. //
  10109. // Determine whether the queue actually needs to be
  10110. // committed.
  10111. //
  10112. // ScanQueueResult can have 1 of 3 values:
  10113. //
  10114. // 0: Some files were missing--must commit queue.
  10115. //
  10116. // 1: All files to be copied are already present and
  10117. // queue is empty--skip committing queue.
  10118. //
  10119. // 2: All files to be copied are present, but
  10120. // del/ren/backup queues not empty--must commit
  10121. // queue. The copy queue will have been emptied, so
  10122. // only del/ren/backup functions will be performed.
  10123. //
  10124. // (jamiehun) see previous case of SetupScanFileQueue
  10125. // for a discussion of DI_FLAGSEX_PREINSTALLBACKUP
  10126. // handling.
  10127. //
  10128. if(!SetupScanFileQueue(UserFileQ,
  10129. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  10130. hwndParent,
  10131. NULL,
  10132. NULL,
  10133. &ScanQueueResult)) {
  10134. //
  10135. // SetupScanFileQueue should really never fail when
  10136. // you don't ask it to call a callback routine, but
  10137. // if it does, just go ahead and commit the queue.
  10138. //
  10139. ScanQueueResult = 0;
  10140. }
  10141. }
  10142. if((Err == NO_ERROR) && (ScanQueueResult != 1)) {
  10143. //
  10144. // We need to commit this file queue. Figure out what
  10145. // message handler to use.
  10146. //
  10147. if(DevInfoElem->InstallParamBlock.InstallMsgHandler) {
  10148. MsgHandler = DevInfoElem->InstallParamBlock.InstallMsgHandler;
  10149. MsgHandlerContext = DevInfoElem->InstallParamBlock.InstallMsgHandlerContext;
  10150. MsgHandlerIsNativeCharWidth = DevInfoElem->InstallParamBlock.InstallMsgHandlerIsNativeCharWidth;
  10151. } else {
  10152. NoProgressUI = (GuiSetupInProgress || (DevInfoElem->InstallParamBlock.Flags & DI_QUIETINSTALL));
  10153. if(MsgHandlerContext = SetupInitDefaultQueueCallbackEx(
  10154. hwndParent,
  10155. (NoProgressUI ? INVALID_HANDLE_VALUE : NULL),
  10156. 0,
  10157. 0,
  10158. NULL))
  10159. {
  10160. FreeMsgHandlerContext = TRUE;
  10161. MsgHandler = SetupDefaultQueueCallback;
  10162. MsgHandlerIsNativeCharWidth = TRUE;
  10163. } else {
  10164. Err = ERROR_NOT_ENOUGH_MEMORY;
  10165. }
  10166. }
  10167. //
  10168. // Copy enqueued files.
  10169. //
  10170. if(Err == NO_ERROR) {
  10171. //
  10172. // Call _SetupVerifyQueuedCatalogs separately (i.e.,
  10173. // don't let it happen automatically as a result of
  10174. // committing the queue that happens below). We do
  10175. // this beforehand so that we know what unique name was
  10176. // generated when an OEM INF was installed into
  10177. // %windir%\Inf (in case we need to delete the
  10178. // INF/PNF/CAT files later if we encounter an error).
  10179. //
  10180. WriteLogEntry(
  10181. LogContext,
  10182. DRIVER_LOG_TIME,
  10183. MSG_LOG_BEGIN_COINST_VERIFY_CAT_TIME,
  10184. NULL); // text message
  10185. Err = _SetupVerifyQueuedCatalogs(
  10186. hwndParent,
  10187. UserFileQ,
  10188. (VERCAT_INSTALL_INF_AND_CAT |
  10189. ((DevInfoElem->SelectedDriver->Flags & DNF_INET_DRIVER)
  10190. ? VERCAT_PRIMARY_DEVICE_INF_FROM_INET : 0)),
  10191. szNewName,
  10192. &OemInfFileToCopy
  10193. );
  10194. WriteLogEntry(
  10195. LogContext,
  10196. DRIVER_LOG_TIME,
  10197. MSG_LOG_END_COINST_VERIFY_CAT_TIME,
  10198. NULL); // text message
  10199. if(Err == NO_ERROR) {
  10200. if(_SetupCommitFileQueue(hwndParent,
  10201. UserFileQ,
  10202. MsgHandler,
  10203. MsgHandlerContext,
  10204. MsgHandlerIsNativeCharWidth
  10205. )) {
  10206. //
  10207. // Check to see whether a reboot is required as a
  10208. // result of committing the queue (i.e., because
  10209. // files were in use, or the INF requested a reboot).
  10210. //
  10211. FileQueueNeedsReboot = SetupPromptReboot(UserFileQ, NULL, TRUE);
  10212. //
  10213. // This should never fail...
  10214. //
  10215. MYASSERT(FileQueueNeedsReboot != -1);
  10216. if(FileQueueNeedsReboot) {
  10217. SetDevnodeNeedsRebootProblem(DevInfoElem, pDeviceInfoSet,
  10218. MSG_LOG_REBOOT_REASON_INUSE);
  10219. }
  10220. } else {
  10221. Err = GetLastError();
  10222. }
  10223. }
  10224. }
  10225. }
  10226. //
  10227. // Close our file queue handle.
  10228. //
  10229. SetupCloseFileQueue(UserFileQ);
  10230. CloseUserFileQ = FALSE;
  10231. //
  10232. // Terminate the default queue callback, if it was created.
  10233. //
  10234. if(FreeMsgHandlerContext) {
  10235. SetupTermDefaultQueueCallback(MsgHandlerContext);
  10236. FreeMsgHandlerContext = FALSE;
  10237. }
  10238. if(Err != NO_ERROR) {
  10239. goto clean0;
  10240. }
  10241. }
  10242. }
  10243. //
  10244. // If all we were asked to do was copy files, then we're done.
  10245. //
  10246. if(!DoFullInstall ||
  10247. (DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY)) {
  10248. goto clean0;
  10249. }
  10250. //
  10251. // Open/create the Driver Reg Key.
  10252. //
  10253. if((hkDrv = SetupDiOpenDevRegKey(DeviceInfoSet,
  10254. DeviceInfoData,
  10255. DICS_FLAG_GLOBAL,
  10256. 0,
  10257. DIREG_DRV,
  10258. KEY_READ | KEY_WRITE)) == INVALID_HANDLE_VALUE) {
  10259. //
  10260. // Assume the driver key doesn't already exist--try to create it.
  10261. //
  10262. if((hkDrv = SetupDiCreateDevRegKey(DeviceInfoSet,
  10263. DeviceInfoData,
  10264. DICS_FLAG_GLOBAL,
  10265. 0,
  10266. DIREG_DRV,
  10267. NULL,
  10268. NULL)) != INVALID_HANDLE_VALUE) {
  10269. //
  10270. // We successfully created the driver key. Set a flag so we'll know
  10271. // to delete it in case we hit an error and need to clean up.
  10272. //
  10273. DeleteDrvRegKey = TRUE;
  10274. } else {
  10275. Err = GetLastError();
  10276. goto clean0;
  10277. }
  10278. }
  10279. //
  10280. // We don't pass a msg handler so no need to worry about ansi
  10281. // vs. unicode issues here.
  10282. //
  10283. Err = InstallFromInfSectionAndNeededSections(NULL,
  10284. hDeviceInf,
  10285. InfSectionWithExt,
  10286. SPINST_INIFILES
  10287. | SPINST_REGISTRY
  10288. | SPINST_INI2REG
  10289. | SPINST_BITREG
  10290. | SPINST_REGSVR
  10291. | SPINST_UNREGSVR
  10292. | SPINST_PROFILEITEMS,
  10293. hkDrv,
  10294. NULL,
  10295. 0,
  10296. NULL,
  10297. NULL,
  10298. INVALID_HANDLE_VALUE,
  10299. NULL,
  10300. NULL
  10301. );
  10302. if(Err == NO_ERROR) {
  10303. //
  10304. // Registering co-installers invalidates our existing co-installer
  10305. // list. Reset this list (migrating the module handles to the devinfo
  10306. // set's list of "things to clean up later".
  10307. // (NOTE: SetupDiCallClassInstaller also does this when its handling
  10308. // DIF_REGISTER_COINSTALLERS, but since we can't be guaranteed we're
  10309. // being called in the context of SetupDiCallClassInstaller, we have
  10310. // to do this ourselves as well.)
  10311. //
  10312. Err = InvalidateHelperModules(DeviceInfoSet,
  10313. DeviceInfoData,
  10314. IHM_COINSTALLERS_ONLY
  10315. );
  10316. }
  10317. clean0: ; // nothing to do
  10318. } except(EXCEPTION_EXECUTE_HANDLER) {
  10319. Err = ERROR_INVALID_PARAMETER;
  10320. if(FreeMsgHandlerContext) {
  10321. SetupTermDefaultQueueCallback(MsgHandlerContext);
  10322. }
  10323. if(CloseUserFileQ) {
  10324. SetupCloseFileQueue(UserFileQ);
  10325. }
  10326. //
  10327. // Reference the following variables so the compiler will respect our statement
  10328. // ordering w.r.t. assignment.
  10329. //
  10330. DeleteDrvRegKey = DeleteDrvRegKey;
  10331. CloseInfHandle = CloseInfHandle;
  10332. OemInfFileToCopy = OemInfFileToCopy;
  10333. }
  10334. if(hkDrv != INVALID_HANDLE_VALUE) {
  10335. RegCloseKey(hkDrv);
  10336. if((Err != NO_ERROR) && DeleteDrvRegKey) {
  10337. SetupDiDeleteDevRegKey(DeviceInfoSet,
  10338. DeviceInfoData,
  10339. DICS_FLAG_GLOBAL | DICS_FLAG_CONFIGGENERAL,
  10340. 0,
  10341. DIREG_DRV
  10342. );
  10343. }
  10344. }
  10345. if(CloseInfHandle) {
  10346. MYASSERT(hDeviceInf != INVALID_HANDLE_VALUE);
  10347. SetupCloseInfFile(hDeviceInf);
  10348. }
  10349. clean1:
  10350. if (Err == NO_ERROR) {
  10351. //
  10352. // give a +ve affirmation of Success
  10353. //
  10354. WriteLogEntry(
  10355. LogContext,
  10356. DoFullInstall ? DRIVER_LOG_INFO : DRIVER_LOG_VERBOSE,
  10357. MSG_LOG_REGISTEREDCOINSTALLERS,
  10358. NULL);
  10359. } else {
  10360. //
  10361. // indicate failed, display error
  10362. //
  10363. WriteLogEntry(
  10364. LogContext,
  10365. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  10366. MSG_LOG_REGISTERCOINSTALLERS_ERROR,
  10367. NULL);
  10368. WriteLogError(
  10369. LogContext,
  10370. DRIVER_LOG_ERROR,
  10371. Err);
  10372. //
  10373. // If we copied the OEM INF into the INF directory under a newly-
  10374. // generated name, delete it now.
  10375. //
  10376. if(OemInfFileToCopy) {
  10377. pSetupUninstallOEMInf(szNewName, LogContext, SUOI_FORCEDELETE, NULL);
  10378. }
  10379. }
  10380. if (slot_section) {
  10381. ReleaseLogInfoSlot(LogContext,slot_section);
  10382. }
  10383. if (pDeviceInfoSet) {
  10384. UnlockDeviceInfoSet(pDeviceInfoSet);
  10385. }
  10386. SetLastError(Err);
  10387. return(Err == NO_ERROR);
  10388. }
  10389. BOOL
  10390. WINAPI
  10391. SetupDiSelectBestCompatDrv(
  10392. IN HDEVINFO DeviceInfoSet,
  10393. IN OUT PSP_DEVINFO_DATA DeviceInfoData
  10394. )
  10395. /*++
  10396. Routine Description:
  10397. Default handler for DIF_SELECTBESTCOMPATDRV
  10398. This routine will select the best driver from the device information element's
  10399. compatible driver list.
  10400. This function will enumerate through all of the drivers and find the one with
  10401. the Best Rank (this is the lowest Rank number). If there are multiple drivers
  10402. with the same Best Rank then we will take the driver with the newest DriverDate.
  10403. Arguments:
  10404. DeviceInfoSet - Supplies a handle to the device information set containing
  10405. the element for which the best compatible driver is to be selected.
  10406. DeviceInfoData - Supplies the address of a SP_DEVINFO_DATA structure for
  10407. which the best compatible driver is to be selected. This element must
  10408. already have a (non-empty) compatible driver list built for it, or this
  10409. API will fail and GetLastError will return ERROR_NO_COMPAT_DRIVERS.
  10410. This is an IN OUT parameter because the class GUID for the device will be
  10411. updated to reflect the class of the selected driver.
  10412. Return Value:
  10413. If the function succeeds, the return value is TRUE.
  10414. If the function fails, the return value is FALSE. To get extended error
  10415. information, call GetLastError.
  10416. --*/
  10417. {
  10418. SP_DRVINFO_DATA DriverInfoData;
  10419. SP_DRVINSTALL_PARAMS DriverInstallParams;
  10420. DWORD BestRank, BasicBestRank;
  10421. DWORDLONG BestDriverVersion, BasicBestDriverVersion;
  10422. DWORD MemberIndex;
  10423. INT BestMemberIndex, BasicBestMemberIndex;
  10424. PSETUP_LOG_CONTEXT LogContext = NULL;
  10425. PDEVICE_INFO_SET pDeviceInfoSet = NULL;
  10426. DWORD Err = NO_ERROR;
  10427. PDEVINFO_ELEM DevInfoElem = NULL;
  10428. FILETIME BestDriverDate, BasicBestDriverDate;
  10429. BestRank = BasicBestRank = RANK_NO_MATCH;
  10430. BestMemberIndex = BasicBestMemberIndex = -1;
  10431. BestDriverVersion = BasicBestDriverVersion = 0;
  10432. if(!(pDeviceInfoSet = AccessDeviceInfoSet(DeviceInfoSet))) {
  10433. Err = ERROR_INVALID_HANDLE;
  10434. goto clean1;
  10435. }
  10436. LogContext = pDeviceInfoSet->InstallParamBlock.LogContext;
  10437. if(DeviceInfoData
  10438. && (DevInfoElem = FindAssociatedDevInfoElem(pDeviceInfoSet,
  10439. DeviceInfoData,
  10440. NULL))!=NULL) {
  10441. LogContext = DevInfoElem->InstallParamBlock.LogContext;
  10442. }
  10443. //
  10444. //Enumerate through all of the drivers and find the Best Rank
  10445. //
  10446. MemberIndex = 0;
  10447. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  10448. while (SetupDiEnumDriverInfo(DeviceInfoSet,
  10449. DeviceInfoData,
  10450. SPDIT_COMPATDRIVER,
  10451. MemberIndex,
  10452. &DriverInfoData)) {
  10453. DriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  10454. if ((SetupDiGetDriverInstallParams(DeviceInfoSet,
  10455. DeviceInfoData,
  10456. &DriverInfoData,
  10457. &DriverInstallParams))) {
  10458. if(DriverInstallParams.Flags & DNF_BAD_DRIVER) {
  10459. //
  10460. // This driver was marked as bad--we don't want to use it, but
  10461. // we should log an informational message as to why it wasn't
  10462. // considered.
  10463. //
  10464. SP_DRVINFO_DETAIL_DATA Data;
  10465. Data.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  10466. if(SetupDiGetDriverInfoDetail(DeviceInfoSet,
  10467. DeviceInfoData,
  10468. &DriverInfoData,
  10469. &Data,
  10470. Data.cbSize,
  10471. NULL) ||
  10472. (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  10473. WriteLogEntry(
  10474. LogContext,
  10475. DRIVER_LOG_INFO,
  10476. MSG_LOG_SELECTBEST_BAD_DRIVER,
  10477. NULL,
  10478. Data.DrvDescription,
  10479. Data.InfFileName,
  10480. Data.SectionName
  10481. );
  10482. }
  10483. } else if(DriverInstallParams.Flags & DNF_BASIC_DRIVER) {
  10484. //
  10485. // This driver is flagged as a "basic functionality" driver.
  10486. // We'll keep track of the best such driver we encounter, but
  10487. // we'll only use a basic driver if there exists no non-basic
  10488. // signed drivers.
  10489. //
  10490. if(DriverInstallParams.Rank <= BasicBestRank) {
  10491. if(BasicBestMemberIndex == -1) {
  10492. //
  10493. // This is the first acceptable basic driver we've
  10494. // encountered...
  10495. //
  10496. BasicBestDriverDate = DriverInfoData.DriverDate;
  10497. BasicBestMemberIndex = (INT)MemberIndex;
  10498. BasicBestDriverVersion = DriverInfoData.DriverVersion;
  10499. } else {
  10500. if((DriverInstallParams.Rank < BasicBestRank) ||
  10501. (CompareFileTime(&BasicBestDriverDate, &(DriverInfoData.DriverDate)) == -1)) {
  10502. //
  10503. // If this new driver has a better (smaller) Rank than
  10504. // the current Best Driver or it has a newer date then
  10505. // make it the Best Driver.
  10506. //
  10507. BasicBestDriverDate = DriverInfoData.DriverDate;
  10508. BasicBestMemberIndex = (INT)MemberIndex;
  10509. BasicBestDriverVersion = DriverInfoData.DriverVersion;
  10510. } else if ((DriverInstallParams.Rank == BasicBestRank) &&
  10511. (CompareFileTime(&BasicBestDriverDate, &(DriverInfoData.DriverDate)) == 0) &&
  10512. (DriverInfoData.DriverVersion > BasicBestDriverVersion)) {
  10513. //
  10514. // If the Rank and DriverDate of the new driver
  10515. // are identical to the current Best driver,
  10516. // then check if the new driver has a newer
  10517. // DriverVersion and if so make it the Best Driver.
  10518. //
  10519. BasicBestDriverDate = DriverInfoData.DriverDate;
  10520. BasicBestMemberIndex = (INT)MemberIndex;
  10521. BasicBestDriverVersion = DriverInfoData.DriverVersion;
  10522. }
  10523. }
  10524. BasicBestRank = DriverInstallParams.Rank;
  10525. }
  10526. } else {
  10527. //
  10528. // This isn't a basic driver. If it's the best one we've seen,
  10529. // remember it.
  10530. //
  10531. if(DriverInstallParams.Rank <= BestRank) {
  10532. if(BestMemberIndex == -1) {
  10533. //
  10534. // This is the first acceptable non-basic driver we've
  10535. // encountered...
  10536. //
  10537. BestDriverDate = DriverInfoData.DriverDate;
  10538. BestMemberIndex = (INT)MemberIndex;
  10539. BestDriverVersion = DriverInfoData.DriverVersion;
  10540. } else {
  10541. //
  10542. // If this new driver has a better (smaller) Rank than
  10543. // the current Best Driver or it has a newer date then
  10544. // make it the Best Driver.
  10545. //
  10546. if((DriverInstallParams.Rank < BestRank) ||
  10547. (CompareFileTime(&BestDriverDate, &(DriverInfoData.DriverDate)) == -1)) {
  10548. BestDriverDate = DriverInfoData.DriverDate;
  10549. BestMemberIndex = (INT)MemberIndex;
  10550. BestDriverVersion = DriverInfoData.DriverVersion;
  10551. } else if ((DriverInstallParams.Rank == BestRank) &&
  10552. (CompareFileTime(&BestDriverDate, &(DriverInfoData.DriverDate)) == 0) &&
  10553. (DriverInfoData.DriverVersion > BestDriverVersion)) {
  10554. //
  10555. // If the Rank and DriverDate of the new driver
  10556. // are identical to the current Best driver,
  10557. // then check if the new driver has a newer
  10558. // DriverVersion and if so make it the Best Driver.
  10559. //
  10560. BestDriverDate = DriverInfoData.DriverDate;
  10561. BestMemberIndex = (INT)MemberIndex;
  10562. BestDriverVersion = DriverInfoData.DriverVersion;
  10563. }
  10564. }
  10565. BestRank = DriverInstallParams.Rank;
  10566. }
  10567. }
  10568. }
  10569. MemberIndex++;
  10570. }
  10571. //
  10572. // If BestRank and BasicBestRank still equal RANK_NO_MATCH then we don't
  10573. // have any compatible drivers
  10574. //
  10575. if((BestRank == RANK_NO_MATCH) && (BasicBestRank == RANK_NO_MATCH)) {
  10576. Err = ERROR_NO_COMPAT_DRIVERS;
  10577. goto clean1;
  10578. }
  10579. //
  10580. // Select best driver from among basic and full-featured offerings as
  10581. // follows:
  10582. //
  10583. // 1. Full-featured, signed driver
  10584. // 2. Basic signed driver
  10585. // 3. Best rank/newest date between full-featured and basic unsigned
  10586. // driver (note: it will be rare that we encounter a basic unsigned
  10587. // driver since this will typically be used only for our in-box
  10588. // offerings, which are always signed)
  10589. //
  10590. if(BestRank < DRIVER_UNTRUSTED_RANK) {
  10591. MemberIndex = (DWORD)BestMemberIndex;
  10592. } else if(BasicBestRank < DRIVER_UNTRUSTED_RANK) {
  10593. MemberIndex = (DWORD)BasicBestMemberIndex;
  10594. } else {
  10595. if(BestRank < BasicBestRank) {
  10596. MemberIndex = (DWORD)BestMemberIndex;
  10597. } else if(BasicBestRank < BestRank) {
  10598. MemberIndex = (DWORD)BasicBestMemberIndex;
  10599. } else {
  10600. //
  10601. // We have both a basic driver and full-featured one, both of which
  10602. // are unsigned, and both of which are equivalently ranked. Pick
  10603. // the newer one. In the unlikely event that they're the same
  10604. // date, pick the full-featured one.
  10605. //
  10606. // We have both a basic driver and full-featured one, both of which
  10607. // are unsigned, and both of which are equivalently ranked. If the
  10608. // driver dates are the same, then pick the one with the newer
  10609. // driver version, otherwise pick the one with the newest date.
  10610. // In the unlikely event that the DriverDate and DriverVersion are
  10611. // the same, pick the full-featured one.
  10612. //
  10613. if (CompareFileTime(&BestDriverDate, &BasicBestDriverDate) == 0) {
  10614. //
  10615. // Driver dates are the same, so take the one with the newest
  10616. // driver version.
  10617. //
  10618. if (BasicBestDriverVersion > BestDriverVersion) {
  10619. MemberIndex = (DWORD)BasicBestMemberIndex;
  10620. } else {
  10621. MemberIndex = (DWORD)BestMemberIndex;
  10622. }
  10623. } else if(CompareFileTime(&BestDriverDate, &BasicBestDriverDate) == -1) {
  10624. MemberIndex = (DWORD)BasicBestMemberIndex;
  10625. } else {
  10626. MemberIndex = (DWORD)BestMemberIndex;
  10627. }
  10628. }
  10629. }
  10630. //
  10631. // (Re-)retrieve the driver info data for the best driver we found.
  10632. //
  10633. if(!SetupDiEnumDriverInfo(DeviceInfoSet,
  10634. DeviceInfoData,
  10635. SPDIT_COMPATDRIVER,
  10636. MemberIndex,
  10637. &DriverInfoData)) {
  10638. //
  10639. // We should never see this error, since we retrieved this driver node
  10640. // just moments ago, and we have the HDEVINFO locked, so no one could
  10641. // have deleted it out from under us.
  10642. //
  10643. Err = GetLastError();
  10644. goto clean1;
  10645. }
  10646. if(!SetupDiSetSelectedDriver(DeviceInfoSet,
  10647. DeviceInfoData,
  10648. &DriverInfoData)) {
  10649. Err = GetLastError();
  10650. }
  10651. clean1:
  10652. if(Err == NO_ERROR) {
  10653. //
  10654. // give a +ve affirmation of Success
  10655. //
  10656. WriteLogEntry(
  10657. LogContext,
  10658. DRIVER_LOG_INFO,
  10659. MSG_LOG_SELECTEDBEST,
  10660. NULL);
  10661. //
  10662. // If we had a basic driver but didn't use it, log an information entry
  10663. //
  10664. if((BasicBestMemberIndex != -1) &&
  10665. (BasicBestMemberIndex != (INT)MemberIndex)) {
  10666. if(SetupDiEnumDriverInfo(DeviceInfoSet,
  10667. DeviceInfoData,
  10668. SPDIT_COMPATDRIVER,
  10669. (DWORD)BasicBestMemberIndex,
  10670. &DriverInfoData)) {
  10671. SP_DRVINFO_DETAIL_DATA Data;
  10672. Data.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  10673. if(SetupDiGetDriverInfoDetail(DeviceInfoSet,
  10674. DeviceInfoData,
  10675. &DriverInfoData,
  10676. &Data,
  10677. Data.cbSize,
  10678. NULL) ||
  10679. (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) {
  10680. WriteLogEntry(
  10681. LogContext,
  10682. DRIVER_LOG_INFO,
  10683. MSG_LOG_SELECTBEST_BASIC_DRIVER_SKIPPED,
  10684. NULL,
  10685. Data.DrvDescription,
  10686. Data.InfFileName,
  10687. Data.SectionName
  10688. );
  10689. }
  10690. }
  10691. }
  10692. } else {
  10693. //
  10694. // indicate failed, display error
  10695. //
  10696. WriteLogEntry(
  10697. LogContext,
  10698. ((Err == ERROR_NO_COMPAT_DRIVERS) ?
  10699. DRIVER_LOG_WARNING :
  10700. DRIVER_LOG_ERROR)
  10701. | SETUP_LOG_BUFFER,
  10702. MSG_LOG_SELECTBEST_ERROR,
  10703. NULL);
  10704. WriteLogError(
  10705. LogContext,
  10706. ((Err == ERROR_NO_COMPAT_DRIVERS) ?
  10707. DRIVER_LOG_WARNING :
  10708. DRIVER_LOG_ERROR),
  10709. Err);
  10710. }
  10711. if (pDeviceInfoSet) {
  10712. UnlockDeviceInfoSet(pDeviceInfoSet);
  10713. }
  10714. SetLastError(Err);
  10715. return(Err == NO_ERROR);
  10716. }
  10717. BOOL
  10718. RetrieveAllDriversForDevice(
  10719. IN PDEVINFO_ELEM DevInfoElem,
  10720. OUT PTSTR *DriverList,
  10721. IN DWORD Flags,
  10722. IN HMACHINE hMachine
  10723. )
  10724. /*++
  10725. Routine Description:
  10726. This routine returns a multi-sz list of all filter drivers (both upper and
  10727. lower, class-specific and device-specific) for the specified device information
  10728. element.
  10729. Arguments:
  10730. DevInfoElem - Specifies the device information element whose list of filter
  10731. drivers are to be retrieved.
  10732. DriverList - If this routine returns TRUE (i.e., there was at least one
  10733. filter driver for this device), then this pointer is filled in to point
  10734. to a newly-allocated buffer containing a multi-sz list of all filters
  10735. associated with this device. If we encountered an out-of-memory error,
  10736. this pointer will be set to NULL.
  10737. Flags - can be one of the following:
  10738. RADFD_FLAG_FUNCTION_DRIVER - include the function driver in the
  10739. DriverList return value.
  10740. RADFD_FLAG_DEVICE_UPPER_FILTERS - include the device upper filters in
  10741. the DriverList return value.
  10742. RADFD_FLAG_DEVICE_LOWER_FILTERS - include the device lower filters in
  10743. the DriverList return value.
  10744. RADFD_FLAG_CLASS_UPPER_FILTERS - include the class upper filters in the
  10745. DriverList return value.
  10746. RADFD_FLAG_CLASS_LOWER_FILTERS - include the class lower filters in the
  10747. DriverList return value.
  10748. RADFD_FLAG_DEVICE_FILTERS - include both the device upper and lower
  10749. filters in the DriverList return value.
  10750. RADFD_FLAG_CLASS_FILTERS include both the class upper and lower filters
  10751. in the DriverList return value.
  10752. Return Value:
  10753. If there is at least one filter driver for the specified device (or we couldn't
  10754. tell because we ran out of memory), the return value is TRUE.
  10755. Otherwise, it is FALSE.
  10756. --*/
  10757. {
  10758. PTSTR Buffer, NewBuffer, CurPos, EndPos, p;
  10759. DWORD BufferSize, UsedSize, RequiredSize;
  10760. DWORD i, NumLists, Err;
  10761. CONFIGRET cr;
  10762. DWORD RegDataType;
  10763. HKEY hk;
  10764. ULONG ulProperty;
  10765. DWORD Gap = sizeof(TCHAR)*2; // extra space at end of buffer for nulls
  10766. *DriverList = NULL;
  10767. BufferSize = 1024 * sizeof(TCHAR); // start out with a reasonably-sized buffer.
  10768. Buffer = MyMalloc(BufferSize+Gap);
  10769. if(Buffer) {
  10770. UsedSize = 0;
  10771. CurPos = Buffer;
  10772. } else {
  10773. //
  10774. // We really don't know whether there were any filters for this device, but
  10775. // if we return TRUE, the NULL DriverList OUT parameter will signal to the
  10776. // caller that we encountered an out-of-memory condition.
  10777. //
  10778. return TRUE;
  10779. }
  10780. //
  10781. // Attempt to open the class key so we can retrieve the class-specific filter lists.
  10782. //
  10783. hk = SetupDiOpenClassRegKey(&(DevInfoElem->ClassGuid), KEY_READ);
  10784. NumLists = (hk == INVALID_HANDLE_VALUE) ? 3 : 5;
  10785. //
  10786. // First, retrieve the UpperFilters and LowerFilters device properties (i.e.,
  10787. // the device-specific filters).
  10788. //
  10789. for(i = 0; i < NumLists; i++) {
  10790. RequiredSize = Gap;
  10791. while(TRUE) {
  10792. //
  10793. // Do we need a larger buffer?
  10794. //
  10795. if((BufferSize<UsedSize) || (RequiredSize > (BufferSize - UsedSize))) {
  10796. BufferSize = UsedSize + RequiredSize;
  10797. NewBuffer = MyRealloc(Buffer, BufferSize+Gap);
  10798. if(NewBuffer) {
  10799. //
  10800. // Adjust our current position pointer.
  10801. //
  10802. CurPos = NewBuffer + (CurPos - Buffer);
  10803. Buffer = NewBuffer;
  10804. } else {
  10805. MyFree(Buffer);
  10806. if(hk != INVALID_HANDLE_VALUE) {
  10807. RegCloseKey(hk);
  10808. }
  10809. return TRUE;
  10810. }
  10811. } else {
  10812. RequiredSize = BufferSize - UsedSize;
  10813. }
  10814. if(i < 3) {
  10815. //
  10816. // Then we're retrieving the device-specific lists.
  10817. //
  10818. if (i == 0) {
  10819. //
  10820. // Check to see if we need to include the function driver
  10821. //
  10822. if (!(Flags & RADFD_FLAG_FUNCTION_DRIVER)) {
  10823. //
  10824. // Skip the function driver.
  10825. //
  10826. break;
  10827. }
  10828. ulProperty = CM_DRP_SERVICE;
  10829. } else if (i == 1) {
  10830. //
  10831. // Check to see if we need to include the device lower filters.
  10832. //
  10833. if (!(Flags & RADFD_FLAG_DEVICE_LOWER_FILTERS)) {
  10834. //
  10835. // Skip the device lower filters.
  10836. //
  10837. break;
  10838. }
  10839. ulProperty = CM_DRP_LOWERFILTERS;
  10840. } else {
  10841. //
  10842. // Check to see if we need to include the device upper filters.
  10843. //
  10844. if (!(Flags & RADFD_FLAG_DEVICE_UPPER_FILTERS)) {
  10845. //
  10846. // Skip the device upper filters.
  10847. //
  10848. break;
  10849. }
  10850. ulProperty = CM_DRP_UPPERFILTERS;
  10851. }
  10852. cr = CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  10853. ulProperty,
  10854. NULL,
  10855. CurPos,
  10856. &RequiredSize,
  10857. 0,
  10858. hMachine
  10859. );
  10860. //
  10861. // Map the CONFIGRET code to Win32 error codes that mimic the
  10862. // behavior of the registry APIs. This way, we can have common
  10863. // handling of the error codes down below...
  10864. //
  10865. switch(cr) {
  10866. case CR_SUCCESS :
  10867. Err = ERROR_SUCCESS;
  10868. break;
  10869. case CR_BUFFER_SMALL :
  10870. Err = ERROR_MORE_DATA;
  10871. break;
  10872. default :
  10873. Err = ERROR_INVALID_DATA; // any old error will do.
  10874. break;
  10875. }
  10876. } else {
  10877. //
  10878. // We're retrieving the class-specific lists.
  10879. //
  10880. if (i == 3) {
  10881. //
  10882. // Check to see if we need to include the class lower filters
  10883. //
  10884. if (!(Flags & RADFD_FLAG_CLASS_LOWER_FILTERS)) {
  10885. //
  10886. // Skip the class lower filters.
  10887. //
  10888. break;
  10889. }
  10890. } else {
  10891. //
  10892. // Check to see if we need to include the class upper filters.
  10893. //
  10894. if (!(Flags & RADFD_FLAG_CLASS_UPPER_FILTERS)) {
  10895. //
  10896. // Skip the class upper filters.
  10897. //
  10898. break;
  10899. }
  10900. }
  10901. Err = RegQueryValueEx(hk,
  10902. ((i == 3) ? pszLowerFilters : pszUpperFilters),
  10903. NULL,
  10904. &RegDataType,
  10905. (PBYTE)CurPos,
  10906. &RequiredSize
  10907. );
  10908. }
  10909. if(Err == ERROR_SUCCESS) {
  10910. //
  10911. // Walk through the service names in the multi-sz list we just retrieved to find
  10912. // the end (just in case someone screwed up when saving out this list and didn't
  10913. // size it properly, etc.)
  10914. //
  10915. // we made sure we have space for a couple of extra nulls (Gap)
  10916. // so add them here
  10917. // this covers all the bad string termination cases
  10918. // it also covers the case where we're given a REG_SZ instead
  10919. // of REG_MULTI_SZ
  10920. //
  10921. p = CurPos;
  10922. EndPos = CurPos+(RequiredSize/sizeof(TCHAR));
  10923. ZeroMemory(EndPos,Gap);
  10924. try {
  10925. while(*CurPos) {
  10926. CurPos += _tcslen(CurPos)+1;
  10927. p = CurPos;
  10928. }
  10929. } except(EXCEPTION_EXECUTE_HANDLER) {
  10930. MYASSERT(CurPos != p);
  10931. CurPos = p;
  10932. *CurPos = TEXT('\0');
  10933. }
  10934. UsedSize = (DWORD)((PBYTE)CurPos - (PBYTE)Buffer) + sizeof(TCHAR);
  10935. MYASSERT(UsedSize <= (BufferSize+Gap));
  10936. break;
  10937. } else if(Err != ERROR_MORE_DATA) {
  10938. //
  10939. // We failed for some reason other than buffer-too-small. Move
  10940. // on to the next filter driver list.
  10941. //
  10942. break;
  10943. }
  10944. }
  10945. }
  10946. if(hk != INVALID_HANDLE_VALUE) {
  10947. RegCloseKey(hk);
  10948. }
  10949. if(UsedSize) {
  10950. //
  10951. // We retrieved a list of services to return to the caller.
  10952. //
  10953. *DriverList = Buffer;
  10954. return TRUE;
  10955. }
  10956. MYASSERT(Buffer);
  10957. MyFree(Buffer);
  10958. return FALSE;
  10959. }
  10960. BOOL
  10961. RetrieveAllDevNodesSharingDriversWithDevice(
  10962. IN PDEVINFO_ELEM DevInfoElem,
  10963. OUT PTSTR *Drivers,
  10964. OUT PDEVNODE *DevNodes,
  10965. OUT ULONG *NumberOfDevNodes,
  10966. IN HMACHINE hMachine
  10967. )
  10968. /*++
  10969. Routine Description:
  10970. This routine returns a multi-sz list of all the devnodes that share a
  10971. driver with the specified device. This includes the device's function driver
  10972. and all filter drivers (both upper and lower, class-specific and device-
  10973. specific).
  10974. This routine returns a multi-sz list of all filter drivers (both upper and
  10975. lower device-specific) for the specified device information
  10976. element.
  10977. Arguments:
  10978. DevInfoElem - Specifies the device information element.
  10979. Drivers -
  10980. DevNodes -
  10981. NumberOfDevNodes -
  10982. Return Value:
  10983. TRUE unless there is an unexpected error such as out of memory.
  10984. --*/
  10985. {
  10986. DWORD Err = ERROR_SUCCESS;
  10987. PTSTR p, Buffer = NULL;
  10988. ULONG BufferSize = 1024;
  10989. PTSTR DriversList = NULL, CurDriver;
  10990. DEVNODE DevNode;
  10991. PDEVNODE NewBuffer, ArrayOfDevNodes;
  10992. ULONG DevNodeArraySize = 10;
  10993. ULONG i;
  10994. CONFIGRET cr;
  10995. *NumberOfDevNodes = 0;
  10996. try {
  10997. //
  10998. // Allocate an array of devnodes. Start with 10 and we will grow it below
  10999. // if we have more.
  11000. //
  11001. if ((ArrayOfDevNodes = MyMalloc(DevNodeArraySize * sizeof(DEVNODE))) == NULL) {
  11002. Err = ERROR_NOT_ENOUGH_MEMORY;
  11003. goto clean0;
  11004. }
  11005. //
  11006. // Always include the devnode that was passed in.
  11007. //
  11008. ArrayOfDevNodes[*NumberOfDevNodes] = DevInfoElem->DevInst;
  11009. (*NumberOfDevNodes)++;
  11010. //
  11011. // Now get a list of all the filter drivers (both upper and lower
  11012. // device-specific) that this device is using and
  11013. // then add any devnode using one of these services to our list.
  11014. //
  11015. if (RetrieveAllDriversForDevice(DevInfoElem,
  11016. &DriversList,
  11017. RADFD_FLAG_FUNCTION_DRIVER | RADFD_FLAG_DEVICE_FILTERS,
  11018. hMachine)) {
  11019. //
  11020. // We need a buffer when we call CM_Get_Device_ID_list_Ex, we will
  11021. // start with a 1024 buffer and grow it as needed.
  11022. //
  11023. Buffer = MyMalloc(BufferSize * sizeof(TCHAR));
  11024. if (!Buffer) {
  11025. Err = ERROR_NOT_ENOUGH_MEMORY;
  11026. goto clean0;
  11027. }
  11028. //
  11029. // Enumerate through all the filters and build up a list of drivers
  11030. // they are using.
  11031. //
  11032. for (CurDriver=DriversList; *CurDriver; CurDriver+=(lstrlen(CurDriver)+1)) {
  11033. while ((cr = CM_Get_Device_ID_List_Ex(
  11034. CurDriver,
  11035. Buffer,
  11036. BufferSize,
  11037. CM_GETIDLIST_FILTER_SERVICE |
  11038. CM_GETIDLIST_DONOTGENERATE,
  11039. hMachine
  11040. )) == CR_BUFFER_SMALL) {
  11041. //
  11042. // If the buffer is too small then we need to reallocate a
  11043. // larger one.
  11044. //
  11045. PTSTR TempBuffer;
  11046. CM_Get_Device_ID_List_Size_Ex(&BufferSize,
  11047. CurDriver,
  11048. CM_GETIDLIST_FILTER_SERVICE,
  11049. hMachine);
  11050. TempBuffer = MyRealloc(Buffer, BufferSize * sizeof(TCHAR));
  11051. if (TempBuffer) {
  11052. Buffer = TempBuffer;
  11053. } else {
  11054. //
  11055. // We couldn't create a larger buffer!
  11056. //
  11057. Err = ERROR_NOT_ENOUGH_MEMORY;
  11058. goto clean0;
  11059. }
  11060. }
  11061. if (cr == CR_SUCCESS) {
  11062. //
  11063. // Enumerate through all the device instance Ids and add them
  11064. // to the list of devnodes.
  11065. //
  11066. for (p=Buffer; *p; p+=(lstrlen(p)+1)) {
  11067. if (CM_Locate_DevInst_Ex(&DevNode,
  11068. p,
  11069. 0,
  11070. hMachine
  11071. ) == CR_SUCCESS) {
  11072. //
  11073. // Check to see if this devnode already exists in
  11074. // our list.
  11075. //
  11076. for (i=0; i<*NumberOfDevNodes; i++) {
  11077. if (ArrayOfDevNodes[i] == DevNode) {
  11078. break;
  11079. }
  11080. }
  11081. if (i == *NumberOfDevNodes) {
  11082. //
  11083. // Check to see if we need to increase our devnode array.
  11084. //
  11085. if (DevNodeArraySize <= *NumberOfDevNodes) {
  11086. DevNodeArraySize += 10;
  11087. NewBuffer = MyRealloc(ArrayOfDevNodes, DevNodeArraySize * sizeof(DEVNODE));
  11088. if (NewBuffer) {
  11089. ArrayOfDevNodes = NewBuffer;
  11090. } else {
  11091. Err = ERROR_NOT_ENOUGH_MEMORY;
  11092. goto clean0;
  11093. }
  11094. }
  11095. ArrayOfDevNodes[*NumberOfDevNodes] = DevNode;
  11096. (*NumberOfDevNodes)++;
  11097. }
  11098. }
  11099. }
  11100. } else {
  11101. //
  11102. // We got another error back so we will fail.
  11103. //
  11104. Err = ERROR_INVALID_DATA;
  11105. goto clean0;
  11106. }
  11107. }
  11108. }
  11109. } except(EXCEPTION_EXECUTE_HANDLER) {
  11110. Err = ERROR_INVALID_PARAMETER;
  11111. //
  11112. // Access the following variables, so that the compiler will respect our
  11113. // statement ordering w.r.t. their assignment.
  11114. //
  11115. Buffer = Buffer;
  11116. ArrayOfDevNodes = ArrayOfDevNodes;
  11117. DriversList = DriversList;
  11118. }
  11119. clean0:
  11120. if (Buffer) {
  11121. MyFree(Buffer);
  11122. }
  11123. if (Err == ERROR_SUCCESS) {
  11124. *DevNodes = ArrayOfDevNodes;
  11125. *Drivers = DriversList;
  11126. } else {
  11127. //
  11128. // If we failed then free all the memory and set the pointers
  11129. // to NULL.
  11130. //
  11131. if (ArrayOfDevNodes) {
  11132. MyFree(ArrayOfDevNodes);
  11133. *DevNodes = NULL;
  11134. }
  11135. if (DriversList) {
  11136. MyFree(DriversList);
  11137. *Drivers = NULL;
  11138. }
  11139. }
  11140. return (Err == ERROR_SUCCESS);
  11141. }
  11142. BOOL
  11143. AnyServicesLoaded(
  11144. IN PCTSTR ServiceNameList,
  11145. OUT PTSTR LoadedService, OPTIONAL
  11146. IN ULONG LoadedServiceSize
  11147. )
  11148. /*++
  11149. Routine Description:
  11150. This routine will determine if any of the services passed in our currently
  11151. loaded.
  11152. Arguments:
  11153. ServiceNameList - multi-sz list of service names.
  11154. LoadedService - buffer that will receive the service the first service in
  11155. the list that is still loaded into memory. This value is only valid
  11156. if the API returns TRUE.
  11157. LoadedServiceSize - size of the LoadedService buffer.
  11158. Return Value:
  11159. TRUE if any of the services in the list are loaded, FALSE if none of them
  11160. are currently loaded.
  11161. --*/
  11162. {
  11163. NTSTATUS Status;
  11164. BOOL bObjectIsLoaded = FALSE;
  11165. DWORD BufSize = 1024;
  11166. PUCHAR Buffer = NULL;
  11167. UNICODE_STRING UnicodeStringDriver;
  11168. UNICODE_STRING UnicodeStringService;
  11169. OBJECT_ATTRIBUTES Attributes;
  11170. HANDLE DirectoryHandle = INVALID_HANDLE_VALUE;
  11171. POBJECT_DIRECTORY_INFORMATION DirInfo;
  11172. POBJECT_NAME_INFORMATION NameInfo;
  11173. ULONG Context = 0;
  11174. ULONG ReturnedLength;
  11175. PTSTR CurServiceName;
  11176. try {
  11177. if (LoadedService) {
  11178. LoadedService[0] = TEXT('\0');
  11179. }
  11180. //
  11181. // If no services were passed in then just leave.
  11182. //
  11183. if (!ServiceNameList) {
  11184. goto clean0;
  11185. }
  11186. Buffer = MyMalloc(BufSize);
  11187. if (!Buffer) {
  11188. goto clean0;
  11189. }
  11190. ZeroMemory(Buffer, BufSize);
  11191. RtlInitUnicodeString(&UnicodeStringDriver, TEXT("\\Driver"));
  11192. InitializeObjectAttributes(&Attributes,
  11193. &UnicodeStringDriver,
  11194. OBJ_CASE_INSENSITIVE,
  11195. NULL,
  11196. NULL
  11197. );
  11198. Status = NtOpenDirectoryObject(&DirectoryHandle,
  11199. DIRECTORY_QUERY,
  11200. &Attributes
  11201. );
  11202. if (!NT_SUCCESS(Status)) {
  11203. goto clean0;
  11204. }
  11205. //
  11206. // Get the actual name of the object directory object.
  11207. //
  11208. NameInfo = (POBJECT_NAME_INFORMATION)Buffer;
  11209. if (!NT_SUCCESS(Status = NtQueryObject(DirectoryHandle,
  11210. ObjectNameInformation,
  11211. NameInfo,
  11212. BufSize,
  11213. (PULONG)NULL))) {
  11214. goto clean0;
  11215. }
  11216. //
  11217. // Grab the driver objects in chuncks instead of one at a time.
  11218. //
  11219. for (Status = NtQueryDirectoryObject(DirectoryHandle,
  11220. Buffer,
  11221. BufSize,
  11222. FALSE,
  11223. FALSE,
  11224. &Context,
  11225. &ReturnedLength
  11226. );
  11227. NT_SUCCESS(Status) && !bObjectIsLoaded;
  11228. Status = NtQueryDirectoryObject(DirectoryHandle,
  11229. Buffer,
  11230. BufSize,
  11231. FALSE,
  11232. FALSE,
  11233. &Context,
  11234. &ReturnedLength
  11235. )) {
  11236. if (!NT_SUCCESS(Status)) {
  11237. break;
  11238. }
  11239. DirInfo = (POBJECT_DIRECTORY_INFORMATION)Buffer;
  11240. while (TRUE) {
  11241. //
  11242. // Check if there is another record. If there isn't, then get out
  11243. // of the loop now.
  11244. //
  11245. if (DirInfo->Name.Length == 0) {
  11246. break;
  11247. }
  11248. for (CurServiceName=(PTSTR)ServiceNameList;
  11249. *CurServiceName;
  11250. CurServiceName+=(lstrlen(CurServiceName)+1)) {
  11251. RtlInitUnicodeString(&UnicodeStringService, CurServiceName);
  11252. if (RtlCompareUnicodeString(&UnicodeStringService, &(DirInfo->Name), TRUE) == 0) {
  11253. bObjectIsLoaded = TRUE;
  11254. if (LoadedService) {
  11255. MYVERIFY(SUCCEEDED(StringCchCopy(LoadedService,
  11256. LoadedServiceSize,
  11257. CurServiceName)));
  11258. }
  11259. break;
  11260. }
  11261. }
  11262. //
  11263. // If one of the drivers is loaded then just stop now.
  11264. //
  11265. if (bObjectIsLoaded) {
  11266. break;
  11267. }
  11268. DirInfo = (POBJECT_DIRECTORY_INFORMATION)(((PUCHAR)DirInfo) +
  11269. sizeof(OBJECT_DIRECTORY_INFORMATION));
  11270. }
  11271. ZeroMemory(Buffer, BufSize);
  11272. }
  11273. } except(EXCEPTION_EXECUTE_HANDLER) {
  11274. bObjectIsLoaded = TRUE;
  11275. //
  11276. // Access the following variables, so that the compiler will respect our
  11277. // statement ordering w.r.t. their assignment.
  11278. //
  11279. Buffer = Buffer;
  11280. }
  11281. clean0:
  11282. if (DirectoryHandle != INVALID_HANDLE_VALUE) {
  11283. NtClose(DirectoryHandle);
  11284. }
  11285. if (Buffer) {
  11286. MyFree(Buffer);
  11287. }
  11288. return bObjectIsLoaded;
  11289. }
  11290. VOID
  11291. RestartSingleDevice(
  11292. IN PDEVINFO_ELEM DevInfoElem,
  11293. IN PDEVICE_INFO_SET pDeviceInfoSet,
  11294. IN BOOL NullDriverInstall,
  11295. IN PSETUP_LOG_CONTEXT LogContext
  11296. )
  11297. /*++
  11298. Routine Description:
  11299. Arguments:
  11300. DevInfoElem -
  11301. pDeviceInfoSet -
  11302. NullDriverInstall -
  11303. LogContext -
  11304. Return Value:
  11305. --*/
  11306. {
  11307. DWORD DevInstCapabilities;
  11308. ULONG cbData;
  11309. ULONG ulStatus, ulProblem;
  11310. TCHAR DeviceFullID[MAX_DEVICE_ID_LEN];
  11311. //
  11312. // Retrieve the device's capabilities. We need to know whether the device is
  11313. // capable of being driven 'raw' (i.e., without a function driver).
  11314. //
  11315. cbData = sizeof(DevInstCapabilities);
  11316. if(CR_SUCCESS != CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  11317. CM_DRP_CAPABILITIES,
  11318. NULL,
  11319. &DevInstCapabilities,
  11320. &cbData,
  11321. 0,
  11322. pDeviceInfoSet->hMachine))
  11323. {
  11324. DevInstCapabilities = 0;
  11325. }
  11326. //
  11327. // If the device instance has a problem but is not disabled. Just
  11328. // restart it. This should be 90% of the cases.
  11329. //
  11330. if((CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevInfoElem->DevInst,
  11331. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  11332. ((ulStatus & DN_HAS_PROBLEM) || !(ulStatus & DN_DRIVER_LOADED))) {
  11333. //
  11334. // Poke at Config Manager to make it load the driver.
  11335. //
  11336. WriteLogEntry(
  11337. LogContext,
  11338. DRIVER_LOG_TIME,
  11339. MSG_LOG_BEGIN_RESTART_TIME,
  11340. NULL); // text message
  11341. CM_Setup_DevInst_Ex(DevInfoElem->DevInst, CM_SETUP_DEVINST_READY, pDeviceInfoSet->hMachine);
  11342. WriteLogEntry(
  11343. LogContext,
  11344. DRIVER_LOG_TIME,
  11345. MSG_LOG_END_RESTART_TIME,
  11346. NULL); // text message
  11347. //
  11348. // If we're installing a 'real' driver (i.e., not null), or if the device is
  11349. // raw-capable, then we want to check and see if the device actually started as
  11350. // a result of CM_Setup_DevInst. If not, a reboot is in order. (There's no need
  11351. // to check when we're doing a null driver install for a non-raw devnode. We know
  11352. // it can't start, and we definitely don't want to generate a 'need reboot' popup
  11353. // in this case!)
  11354. //
  11355. if(!NullDriverInstall || (DevInstCapabilities & CM_DEVCAP_RAWDEVICEOK)) {
  11356. CheckIfDevStarted(DevInfoElem, pDeviceInfoSet);
  11357. }
  11358. } else {
  11359. CONFIGRET cr;
  11360. TCHAR VetoName[MAX_PATH];
  11361. PNP_VETO_TYPE VetoType;
  11362. //
  11363. // If there is a device instance with no problem, then we
  11364. // should remove it (to unload the current drivers off of
  11365. // it), and then call CM_Setup_DevInst on it. If the
  11366. // device instance refuses to remove, then set the flags
  11367. // that say we need to reboot.
  11368. //
  11369. // NOTE: In Win9x, virtual removal of a devnode (e.g., to
  11370. // unload the driver(s) for it), resulted in the devnode's
  11371. // deletion. Thus, on Win9x, it was necessary to
  11372. // re-enumerate the devnode's parent to cause the devnode
  11373. // to be re-created (and subsequently started). This is
  11374. // inefficient, especially if we're dealing with a root-
  11375. // enumerated device (hence requiring a reenumeration of
  11376. // the entire tree). Since the device installer
  11377. // functionality of setupapi will apparently never be used
  11378. // on Win9x, we can optimize this such that we just call
  11379. // CM_Setup_DevInst on this devnode. We know it didn't
  11380. // actually go away, because devnodes only go away on NT
  11381. // when their underlying hardware is physically removed.
  11382. //
  11383. WriteLogEntry(
  11384. LogContext,
  11385. DRIVER_LOG_TIME,
  11386. MSG_LOG_BEGIN_REMOVE_TIME,
  11387. NULL); // text message
  11388. cr = CM_Query_And_Remove_SubTree_Ex(DevInfoElem->DevInst,
  11389. &VetoType,
  11390. VetoName,
  11391. SIZECHARS(VetoName),
  11392. (DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NOUIONQUERYREMOVE)
  11393. ? CM_REMOVE_UI_NOT_OK
  11394. : CM_REMOVE_UI_OK,
  11395. pDeviceInfoSet->hMachine
  11396. );
  11397. WriteLogEntry(
  11398. LogContext,
  11399. DRIVER_LOG_TIME,
  11400. MSG_LOG_END_REMOVE_TIME,
  11401. NULL); // text message
  11402. if(cr == CR_SUCCESS) {
  11403. WriteLogEntry(
  11404. LogContext,
  11405. DRIVER_LOG_TIME,
  11406. MSG_LOG_BEGIN_RESTART_TIME,
  11407. NULL); // text message
  11408. CM_Setup_DevInst_Ex(DevInfoElem->DevInst,
  11409. CM_SETUP_DEVINST_READY,
  11410. pDeviceInfoSet->hMachine
  11411. );
  11412. WriteLogEntry(
  11413. LogContext,
  11414. DRIVER_LOG_TIME,
  11415. MSG_LOG_END_RESTART_TIME,
  11416. NULL); // text message
  11417. //
  11418. // If we're installing a 'real' driver (i.e., not null),
  11419. // or if the device is raw-capable, then we want to
  11420. // check and see if the device actually started as a
  11421. // result of CM_Setup_DevInst. If not, a reboot is in
  11422. // order. (There's no need to check when we're doing a
  11423. // null driver install for a non-raw devnode. We know
  11424. // it can't start, and we definitely don't want to
  11425. // generate a 'need reboot' popup in this case!)
  11426. //
  11427. if(!NullDriverInstall || (DevInstCapabilities & CM_DEVCAP_RAWDEVICEOK)) {
  11428. CheckIfDevStarted(DevInfoElem,pDeviceInfoSet);
  11429. }
  11430. } else {
  11431. //
  11432. // If the failure was due to a veto, then log
  11433. // information about who vetoed us.
  11434. //
  11435. // SPLOG-- write out a log entry
  11436. //
  11437. if(cr == CR_REMOVE_VETOED) {
  11438. if( CM_Get_Device_ID(DevInfoElem->DevInst,
  11439. DeviceFullID,
  11440. SIZECHARS(DeviceFullID),
  11441. 0
  11442. ) == CR_SUCCESS ) {
  11443. _WriteVetoLogEntry(
  11444. LogContext,
  11445. DRIVER_LOG_WARNING,
  11446. MSG_LOG_REMOVE_VETOED_IN_INSTALL,
  11447. DeviceFullID,
  11448. VetoName,
  11449. VetoType);
  11450. }
  11451. }
  11452. //
  11453. // If the failure was due to the device not being there,
  11454. // then prompting for reboot isn't going to help
  11455. // anything (plus, you can't set a problem on a non-
  11456. // existent devnode anyway). This could happen, for
  11457. // example, if the user plugged in a USB mouse, then
  11458. // unplugged it again before we got a chance to
  11459. // complete the device installation. In this case,
  11460. // we'll just ignore the failure and continue on.
  11461. //
  11462. if(cr != CR_INVALID_DEVNODE) {
  11463. SetDevnodeNeedsRebootProblemWithArg2(DevInfoElem,
  11464. pDeviceInfoSet,
  11465. MSG_LOG_REBOOT_REASON_QR_VETOED,
  11466. cr,
  11467. (ULONG_PTR)_MapCmRetToString(cr)
  11468. );
  11469. }
  11470. }
  11471. }
  11472. }
  11473. VOID
  11474. RestartAllDevicesUsingDrivers(
  11475. IN PDEVINFO_ELEM DevInfoElem,
  11476. IN PDEVICE_INFO_SET pDeviceInfoSet,
  11477. IN BOOL NullDriverInstall,
  11478. IN PSETUP_LOG_CONTEXT LogContext
  11479. )
  11480. /*++
  11481. Routine Description:
  11482. Arguments:
  11483. DevInfoElem -
  11484. pDeviceInfoSet -
  11485. NullDriverInstall -
  11486. LogContext -
  11487. Return Value:
  11488. --*/
  11489. {
  11490. BOOL bNeedReboot = FALSE;
  11491. PTSTR CurDriver, DriverList = NULL;
  11492. PDEVNODE DevNodeList = NULL;
  11493. ULONG NumberOfDevNodes, LastDevNodeStopped, i;
  11494. ULONG ulStatus, ulProblem;
  11495. PBOOL DevNodeStartedList = NULL;
  11496. TCHAR DeviceFullID[MAX_DEVICE_ID_LEN];
  11497. TCHAR LoadedService[MAX_SERVICE_NAME_LEN];
  11498. CONFIGRET cr;
  11499. try {
  11500. if (RetrieveAllDevNodesSharingDriversWithDevice(DevInfoElem,
  11501. &DriverList,
  11502. &DevNodeList,
  11503. &NumberOfDevNodes,
  11504. pDeviceInfoSet->hMachine)) {
  11505. //
  11506. // Allocate an array of BOOLs so we can remember if each devnode was
  11507. // started before we tried to unload all of the drivers.
  11508. //
  11509. if (NumberOfDevNodes) {
  11510. DevNodeStartedList = MyMalloc(NumberOfDevNodes * sizeof(BOOL));
  11511. if (!DevNodeStartedList) {
  11512. bNeedReboot = TRUE;
  11513. goto clean0;
  11514. }
  11515. }
  11516. //
  11517. // First we will enumerate through all of the devices and remember
  11518. // if they were started before we remove/restart them all. We need
  11519. // to do this step first since we don't have any devnode dependency
  11520. // information so stopping the first one could affect one of the
  11521. // others in the list.
  11522. //
  11523. for (i=0; i<NumberOfDevNodes; i++) {
  11524. if((CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevNodeList[i],
  11525. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  11526. (!(ulStatus & DN_HAS_PROBLEM) && (ulStatus & DN_DRIVER_LOADED))) {
  11527. DevNodeStartedList[i] = TRUE;
  11528. } else {
  11529. DevNodeStartedList[i] = FALSE;
  11530. }
  11531. }
  11532. //
  11533. // Next stop all of the devnodes that are using one of the drivers
  11534. // associated with our new device.
  11535. //
  11536. for (i=0; i<NumberOfDevNodes; i++) {
  11537. //
  11538. // Remember the last devnode that we tried to stop.
  11539. //
  11540. LastDevNodeStopped = i;
  11541. if(CM_Get_Device_ID(DevNodeList[i],
  11542. DeviceFullID,
  11543. SIZECHARS(DeviceFullID),
  11544. 0
  11545. ) != CR_SUCCESS ) {
  11546. DeviceFullID[0] = TEXT('\0');
  11547. }
  11548. //
  11549. // Only attempt to stop the device if it is currently started.
  11550. //
  11551. if((CM_Get_DevInst_Status_Ex(&ulStatus, &ulProblem, DevNodeList[i],
  11552. 0,pDeviceInfoSet->hMachine) == CR_SUCCESS) &&
  11553. (!(ulStatus & DN_HAS_PROBLEM) && (ulStatus & DN_DRIVER_LOADED))) {
  11554. //
  11555. // Since the devnode is started we need to query remove it.
  11556. //
  11557. TCHAR VetoName[MAX_PATH];
  11558. PNP_VETO_TYPE VetoType;
  11559. //
  11560. // Remove the devnode (to unload the current drivers off of
  11561. // it). If the device instance refuses to remove, then set
  11562. // the flags that say we need to reboot.
  11563. //
  11564. WriteLogEntry(
  11565. LogContext,
  11566. DRIVER_LOG_TIME,
  11567. MSG_LOG_BEGIN_REMOVE_TIME_DEVICE,
  11568. NULL,
  11569. DeviceFullID);
  11570. cr = CM_Query_And_Remove_SubTree_Ex(DevNodeList[i],
  11571. &VetoType,
  11572. VetoName,
  11573. SIZECHARS(VetoName),
  11574. CM_REMOVE_NO_RESTART |
  11575. ((DevInfoElem->InstallParamBlock.FlagsEx & DI_FLAGSEX_NOUIONQUERYREMOVE)
  11576. ? CM_REMOVE_UI_NOT_OK
  11577. : CM_REMOVE_UI_OK),
  11578. pDeviceInfoSet->hMachine
  11579. );
  11580. WriteLogEntry(
  11581. LogContext,
  11582. DRIVER_LOG_TIME,
  11583. MSG_LOG_END_REMOVE_TIME_DEVICE,
  11584. NULL,
  11585. DeviceFullID);
  11586. if(cr != CR_SUCCESS) {
  11587. //
  11588. // If the failure was due to a veto, then log
  11589. // information about who vetoed us.
  11590. //
  11591. // SPLOG-- write out a log entry
  11592. //
  11593. if(cr == CR_REMOVE_VETOED) {
  11594. _WriteVetoLogEntry(
  11595. LogContext,
  11596. DRIVER_LOG_WARNING,
  11597. MSG_LOG_REMOVE_VETOED_IN_INSTALL,
  11598. DeviceFullID,
  11599. VetoName,
  11600. VetoType);
  11601. }
  11602. //
  11603. // If the failure was due to the device not being there,
  11604. // then prompting for reboot isn't going to help
  11605. // anything (plus, you can't set a problem on a non-
  11606. // existent devnode anyway). This could happen, for
  11607. // example, if the user plugged in a USB mouse, then
  11608. // unplugged it again before we got a chance to
  11609. // complete the device installation. In this case,
  11610. // we'll just ignore the failure and continue on.
  11611. //
  11612. if(cr != CR_INVALID_DEVNODE) {
  11613. bNeedReboot = TRUE;
  11614. WriteLogEntry(
  11615. LogContext,
  11616. DRIVER_LOG_WARNING, // should this be a warning?
  11617. MSG_LOG_REBOOT_REASON_QR_VETOED,
  11618. NULL,
  11619. cr,
  11620. (ULONG_PTR)_MapCmRetToString(cr),
  11621. DeviceFullID);
  11622. }
  11623. }
  11624. }
  11625. //
  11626. // Don't bother stopping the rest of the drivers if we need a reboot
  11627. //
  11628. if (bNeedReboot) {
  11629. break;
  11630. }
  11631. }
  11632. if (!bNeedReboot) {
  11633. //
  11634. // Verify that all of the drivers have unloaded. If just one did not
  11635. // unload then we need to prompt for a reboot.
  11636. //
  11637. if (AnyServicesLoaded(DriverList, LoadedService, SIZECHARS(LoadedService))) {
  11638. bNeedReboot = TRUE;
  11639. WriteLogEntry(
  11640. LogContext,
  11641. DRIVER_LOG_WARNING,
  11642. MSG_LOG_REBOOT_REASON_DRIVER_LOADED,
  11643. NULL,
  11644. LoadedService);
  11645. }
  11646. }
  11647. //
  11648. // Now start up all the devices that we stopped.
  11649. //
  11650. for (i=0; i<=LastDevNodeStopped; i++) {
  11651. if(CM_Get_Device_ID(DevNodeList[i],
  11652. DeviceFullID,
  11653. SIZECHARS(DeviceFullID),
  11654. 0
  11655. ) != CR_SUCCESS ) {
  11656. DeviceFullID[0] = TEXT('\0');
  11657. }
  11658. WriteLogEntry(
  11659. LogContext,
  11660. DRIVER_LOG_TIME,
  11661. MSG_LOG_BEGIN_RESTART_TIME_DEVICE,
  11662. NULL,
  11663. DeviceFullID);
  11664. CM_Setup_DevInst_Ex(DevNodeList[i],
  11665. CM_SETUP_DEVNODE_READY,
  11666. pDeviceInfoSet->hMachine);
  11667. WriteLogEntry(
  11668. LogContext,
  11669. DRIVER_LOG_TIME,
  11670. MSG_LOG_END_RESTART_TIME_DEVICE,
  11671. NULL,
  11672. DeviceFullID);
  11673. }
  11674. //
  11675. // Finally make one last pass through all the devnodes and verify
  11676. // that the ones that were started initially are started now.
  11677. // If the devnode wasn't started initially then it is OK that it
  11678. // isn't started now.
  11679. //
  11680. // This last pass can be skipped if we already need a reboot, since
  11681. // it is simply a verification pass.
  11682. //
  11683. if (!bNeedReboot) {
  11684. for (i=0; i<NumberOfDevNodes; i++) {
  11685. if (DevNodeStartedList[i]) {
  11686. if(CM_Get_Device_ID(DevNodeList[i],
  11687. DeviceFullID,
  11688. SIZECHARS(DeviceFullID),
  11689. 0
  11690. ) != CR_SUCCESS ) {
  11691. DeviceFullID[0] = TEXT('\0');
  11692. }
  11693. if ((cr = CM_Get_DevNode_Status_Ex(&ulStatus, &ulProblem, DevNodeList[i],
  11694. 0, pDeviceInfoSet->hMachine)) == CR_SUCCESS) {
  11695. if (!(ulStatus & DN_STARTED)) {
  11696. //
  11697. // This device was started before and now it isn't started,
  11698. // so a reboot is needed.
  11699. //
  11700. bNeedReboot = TRUE;
  11701. if (ulStatus & DN_HAS_PROBLEM) {
  11702. //
  11703. // The device now has a problem when it was
  11704. // working fine before. Log the problem.
  11705. //
  11706. WriteLogEntry(
  11707. LogContext,
  11708. DRIVER_LOG_WARNING,
  11709. MSG_LOG_REBOOT_REASON_DEVHASPROBLEM,
  11710. NULL,
  11711. (DWORD)ulProblem,
  11712. _MapCmProbToString((DWORD)ulProblem),
  11713. DeviceFullID);
  11714. } else if (ulStatus & DN_PRIVATE_PROBLEM) {
  11715. //
  11716. // some private problem, change into need reboot
  11717. // and log private problem
  11718. //
  11719. WriteLogEntry(
  11720. LogContext,
  11721. DRIVER_LOG_WARNING,
  11722. MSG_LOG_REBOOT_REASON_PRIVATEPROBLEM,
  11723. NULL,
  11724. NULL,
  11725. NULL,
  11726. DeviceFullID);
  11727. } else {
  11728. //
  11729. // not started for some other reason
  11730. // indicate reboot required and log this issue
  11731. //
  11732. WriteLogEntry(
  11733. LogContext,
  11734. DRIVER_LOG_WARNING,
  11735. MSG_LOG_REBOOT_REASON_NOTSTARTED,
  11736. NULL,
  11737. NULL,
  11738. NULL,
  11739. DeviceFullID);
  11740. }
  11741. }
  11742. } else {
  11743. bNeedReboot = TRUE;
  11744. WriteLogEntry(
  11745. LogContext,
  11746. DRIVER_LOG_WARNING,
  11747. MSG_LOG_REBOOT_REASON_DEVHASPROBLEM,
  11748. NULL,
  11749. cr,
  11750. (ULONG_PTR)_MapCmRetToString(cr),
  11751. DeviceFullID);
  11752. }
  11753. }
  11754. }
  11755. }
  11756. } else {
  11757. //
  11758. // If we can't get the list of drivers for some reason then just
  11759. // set the needs reboot flag.
  11760. //
  11761. bNeedReboot = TRUE;
  11762. }
  11763. if (!bNeedReboot) {
  11764. //
  11765. // At this point we need to check that the device that we just installed
  11766. // is actually started, unless it is a NULL driver install.
  11767. //
  11768. DWORD DevInstCapabilities;
  11769. ULONG cbData;
  11770. cbData = sizeof(DevInstCapabilities);
  11771. if(CR_SUCCESS != CM_Get_DevInst_Registry_Property_Ex(DevInfoElem->DevInst,
  11772. CM_DRP_CAPABILITIES,
  11773. NULL,
  11774. &DevInstCapabilities,
  11775. &cbData,
  11776. 0,
  11777. pDeviceInfoSet->hMachine))
  11778. {
  11779. DevInstCapabilities = 0;
  11780. }
  11781. if(!NullDriverInstall || (DevInstCapabilities & CM_DEVCAP_RAWDEVICEOK)) {
  11782. CheckIfDevStarted(DevInfoElem,pDeviceInfoSet);
  11783. }
  11784. }
  11785. } except(EXCEPTION_EXECUTE_HANDLER) {
  11786. bNeedReboot = TRUE;
  11787. //
  11788. // Access the following variables, so that the compiler will respect our
  11789. // statement ordering w.r.t. their assignment.
  11790. //
  11791. DriverList = DriverList;
  11792. DevNodeList = DevNodeList;
  11793. DevNodeStartedList = DevNodeStartedList;
  11794. }
  11795. clean0:
  11796. if (DriverList) {
  11797. MyFree(DriverList);
  11798. }
  11799. if (DevNodeList) {
  11800. MyFree(DevNodeList);
  11801. }
  11802. if (DevNodeStartedList) {
  11803. MyFree(DevNodeStartedList);
  11804. }
  11805. if (bNeedReboot) {
  11806. CM_Set_DevInst_Problem_Ex(DevInfoElem->DevInst,
  11807. CM_PROB_NEED_RESTART,
  11808. CM_SET_DEVINST_PROBLEM_OVERRIDE,
  11809. pDeviceInfoSet->hMachine);
  11810. }
  11811. }
  11812. VOID
  11813. AppendLoadIncludedInfs(
  11814. IN HINF hDeviceInf,
  11815. IN PCTSTR InfFileName,
  11816. IN PCTSTR InfSectionName,
  11817. IN BOOL AppendLayoutInfs
  11818. )
  11819. /*++
  11820. Routine Description:
  11821. This routine processes the "include=" line in the specified section of the
  11822. specified INF. For each filename entry on this line, it attempts to append-load
  11823. that file to the supplied INF (first, from the location where the original INF
  11824. was located, and if that fails, then using the default INF search path).
  11825. Arguments:
  11826. hDeviceInf - supplies a handle to the INF containing the section specified by
  11827. InfSectionName. Upon return, this INF handle will also contain any additional
  11828. INFs that were append-loaded based on INFs listed in the "include=" entry of
  11829. the InfSectionName section.
  11830. InfFileName - supplies the full path of the INF whose handle was supplied in
  11831. the hDeviceInf parameter. The path component is used in an attempt to first
  11832. locate the specified included INFs in the same location as that of the original
  11833. INF.
  11834. InfSectionName - supplies the name of the section containing an "include=" line
  11835. whose fields are simply filenames of INFs to be append loaded to the original
  11836. INF whose handle is supplied in the hDeviceInf parameter.
  11837. AppendLayoutInfs - if non-zero (TRUE), then we will attempt to append-load the
  11838. corresponding layout INF for each included INF.
  11839. Return Value:
  11840. none.
  11841. --*/
  11842. {
  11843. TCHAR DefaultInfPath[MAX_PATH];
  11844. PTSTR FileNamePos;
  11845. INFCONTEXT InfContext;
  11846. DWORD FieldIndex;
  11847. BOOL b;
  11848. //
  11849. // Store the full directory path to where the supplied INF is located, so we
  11850. // can first attempt to append-load the included INFs from that same directory.
  11851. //
  11852. MYVERIFY(SUCCEEDED(StringCchCopy(DefaultInfPath,
  11853. SIZECHARS(DefaultInfPath),
  11854. InfFileName)));
  11855. FileNamePos = (PTSTR)pSetupGetFileTitle(DefaultInfPath);
  11856. if(SetupFindFirstLine(hDeviceInf, InfSectionName, TEXT("include"), &InfContext)) {
  11857. for(FieldIndex = 1;
  11858. SetupGetStringField(&InfContext,
  11859. FieldIndex,
  11860. FileNamePos,
  11861. (DWORD)((DefaultInfPath + SIZECHARS(DefaultInfPath)) - FileNamePos),
  11862. NULL);
  11863. FieldIndex++)
  11864. {
  11865. //
  11866. // Try full path and if that fails just use the inf name
  11867. // and let the open routine try to locate the inf.
  11868. // Ignore errors. We'll catch them later, during the install phases.
  11869. //
  11870. b = SetupOpenAppendInfFile(DefaultInfPath, hDeviceInf, NULL);
  11871. if(!b) {
  11872. b = SetupOpenAppendInfFile(FileNamePos, hDeviceInf, NULL);
  11873. }
  11874. //
  11875. // If we successfully append-loaded the included INF, and if we're also
  11876. // supposed to be append-loading any associated layout INFs, then do that
  11877. // now.
  11878. //
  11879. if(b && AppendLayoutInfs) {
  11880. SetupOpenAppendInfFile(NULL, hDeviceInf, NULL);
  11881. }
  11882. }
  11883. }
  11884. }
  11885. DWORD
  11886. InstallFromInfSectionAndNeededSections(
  11887. IN HWND Owner, OPTIONAL
  11888. IN HINF InfHandle,
  11889. IN PCTSTR SectionName,
  11890. IN UINT Flags,
  11891. IN HKEY RelativeKeyRoot, OPTIONAL
  11892. IN PCTSTR SourceRootPath, OPTIONAL
  11893. IN UINT CopyFlags,
  11894. IN PSP_FILE_CALLBACK MsgHandler,
  11895. IN PVOID Context, OPTIONAL
  11896. IN HDEVINFO DeviceInfoSet, OPTIONAL
  11897. IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL
  11898. IN HSPFILEQ UserFileQ OPTIONAL
  11899. )
  11900. /*++
  11901. Routine Description:
  11902. This routine calls SetupInstallFromInfSection for the specified install section,
  11903. as well as for any additional sections specified in a "needs=" line contained in
  11904. that section.
  11905. Arguments:
  11906. Same as for SetupInstallFromInfSection, except for UserFileQ. If UserFileQ is
  11907. non-NULL, then we will only install files (via pSetupInstallFiles) using this
  11908. file queue.
  11909. Return Value:
  11910. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error code
  11911. indicating the cause of the failure.
  11912. --*/
  11913. {
  11914. DWORD FieldIndex, Err;
  11915. INFCONTEXT InfContext;
  11916. BOOL NeedsEntriesToProcess;
  11917. TCHAR SectionToInstall[MAX_SECT_NAME_LEN];
  11918. MYVERIFY(SUCCEEDED(StringCchCopy(SectionToInstall,
  11919. SIZECHARS(SectionToInstall),
  11920. SectionName)));
  11921. NeedsEntriesToProcess = SetupFindFirstLine(InfHandle,
  11922. SectionName,
  11923. TEXT("needs"),
  11924. &InfContext
  11925. );
  11926. Err = NO_ERROR;
  11927. for(FieldIndex = 0; (!FieldIndex || NeedsEntriesToProcess); FieldIndex++) {
  11928. if(FieldIndex) {
  11929. //
  11930. // Get next section name on "needs=" line to be processed.
  11931. //
  11932. if(!SetupGetStringField(&InfContext,
  11933. FieldIndex,
  11934. SectionToInstall,
  11935. SIZECHARS(SectionToInstall),
  11936. NULL)) {
  11937. //
  11938. // We've exhausted all the extra sections we needed to install.
  11939. //
  11940. break;
  11941. }
  11942. }
  11943. if(UserFileQ) {
  11944. //
  11945. // The caller supplied their own file queue, so all we can do is copy
  11946. // files. Make sure that file copying is all they want, and that they
  11947. // gave us a valid file queue handle.
  11948. //
  11949. MYASSERT(Flags == SPINST_FILES);
  11950. MYASSERT(UserFileQ != INVALID_HANDLE_VALUE);
  11951. Err = pSetupInstallFiles(InfHandle,
  11952. NULL,
  11953. SectionToInstall,
  11954. SourceRootPath,
  11955. MsgHandler,
  11956. Context,
  11957. CopyFlags,
  11958. Owner,
  11959. UserFileQ,
  11960. TRUE
  11961. );
  11962. } else {
  11963. //
  11964. // The caller didn't supply their own file queue, so we can just use
  11965. // SetupInstallFromInfSection.
  11966. //
  11967. if(!_SetupInstallFromInfSection(Owner,
  11968. InfHandle,
  11969. SectionToInstall,
  11970. Flags,
  11971. RelativeKeyRoot,
  11972. SourceRootPath,
  11973. CopyFlags,
  11974. MsgHandler,
  11975. Context,
  11976. DeviceInfoSet,
  11977. DeviceInfoData,
  11978. TRUE,
  11979. NULL)) {
  11980. Err = GetLastError();
  11981. break;
  11982. }
  11983. }
  11984. }
  11985. return Err;
  11986. }
  11987. DWORD
  11988. pSetupCopyRelatedInfs(
  11989. IN HINF hInf,
  11990. IN PCTSTR InfFileName, OPTIONAL
  11991. IN PCTSTR InfSectionName,
  11992. IN DWORD OEMSourceMediaType,
  11993. IN PSETUP_LOG_CONTEXT LogContext OPTIONAL
  11994. )
  11995. /*++
  11996. Routine Description:
  11997. This routine processes "CopyINF" directives in the DDInstall section of the
  11998. primary INF.
  11999. CopyINF is not processed under following cases:
  12000. Primary INF is in driver search path
  12001. The CopyINF is specified in an included section.
  12002. Arguments:
  12003. hInf - supplies a handle to the INF containing the section specified by
  12004. InfSectionName.
  12005. InfFileName - supplies the full path of the INF whose handle was supplied in
  12006. the hDeviceInf parameter. The path component is used in an attempt to
  12007. locate the specified INFs. If not specified, we try to get this from hInf
  12008. InfSectionName - supplies the name of the section containing "CopyINF=" lines.
  12009. OEMSourceMediaType - Specifies the type of source media that the location
  12010. information references. May be one of the following values:
  12011. SPOST_NONE - No source media information should be stored in the PNF
  12012. file. (OEMSourceMediaLocation is ignored in this case.)
  12013. SPOST_PATH - OEMSourceMediaLocation contains a path to the source media.
  12014. For example, if the media is on a floppy, this path might
  12015. be "A:\". If OEMSourceMediaLocation is NULL, then the path
  12016. is assumed to be the path where the INF is located (unless
  12017. the INF has a corresponding PNF in that location, in which
  12018. case that PNF's source media information will be
  12019. transferred to the destination PNF).
  12020. SPOST_URL - OEMSourceMediaLocation contains a URL indicating the
  12021. internet location where the INF/driver files were retrieved
  12022. from. If OEMSourceMediaLocation is NULL, then it is
  12023. assumed that the default Code Download Manager location was
  12024. used.
  12025. LogContext - used for logging. If not specified, we get this from hInf
  12026. Return Value:
  12027. none.
  12028. --*/
  12029. {
  12030. INFCONTEXT CopyInfLineContext;
  12031. TCHAR CombinedPath[MAX_PATH*2];
  12032. TCHAR FullSourcePath[MAX_PATH];
  12033. PTSTR Title;
  12034. PCTSTR Field;
  12035. PCTSTR SourcePath;
  12036. DWORD Status;
  12037. DWORD FieldCount;
  12038. DWORD FieldIndex;
  12039. DWORD RetVal;
  12040. PLOADED_INF pInf = NULL;
  12041. if(hInf == NULL || InfSectionName == NULL) {
  12042. return ERROR_INVALID_PARAMETER;
  12043. }
  12044. pInf = (PLOADED_INF)hInf;
  12045. if(!LockInf(pInf)) {
  12046. return ERROR_INVALID_HANDLE;
  12047. }
  12048. if(!LogContext) {
  12049. LogContext = pInf->LogContext;
  12050. }
  12051. if(!InfFileName) {
  12052. InfFileName = pInf->VersionBlock.Filename;
  12053. }
  12054. //
  12055. // if primary INF is from OEM location, then process CopyINF directives
  12056. // note that if the INF is in search path, we ignore CopyINF
  12057. // we also ignore CopyINF's pulled in from other INF's (ie, don't process
  12058. // Include/Needs).
  12059. //
  12060. if(!pSetupInfIsFromOemLocation(InfFileName, FALSE)) {
  12061. //
  12062. // Primary INF is on search path, ignore CopyINF directives
  12063. //
  12064. Status = NO_ERROR;
  12065. goto final;
  12066. }
  12067. MYVERIFY(SUCCEEDED(StringCchCopy(CombinedPath,MAX_PATH,InfFileName)));
  12068. Title = (PTSTR)pSetupGetFileTitle(CombinedPath);
  12069. if (!Title) {
  12070. //
  12071. // shouldn't happen
  12072. //
  12073. MYASSERT(Title);
  12074. Status = ERROR_INVALID_PARAMETER;
  12075. goto final;
  12076. }
  12077. //
  12078. // we look for keyword "CopyInf" in the install section
  12079. //
  12080. if (SetupFindFirstLine(hInf,
  12081. InfSectionName,
  12082. SZ_KEY_COPYINF,
  12083. &CopyInfLineContext)) {
  12084. PSETUP_LOG_CONTEXT SavedLogContext = NULL;
  12085. BOOL ChangedThreadLogContext = SetThreadLogContext(LogContext,&SavedLogContext);
  12086. //
  12087. // we've pushed log context so SetupCopyOemInf will log correctly
  12088. //
  12089. do {
  12090. //
  12091. // CopyInf = a.inf,b.inf,c.inf...
  12092. // a.inf will be at index 1.
  12093. //
  12094. FieldCount = SetupGetFieldCount(&CopyInfLineContext);
  12095. for(FieldIndex = 1;FieldIndex<=FieldCount;FieldIndex++) {
  12096. Status = NO_ERROR;
  12097. Field = pSetupGetField(&CopyInfLineContext,FieldIndex);
  12098. MYVERIFY(SUCCEEDED(StringCchCopy(Title,
  12099. SIZECHARS(CombinedPath)-(Title-CombinedPath),
  12100. Field)));
  12101. //
  12102. // we have a listed INF, obtain canonical pathname
  12103. // for this INF
  12104. // (note that we assume the INF is relative
  12105. // to original INF and is typically just a filename)
  12106. //
  12107. RetVal = GetFullPathName(CombinedPath,
  12108. MAX_PATH,
  12109. FullSourcePath,
  12110. NULL);
  12111. if (RetVal == 0 || RetVal > MAX_PATH) {
  12112. SourcePath = CombinedPath;
  12113. } else {
  12114. SourcePath = FullSourcePath;
  12115. }
  12116. if(!SetupCopyOEMInf(FullSourcePath,
  12117. NULL,
  12118. OEMSourceMediaType,
  12119. 0,
  12120. NULL,
  12121. 0,
  12122. NULL,
  12123. NULL)) {
  12124. Status = GetLastError();
  12125. }
  12126. if (Status != NO_ERROR) {
  12127. WriteLogEntry(
  12128. LogContext,
  12129. DRIVER_LOG_ERROR | SETUP_LOG_BUFFER,
  12130. MSG_LOG_COPYINF_ERROR,
  12131. NULL,
  12132. FullSourcePath);
  12133. WriteLogError(
  12134. LogContext,
  12135. DRIVER_LOG_ERROR,
  12136. Status);
  12137. } else {
  12138. WriteLogEntry(
  12139. LogContext,
  12140. DRIVER_LOG_INFO,
  12141. MSG_LOG_COPYINF_OK,
  12142. NULL,
  12143. FullSourcePath);
  12144. }
  12145. }
  12146. } while (SetupFindNextMatchLine(&CopyInfLineContext,
  12147. SZ_KEY_COPYINF,
  12148. &CopyInfLineContext));
  12149. if (ChangedThreadLogContext) {
  12150. //
  12151. // restore thread log context
  12152. //
  12153. SetThreadLogContext(SavedLogContext,NULL);
  12154. }
  12155. }
  12156. Status = NO_ERROR;
  12157. final:
  12158. if(pInf) {
  12159. UnlockInf(pInf);
  12160. }
  12161. return Status;
  12162. }
  12163. VOID
  12164. SetDevnodeNeedsRebootProblemWithArg2(
  12165. IN PDEVINFO_ELEM DevInfoElem,
  12166. IN PDEVICE_INFO_SET pDevInfoSet,
  12167. IN DWORD Reason, OPTIONAL
  12168. IN ULONG_PTR Arg1, OPTIONAL
  12169. IN ULONG_PTR Arg2 OPTIONAL
  12170. )
  12171. /*++
  12172. Routine Description:
  12173. This routine sets DI_NEEDREBOOT,
  12174. sets the problem of the specified devnode to be CM_PROB_NEED_RESTART
  12175. and logs information about why we did this
  12176. Arguments:
  12177. DevInfoElem )_ identify the devnode with the problem
  12178. DevInfoSet )
  12179. Reason - Supplies a string resource ID for logging the reason a reboot is
  12180. required. If this is 0, nothing will be logged.
  12181. Arg1/Arg2 - optional arguments %1 and %2 of the logged message
  12182. Return Value:
  12183. none.
  12184. --*/
  12185. {
  12186. TCHAR szDevID[MAX_DEVICE_ID_LEN];
  12187. CONFIGRET cr;
  12188. DevInfoElem->InstallParamBlock.Flags |= DI_NEEDREBOOT;
  12189. if((cr = CM_Get_Device_ID_Ex(DevInfoElem->DevInst,
  12190. szDevID,
  12191. SIZECHARS(szDevID),
  12192. 0,
  12193. pDevInfoSet->hMachine)) != CR_SUCCESS) {
  12194. szDevID[0] = TEXT('\0');
  12195. }
  12196. CM_Set_DevInst_Problem_Ex(DevInfoElem->DevInst,
  12197. CM_PROB_NEED_RESTART,
  12198. CM_SET_DEVINST_PROBLEM_OVERRIDE,
  12199. pDevInfoSet->hMachine);
  12200. if (Reason) {
  12201. //
  12202. // if the caller gave a reason, log why a reboot is required
  12203. //
  12204. WriteLogEntry(
  12205. DevInfoElem->InstallParamBlock.LogContext,
  12206. DRIVER_LOG_WARNING, // should this be a warning?
  12207. Reason,
  12208. NULL,
  12209. Arg1,
  12210. Arg2,
  12211. szDevID);
  12212. }
  12213. }
  12214. DWORD
  12215. MarkQueueForDeviceInstall(
  12216. IN HSPFILEQ QueueHandle,
  12217. IN HINF DeviceInfHandle,
  12218. IN PCTSTR DeviceDesc OPTIONAL
  12219. )
  12220. /*++
  12221. Routine Description:
  12222. This routine adds catalog info entries (if not already present) into a file
  12223. queue for the INFs represented by the supplied INF handle. It also marks
  12224. the first INF's catalog entry (whether newly-created or not) with a flag
  12225. indicating that this is the 'primary' device INF for this installation. It
  12226. then sets a flag in the queue indicating that the behavior when subsequently
  12227. calling _SetupVerifyQueuedCatalogs should be to copy the INF into the
  12228. %windir%\Inf directory (as opposed to merely creating a zero-length file
  12229. there of the correct name so that the catfile's name is guaranteed unique).
  12230. Finally, it retrieves the driver signing policy and associates it with the
  12231. queue (up until this point, the queue has associated with it the non-driver
  12232. signing policy).
  12233. Arguments:
  12234. QueueHandle - supplies a handle to the file queue to be marked as a device
  12235. install file queue.
  12236. DeviceInfHandle - supplies a handle to the device INF upon which this
  12237. installation is based. In addition to the "primary" device INF, this
  12238. handle may also contain one or more append-loaded INFs.
  12239. Return Value:
  12240. If successful, the return value is NO_ERROR, otherwise, it is a Win32 error
  12241. code indicating the cause of the failure.
  12242. --*/
  12243. {
  12244. PSP_FILE_QUEUE Queue;
  12245. TCHAR TempBuffer[MAX_PATH];
  12246. LONG InfStringId, CatStringId, OriginalInfStringId;
  12247. PLOADED_INF pInf;
  12248. DWORD Err;
  12249. PTSTR InfDeviceDesc;
  12250. PSPQ_CATALOG_INFO CatalogNode, PrevCatalogNode, NewCatalogNode;
  12251. BOOL DifferentOriginalName;
  12252. TCHAR OriginalInfName[MAX_PATH];
  12253. BOOL UnlockInf;
  12254. BOOL UseOriginalInfName;
  12255. //
  12256. // Queue handle is actually a pointer to the queue structure.
  12257. //
  12258. Queue = (PSP_FILE_QUEUE)QueueHandle;
  12259. NewCatalogNode = NULL;
  12260. Err = NO_ERROR;
  12261. InfDeviceDesc = NULL;
  12262. UnlockInf = FALSE;
  12263. try {
  12264. if(LockInf((PLOADED_INF)DeviceInfHandle)) {
  12265. UnlockInf = TRUE;
  12266. } else {
  12267. Err = ERROR_INVALID_HANDLE;
  12268. goto clean0;
  12269. }
  12270. //
  12271. // We want to process each INF in the LOADED_INF list...
  12272. //
  12273. for(pInf = (PLOADED_INF)DeviceInfHandle; pInf; pInf = pInf->Next) {
  12274. //
  12275. // First, get the (potentially decorated) CatalogFile= entry from
  12276. // the version block of this INF member, as well as the INF's
  12277. // original name (if different from the INF's current name).
  12278. //
  12279. Err = pGetInfOriginalNameAndCatalogFile(
  12280. pInf,
  12281. NULL,
  12282. &DifferentOriginalName,
  12283. OriginalInfName,
  12284. SIZECHARS(OriginalInfName),
  12285. TempBuffer,
  12286. SIZECHARS(TempBuffer),
  12287. NULL // always native OS/arch (ver doesn't matter for CatalogFile=)
  12288. );
  12289. if(Err != NO_ERROR) {
  12290. goto clean0;
  12291. }
  12292. if(DifferentOriginalName) {
  12293. //
  12294. // Add the INF's original (simple) filename to our string table.
  12295. //
  12296. OriginalInfStringId = pSetupStringTableAddString(
  12297. Queue->StringTable,
  12298. OriginalInfName,
  12299. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  12300. );
  12301. if(OriginalInfStringId == -1) {
  12302. Err = ERROR_NOT_ENOUGH_MEMORY;
  12303. goto clean0;
  12304. }
  12305. } else {
  12306. //
  12307. // INF's original name is the same as its present name.
  12308. //
  12309. OriginalInfStringId = -1;
  12310. }
  12311. if(*TempBuffer) {
  12312. CatStringId = pSetupStringTableAddString(Queue->StringTable,
  12313. TempBuffer,
  12314. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  12315. );
  12316. if(CatStringId == -1) {
  12317. Err = ERROR_NOT_ENOUGH_MEMORY;
  12318. goto clean0;
  12319. }
  12320. } else {
  12321. //
  12322. // This INF doesn't have a CatalogFile= entry.
  12323. //
  12324. CatStringId = -1;
  12325. }
  12326. //
  12327. // Now, get the INF's full path.
  12328. //
  12329. MYVERIFY(SUCCEEDED(StringCchCopy(TempBuffer,
  12330. SIZECHARS(TempBuffer),
  12331. pInf->VersionBlock.Filename)));
  12332. InfStringId = pSetupStringTableAddString(Queue->StringTable,
  12333. TempBuffer,
  12334. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  12335. );
  12336. if(InfStringId == -1) {
  12337. Err = ERROR_NOT_ENOUGH_MEMORY;
  12338. goto clean0;
  12339. }
  12340. //
  12341. // Now search for an existing catalog node (there'll typically be
  12342. // one unless the device INF doesn't copy any files, such as a
  12343. // modem INF).
  12344. //
  12345. for(PrevCatalogNode=NULL, CatalogNode=Queue->CatalogList;
  12346. CatalogNode;
  12347. CatalogNode=CatalogNode->Next) {
  12348. if(CatalogNode->InfFullPath == InfStringId) {
  12349. //
  12350. // Already in there. No need to create a new node.
  12351. // Break out here, with CatalogNode pointing at the
  12352. // proper node for this catalog file.
  12353. //
  12354. // In this case, PrevCatalogNode should not be used later,
  12355. // but it shouldn't need to be used, since we won't be
  12356. // adding anything new onto the list of catalog nodes.
  12357. //
  12358. // NOTE: Our alternate catalog should be correct because
  12359. // either (a) the altplatform info was in effect when the
  12360. // INF was added, or (b) the altplatform info was applied
  12361. // after the INF's addition, and it was updated at that
  12362. // time.
  12363. //
  12364. MYASSERT(CatalogNode->CatalogFileFromInf == CatStringId);
  12365. MYASSERT(CatalogNode->InfOriginalName == OriginalInfStringId);
  12366. break;
  12367. }
  12368. //
  12369. // PrevCatalogNode will end up pointing to the final node
  12370. // currently in the linked list, in the case where we need
  12371. // to allocate a new node. This is useful so we don't have to
  12372. // traverse the list again later when we add the new catalog
  12373. // node to the list for this queue.
  12374. //
  12375. PrevCatalogNode = CatalogNode;
  12376. }
  12377. //
  12378. // If we didn't find an existing catalog node, then add one now.
  12379. //
  12380. if(!CatalogNode) {
  12381. //
  12382. // Need to create a new catalog node.
  12383. //
  12384. NewCatalogNode = MyMalloc(sizeof(SPQ_CATALOG_INFO));
  12385. if(!NewCatalogNode) {
  12386. Err = ERROR_NOT_ENOUGH_MEMORY;
  12387. goto clean0;
  12388. }
  12389. ZeroMemory(NewCatalogNode, sizeof(SPQ_CATALOG_INFO));
  12390. NewCatalogNode->CatalogFileFromInf = CatStringId;
  12391. NewCatalogNode->InfOriginalName = OriginalInfStringId;
  12392. NewCatalogNode->InfFullPath = InfStringId;
  12393. NewCatalogNode->InfFinalPath = -1;
  12394. NewCatalogNode->AltCatalogFileFromInfPending = -1;
  12395. //
  12396. // If this queue has alternate platform info associated with
  12397. // it, then we need to retrieve the alternate catalog to be
  12398. // used for digital signature verification.
  12399. //
  12400. if(Queue->Flags & FQF_USE_ALT_PLATFORM) {
  12401. if(pSetupGetCatalogFileValue(&(pInf->VersionBlock),
  12402. TempBuffer,
  12403. SIZECHARS(TempBuffer),
  12404. &(Queue->AltPlatformInfo))) {
  12405. NewCatalogNode->AltCatalogFileFromInf =
  12406. pSetupStringTableAddString(Queue->StringTable,
  12407. TempBuffer,
  12408. STRTAB_CASE_INSENSITIVE | STRTAB_BUFFER_WRITEABLE
  12409. );
  12410. if(NewCatalogNode->AltCatalogFileFromInf == -1) {
  12411. Err = ERROR_NOT_ENOUGH_MEMORY;
  12412. goto clean0;
  12413. }
  12414. } else {
  12415. //
  12416. // This INF doesn't have a CatalogFile= entry.
  12417. //
  12418. NewCatalogNode->AltCatalogFileFromInf = -1;
  12419. }
  12420. } else {
  12421. //
  12422. // No alternate platform info associated with the queue at
  12423. // this time.
  12424. //
  12425. NewCatalogNode->AltCatalogFileFromInf = -1;
  12426. }
  12427. if(Queue->CatalogList) {
  12428. PrevCatalogNode->Next = NewCatalogNode;
  12429. } else {
  12430. Queue->CatalogList = NewCatalogNode;
  12431. }
  12432. //
  12433. // Reset NewCatalogNode so we won't try to free it in case we
  12434. // encounter a subsequent error.
  12435. //
  12436. CatalogNode = NewCatalogNode;
  12437. NewCatalogNode = NULL;
  12438. //
  12439. // We've successfully added a new, as yet unvalidated, catalog
  12440. // node. We must therefore reset the the "catalog
  12441. // verifications done" flags so that we'll redo them later.
  12442. //
  12443. Queue->Flags &= ~(FQF_DID_CATALOGS_OK | FQF_DID_CATALOGS_FAILED);
  12444. }
  12445. if(pInf == (PLOADED_INF)DeviceInfHandle) {
  12446. //
  12447. // At this point, CatalogNode points to the node representing
  12448. // the device INF upon which this device installation is based.
  12449. // Mark this node as such, so that _SetupVerifyQueuedCatalogs
  12450. // can return the INF's new name if it's an OEM INF.
  12451. //
  12452. CatalogNode->Flags |= CATINFO_FLAG_PRIMARY_DEVICE_INF;
  12453. }
  12454. }
  12455. if(!(Queue->Flags & FQF_DEVICE_INSTALL)) {
  12456. //
  12457. // This queue wasn't previously known to be a device install queue,
  12458. // so it's possible the catalog nodes have already been verified
  12459. // subject to non-driver signing policy. Further, it's possible
  12460. // (albeit unlikely) that a non-device INF was passed into this
  12461. // routine, and that a catalog node for that INF already existed in
  12462. // our catalog list. In that case, one of our "catalog
  12463. // verifications done" flags would be set, but would not have been
  12464. // cleared above since we didn't add any catalog nodes. All of
  12465. // this discussion simply to justify that we really do need to
  12466. // clear the bits here too... :-(
  12467. //
  12468. Queue->Flags &= ~(FQF_DID_CATALOGS_OK | FQF_DID_CATALOGS_FAILED);
  12469. //
  12470. // Note: We don't clear the CATINFO_FLAG_NEWLY_COPIED flags for any
  12471. // of the catalog nodes, because we want to make sure we re-use
  12472. // those same names when re-doing verification (e.g., maybe the
  12473. // first time around the INF was installed into %windir%\Inf as a
  12474. // zero-length file--we want to re-use the same filename to now hold
  12475. // our INF).
  12476. //
  12477. //
  12478. // Since we previously didn't know this was a device install queue,
  12479. // we shouldn't have a ValidationPlatform. Make sure that's the
  12480. // case, because the call below would blow away any we had (thus
  12481. // causing a memory leak).
  12482. //
  12483. MYASSERT(!(Queue->ValidationPlatform));
  12484. //
  12485. // Retrieve the codesigning policy in effect for this device (thus
  12486. // replacing the default non-driver signing policy that was
  12487. // associated with the queue when it was originally created).
  12488. //
  12489. IsInfForDeviceInstall(Queue->LogContext,
  12490. NULL,
  12491. (PLOADED_INF)DeviceInfHandle,
  12492. (DeviceDesc ? NULL : &InfDeviceDesc),
  12493. &(Queue->ValidationPlatform),
  12494. &(Queue->DriverSigningPolicy),
  12495. &UseOriginalInfName,
  12496. FALSE
  12497. );
  12498. if(UseOriginalInfName) {
  12499. Queue->Flags |= FQF_KEEP_INF_AND_CAT_ORIGINAL_NAMES;
  12500. }
  12501. //
  12502. // If the caller supplied us with a device description (or we got
  12503. // one from IsInfForDeviceInstall), attempt to add that string to
  12504. // the queue's string table in case we need to give a digital
  12505. // signature verification failure popup for this queue.
  12506. //
  12507. //
  12508. // NOTE: When adding the following string to the string table, we
  12509. // cast away its CONST-ness to avoid a compiler warning. Since we
  12510. // are adding it case-sensitively, we are guaranteed it will not be
  12511. // modified.
  12512. //
  12513. if(DeviceDesc) {
  12514. Queue->DeviceDescStringId = pSetupStringTableAddString(Queue->StringTable,
  12515. (PTSTR)DeviceDesc,
  12516. STRTAB_CASE_SENSITIVE
  12517. );
  12518. } else if(InfDeviceDesc) {
  12519. //
  12520. // Use the more generic description based on the device's class
  12521. //
  12522. Queue->DeviceDescStringId = pSetupStringTableAddString(Queue->StringTable,
  12523. InfDeviceDesc,
  12524. STRTAB_CASE_SENSITIVE
  12525. );
  12526. }
  12527. //
  12528. // Set a flag in the queue that indicates this is for a device
  12529. // installation. If we're doing a native platform installation
  12530. // (i.e., the FQF_USE_ALT_PLATFORM isn't set), then this also
  12531. // causes us to copy the INF into %windir%\Inf instead of merely
  12532. // creating a zero-length placeholder file there upon which the
  12533. // corresponding CAT file's installation is based.
  12534. //
  12535. Queue->Flags |= FQF_DEVICE_INSTALL;
  12536. } else {
  12537. //
  12538. // This queue has previously been marked as a device install queue.
  12539. // However, we still want to update the device description, if the
  12540. // caller supplied one.
  12541. //
  12542. if(DeviceDesc) {
  12543. Queue->DeviceDescStringId = pSetupStringTableAddString(Queue->StringTable,
  12544. (PTSTR)DeviceDesc,
  12545. STRTAB_CASE_SENSITIVE
  12546. );
  12547. }
  12548. }
  12549. clean0: ; // nothing to do.
  12550. } except(EXCEPTION_EXECUTE_HANDLER) {
  12551. //
  12552. // If we hit an AV, then use invalid parameter error, otherwise, assume
  12553. // an inpage error when dealing with a mapped-in file.
  12554. //
  12555. Err = (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
  12556. ? ERROR_INVALID_PARAMETER
  12557. : ERROR_READ_FAULT;
  12558. //
  12559. // Access the following variables, so that the compiler will respect our
  12560. // statement ordering w.r.t. their assignment.
  12561. //
  12562. UnlockInf = UnlockInf;
  12563. NewCatalogNode = NewCatalogNode;
  12564. }
  12565. if(UnlockInf) {
  12566. UnlockInf((PLOADED_INF)DeviceInfHandle);
  12567. }
  12568. if(NewCatalogNode) {
  12569. MyFree(NewCatalogNode);
  12570. }
  12571. if(InfDeviceDesc) {
  12572. MyFree(InfDeviceDesc);
  12573. }
  12574. return Err;
  12575. }