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.

1492 lines
36 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. afpnp.c
  5. Abstract:
  6. Routines to manage installation of devices via the answer file.
  7. The main entry points are:
  8. CreateAfDriverTable
  9. DestroyAfDriverTable
  10. SyssetupInstallAnswerFileDriver
  11. CountAfDrivers
  12. The rest of the functions are utilities or routines used by outside
  13. callers only in a special case of some sort.
  14. Author:
  15. Jim Schmidt (jimschm) 20-Mar-1998
  16. Revision History:
  17. --*/
  18. #include "setupp.h"
  19. #pragma hdrstop
  20. //
  21. // Contants
  22. //
  23. #if DBG
  24. #define PNP_DEBUG 1
  25. #else
  26. #define PNP_DEBUG 0
  27. #endif
  28. #if PNP_DEBUG
  29. #define PNP_DBGPRINT(x) DebugPrintWrapper x
  30. #else
  31. #define PNP_DBGPRINT(x)
  32. #endif
  33. //
  34. // Local prototypes
  35. //
  36. BOOL
  37. pBuildAfDriverAttribs (
  38. IN OUT PAF_DRIVER_ATTRIBS Attribs
  39. );
  40. BOOL
  41. pAddAfDriver (
  42. IN PAF_DRIVER_ATTRIBS Driver,
  43. IN HDEVINFO hDevInfo,
  44. IN PSP_DEVINFO_DATA DeviceInfoData,
  45. IN BOOL First
  46. );
  47. PAF_DRIVER_ATTRIBS
  48. pGetSelectedSourceDriver (
  49. IN PAF_DRIVERS Drivers,
  50. IN HDEVINFO hDevInfo,
  51. IN PSP_DEVINFO_DATA DeviceInfoData
  52. );
  53. //
  54. // Implementation
  55. //
  56. #if DBG
  57. VOID
  58. DebugPrintWrapper (
  59. PCSTR FormatStr,
  60. ...
  61. )
  62. {
  63. va_list list;
  64. WCHAR OutStr[2048];
  65. WCHAR UnicodeFormatStr[256];
  66. //
  67. // Args are wchar by default!!
  68. //
  69. MultiByteToWideChar (CP_ACP, 0, FormatStr, -1, UnicodeFormatStr, 256);
  70. va_start (list, FormatStr);
  71. vswprintf (OutStr, UnicodeFormatStr, list);
  72. va_end (list);
  73. SetupDebugPrint (OutStr);
  74. }
  75. #endif
  76. HINF
  77. pOpenAnswerFile (
  78. VOID
  79. )
  80. {
  81. HINF AnswerInf;
  82. WCHAR AnswerFile[MAX_PATH];
  83. GetSystemDirectory(AnswerFile,MAX_PATH);
  84. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  85. AnswerInf = SetupOpenInfFile(AnswerFile,NULL,INF_STYLE_OLDNT,NULL);
  86. return AnswerInf;
  87. }
  88. #define S_DEVICE_DRIVERSW L"DeviceDrivers"
  89. VOID
  90. MySmartFree (
  91. PCVOID p
  92. )
  93. {
  94. if (p) {
  95. MyFree (p);
  96. }
  97. }
  98. PVOID
  99. MySmartAlloc (
  100. PCVOID Old, OPTIONAL
  101. UINT Size
  102. )
  103. {
  104. if (Old) {
  105. return MyRealloc ((PVOID) Old, Size);
  106. }
  107. return MyMalloc (Size);
  108. }
  109. PVOID
  110. ReusableAlloc (
  111. IN OUT PBUFFER Buf,
  112. IN UINT SizeNeeded
  113. )
  114. {
  115. if (!Buf->Buffer || Buf->Size < SizeNeeded) {
  116. Buf->Size = SizeNeeded - (SizeNeeded & 1023) + 1024;
  117. if (Buf->Buffer) {
  118. MyFree (Buf->Buffer);
  119. }
  120. Buf->Buffer = (PWSTR) MyMalloc (Buf->Size);
  121. if (!Buf->Buffer) {
  122. PNP_DBGPRINT (( "SETUP: Mem alloc failed for %u bytes. \n", Buf->Size ));
  123. Buf->Size = 0;
  124. return NULL;
  125. }
  126. }
  127. return Buf->Buffer;
  128. }
  129. VOID
  130. ReusableFree (
  131. IN OUT PBUFFER Buf
  132. )
  133. {
  134. MySmartFree (Buf->Buffer);
  135. ZeroMemory (Buf, sizeof (BUFFER));
  136. }
  137. PWSTR
  138. MultiSzAppendString (
  139. IN OUT PMULTISZ MultiSz,
  140. IN PCWSTR String
  141. )
  142. {
  143. UINT BytesNeeded;
  144. UINT NewSize;
  145. PWSTR p;
  146. BytesNeeded = (UINT)((PBYTE) MultiSz->End - (PBYTE) MultiSz->Start);
  147. BytesNeeded += (UINT)(((PBYTE) wcschr (String, 0)) - (PBYTE) String) + sizeof (WCHAR);
  148. BytesNeeded += sizeof (WCHAR);
  149. if (!MultiSz->Start || MultiSz->Size < BytesNeeded) {
  150. NewSize = BytesNeeded - (BytesNeeded & 0xfff) + 0x1000;
  151. p = (PWSTR) MySmartAlloc (MultiSz->Start, NewSize);
  152. if (!p) {
  153. PNP_DBGPRINT (( "SETUP: Mem alloc failed for %u bytes", NewSize ));
  154. return NULL;
  155. }
  156. MultiSz->End = p + (MultiSz->End - MultiSz->Start);
  157. MultiSz->Start = p;
  158. MultiSz->Size = BytesNeeded;
  159. }
  160. p = MultiSz->End;
  161. lstrcpyW (p, String);
  162. MultiSz->End = wcschr (p, 0) + 1;
  163. MYASSERT (((PBYTE) MultiSz->Start + BytesNeeded) >= ((PBYTE) MultiSz->End + sizeof (WCHAR)));
  164. *MultiSz->End = 0;
  165. return p;
  166. }
  167. VOID
  168. MultiSzFree (
  169. IN OUT PMULTISZ MultiSz
  170. )
  171. {
  172. MySmartFree (MultiSz->Start);
  173. ZeroMemory (MultiSz, sizeof (MULTISZ));
  174. }
  175. BOOL
  176. EnumFirstMultiSz (
  177. IN OUT PMULTISZ_ENUM EnumPtr,
  178. IN PCWSTR MultiSz
  179. )
  180. {
  181. EnumPtr->Start = MultiSz;
  182. EnumPtr->Current = MultiSz;
  183. return MultiSz && *MultiSz;
  184. }
  185. BOOL
  186. EnumNextMultiSz (
  187. IN OUT PMULTISZ_ENUM EnumPtr
  188. )
  189. {
  190. if (!EnumPtr->Current || *EnumPtr->Current == 0) {
  191. return FALSE;
  192. }
  193. EnumPtr->Current = wcschr (EnumPtr->Current, 0) + 1;
  194. return *EnumPtr->Current;
  195. }
  196. BOOL
  197. pBuildAfDriverAttribs (
  198. IN OUT PAF_DRIVER_ATTRIBS Attribs
  199. )
  200. /*++
  201. Routine Description:
  202. pBuildAfDriverAttribs updates the driver attribute structure by setting all
  203. the members of the structure. If the members were previously set, this
  204. function is a NOP.
  205. Arguments:
  206. Attribs - Specifies the answer file driver attribute structure, which does
  207. not need to be empty. Receives the attributes.
  208. Return Value:
  209. TRUE if the driver is valid, or FALSE if something went wrong during
  210. attribute gathering.
  211. --*/
  212. {
  213. PWSTR p;
  214. INFCONTEXT ic;
  215. BUFFER Buf = BUFFER_INIT;
  216. if (Attribs->Initialized) {
  217. return TRUE;
  218. }
  219. Attribs->Initialized = TRUE;
  220. //
  221. // Compute paths
  222. //
  223. Attribs->FilePath = pSetupDuplicateString (Attribs->InfPath);
  224. p = wcsrchr (Attribs->FilePath, L'\\');
  225. if (p) {
  226. *p = 0;
  227. }
  228. Attribs->Broken = (Attribs->InfPath == NULL) ||
  229. (Attribs->FilePath == NULL);
  230. //
  231. // Open the INF and look for ClassInstall32
  232. //
  233. if (!Attribs->Broken) {
  234. Attribs->InfHandle = SetupOpenInfFile (Attribs->InfPath, NULL, INF_STYLE_WIN4, NULL);
  235. Attribs->Broken = (Attribs->InfHandle == INVALID_HANDLE_VALUE);
  236. }
  237. if (!Attribs->Broken) {
  238. #if defined _X86_
  239. Attribs->ClassInstall32Section = L"ClassInstall32.NTx86";
  240. #elif defined _AMD64_
  241. Attribs->ClassInstall32Section = L"ClassInstall32.NTAMD64";
  242. #elif defined _IA64_
  243. Attribs->ClassInstall32Section = L"ClassInstall32.NTIA64";
  244. #else
  245. #error "No Target Architecture"
  246. #endif
  247. if (!SetupFindFirstLine (
  248. Attribs->InfHandle,
  249. Attribs->ClassInstall32Section,
  250. NULL,
  251. &ic
  252. )) {
  253. Attribs->ClassInstall32Section = L"ClassInstall32.NT";
  254. if (!SetupFindFirstLine (
  255. Attribs->InfHandle,
  256. Attribs->ClassInstall32Section,
  257. NULL,
  258. &ic
  259. )) {
  260. Attribs->ClassInstall32Section = L"ClassInstall32";
  261. if (!SetupFindFirstLine (
  262. Attribs->InfHandle,
  263. Attribs->ClassInstall32Section,
  264. NULL,
  265. &ic
  266. )) {
  267. Attribs->ClassInstall32Section = NULL;
  268. }
  269. }
  270. }
  271. }
  272. if (!Attribs->Broken && Attribs->ClassInstall32Section) {
  273. //
  274. // ClassInstall32 was found, so there's got to be a GUID
  275. //
  276. if (SetupFindFirstLine (
  277. Attribs->InfHandle,
  278. L"Version",
  279. L"ClassGUID",
  280. &ic
  281. )) {
  282. p = (PWSTR) SyssetupGetStringField (&ic, 1, &Buf);
  283. if (!p) {
  284. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: Invalid GUID line. \n" ));
  285. } else {
  286. if (!pSetupGuidFromString (p, &Attribs->Guid)) {
  287. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: Invalid GUID. \n" ));
  288. }
  289. }
  290. }
  291. else {
  292. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: ClassInstall32 found but GUID not found. \n" ));
  293. }
  294. }
  295. ReusableFree (&Buf);
  296. return !Attribs->Broken;
  297. }
  298. PCWSTR
  299. SyssetupGetStringField (
  300. IN PINFCONTEXT InfContext,
  301. IN DWORD Field,
  302. IN OUT PBUFFER Buf
  303. )
  304. /*++
  305. Routine Description:
  306. SyssetupGetStringField is a wrapper for SetupGetStringField. It uses the
  307. BUFFER structure to minimize allocation requests.
  308. Arguments:
  309. InfContext - Specifies the INF context as provided by other Setup API
  310. functions.
  311. Field - Specifies the field to query.
  312. Buf - Specifies the buffer to reuse. Any previously allocated
  313. pointers to this buffer's data are invalid. The caller must
  314. free the buffer.
  315. Return Value:
  316. A pointer to the string, allocated in Buf, or NULL if the field does not
  317. exist or an error occurred.
  318. --*/
  319. {
  320. DWORD SizeNeeded;
  321. DWORD BytesNeeded;
  322. PWSTR p;
  323. if (!SetupGetStringField (InfContext, Field, NULL, 0, &SizeNeeded)) {
  324. return NULL;
  325. }
  326. BytesNeeded = (SizeNeeded + 1) * sizeof (WCHAR);
  327. p = ReusableAlloc (Buf, BytesNeeded);
  328. if (p) {
  329. if (!SetupGetStringField (InfContext, Field, p, SizeNeeded, NULL)) {
  330. return NULL;
  331. }
  332. }
  333. return p;
  334. }
  335. INT
  336. CountAfDrivers (
  337. IN PAF_DRIVERS Drivers,
  338. OUT INT *ClassInstallers OPTIONAL
  339. )
  340. /*++
  341. Routine Description:
  342. CountAfDrivers enumerates the drivers in the table specified and returns
  343. the count. The caller can also receive the number of class installers (a
  344. subset of the driver list). Querying the number of class installers may
  345. take a little time if there are a lot of drivers listed in the answer file
  346. and the driver INFs have not been opened yet. (Otherwise this routine is
  347. very fast.)
  348. Arguments:
  349. Drivers - Specifies the driver table to process.
  350. ClassInstallers - Receives a count of the number of class installers
  351. specified in the answer file.
  352. Return Value:
  353. The number of drivers specified in the answer file.
  354. --*/
  355. {
  356. AF_DRIVER_ENUM e;
  357. INT UniqueDriverDirs;
  358. MYASSERT (Drivers && Drivers->DriverTable);
  359. //
  360. // Count entries in the DriverTable string table, and open each one to look for
  361. // a ClassInstall32 section
  362. //
  363. UniqueDriverDirs = 0;
  364. *ClassInstallers = 0;
  365. if (EnumFirstAfDriver (&e, Drivers)) {
  366. do {
  367. if (ClassInstallers) {
  368. if (e.Driver->ClassInstall32Section) {
  369. *ClassInstallers += 1;
  370. }
  371. }
  372. UniqueDriverDirs++;
  373. } while (EnumNextAfDriver (&e));
  374. }
  375. return UniqueDriverDirs;
  376. }
  377. PAF_DRIVERS
  378. CreateAfDriverTable (
  379. VOID
  380. )
  381. /*++
  382. Routine Description:
  383. CreateAfDriverTable generates a string table populated with the paths
  384. to device driver INFs specified in the answer file. This is the first step
  385. in processing the [DeviceDrivers] section of unattend.txt.
  386. The caller must destroy a non-NULL driver table via DestroyAfDriverTable
  387. to free memory used by the table and each entry in the table.
  388. Arguments:
  389. None.
  390. Return Value:
  391. A pointer to the populated string table, or NULL if no entries exist.
  392. --*/
  393. {
  394. PAF_DRIVERS Drivers;
  395. HINF AnswerInf;
  396. PVOID NewDriverTable;
  397. INFCONTEXT ic;
  398. PWSTR InfPath;
  399. PCWSTR OriginalInstallMedia;
  400. PWSTR PnpId;
  401. PWSTR p;
  402. BOOL FoundOne = FALSE;
  403. PAF_DRIVER_ATTRIBS Attribs;
  404. PAF_DRIVER_ATTRIBS FirstAttribs = NULL;
  405. BUFFER b1, b2, b3;
  406. LONG Index;
  407. //
  408. // Init
  409. //
  410. AnswerInf = pOpenAnswerFile();
  411. if (AnswerInf == INVALID_HANDLE_VALUE) {
  412. return NULL;
  413. }
  414. NewDriverTable = pSetupStringTableInitializeEx (sizeof (PAF_DRIVER_ATTRIBS), 0);
  415. if (!NewDriverTable) {
  416. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: String table alloc failed. \n" ));
  417. SetupCloseInfFile (AnswerInf);
  418. return NULL;
  419. }
  420. ZeroMemory (&b1, sizeof (b1));
  421. ZeroMemory (&b2, sizeof (b2));
  422. ZeroMemory (&b3, sizeof (b3));
  423. //
  424. // Build a list of unique INF paths that are in the [DeviceDrivers]
  425. // section of the answer file, if any.
  426. //
  427. if (SetupFindFirstLine (AnswerInf, S_DEVICE_DRIVERSW, NULL, &ic)) {
  428. do {
  429. //
  430. // Get the data from the answer file
  431. //
  432. p = (PWSTR) SyssetupGetStringField (&ic, 0, &b1);
  433. if (!p) {
  434. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: Invalid answer file line ignored. \n" ));
  435. continue;
  436. }
  437. PnpId = p;
  438. p = (PWSTR) SyssetupGetStringField (&ic, 1, &b2);
  439. if (!p) {
  440. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: Invalid answer file line ignored. \n" ));
  441. continue;
  442. }
  443. InfPath = p;
  444. p = (PWSTR) SyssetupGetStringField (&ic, 2, &b3);
  445. if (!p) {
  446. PNP_DBGPRINT (( "SETUP: No original media path; assuming floppy \n" ));
  447. OriginalInstallMedia = IsNEC_98 ? L"C:\\" : L"A:\\";
  448. } else {
  449. OriginalInstallMedia = p;
  450. }
  451. //
  452. // Check to see if INF path has already been added. If so, add PNP
  453. // ID to list of IDs, and continue to next PNP ID.
  454. //
  455. Index = pSetupStringTableLookUpString (
  456. NewDriverTable,
  457. InfPath,
  458. STRTAB_CASE_INSENSITIVE
  459. );
  460. if (Index != -1) {
  461. //
  462. // Get the Attribs struct
  463. //
  464. if (!pSetupStringTableGetExtraData (
  465. NewDriverTable,
  466. Index,
  467. &Attribs,
  468. sizeof (Attribs)
  469. )) {
  470. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: String table extra data failure. \n" ));
  471. continue;
  472. }
  473. MultiSzAppendString (&Attribs->PnpIdList, PnpId);
  474. continue;
  475. }
  476. //
  477. // New INF path: Allocate an attribute structure and put the path in a
  478. // string table.
  479. //
  480. Attribs = (PAF_DRIVER_ATTRIBS) MyMalloc (sizeof (AF_DRIVER_ATTRIBS));
  481. if (!Attribs) {
  482. PNP_DBGPRINT ((
  483. "SETUP: CreateAfDriverTable: Mem alloc failed for %u bytes. \n",
  484. sizeof (AF_DRIVER_ATTRIBS)
  485. ));
  486. break;
  487. }
  488. ZeroMemory (Attribs, sizeof (AF_DRIVER_ATTRIBS));
  489. Attribs->InfHandle = INVALID_HANDLE_VALUE;
  490. Attribs->InfPath = pSetupDuplicateString (InfPath);
  491. Attribs->OriginalInstallMedia = pSetupDuplicateString (OriginalInstallMedia);
  492. MultiSzAppendString (&Attribs->PnpIdList, PnpId);
  493. Attribs->Next = FirstAttribs;
  494. FirstAttribs = Attribs;
  495. pSetupStringTableAddStringEx (
  496. NewDriverTable,
  497. InfPath,
  498. STRTAB_CASE_INSENSITIVE,
  499. &Attribs,
  500. sizeof (Attribs)
  501. );
  502. FoundOne = TRUE;
  503. } while (SetupFindNextLine (&ic, &ic));
  504. }
  505. //
  506. // Clean up and exit
  507. //
  508. SetupCloseInfFile (AnswerInf);
  509. ReusableFree (&b1);
  510. ReusableFree (&b2);
  511. ReusableFree (&b3);
  512. if (FoundOne) {
  513. Drivers = (PAF_DRIVERS) MyMalloc (sizeof (AF_DRIVERS));
  514. if (Drivers) {
  515. Drivers->DriverTable = NewDriverTable;
  516. Drivers->FirstDriver = FirstAttribs;
  517. //
  518. // Exit with success
  519. //
  520. return Drivers;
  521. }
  522. else {
  523. PNP_DBGPRINT (( "SETUP: CreateAfDriverTable: Can't allocate %u bytes. \n", sizeof (AF_DRIVERS) ));
  524. }
  525. }
  526. //
  527. // Failure or empty
  528. //
  529. pSetupStringTableDestroy (NewDriverTable);
  530. return NULL;
  531. }
  532. VOID
  533. DestroyAfDriverTable (
  534. IN PAF_DRIVERS Drivers
  535. )
  536. /*++
  537. Routine Description:
  538. DestroyAfDriverTable enumerates the specified driver table and cleans up
  539. all memory used by the table.
  540. Arguments:
  541. Drivers - Specifies the table to clean up. Caller should not use table
  542. handle after this routine completes.
  543. Return Value:
  544. None.
  545. --*/
  546. {
  547. AF_DRIVER_ENUM e;
  548. if (!Drivers) {
  549. return;
  550. }
  551. MYASSERT (Drivers->DriverTable);
  552. if (EnumFirstAfDriverEx (&e, Drivers, TRUE)) {
  553. do {
  554. MySmartFree (e.Driver->InfPath);
  555. MySmartFree (e.Driver->FilePath);
  556. MultiSzFree (&e.Driver->PnpIdList);
  557. if (e.Driver->InfHandle != INVALID_HANDLE_VALUE) {
  558. SetupCloseInfFile (e.Driver->InfHandle);
  559. }
  560. } while (EnumNextAfDriver (&e));
  561. }
  562. pSetupStringTableDestroy (Drivers->DriverTable);
  563. }
  564. BOOL
  565. EnumFirstAfDriver (
  566. OUT PAF_DRIVER_ENUM EnumPtr,
  567. IN PAF_DRIVERS Drivers
  568. )
  569. /*++
  570. Routine Description:
  571. EnumFirstAfDriver returns attributes for the first answer file-supplied
  572. driver. The driver is returned in the enum structure.
  573. Arguments:
  574. EnumPtr - Receives a pointer to the first valid driver (supplied in the
  575. answer file).
  576. Drivers - Specifies the driver table to enumerate.
  577. Return Value:
  578. TRUE if a driver was enumerated, or FALSE if none exist.
  579. --*/
  580. {
  581. return EnumFirstAfDriverEx (EnumPtr, Drivers, FALSE);
  582. }
  583. BOOL
  584. EnumFirstAfDriverEx (
  585. OUT PAF_DRIVER_ENUM EnumPtr,
  586. IN PAF_DRIVERS Drivers,
  587. IN BOOL WantAll
  588. )
  589. /*++
  590. Routine Description:
  591. EnumFirstAfDriverEx works the same as EnumFirstAfDriver, except it
  592. optionally enumerates all drivers (i.e., those considered "broken").
  593. Arguments:
  594. EnumPtr - Receives the first driver supplied in the answer file.
  595. Drivers - Specifies the driver table to enumerate.
  596. WantAll - Specifies TRUE if broken drivers should be enumerated, or FALSE
  597. if they should be skipped.
  598. Return Value:
  599. TRUE if a driver was enumerated, or FALSE if none exist.
  600. --*/
  601. {
  602. if (!Drivers) {
  603. return FALSE;
  604. }
  605. MYASSERT (Drivers->DriverTable);
  606. EnumPtr->Driver = Drivers->FirstDriver;
  607. EnumPtr->WantAll = WantAll;
  608. if (!WantAll && EnumPtr->Driver) {
  609. //
  610. // Make sure attribs are accurate
  611. //
  612. pBuildAfDriverAttribs (EnumPtr->Driver);
  613. }
  614. if (!WantAll && EnumPtr->Driver && EnumPtr->Driver->Broken) {
  615. return EnumNextAfDriver (EnumPtr);
  616. }
  617. return EnumPtr->Driver != NULL;
  618. }
  619. BOOL
  620. EnumNextAfDriver (
  621. IN OUT PAF_DRIVER_ENUM EnumPtr
  622. )
  623. /*++
  624. Routine Description:
  625. EnumNextAfDriver continues an enumeration started by
  626. EnumFirstAfDriver(Ex).
  627. Arguments:
  628. EnumPtr - Specifies the enumeration to continue. Receives the next driver
  629. pointer.
  630. Return Value:
  631. TRUE if another driver was enumerated, or FALSE if no more drivers exist.
  632. --*/
  633. {
  634. if (!EnumPtr->Driver) {
  635. return FALSE;
  636. }
  637. do {
  638. EnumPtr->Driver = EnumPtr->Driver->Next;
  639. if (!EnumPtr->WantAll && EnumPtr->Driver) {
  640. //
  641. // Make sure attribs are accurate
  642. //
  643. pBuildAfDriverAttribs (EnumPtr->Driver);
  644. }
  645. } while (EnumPtr->Driver && EnumPtr->Driver->Broken && !EnumPtr->WantAll);
  646. return EnumPtr->Driver != NULL;
  647. }
  648. PWSTR
  649. pMyGetDeviceRegistryProperty (
  650. IN HDEVINFO hDevInfo,
  651. IN PSP_DEVINFO_DATA DeviceInfoData,
  652. IN DWORD Property,
  653. IN OUT PBUFFER Buf
  654. )
  655. {
  656. DWORD SizeNeeded;
  657. DWORD Type;
  658. PBYTE p;
  659. SizeNeeded = 0;
  660. SetupDiGetDeviceRegistryProperty (
  661. hDevInfo,
  662. DeviceInfoData,
  663. Property,
  664. &Type,
  665. NULL,
  666. 0,
  667. &SizeNeeded
  668. );
  669. if (!SizeNeeded) {
  670. return NULL;
  671. }
  672. if (Type != REG_MULTI_SZ) {
  673. PNP_DBGPRINT (( "SETUP: Device ID not REG_MULTI_SZ. \n" ));
  674. return NULL;
  675. }
  676. p = ReusableAlloc (Buf, SizeNeeded);
  677. if (!p) {
  678. return NULL;
  679. }
  680. if (!SetupDiGetDeviceRegistryProperty (
  681. hDevInfo,
  682. DeviceInfoData,
  683. Property,
  684. NULL,
  685. p,
  686. SizeNeeded,
  687. NULL
  688. )) {
  689. return NULL;
  690. }
  691. return (PWSTR) p;
  692. }
  693. VOID
  694. pAddIdsToStringTable (
  695. IN OUT PVOID StringTable,
  696. IN PWSTR IdString
  697. )
  698. {
  699. MULTISZ_ENUM e;
  700. if (EnumFirstMultiSz (&e, IdString)) {
  701. do {
  702. PNP_DBGPRINT (( "SETUP: Device has PNP ID %s \n", e.Current));
  703. pSetupStringTableAddString (StringTable, (PWSTR) e.Current, STRTAB_CASE_INSENSITIVE);
  704. } while (EnumNextMultiSz (&e));
  705. }
  706. }
  707. PSP_DRVINFO_DETAIL_DATA
  708. pMyGetDriverInfoDetail (
  709. IN HDEVINFO hDevInfo,
  710. IN PSP_DEVINFO_DATA DeviceInfoData,
  711. IN PSP_DRVINFO_DATA DriverInfoData,
  712. IN OUT PBUFFER Buf
  713. )
  714. {
  715. PSP_DRVINFO_DETAIL_DATA Ptr;
  716. DWORD SizeNeeded = 0;
  717. SetupDiGetDriverInfoDetail (
  718. hDevInfo,
  719. DeviceInfoData,
  720. DriverInfoData,
  721. NULL,
  722. 0,
  723. &SizeNeeded
  724. );
  725. if (!SizeNeeded) {
  726. PNP_DBGPRINT (( "SETUP: SetupDiGetDriverInfoDetail failed to get size for answer file driver, error 0%Xh. \n", GetLastError() ));
  727. return NULL;
  728. }
  729. Ptr = (PSP_DRVINFO_DETAIL_DATA) ReusableAlloc (Buf, SizeNeeded);
  730. if (!Ptr) {
  731. return NULL;
  732. }
  733. Ptr->cbSize = sizeof (SP_DRVINFO_DETAIL_DATA);
  734. if (!SetupDiGetDriverInfoDetail (
  735. hDevInfo,
  736. DeviceInfoData,
  737. DriverInfoData,
  738. Ptr,
  739. SizeNeeded,
  740. NULL
  741. )) {
  742. PNP_DBGPRINT (( "SETUP: SetupDiGetDriverInfoDetail failed for answer file driver, error 0%Xh. \n", GetLastError() ));
  743. return NULL;
  744. }
  745. return Ptr;
  746. }
  747. BOOL
  748. SyssetupInstallAnswerFileDriver (
  749. IN PAF_DRIVERS Drivers,
  750. IN HDEVINFO hDevInfo,
  751. IN PSP_DEVINFO_DATA DeviceInfoData,
  752. OUT PAF_DRIVER_ATTRIBS *AfDriver
  753. )
  754. /*++
  755. Routine Description:
  756. SyssetupInstallAnswerFileDriver builds a device list from each
  757. answer file-specified driver and tests it against the current
  758. device. If support is found, the device is installed.
  759. Arguments:
  760. Drivers - Specifies the structure that maintains answer file-supplied
  761. driver attributes. If Drivers is NULL, no processing is
  762. performed.
  763. hDevInfo - Specifies the device info handle for the device being
  764. processed
  765. DeviceInfoData - Specifies device state.
  766. AfDriver - Receives a pointer to the selected answer file driver
  767. details, or NULL if no answer file driver was selected.
  768. Return Value:
  769. Returns TRUE if a driver was successfully installed.
  770. --*/
  771. {
  772. AF_DRIVER_ENUM e;
  773. PVOID PnpIdTable;
  774. BUFFER Buf = BUFFER_INIT;
  775. BOOL b = FALSE;
  776. PWSTR IdString;
  777. MULTISZ_ENUM AfId;
  778. BOOL First = TRUE;
  779. WCHAR CurrentId[512];
  780. PWSTR p;
  781. SP_DEVINSTALL_PARAMS deviceInstallParams;
  782. *AfDriver = NULL;
  783. PnpIdTable = pSetupStringTableInitialize();
  784. if (!PnpIdTable) {
  785. return FALSE;
  786. }
  787. __try {
  788. //
  789. // Enumeration will fail if there are no drivers specified in the answer file
  790. //
  791. if (!EnumFirstAfDriver (&e, Drivers)) {
  792. __leave;
  793. }
  794. //
  795. // Determine IDs of the device
  796. //
  797. IdString = pMyGetDeviceRegistryProperty (
  798. hDevInfo,
  799. DeviceInfoData,
  800. SPDRP_HARDWAREID,
  801. &Buf
  802. );
  803. if (IdString) {
  804. pAddIdsToStringTable (PnpIdTable, IdString);
  805. }
  806. IdString = pMyGetDeviceRegistryProperty (
  807. hDevInfo,
  808. DeviceInfoData,
  809. SPDRP_COMPATIBLEIDS,
  810. &Buf
  811. );
  812. if (IdString) {
  813. pAddIdsToStringTable (PnpIdTable, IdString);
  814. }
  815. //
  816. // For each af-supplied driver, compare driver IDs against device IDs
  817. //
  818. do {
  819. //
  820. // Look for PNP match
  821. //
  822. if (EnumFirstMultiSz (&AfId, e.Driver->PnpIdList.Start)) {
  823. do {
  824. if (-1 != pSetupStringTableLookUpString (
  825. PnpIdTable,
  826. (PWSTR) AfId.Current,
  827. STRTAB_CASE_INSENSITIVE
  828. )) {
  829. //
  830. // Found match, add INF to the list of choices
  831. //
  832. if (!pAddAfDriver (e.Driver, hDevInfo, DeviceInfoData, First)) {
  833. __leave;
  834. }
  835. First = FALSE;
  836. }
  837. } while (EnumNextMultiSz (&AfId));
  838. }
  839. } while (EnumNextAfDriver (&e));
  840. //
  841. // If First is still TRUE, then we have no match
  842. //
  843. if (First) {
  844. __leave;
  845. }
  846. //
  847. // Prepare for driver install by choosing the driver
  848. //
  849. b = SetupDiCallClassInstaller (
  850. DIF_SELECTBESTCOMPATDRV,
  851. hDevInfo,
  852. DeviceInfoData
  853. );
  854. if (!b) {
  855. PNP_DBGPRINT (( "SETUP: SetupDiCallClassInstaller failed for answer file driver, error 0%Xh. \n", GetLastError() ));
  856. //
  857. // reset the struct
  858. //
  859. deviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  860. if (SetupDiGetDeviceInstallParams (hDevInfo, DeviceInfoData, &deviceInstallParams)) {
  861. ZeroMemory (deviceInstallParams.DriverPath, sizeof (deviceInstallParams.DriverPath));
  862. deviceInstallParams.Flags &= ~DI_ENUMSINGLEINF;
  863. deviceInstallParams.FlagsEx &= ~DI_FLAGSEX_APPENDDRIVERLIST;
  864. if (SetupDiSetDeviceInstallParams (hDevInfo, DeviceInfoData, &deviceInstallParams)) {
  865. if (!SetupDiDestroyDriverInfoList (hDevInfo, DeviceInfoData, SPDIT_COMPATDRIVER)) {
  866. PNP_DBGPRINT (( "SETUP: SyssetupInstallAnswerFileDriver: SetupDiDestroyDriverInfoList() failed. Error = 0%Xh \n", GetLastError() ));
  867. }
  868. } else {
  869. PNP_DBGPRINT (( "SETUP: SyssetupInstallAnswerFileDriver: SetupDiSetDeviceInstallParams() failed. Error = 0%Xh \n", GetLastError() ));
  870. }
  871. } else {
  872. PNP_DBGPRINT (( "SETUP: SyssetupInstallAnswerFileDriver: SetupDiGetDeviceInstallParams() failed. Error = 0%Xh \n", GetLastError() ));
  873. }
  874. } else {
  875. //
  876. // Identify which driver of ours, if any, was chosen
  877. //
  878. *AfDriver = pGetSelectedSourceDriver (Drivers, hDevInfo, DeviceInfoData);
  879. if (*AfDriver == NULL) {
  880. PNP_DBGPRINT (( "SETUP: WARNING: Answer File Driver was not chosen for its device. \n" ));
  881. }
  882. }
  883. }
  884. __finally {
  885. pSetupStringTableDestroy (PnpIdTable);
  886. ReusableFree (&Buf);
  887. }
  888. return b;
  889. }
  890. BOOL
  891. pAddAfDriver (
  892. IN PAF_DRIVER_ATTRIBS Driver,
  893. IN HDEVINFO hDevInfo,
  894. IN PSP_DEVINFO_DATA DeviceInfoData,
  895. IN BOOL First
  896. )
  897. /*++
  898. Routine Description:
  899. pAddAfDriver adds the INF specified in the answer file to the list of INFs.
  900. This causes the PNP setup code to include it when finding the best device
  901. driver.
  902. Arguments:
  903. Driver - Specifies the attributes of the answer file-supplied driver
  904. hDevInfo - Specifies the current device
  905. DeviceInfoData - Specifies current device info
  906. First - TRUE if this is the first answer file-supplied INF for the
  907. device, otherwise FALSE
  908. Return Value:
  909. TRUE if the INF was added to the device install parameters, FALSE otherwise
  910. --*/
  911. {
  912. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  913. HKEY Key;
  914. //
  915. // Fill in DeviceInstallParams struct
  916. //
  917. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  918. if (!SetupDiGetDeviceInstallParams (hDevInfo, DeviceInfoData, &DeviceInstallParams)) {
  919. PNP_DBGPRINT (( "SETUP: pAddAfDriver: SetupDiGetDeviceInstallParams() failed. Error = 0%Xh \n", GetLastError() ));
  920. return FALSE;
  921. }
  922. //
  923. // Modify the struct
  924. //
  925. MYASSERT (!DeviceInstallParams.DriverPath[0]);
  926. lstrcpynW (DeviceInstallParams.DriverPath, Driver->InfPath, MAX_PATH);
  927. DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  928. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_APPENDDRIVERLIST;
  929. //
  930. // Tell setup api where to find the driver
  931. //
  932. if (!SetupDiSetDeviceInstallParams (hDevInfo, DeviceInfoData, &DeviceInstallParams)) {
  933. PNP_DBGPRINT (( "SETUP: pAddAfDriver: SetupDiSetDeviceInstallParams() failed. Error = 0%Xh \n", GetLastError() ));
  934. return FALSE;
  935. }
  936. if( !SetupDiBuildDriverInfoList( hDevInfo, DeviceInfoData, SPDIT_COMPATDRIVER ) ) {
  937. PNP_DBGPRINT (( "SETUP: pAddAfDriver: SetupDiBuildDriverInfoList() failed. Error = 0%Xh \n", GetLastError() ));
  938. return FALSE;
  939. }
  940. //
  941. // Install ClassInstall32 if necessary
  942. //
  943. if (Driver->ClassInstall32Section) {
  944. //
  945. // Is class already installed?
  946. //
  947. Key = SetupDiOpenClassRegKey (&Driver->Guid, KEY_READ);
  948. if (Key == (HKEY) INVALID_HANDLE_VALUE || !Key) {
  949. //
  950. // No, install class.
  951. //
  952. if (!SetupDiInstallClass (NULL, Driver->InfPath, DI_FORCECOPY, NULL)) {
  953. PNP_DBGPRINT (( "SETUP: pAddAfDriver: SetupDiInstallClass() failed. Error = 0%Xh \n", GetLastError() ));
  954. }
  955. } else {
  956. RegCloseKey (Key);
  957. }
  958. }
  959. return TRUE;
  960. }
  961. PAF_DRIVER_ATTRIBS
  962. pGetSelectedSourceDriver (
  963. IN PAF_DRIVERS Drivers,
  964. IN HDEVINFO hDevInfo,
  965. IN PSP_DEVINFO_DATA DeviceInfoData
  966. )
  967. /*++
  968. Routine Description:
  969. pGetSelectedSourceDriver finds which answer file driver was selected, if
  970. any.
  971. Arguments:
  972. Drivers - Specifies the answer file driver table, as created by
  973. CreateAfDriverTable
  974. hDevInfo - Specifies the current device. The driver for this
  975. device must be selected, but not yet installed.
  976. DeviceInfoData - Specifies the device data
  977. Return Value:
  978. A pointer to the answer file driver attributes, or NULL if no answer file
  979. driver was selected for the device.
  980. --*/
  981. {
  982. SP_DRVINFO_DATA DriverData;
  983. PAF_DRIVER_ATTRIBS OurDriver = NULL;
  984. PSP_DRVINFO_DETAIL_DATA DetailData;
  985. BUFFER Buf = BUFFER_INIT;
  986. AF_DRIVER_ENUM e;
  987. __try {
  988. //
  989. // After the PNP subsystem installs a driver for the device, we get the
  990. // actual installed device INF path, and see if it was one of our
  991. // answer file-supplied drivers.
  992. //
  993. DriverData.cbSize = sizeof(SP_DRVINFO_DATA);
  994. if (!SetupDiGetSelectedDriver (hDevInfo, DeviceInfoData, &DriverData)) {
  995. PNP_DBGPRINT (( "SETUP: SetupDiGetSelectedDriver failed for answer file driver, error 0%Xh. \n", GetLastError() ));
  996. } else {
  997. DetailData = pMyGetDriverInfoDetail (hDevInfo, DeviceInfoData, &DriverData, &Buf);
  998. if (DetailData) {
  999. //
  1000. // Check our driver list
  1001. //
  1002. if (EnumFirstAfDriver (&e, Drivers)) {
  1003. do {
  1004. if (!lstrcmpi (e.Driver->InfPath, DetailData->InfFileName)) {
  1005. //
  1006. // Match found
  1007. //
  1008. OurDriver = e.Driver;
  1009. break;
  1010. }
  1011. } while (EnumNextAfDriver (&e));
  1012. }
  1013. } else {
  1014. PNP_DBGPRINT (( "SETUP: No driver details available, error 0%Xh. \n", GetLastError() ));
  1015. }
  1016. }
  1017. }
  1018. __finally {
  1019. ReusableFree (&Buf);
  1020. }
  1021. return OurDriver;
  1022. }
  1023. BOOL
  1024. SyssetupFixAnswerFileDriverPath (
  1025. IN PAF_DRIVER_ATTRIBS Driver,
  1026. IN HDEVINFO hDevInfo,
  1027. IN PSP_DEVINFO_DATA DeviceInfoData
  1028. )
  1029. /*++
  1030. Routine Description:
  1031. SyssetupFixAnswerFileDriverPath calls SetupCopyOEMFile to copy the device
  1032. INF over itself. The source is the same as the destination, which causes
  1033. the PNF to be rebuilt, and doesn't cause any copy
  1034. activity.
  1035. Arguments:
  1036. Driver - Specifies the attributes of the answer file-supplied driver
  1037. hDevInfo - Specifies the device. The driver for this device must
  1038. already be installed.
  1039. DeviceInfoData - Specifies the device info
  1040. Return Value:
  1041. TRUE if the PNF was updated, FALSE otherwise.
  1042. --*/
  1043. {
  1044. HKEY Key = NULL;
  1045. LONG rc;
  1046. DWORD Type;
  1047. DWORD DataSize;
  1048. WCHAR Data[MAX_PATH - 48];
  1049. WCHAR WinDir[48];
  1050. WCHAR FullNtInfPath[MAX_PATH];
  1051. BOOL b = FALSE;
  1052. __try {
  1053. //
  1054. // Now the driver in the temp dir has been installed. We must
  1055. // get the PNF to point to the original media. We do this by
  1056. // recopying the INF over itself.
  1057. //
  1058. Key = SetupDiOpenDevRegKey (
  1059. hDevInfo,
  1060. DeviceInfoData,
  1061. DICS_FLAG_GLOBAL,
  1062. 0,
  1063. DIREG_DRV,
  1064. KEY_READ
  1065. );
  1066. if (!Key) {
  1067. PNP_DBGPRINT (( "SETUP: Can't open key for device, error 0%Xh. \n", GetLastError() ));
  1068. __leave;
  1069. }
  1070. DataSize = sizeof (Data);
  1071. rc = RegQueryValueEx (
  1072. Key,
  1073. REGSTR_VAL_INFPATH,
  1074. NULL,
  1075. &Type,
  1076. (PBYTE) Data,
  1077. &DataSize
  1078. );
  1079. if (rc != ERROR_SUCCESS) {
  1080. PNP_DBGPRINT (( "SETUP: Can't query value for device, error 0%Xh. \n", rc ));
  1081. __leave;
  1082. }
  1083. if (!GetSystemWindowsDirectory (WinDir, sizeof (WinDir) / sizeof (WinDir[0]))) {
  1084. MYASSERT (FALSE);
  1085. PNP_DBGPRINT (( "SETUP: Can't get %%windir%%, error 0%Xh. \n", GetLastError() ));
  1086. __leave;
  1087. }
  1088. wsprintfW (FullNtInfPath, L"%s\\INF\\%s", WinDir, Data);
  1089. MYASSERT (GetFileAttributes (FullNtInfPath) != 0xFFFFFFFF);
  1090. //
  1091. // We now have the installed INF path. Recopy the INF so we can
  1092. // change the original media path.
  1093. //
  1094. b = SetupCopyOEMInf (
  1095. FullNtInfPath,
  1096. Driver->OriginalInstallMedia,
  1097. SPOST_PATH,
  1098. SP_COPY_SOURCE_ABSOLUTE|SP_COPY_NOSKIP|SP_COPY_NOBROWSE,
  1099. NULL,
  1100. 0,
  1101. NULL,
  1102. NULL
  1103. );
  1104. if (!b) {
  1105. PNP_DBGPRINT (( "SETUP: pFixSourceInfPath: SetupCopyOEMInf() failed. Error = 0%Xh \n", GetLastError() ));
  1106. b = TRUE;
  1107. }
  1108. }
  1109. __finally {
  1110. if (Key) {
  1111. RegCloseKey (Key);
  1112. }
  1113. }
  1114. return b;
  1115. }