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.

1868 lines
56 KiB

  1. /*
  2. Module Name:
  3. netinfp.c
  4. Abstract:
  5. This module implements our routines to parse net card INF files.
  6. Author:
  7. Andy Herron Mar 12 1998
  8. Revision History:
  9. */
  10. #include "binl.h"
  11. #pragma hdrstop
  12. #include "netinfp.h"
  13. // for verbose output, define the following
  14. //#define NET_INF_VERBOSE 1
  15. ULONG
  16. NetInfAllocateNetcardInfo (
  17. PWCHAR InfPath,
  18. ULONG Architecture,
  19. PNETCARD_INF_BLOCK *pNetCards
  20. )
  21. /*++
  22. Routine Description:
  23. This function is allocates the block that contains all the relavent info
  24. related to a given setup directory's INF files.
  25. Arguments:
  26. InfPath - path to INF directory. default is %systemroot%\inf if NULL.
  27. pNetCards - A pointer to a pointer that receives the allocated
  28. NETCARD_INF_BLOCK block allocated. NULL if we return an error.
  29. Return Value:
  30. Windows Error.
  31. --*/
  32. {
  33. ULONG i;
  34. PNETCARD_INF_BLOCK pBlock;
  35. *pNetCards = BinlAllocateMemory( sizeof( NETCARD_INF_BLOCK ) +
  36. (wcslen( InfPath )+1) * sizeof(WCHAR) );
  37. if (*pNetCards == NULL) {
  38. return ERROR_NOT_ENOUGH_MEMORY;
  39. }
  40. memset( (PCHAR) *pNetCards, '\0', sizeof( NETCARD_RESPONSE_DATABASE ) );
  41. pBlock = *pNetCards;
  42. pBlock->ReferenceCount = 2; // one for being alive. one for referenced
  43. for (i = 0; i < NETCARD_HASH_TABLE_SIZE; i++) {
  44. InitializeListHead( &pBlock->NetCardEntries[i] );
  45. }
  46. InitializeCriticalSection( &pBlock->Lock );
  47. wcscpy( pBlock->InfDirectory, InfPath );
  48. pBlock->Architecture = Architecture;
  49. pBlock->FileListCallbackFunction = NULL;
  50. pBlock->InfBlockEntry.Flink = NULL;
  51. return ERROR_SUCCESS;
  52. }
  53. ULONG
  54. GetNetCardList (
  55. PNETCARD_INF_BLOCK pNetCards
  56. )
  57. /*++
  58. Routine Description:
  59. We go through all the INF files on the server to pick out the net
  60. cards supported and the required reg fields to send to the client.
  61. This function uses the FindFirstFile and SetupOpenInfFile APIs to
  62. enumerate all the inf files and process all net card INFs.
  63. Arguments:
  64. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  65. the persistant info required for the netcards.
  66. Return Value:
  67. Windows Error.
  68. --*/
  69. {
  70. ULONG err = ERROR_SUCCESS;
  71. HINF infHandle;
  72. WCHAR fileBuffer[ MAX_PATH ];
  73. HANDLE findHandle = INVALID_HANDLE_VALUE;
  74. WIN32_FIND_DATAW findData;
  75. PWCHAR endOfPath;
  76. //
  77. // We would call SetupGetInfFileList here rather than FindFirstFile,
  78. // but then we'd have to open all the INFs three times rather than
  79. // once. Once to figure out how much space the file name buffer requires,
  80. // once to fill in the file name buffer, and once to do our own
  81. // processing.
  82. // We'll skip the first two passes since they're just a waste of time
  83. // by calling FindFirstFile.
  84. //
  85. if (0 > _snwprintf( fileBuffer,
  86. MAX_PATH,
  87. L"%ws\\*.inf",
  88. pNetCards->InfDirectory )) {
  89. err = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  90. BinlPrintDbg(( DEBUG_NETINF,"_snwprintf failed" ));
  91. goto exitGetCards;
  92. }
  93. fileBuffer[MAX_PATH-1] = L'\0';
  94. findHandle = FindFirstFileW( fileBuffer, &findData );
  95. if (findHandle == INVALID_HANDLE_VALUE) {
  96. //
  97. // we're in trouble. can't enumerate all the files.
  98. //
  99. err = GetLastError();
  100. BinlPrintDbg(( DEBUG_NETINF,"FindFirstFile returned 0x%x\n", err ));
  101. goto exitGetCards;
  102. }
  103. wsprintf( fileBuffer, L"%ws\\",pNetCards->InfDirectory);
  104. endOfPath = fileBuffer + wcslen( fileBuffer );
  105. do {
  106. //
  107. // Skip directories
  108. //
  109. if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  110. continue;
  111. }
  112. //
  113. // make sure we have enough room.
  114. //
  115. if ( ((endOfPath - fileBuffer)/sizeof(WCHAR)) + wcslen(findData.cFileName) + 1 > MAX_PATH) {
  116. err = ERROR_NOT_ENOUGH_SERVER_MEMORY;
  117. continue;
  118. }
  119. wcscpy( endOfPath, findData.cFileName );
  120. //
  121. // try to be resiliant for ill formatted INF files.
  122. //
  123. try {
  124. infHandle = SetupOpenInfFileW( fileBuffer,
  125. L"NET", // class of inf file
  126. INF_STYLE_WIN4 | INF_STYLE_CACHE_ENABLE,
  127. NULL );
  128. if (infHandle != INVALID_HANDLE_VALUE) {
  129. err = ProcessInfFile( pNetCards,
  130. infHandle,
  131. findData.cFileName );
  132. SetupCloseInfFile( infHandle );
  133. } else {
  134. err = GetLastError();
  135. }
  136. } except (EXCEPTION_EXECUTE_HANDLER) {
  137. //
  138. // log an error here that we trapped out on a bad INF
  139. //
  140. PWCHAR strings[3];
  141. strings[0] = pNetCards->InfDirectory;
  142. strings[1] = findData.cFileName;
  143. strings[2] = NULL;
  144. BinlReportEventW( ERROR_BINL_ERR_IN_INF,
  145. EVENTLOG_WARNING_TYPE,
  146. 2,
  147. 0,
  148. strings,
  149. NULL
  150. );
  151. }
  152. if (err == ERROR_NOT_ENOUGH_MEMORY) {
  153. break;
  154. }
  155. #ifdef NET_INF_VERBOSE
  156. if (err != ERROR_SUCCESS && err != ERROR_CLASS_MISMATCH) {
  157. BinlPrintDbg(( DEBUG_NETINF,"ProcessInfFile returned 0x%x for %S\n", err, fileBuffer ));
  158. }
  159. #endif
  160. err = ERROR_SUCCESS;
  161. } while (FindNextFileW(findHandle,&findData));
  162. exitGetCards:
  163. if (findHandle != INVALID_HANDLE_VALUE) {
  164. FindClose( findHandle );
  165. }
  166. return err;
  167. }
  168. ULONG
  169. ProcessInfFile (
  170. PNETCARD_INF_BLOCK pNetCards,
  171. HINF InfHandle,
  172. PWCHAR InfFileName
  173. )
  174. /*++
  175. Routine Description:
  176. This function uses the SetupXxxx APIs to process a given INF file for
  177. all net card drivers. Each INF file is first parsed for the MANUFACTURERS
  178. section. This section contains all the section keys that contain all
  179. the devices. We then enumerate all the devices in each manufacturer's
  180. section and call off to ParseCardDetails to add it to our list.
  181. As an example, the net557.inf file looks like this :
  182. [Manufacturer]
  183. %Intel% = Intel
  184. %ATI% = ATI
  185. %Compaq% = Compaq
  186. %HPTX% = HPTX
  187. %IBM% = IBM
  188. %Microdyne% = Microdyne
  189. %Samsung% = Samsung
  190. and the [ATI] section looks like this :
  191. [ATI]
  192. ; DisplayName Section DeviceID
  193. %AT2560B.DeviceDesc% = AT2560B.ndi, PCI\VEN_1259&DEV_2560&REV_01
  194. %AT2560C.DeviceDesc% = AT2560C.ndi, PCI\VEN_8086&DEV_1229&SUBSYS_25601259
  195. %AT2560CFX.DeviceDesc% = AT2560CFX.ndi, PCI\VEN_8086&DEV_1229&SUBSYS_25611259
  196. Arguments:
  197. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  198. the persistant info required for the netcards.
  199. InfHandle - handle open to INF file, guarenteed to be net driver
  200. InfFileName - wide form of relative file name we have open.
  201. Return Value:
  202. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  203. --*/
  204. {
  205. ULONG err = ERROR_SUCCESS;
  206. INFCONTEXT manufacturerEnumContext;
  207. INFCONTEXT deviceEnumContext;
  208. PWCHAR manufacturer = NULL;
  209. ULONG sizeRequired;
  210. ULONG sizeAllocated = 0;
  211. PWCHAR strings[3];
  212. //
  213. // We need to enumerate through the Manufacturer section first
  214. //
  215. if (SetupFindFirstLineW( InfHandle,
  216. L"Manufacturer",
  217. NULL,
  218. &manufacturerEnumContext
  219. ) == FALSE) {
  220. err = GetLastError();
  221. BinlPrintDbg(( DEBUG_NETINF, "SetupFindFirstLine failed with 0x%x in %S for Manufacturer\n",
  222. err, InfFileName ));
  223. //
  224. // log an error here that we couldn't parse INF
  225. //
  226. {
  227. strings[0] = InfFileName;
  228. strings[1] = L"Manufacturer";
  229. strings[2] = NULL;
  230. BinlReportEventW( ERROR_BINL_ERR_IN_SECTION,
  231. EVENTLOG_WARNING_TYPE,
  232. 2,
  233. sizeof(ULONG),
  234. strings,
  235. &err
  236. );
  237. }
  238. goto exitProcessInf;
  239. }
  240. while (1) {
  241. err = GetSetupWideTextField( &manufacturerEnumContext,
  242. 1,
  243. &manufacturer,
  244. &sizeAllocated );
  245. if (err == ERROR_SUCCESS) {
  246. //
  247. // we enumerate through each manufacturer section for drivers
  248. //
  249. // since we need the display name in unicode, we use the wide
  250. // APIs.
  251. //
  252. if (SetupFindFirstLineW( InfHandle,
  253. manufacturer,
  254. NULL,
  255. &deviceEnumContext ) == TRUE) {
  256. while (1) {
  257. err = ParseCardDetails( pNetCards,
  258. InfHandle,
  259. InfFileName,
  260. &deviceEnumContext );
  261. if (err == ERROR_NOT_ENOUGH_MEMORY) {
  262. break;
  263. }
  264. if ( SetupFindNextLine( &deviceEnumContext,
  265. &deviceEnumContext ) == FALSE) {
  266. break;
  267. }
  268. }
  269. err = ERROR_SUCCESS; // try the next card regardless
  270. } else {
  271. err = GetLastError();
  272. BinlPrintDbg(( DEBUG_NETINF, "SetupFindFirstLine failed with 0x%x in %S for Manufacturer\n",
  273. err, InfFileName ));
  274. }
  275. } else {
  276. BinlPrintDbg(( DEBUG_NETINF, "GetSetupWideTextField failed with 0x%x in %S for Manufacturer\n",
  277. err, InfFileName ));
  278. }
  279. if (err != ERROR_SUCCESS &&
  280. err != ERROR_NOT_SUPPORTED) {
  281. // log an error here? (and continue)
  282. }
  283. //
  284. // if we ran out of memory on the inner loop, bail.
  285. //
  286. if (err == ERROR_NOT_ENOUGH_MEMORY) {
  287. break;
  288. }
  289. if ( SetupFindNextLine( &manufacturerEnumContext,
  290. &manufacturerEnumContext ) == FALSE) {
  291. break;
  292. }
  293. }
  294. exitProcessInf:
  295. #ifdef NET_INF_VERBOSE
  296. BinlPrintDbg(( DEBUG_NETINF, "BINL netinf returning 0x%x for %S\n", err, InfFileName ));
  297. #endif
  298. if (manufacturer) {
  299. BinlFreeMemory(manufacturer);
  300. }
  301. return err;
  302. }
  303. ULONG
  304. ParseCardDetails (
  305. PNETCARD_INF_BLOCK pNetCards,
  306. HINF InfHandle,
  307. PWCHAR InfFileName,
  308. PINFCONTEXT DeviceEnumContext
  309. )
  310. /*++
  311. Routine Description:
  312. This function uses the SetupXxxx APIs to process an INF file for a given
  313. driver instance. We check to see if it's already on the list (by hw
  314. description) and if it isn't, create a new one, get the rest of the info,
  315. and put it on the list.
  316. Arguments:
  317. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  318. the persistant info required for the netcards.
  319. InfHandle - handle open to INF file, guarenteed to be net driver
  320. InfFileName - wide form of relative file name we have open.
  321. DeviceEnumContext - current line that has device's hardware, name, section
  322. Return Value:
  323. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  324. --*/
  325. {
  326. ULONG err = ERROR_SUCCESS;
  327. PLIST_ENTRY listEntry, listHead;
  328. PNETCARD_RESPONSE_DATABASE pEntry = NULL;
  329. LONG hwLength;
  330. PWCHAR nextField;
  331. ULONG sizeRequired;
  332. UNICODE_STRING hwString;
  333. PWCHAR sectionToLog = NULL;
  334. PWCHAR deviceName = NULL;
  335. PWCHAR deviceSection = NULL;
  336. PWCHAR deviceHw = NULL;
  337. ULONG hashValue;
  338. err = GetSetupWideTextField( DeviceEnumContext,
  339. 2,
  340. &deviceHw,
  341. NULL );
  342. if (err != ERROR_SUCCESS) {
  343. goto exitParseCardDetails;
  344. }
  345. BinlAssert(deviceHw != NULL);
  346. // convert it to uppercase to speed our searches
  347. RtlInitUnicodeString( &hwString, deviceHw );
  348. RtlUpcaseUnicodeString( &hwString, &hwString, FALSE );
  349. err = CheckHwDescription( deviceHw );
  350. if (err != ERROR_SUCCESS) {
  351. // this should fail if it's not the format we expect.
  352. goto exitParseCardDetails;
  353. }
  354. //
  355. // We sort the list by HwDescription so that we only have
  356. // one entry for each one. Ensure that this one is not
  357. // already in the list.
  358. //
  359. COMPUTE_STRING_HASH( deviceHw, &hashValue );
  360. listHead = &pNetCards->NetCardEntries[HASH_TO_INF_INDEX(hashValue)];
  361. listEntry = listHead->Flink;
  362. hwLength = wcslen( deviceHw );
  363. pEntry = NULL;
  364. while ( listEntry != listHead ) {
  365. pEntry = (PNETCARD_RESPONSE_DATABASE) CONTAINING_RECORD(
  366. listEntry,
  367. NETCARD_RESPONSE_DATABASE,
  368. NetCardEntry );
  369. err = CompareStringW( LOCALE_SYSTEM_DEFAULT,
  370. 0,
  371. deviceHw,
  372. hwLength,
  373. pEntry->HardwareId,
  374. -1
  375. );
  376. if (err == 2) {
  377. break; // a match was found.
  378. }
  379. pEntry = NULL;
  380. if (err == 3) {
  381. break; // it's greater, add it before listEntry
  382. }
  383. listEntry = listEntry->Flink;
  384. }
  385. if (pEntry != NULL) {
  386. //
  387. // we've found a dup, don't process this one.
  388. //
  389. err = ERROR_SUCCESS; // no problems here
  390. pEntry = NULL;
  391. #ifdef NET_INF_VERBOSE
  392. BinlPrintDbg(( DEBUG_NETINF, "skipping dup of %S\n", deviceHw ));
  393. #endif
  394. goto exitParseCardDetails;
  395. }
  396. //
  397. // the inf name and section name are mandatory
  398. //
  399. err = GetSetupWideTextField( DeviceEnumContext,
  400. 0,
  401. &deviceName,
  402. NULL );
  403. if (err != ERROR_SUCCESS) {
  404. BinlPrintDbg(( DEBUG_NETINF, "failed to get device name for %S\n", deviceHw ));
  405. goto exitParseCardDetails;
  406. }
  407. err = GetSetupWideTextField( DeviceEnumContext,
  408. 1,
  409. &deviceSection,
  410. NULL );
  411. if (err != ERROR_SUCCESS) {
  412. BinlPrintDbg(( DEBUG_NETINF, "failed to get device section for %S\n", deviceHw ));
  413. goto exitParseCardDetails;
  414. }
  415. sectionToLog = deviceSection;
  416. if ((*deviceName == L'\0') ||
  417. (*deviceSection == L'\0')) {
  418. err = ERROR_NOT_SUPPORTED;
  419. BinlPrintDbg(( DEBUG_NETINF, "Empty Name or Section not supported for %S\n", deviceHw ));
  420. goto exitParseCardDetails;
  421. }
  422. //
  423. // Allocate the buffer space required for the fields we need
  424. //
  425. sizeRequired = sizeof( NETCARD_RESPONSE_DATABASE ) +
  426. ( wcslen( InfFileName ) + 2 ) * sizeof(WCHAR);
  427. pEntry = (PNETCARD_RESPONSE_DATABASE) BinlAllocateMemory( sizeRequired );
  428. if (pEntry == NULL) {
  429. //
  430. // Doh! we couldn't allocate a simple buffer. we're done.
  431. //
  432. BinlPrintDbg(( DEBUG_NETINF, "failed to allocate new entry for %S\n", deviceHw ));
  433. err = ERROR_NOT_ENOUGH_MEMORY;
  434. goto exitParseCardDetails;
  435. }
  436. memset( (PCHAR) pEntry, '\0', sizeRequired );
  437. nextField = (PWCHAR)(PCHAR)(((PCHAR) pEntry) + sizeof( NETCARD_RESPONSE_DATABASE ));
  438. //
  439. // We hold the lock, so we don't need to reference all the
  440. // entries. Just start off the ref count at 1 for an entry
  441. // that is alive but not in use.
  442. //
  443. pEntry->ReferenceCount = 1;
  444. pEntry->InfFileName = nextField;
  445. CopyMemory( nextField, InfFileName, wcslen( InfFileName ) * sizeof(WCHAR));
  446. pEntry->SectionName = deviceSection;
  447. deviceSection = NULL;
  448. pEntry->HardwareId = deviceHw;
  449. deviceHw = NULL;
  450. InitializeListHead( &pEntry->FileCopyList );
  451. pEntry->DriverDescription = deviceName;
  452. deviceName = NULL;
  453. InitializeListHead( &pEntry->Registry );
  454. //
  455. // There's a few more fields we need to fill in before we're done with
  456. // this entry. We need to get :
  457. // DriverName "e100bnt.sys"
  458. // SectionNameExt "F1100C.ndi.ntx86"
  459. // ServiceName "E100B"
  460. // Registry Additions REG_MULTI_SZ
  461. //
  462. //
  463. // determine SectionNameExt by first trying to tack on ".ntx86", if that
  464. // doesn't work, try tacking on ".nt". If that doesn't work, there aren't
  465. // any extensions.
  466. //
  467. err = GetExtendedSectionName( pNetCards,
  468. InfHandle,
  469. InfFileName,
  470. pEntry );
  471. if (err != ERROR_SUCCESS) {
  472. BinlPrintDbg(( DEBUG_NETINF, "failed to get extended section for %S\n", deviceHw ));
  473. goto exitParseCardDetails;
  474. }
  475. err = GetServiceAndDriver( pNetCards,
  476. InfHandle,
  477. InfFileName,
  478. pEntry );
  479. if (err != ERROR_SUCCESS) {
  480. goto exitParseCardDetails;
  481. }
  482. //
  483. // this gets both the CopyFiles and the misc registry settings.
  484. //
  485. err = GetRegistryParametersForDriver( pNetCards,
  486. InfHandle,
  487. InfFileName,
  488. pEntry );
  489. if (err != ERROR_SUCCESS) {
  490. goto exitParseCardDetails;
  491. }
  492. //
  493. // Either pInfEntry is NULL, in which case listEntry is equal
  494. // to the head of the list, or it's not NULL, in which case
  495. // listEntry is equal to that entries listEntry. In either
  496. // case, we can simply insert this new entry onto the tail
  497. // of listEntry.
  498. //
  499. InsertTailList( listEntry, &pEntry->NetCardEntry );
  500. exitParseCardDetails:
  501. if (err != ERROR_SUCCESS && err != ERROR_NOT_SUPPORTED) {
  502. PWCHAR strings[3];
  503. strings[0] = InfFileName;
  504. strings[1] = sectionToLog;
  505. strings[2] = NULL;
  506. BinlReportEventW( ERROR_BINL_ERR_IN_SECTION,
  507. EVENTLOG_WARNING_TYPE,
  508. (sectionToLog == NULL) ? 1 : 2,
  509. sizeof(ULONG),
  510. strings,
  511. &err
  512. );
  513. }
  514. //
  515. // free anything that didn't get used
  516. //
  517. if (deviceName) {
  518. BinlFreeMemory(deviceName);
  519. }
  520. if (deviceSection) {
  521. BinlFreeMemory(deviceSection);
  522. }
  523. if (deviceHw) {
  524. BinlFreeMemory(deviceHw);
  525. }
  526. if (pEntry != NULL && err != ERROR_SUCCESS) {
  527. NetInfDereferenceNetcardEntry( pEntry );
  528. }
  529. return err;
  530. }
  531. ULONG
  532. GetExtendedSectionName (
  533. PNETCARD_INF_BLOCK pNetCards,
  534. HINF InfHandle,
  535. PWCHAR InfFileName,
  536. PNETCARD_RESPONSE_DATABASE pEntry
  537. )
  538. /*++
  539. Routine Description:
  540. This function uses the SetupXxxx APIs to process an INF file for a given
  541. driver instance. We parse the inf file for the extended section name
  542. for the specified platform (x86, alpha, ia64, etc).
  543. Arguments:
  544. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  545. the persistant info required for the netcards.
  546. InfHandle - handle open to INF file, guarenteed to be net driver
  547. InfFileName - wide form of relative file name we have open.
  548. pEntry - entry for which to get section names, base section name present
  549. Return Value:
  550. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  551. --*/
  552. {
  553. ULONG err;
  554. PWCHAR extSectionName;
  555. ULONG sizeRequired;
  556. INFCONTEXT context;
  557. PWCHAR architecture;
  558. // allocate space for the longest name we need, we'll shorten it later.
  559. switch(pNetCards->Architecture) {
  560. #if 0
  561. // obsolete architectures.
  562. case PROCESSOR_ARCHITECTURE_ALPHA;
  563. architecture = L"alpha";
  564. break;
  565. case PROCESSOR_ARCHITECTURE_ALPHA64:
  566. architecture = L"axp64";
  567. break;
  568. case PROCESSOR_ARCHITECTURE_MIPS:
  569. architecture = L"mips";
  570. break;
  571. case PROCESSOR_ARCHITECTURE_PPC:
  572. architecture = L"ppc";
  573. break;
  574. #endif
  575. case PROCESSOR_ARCHITECTURE_AMD64:
  576. architecture = L"amd64";
  577. break;
  578. case PROCESSOR_ARCHITECTURE_IA64:
  579. architecture = L"ia64";
  580. break;
  581. case PROCESSOR_ARCHITECTURE_INTEL:
  582. default:
  583. architecture = L"x86";
  584. break;
  585. }
  586. sizeRequired = wcslen( pEntry->SectionName ) +
  587. wcslen( architecture ) +
  588. sizeof( ".nt" ); // sizeof contains the '\0'
  589. extSectionName = (PWCHAR) BinlAllocateMemory( sizeRequired * sizeof(WCHAR) );
  590. if (extSectionName == NULL) {
  591. BinlPrintDbg(( DEBUG_NETINF, "failed to allocate ext section buffer for %S\n", pEntry->HardwareId ));
  592. return ERROR_NOT_ENOUGH_MEMORY;
  593. }
  594. //
  595. // first try to find the .ntx86 form.
  596. //
  597. wsprintf(
  598. extSectionName,
  599. L"%ws.nt%ws",
  600. pEntry->SectionName,
  601. architecture);
  602. if (SetupFindFirstLineW(InfHandle,
  603. extSectionName,
  604. NULL,
  605. &context) == TRUE) {
  606. pEntry->SectionNameExt = extSectionName;
  607. return ERROR_SUCCESS;
  608. }
  609. //
  610. // next try to find the .nt form.
  611. //
  612. wsprintf( extSectionName, L"%ws.nt",pEntry->SectionName );
  613. if (SetupFindFirstLineW(InfHandle,
  614. extSectionName,
  615. NULL,
  616. &context) == TRUE) {
  617. pEntry->SectionNameExt = extSectionName;
  618. return ERROR_SUCCESS;
  619. }
  620. BinlFreeMemory( extSectionName );
  621. pEntry->SectionNameExt = pEntry->SectionName;
  622. return ERROR_SUCCESS;
  623. }
  624. ULONG
  625. GetServiceAndDriver (
  626. PNETCARD_INF_BLOCK pNetCards,
  627. HINF InfHandle,
  628. PWCHAR InfFileName,
  629. PNETCARD_RESPONSE_DATABASE pEntry
  630. )
  631. /*++
  632. Routine Description:
  633. This function uses the SetupXxxx APIs to process an INF file for a given
  634. driver instance. We parse the inf file for the service name and driver
  635. name for each platform we support (x86 and alpha).
  636. Arguments:
  637. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  638. the persistant info required for the netcards.
  639. InfHandle - handle open to INF file, guarenteed to be net driver
  640. InfFileName - wide form of relative file name we have open.
  641. pEntry - entry for which to get section names, ext section name present
  642. Return Value:
  643. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  644. --*/
  645. {
  646. ULONG err = ERROR_SUCCESS;
  647. PWCHAR servSectionName = NULL;
  648. ULONG sizeRequired;
  649. INFCONTEXT context;
  650. LONG lineCount;
  651. PWCHAR serviceString = NULL;
  652. PWCHAR driverFullName = NULL;
  653. PWCHAR driverName;
  654. PWCHAR postSlash;
  655. // allocate space for the longest name we need, we'll shorten it later.
  656. sizeRequired = wcslen( pEntry->SectionNameExt ) + (sizeof(L".Services")/sizeof(WCHAR)); //sizeof contains the '\0'
  657. servSectionName = (PWCHAR) BinlAllocateMemory( sizeRequired * sizeof(WCHAR) );
  658. if (servSectionName == NULL) {
  659. err = ERROR_NOT_ENOUGH_MEMORY;
  660. BinlPrintDbg(( DEBUG_NETINF, "failed to alloc service section for %S\n", pEntry->HardwareId ));
  661. goto exitGetService;
  662. }
  663. wsprintf( servSectionName, L"%ws.Services", pEntry->SectionNameExt);
  664. lineCount = SetupGetLineCountW( InfHandle, servSectionName);
  665. if ((lineCount == 0 || lineCount == -1) &&
  666. (pEntry->SectionNameExt != pEntry->SectionName)) {
  667. //
  668. // hmm.. the service section wasn't there. for grins, try the
  669. // base service name.
  670. //
  671. BinlAssert( wcslen(pEntry->SectionName) <= wcslen(pEntry->SectionNameExt));
  672. wsprintf( servSectionName, L"%ws.Services", pEntry->SectionName);
  673. lineCount = SetupGetLineCountW( InfHandle, servSectionName);
  674. }
  675. if (lineCount == 0 || lineCount == -1) {
  676. err = GetLastError();
  677. if (err == ERROR_SUCCESS) {
  678. err = ERROR_NOT_SUPPORTED;
  679. }
  680. BinlPrintDbg(( DEBUG_NETINF, "failed to find service section for %S in %S\n",
  681. pEntry->HardwareId, InfFileName ));
  682. goto exitGetService;
  683. }
  684. if (SetupFindFirstLineW( InfHandle,
  685. servSectionName,
  686. L"AddService",
  687. &context ) == FALSE) {
  688. err = GetLastError();
  689. BinlPrintDbg(( DEBUG_NETINF, "failed to find AddService value for %S\n", pEntry->HardwareId ));
  690. goto exitGetService;
  691. }
  692. err = GetSetupWideTextField(&context,
  693. 1,
  694. &pEntry->ServiceName, // "E100B"
  695. NULL );
  696. if (err != ERROR_SUCCESS) {
  697. BinlPrintDbg(( DEBUG_NETINF, "failed to find service name for %S\n", pEntry->HardwareId ));
  698. goto exitGetService;
  699. }
  700. err = GetSetupWideTextField(&context,
  701. 3,
  702. &serviceString, // "e100b.Service"
  703. NULL );
  704. if (err != ERROR_SUCCESS) {
  705. BinlPrintDbg(( DEBUG_NETINF, "failed to find service install section for %S\n", pEntry->HardwareId ));
  706. goto exitGetService;
  707. }
  708. //
  709. // go get the driver name from the service section
  710. //
  711. err = GetSetupLineWideText( NULL,
  712. InfHandle,
  713. serviceString,
  714. L"ServiceBinary",
  715. &driverFullName,
  716. NULL );
  717. if (err != ERROR_SUCCESS) {
  718. BinlPrintDbg(( DEBUG_NETINF, "failed to find driver binary for %S\n", pEntry->HardwareId ));
  719. goto exitGetService;
  720. }
  721. //
  722. // The driver comes down as a fully qualified path. Let's strip off the
  723. // path and just store off the filename.
  724. //
  725. driverName = postSlash = driverFullName;
  726. while (*driverName != L'\0') {
  727. if (*driverName == OBJ_NAME_PATH_SEPARATOR) {
  728. postSlash = driverName + 1;
  729. }
  730. driverName++;
  731. }
  732. //
  733. // save off the root driver name into the entry
  734. //
  735. pEntry->DriverName = BinlStrDup( postSlash );
  736. if (pEntry->DriverName == NULL) {
  737. err = ERROR_NOT_ENOUGH_MEMORY;
  738. BinlPrintDbg(( DEBUG_NETINF, "failed to alloc memory for driver name for %S\n", pEntry->HardwareId ));
  739. goto exitGetService;
  740. }
  741. exitGetService:
  742. if ( driverFullName ) {
  743. BinlFreeMemory( driverFullName );
  744. }
  745. if ( serviceString ) {
  746. BinlFreeMemory( serviceString );
  747. }
  748. if ( servSectionName ) {
  749. BinlFreeMemory( servSectionName );
  750. }
  751. return err;
  752. }
  753. ULONG
  754. GetRegistryParametersForDriver (
  755. PNETCARD_INF_BLOCK pNetCards,
  756. HINF InfHandle,
  757. PWCHAR InfFileName,
  758. PNETCARD_RESPONSE_DATABASE pEntry
  759. )
  760. /*++
  761. Routine Description:
  762. This function uses the SetupXxxx APIs to process an INF file for a given
  763. driver instance. We parse the inf file for the registry parameters
  764. for each platform we support (x86 and alpha).
  765. We pass in values to update so that we can use the same code for both
  766. architectures.
  767. Arguments:
  768. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  769. the persistant info required for the netcards.
  770. InfHandle - handle open to INF file, guarenteed to be net driver
  771. InfFileName - wide form of relative file name we have open.
  772. pEntry - entry for which to get registry settings for
  773. Return Value:
  774. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  775. --*/
  776. {
  777. ULONG err = ERROR_SUCCESS;
  778. INFCONTEXT infContext;
  779. ULONG bufferLength;
  780. PWCHAR keyBuffer = NULL;
  781. ULONG keyBufferLength = 0;
  782. if (SetupFindFirstLineW( InfHandle,
  783. pEntry->SectionNameExt,
  784. NULL,
  785. &infContext) == FALSE) {
  786. err = GetLastError();
  787. BinlPrintDbg(( DEBUG_NETINF, "failed to find section name of %S in %S\n",
  788. pEntry->SectionNameExt, InfFileName ));
  789. goto exitGetRegistry;
  790. }
  791. //
  792. // process each line in the section by either storing it off if it's one
  793. // we don't recognize, ignoring it, or (for AddReg) process each value
  794. // as yet another section to process.
  795. //
  796. while (1) {
  797. //
  798. // process current line represented by infContext then go back for
  799. // another
  800. //
  801. err = GetSetupWideTextField(&infContext,
  802. 0,
  803. &keyBuffer,
  804. &keyBufferLength );
  805. if (err != ERROR_SUCCESS) {
  806. BinlPrintDbg(( DEBUG_NETINF, "failed to find service name for %S\n", pEntry->HardwareId ));
  807. goto exitGetRegistry;
  808. }
  809. if (CompareStringW( LOCALE_INVARIANT,
  810. NORM_IGNORECASE,
  811. keyBuffer,
  812. -1,
  813. L"CopyFiles",
  814. -1 ) == 2) {
  815. // for each value, read off the CopyFiles section
  816. ULONG limit, i;
  817. limit = SetupGetFieldCount( &infContext );
  818. for (i = 1; i <= limit; i++ ) {
  819. err = GetSetupWideTextField(&infContext,
  820. i,
  821. &keyBuffer,
  822. &keyBufferLength );
  823. if (err != ERROR_SUCCESS) {
  824. break;
  825. }
  826. if (*keyBuffer == L'\0') {
  827. goto getNextCopySubsection;
  828. }
  829. err = ProcessCopyFilesSubsection( pNetCards,
  830. InfHandle,
  831. InfFileName,
  832. pEntry,
  833. keyBuffer );
  834. if (err != ERROR_SUCCESS) {
  835. #ifdef NET_INF_VERBOSE
  836. BinlPrintDbg(( DEBUG_NETINF, "failed with 0x%x in section name of %S in %S\n",
  837. err, keyBuffer, InfFileName ));
  838. #endif
  839. break;
  840. }
  841. getNextCopySubsection:
  842. NOTHING;
  843. }
  844. //
  845. // we'll ignore errors during processing subsections for now, as
  846. // some sections are reported as not found.
  847. //
  848. if (err != ERROR_NOT_ENOUGH_MEMORY) {
  849. err = ERROR_SUCCESS;
  850. }
  851. } else if (CompareStringW( LOCALE_INVARIANT,
  852. NORM_IGNORECASE,
  853. keyBuffer,
  854. -1,
  855. L"AddReg",
  856. -1 ) == 2) {
  857. // for each value, read off the registry section
  858. ULONG limit, i;
  859. limit = SetupGetFieldCount( &infContext );
  860. for (i = 1; i <= limit; i++ ) {
  861. err = GetSetupWideTextField(&infContext,
  862. i,
  863. &keyBuffer,
  864. &keyBufferLength );
  865. if (err != ERROR_SUCCESS) {
  866. break;
  867. }
  868. if (*keyBuffer == L'\0') {
  869. goto getNextRegistrySubsection;
  870. }
  871. err = ProcessRegistrySubsection( pNetCards,
  872. InfHandle,
  873. InfFileName,
  874. pEntry,
  875. keyBuffer );
  876. if (err != ERROR_SUCCESS) {
  877. #ifdef NET_INF_VERBOSE
  878. BinlPrintDbg(( DEBUG_NETINF, "failed with 0x%x in section name of %S in %S\n",
  879. err, keyBuffer, InfFileName ));
  880. #endif
  881. break;
  882. }
  883. getNextRegistrySubsection:
  884. NOTHING;
  885. }
  886. //
  887. // we'll ignore errors during processing subsections for now, as
  888. // some sections are reported as not found.
  889. //
  890. if (err != ERROR_NOT_ENOUGH_MEMORY) {
  891. err = ERROR_SUCCESS;
  892. }
  893. } else {
  894. PWCHAR textLine = NULL;
  895. //
  896. // so far as we know, the only other ones are characteristics and
  897. // BusType. but there could certainly be others.
  898. //
  899. err = GetSetupLineWideText( &infContext,
  900. NULL,
  901. NULL,
  902. NULL,
  903. &textLine,
  904. NULL );
  905. if (err == ERROR_SUCCESS) {
  906. PNETCARD_REGISTRY_PARAMETERS regParam;
  907. regParam = (PNETCARD_REGISTRY_PARAMETERS) BinlAllocateMemory(
  908. sizeof(NETCARD_REGISTRY_PARAMETERS));
  909. if (regParam == NULL) {
  910. BinlFreeMemory( textLine );
  911. err = ERROR_NOT_ENOUGH_MEMORY;
  912. break;
  913. }
  914. RtlInitUnicodeString( &regParam->Parameter, keyBuffer );
  915. keyBuffer = NULL;
  916. keyBufferLength = 0;
  917. RtlInitUnicodeString( &regParam->Value, textLine );
  918. //
  919. // The only ones we know about are BusType, Characteristics,
  920. // and
  921. // BusType is an integer. Characteristics (and anything else
  922. // just to be safe) is a string.
  923. //
  924. if ((CompareStringW( LOCALE_INVARIANT,
  925. NORM_IGNORECASE,
  926. regParam->Parameter.Buffer,
  927. -1,
  928. L"Characteristics",
  929. -1) == 2) ||
  930. (CompareStringW( LOCALE_INVARIANT,
  931. NORM_IGNORECASE,
  932. regParam->Parameter.Buffer,
  933. -1,
  934. L"BusType",
  935. -1) == 2)) {
  936. ULONG tmpValue = 0;
  937. regParam->Type = NETCARD_REGISTRY_TYPE_INT;
  938. //
  939. // ensure the value is in decimal
  940. //
  941. err = RtlUnicodeStringToInteger( &regParam->Value, 0, &tmpValue );
  942. if (err == STATUS_SUCCESS) {
  943. PWCHAR valueBuffer;
  944. UNICODE_STRING decimalString;
  945. //
  946. // now that we have the value, convert it to decimal
  947. //
  948. valueBuffer = (PWCHAR) BinlAllocateMemory( 20 * sizeof(WCHAR) );
  949. if (valueBuffer == NULL) {
  950. BinlFreeMemory( textLine );
  951. BinlFreeMemory( regParam->Parameter.Buffer );
  952. BinlFreeMemory( regParam );
  953. err = ERROR_NOT_ENOUGH_MEMORY;
  954. goto exitGetRegistry;
  955. }
  956. decimalString.Buffer = valueBuffer;
  957. decimalString.Length = 0;
  958. decimalString.MaximumLength = 20 * sizeof(WCHAR);
  959. err = RtlIntegerToUnicodeString( tmpValue, 10, &decimalString );
  960. if ( err == STATUS_SUCCESS ) {
  961. //
  962. // if it succeeded, reset the value to the new
  963. // buffer, otherwise leave the old one in place.
  964. //
  965. BinlFreeMemory( textLine );
  966. RtlInitUnicodeString( &regParam->Value, valueBuffer );
  967. }
  968. }
  969. } else {
  970. regParam->Type = NETCARD_REGISTRY_TYPE_STRING;
  971. }
  972. InsertTailList( &pEntry->Registry, &regParam->RegistryListEntry );
  973. }
  974. }
  975. if (SetupFindNextLine( &infContext, &infContext ) == FALSE ) {
  976. break;
  977. }
  978. }
  979. err = ERROR_SUCCESS;
  980. exitGetRegistry:
  981. if ( keyBuffer ) {
  982. BinlFreeMemory( keyBuffer );
  983. }
  984. return err;
  985. }
  986. ULONG
  987. ProcessRegistrySubsection (
  988. PNETCARD_INF_BLOCK pNetCards,
  989. HINF InfHandle,
  990. PWCHAR InfFileName,
  991. PNETCARD_RESPONSE_DATABASE pEntry,
  992. PWCHAR SectionToParse
  993. )
  994. /*++
  995. Routine Description:
  996. This function uses the SetupXxxx APIs to process an INF file for a given
  997. driver instance. We parse the inf file for the registry section given.
  998. Note that this is a different format than the extended install section.
  999. Here's an example of the lines we parse :
  1000. HKR, Ndi\params\NumCoalesce, type, 0, "int"
  1001. HKR, , MsPciScan, 0, "2"
  1002. Note that we skip everything in the Ndi registry area.
  1003. Arguments:
  1004. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  1005. the persistant info required for the netcards.
  1006. InfHandle - handle open to INF file, guarenteed to be net driver
  1007. InfFileName - wide form of relative file name we have open.
  1008. pEntry - entry for which to get registry settings for
  1009. SectionToParse - what section in the INF do we start with
  1010. Return Value:
  1011. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  1012. --*/
  1013. {
  1014. ULONG err = ERROR_SUCCESS;
  1015. INFCONTEXT infContext;
  1016. ULONG bufferLength;
  1017. PWCHAR keyBuffer = NULL;
  1018. ULONG keyBufferLength = 0;
  1019. PWCHAR parameterBuffer = NULL;
  1020. PWCHAR valueBuffer;
  1021. if (SetupFindFirstLineW( InfHandle,
  1022. SectionToParse,
  1023. NULL,
  1024. &infContext) == FALSE) {
  1025. err = GetLastError();
  1026. BinlPrintDbg(( DEBUG_NETINF, "failed to find section name of %S in %S\n",
  1027. SectionToParse, InfFileName ));
  1028. goto exitGetRegistry;
  1029. }
  1030. //
  1031. // process each line in the section by either storing it off if it's one
  1032. // we don't recognize, ignoring it, or (for AddReg) process each value
  1033. // as yet another section to process.
  1034. //
  1035. while (1) {
  1036. //
  1037. // process current line represented by infContext then go back for
  1038. // another
  1039. //
  1040. err = GetSetupWideTextField(&infContext,
  1041. 1,
  1042. &keyBuffer,
  1043. &keyBufferLength );
  1044. if (err != ERROR_SUCCESS) {
  1045. BinlPrintDbg(( DEBUG_NETINF, "failed to find registry value in %S in %S\n", SectionToParse, InfFileName ));
  1046. goto OnToNextValue;
  1047. }
  1048. if (CompareStringW( LOCALE_INVARIANT,
  1049. NORM_IGNORECASE,
  1050. keyBuffer,
  1051. -1,
  1052. L"HKR",
  1053. -1 ) != 2) {
  1054. BinlPrintDbg(( DEBUG_NETINF, "got something other than HKR, %S for %S\n", keyBuffer, InfFileName ));
  1055. goto OnToNextValue;
  1056. }
  1057. err = GetSetupWideTextField(&infContext,
  1058. 2,
  1059. &keyBuffer,
  1060. &keyBufferLength );
  1061. if (err != ERROR_SUCCESS) {
  1062. BinlPrintDbg(( DEBUG_NETINF, "failed to get 2nd field in %S in %S\n", SectionToParse, InfFileName ));
  1063. goto OnToNextValue;
  1064. }
  1065. if (IsSubString( L"Ndi", keyBuffer, TRUE )) {
  1066. goto OnToNextValue;
  1067. }
  1068. //
  1069. // not part of the NDIS settings, we'll save this one off.
  1070. //
  1071. parameterBuffer = NULL;
  1072. err = GetSetupWideTextField(&infContext,
  1073. 3,
  1074. &parameterBuffer,
  1075. NULL );
  1076. if (err != ERROR_SUCCESS) {
  1077. BinlPrintDbg(( DEBUG_NETINF, "failed to get 3rd field in %S in %S\n", SectionToParse, InfFileName ));
  1078. goto OnToNextValue;
  1079. }
  1080. //
  1081. // check for empty parameter strings. there are some infs that
  1082. // contain empty parameter names
  1083. //
  1084. valueBuffer = parameterBuffer;
  1085. while (*valueBuffer == L' ') {
  1086. valueBuffer++;
  1087. }
  1088. if (*valueBuffer != L'\0') {
  1089. ULONG fieldFlags;
  1090. ULONG regType;
  1091. valueBuffer = NULL;
  1092. if (SetupGetIntField( &infContext, 4, &fieldFlags) == FALSE) {
  1093. err = GetLastError();
  1094. BinlPrintDbg(( DEBUG_NETINF, "failed to get 4th field in %S in %S\n", parameterBuffer, InfFileName ));
  1095. BinlFreeMemory( parameterBuffer );
  1096. goto OnToNextValue;
  1097. }
  1098. if ((fieldFlags & FLG_ADDREG_TYPE_MASK) == FLG_ADDREG_TYPE_SZ) {
  1099. //
  1100. // the value is a string.
  1101. //
  1102. err = GetSetupWideTextField(&infContext,
  1103. 5,
  1104. &valueBuffer,
  1105. NULL );
  1106. if (err != ERROR_SUCCESS) {
  1107. BinlPrintDbg(( DEBUG_NETINF, "failed to get 5th field in %S in %S\n", parameterBuffer, InfFileName ));
  1108. }
  1109. if (*valueBuffer == L'\0') {
  1110. #ifdef NET_INF_VERBOSE
  1111. BinlPrintDbg(( DEBUG_NETINF, "found empty value for %S in %S\n", parameterBuffer, InfFileName ));
  1112. #endif
  1113. BinlFreeMemory( valueBuffer );
  1114. BinlFreeMemory( parameterBuffer );
  1115. goto OnToNextValue;
  1116. }
  1117. regType = NETCARD_REGISTRY_TYPE_STRING;
  1118. } else if ((fieldFlags & FLG_ADDREG_TYPE_MASK) == FLG_ADDREG_TYPE_DWORD) {
  1119. ULONG intValue;
  1120. regType = NETCARD_REGISTRY_TYPE_INT;
  1121. //
  1122. // the value is a dword, let's grab it and store off it's
  1123. // string representation
  1124. //
  1125. if (SetupGetIntField( &infContext, 5, &intValue) == FALSE) {
  1126. err = GetLastError();
  1127. BinlPrintDbg(( DEBUG_NETINF, "failed to get value field in %S in %S\n", parameterBuffer, InfFileName ));
  1128. } else {
  1129. UNICODE_STRING valueString;
  1130. WCHAR resultBuffer[16];
  1131. valueString.Buffer = resultBuffer;
  1132. valueString.Length = 0;
  1133. valueString.MaximumLength = 16 * sizeof(WCHAR);
  1134. err = RtlIntegerToUnicodeString( intValue, 10, &valueString );
  1135. if (err == ERROR_SUCCESS) {
  1136. valueBuffer = BinlAllocateMemory( valueString.Length + sizeof(WCHAR) );
  1137. if (valueBuffer == NULL) {
  1138. BinlFreeMemory( parameterBuffer );
  1139. err = ERROR_NOT_ENOUGH_MEMORY;
  1140. break;
  1141. }
  1142. CopyMemory( valueBuffer, resultBuffer, valueString.Length );
  1143. }
  1144. }
  1145. } else {
  1146. BinlPrintDbg(( DEBUG_NETINF, "currently don't parse flags=0x%x in %S %S\n", fieldFlags, parameterBuffer, InfFileName ));
  1147. err = ERROR_NOT_SUPPORTED;
  1148. }
  1149. if (err == ERROR_SUCCESS) {
  1150. PNETCARD_REGISTRY_PARAMETERS regParam;
  1151. //
  1152. // we have a parameter name and an associated value to store
  1153. // off. let's allocate the list entry and store it on the list.
  1154. //
  1155. regParam = (PNETCARD_REGISTRY_PARAMETERS) BinlAllocateMemory(
  1156. sizeof(NETCARD_REGISTRY_PARAMETERS));
  1157. if (regParam == NULL) {
  1158. BinlFreeMemory( valueBuffer );
  1159. BinlFreeMemory( parameterBuffer );
  1160. err = ERROR_NOT_ENOUGH_MEMORY;
  1161. break;
  1162. }
  1163. regParam->Type = regType;
  1164. RtlInitUnicodeString( &regParam->Parameter, parameterBuffer );
  1165. parameterBuffer = NULL;
  1166. RtlInitUnicodeString( &regParam->Value, valueBuffer );
  1167. valueBuffer = NULL;
  1168. InsertTailList( &pEntry->Registry, &regParam->RegistryListEntry );
  1169. }
  1170. }
  1171. if (parameterBuffer) {
  1172. BinlFreeMemory( parameterBuffer );
  1173. }
  1174. OnToNextValue:
  1175. if (SetupFindNextLine( &infContext, &infContext ) == FALSE ) {
  1176. break;
  1177. }
  1178. }
  1179. err = ERROR_SUCCESS;
  1180. exitGetRegistry:
  1181. if ( keyBuffer ) {
  1182. BinlFreeMemory( keyBuffer );
  1183. }
  1184. return err;
  1185. }
  1186. ULONG
  1187. ProcessCopyFilesSubsection (
  1188. PNETCARD_INF_BLOCK pNetCards,
  1189. HINF InfHandle,
  1190. PWCHAR InfFileName,
  1191. PNETCARD_RESPONSE_DATABASE pEntry,
  1192. PWCHAR SectionToParse
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function uses the SetupXxxx APIs to process an INF file for a given
  1197. driver instance. We parse the inf file for the registry section given.
  1198. Note that this is a different format than the extended install section.
  1199. Here's an example of the lines we parse :
  1200. CopyFiles = @elnk90.sys
  1201. CopyFiles = e100b.CopyFiles
  1202. [e100b.CopyFiles]
  1203. e100bnt.sys,,,2
  1204. n100.sys,n100nt.sys,,2
  1205. Arguments:
  1206. pNetCards - A pointer to NETCARD_INF_BLOCK block allocated. Contains all
  1207. the persistant info required for the netcards.
  1208. InfHandle - handle open to INF file, guarenteed to be net driver
  1209. InfFileName - wide form of relative file name we have open.
  1210. pEntry - entry for which to get registry settings for
  1211. SectionToParse - what section in the INF do we start with
  1212. Return Value:
  1213. Windows Error. We stop processing altogether at ERROR_NOT_ENOUGH_MEMORY
  1214. --*/
  1215. {
  1216. PNETCARD_FILECOPY_PARAMETERS fileCopy;
  1217. ULONG err = ERROR_SUCCESS;
  1218. INFCONTEXT infContext;
  1219. PWCHAR sourceFileBuffer = NULL;
  1220. ULONG sourceFileBufferLength = 0;
  1221. PWCHAR destFileBuffer = NULL;
  1222. PWCHAR sourceFile;
  1223. ULONG destFileBufferLength = 0;
  1224. PWCHAR tempPtr;
  1225. if (*SectionToParse == L'@') {
  1226. if (CompareStringW( LOCALE_SYSTEM_DEFAULT,
  1227. NORM_IGNORECASE,
  1228. SectionToParse+1,
  1229. -1,
  1230. pEntry->DriverName,
  1231. -1 ) == 2) {
  1232. if (pNetCards->FileListCallbackFunction != NULL) {
  1233. err = (*pNetCards->FileListCallbackFunction)( pNetCards->FileListCallbackContext,
  1234. InfFileName,
  1235. pEntry->DriverName );
  1236. } else {
  1237. err = STATUS_SUCCESS;
  1238. }
  1239. BinlPrintDbg(( DEBUG_NETINF, "Ignoring driver file %S as we already know that.\n", SectionToParse ));
  1240. return err;
  1241. }
  1242. //
  1243. // the section name itself represents the file to copy
  1244. //
  1245. fileCopy = (PNETCARD_FILECOPY_PARAMETERS) BinlAllocateMemory(
  1246. sizeof(NETCARD_FILECOPY_PARAMETERS));
  1247. if (fileCopy == NULL) {
  1248. return ERROR_NOT_ENOUGH_MEMORY;
  1249. }
  1250. RtlInitUnicodeString( &fileCopy->DestFile, NULL );
  1251. fileCopy->SourceFile.Length = (USHORT)(wcslen( SectionToParse+1 ) * sizeof(WCHAR));
  1252. fileCopy->SourceFile.MaximumLength = fileCopy->SourceFile.Length + sizeof(WCHAR);
  1253. fileCopy->SourceFile.Buffer = (PWCHAR) BinlAllocateMemory( fileCopy->SourceFile.MaximumLength );
  1254. if (fileCopy->SourceFile.Buffer == NULL) {
  1255. BinlFreeMemory( fileCopy );
  1256. return ERROR_NOT_ENOUGH_MEMORY;
  1257. }
  1258. wcscpy( fileCopy->SourceFile.Buffer, SectionToParse+1 ); // skip @
  1259. if (pNetCards->FileListCallbackFunction != NULL) {
  1260. err = (*pNetCards->FileListCallbackFunction)( pNetCards->FileListCallbackContext,
  1261. InfFileName,
  1262. fileCopy->SourceFile.Buffer );
  1263. } else {
  1264. err = STATUS_SUCCESS;
  1265. }
  1266. InsertTailList( &pEntry->FileCopyList, &fileCopy->FileCopyListEntry );
  1267. return err;
  1268. }
  1269. if (SetupFindFirstLineW( InfHandle,
  1270. SectionToParse,
  1271. NULL,
  1272. &infContext) == FALSE) {
  1273. err = GetLastError();
  1274. BinlPrintDbg(( DEBUG_NETINF, "failed to find section name of %S in %S\n",
  1275. SectionToParse, InfFileName ));
  1276. goto exitGetRegistry;
  1277. }
  1278. //
  1279. // process each line in the section by storing it off
  1280. //
  1281. while (1) {
  1282. //
  1283. // process current line represented by infContext then go back for
  1284. // another
  1285. //
  1286. err = GetSetupWideTextField(&infContext,
  1287. 1,
  1288. &destFileBuffer,
  1289. &destFileBufferLength );
  1290. if (err != ERROR_SUCCESS) {
  1291. BinlPrintDbg(( DEBUG_NETINF, "failed to find registry value in %S in %S\n", SectionToParse, InfFileName ));
  1292. goto OnToNextValue;
  1293. }
  1294. if (CompareStringW( LOCALE_SYSTEM_DEFAULT,
  1295. NORM_IGNORECASE,
  1296. destFileBuffer,
  1297. -1,
  1298. pEntry->DriverName,
  1299. -1 ) == 2) {
  1300. if (pNetCards->FileListCallbackFunction != NULL) {
  1301. err = (*pNetCards->FileListCallbackFunction)( pNetCards->FileListCallbackContext,
  1302. InfFileName,
  1303. pEntry->DriverName );
  1304. if (err != ERROR_SUCCESS) {
  1305. goto exitGetRegistry;
  1306. }
  1307. }
  1308. BinlPrintDbg(( DEBUG_NETINF, "Ignoring driver file %S as we already know that.\n", sourceFileBuffer ));
  1309. goto OnToNextValue;
  1310. }
  1311. //
  1312. // ensure that there's a value there.
  1313. //
  1314. tempPtr = destFileBuffer;
  1315. while (*tempPtr == L' ') {
  1316. tempPtr++;
  1317. }
  1318. if (*tempPtr == L'\0') {
  1319. BinlPrintDbg(( DEBUG_NETINF, "Ignoring null file to copy in %S.\n", InfFileName ));
  1320. goto OnToNextValue;
  1321. }
  1322. fileCopy = (PNETCARD_FILECOPY_PARAMETERS) BinlAllocateMemory(
  1323. sizeof(NETCARD_FILECOPY_PARAMETERS));
  1324. if (fileCopy == NULL) {
  1325. err = ERROR_NOT_ENOUGH_MEMORY;
  1326. goto exitGetRegistry;
  1327. }
  1328. err = GetSetupWideTextField(&infContext,
  1329. 2,
  1330. &sourceFileBuffer,
  1331. &sourceFileBufferLength );
  1332. if (err != ERROR_SUCCESS) {
  1333. sourceFile = NULL;
  1334. } else {
  1335. tempPtr = sourceFileBuffer;
  1336. while (*tempPtr == L' ') {
  1337. tempPtr++;
  1338. }
  1339. if (*tempPtr == L'\0') {
  1340. sourceFile = NULL;
  1341. } else {
  1342. sourceFile = sourceFileBuffer;
  1343. sourceFileBuffer = NULL;
  1344. sourceFileBufferLength = 0;
  1345. }
  1346. }
  1347. err = ERROR_SUCCESS;
  1348. if (sourceFile == NULL) {
  1349. //
  1350. // if only the dest is given, only fill in the source since
  1351. // the client code is written that way already.
  1352. //
  1353. RtlInitUnicodeString( &fileCopy->DestFile, NULL );
  1354. RtlInitUnicodeString( &fileCopy->SourceFile, destFileBuffer );
  1355. if (pNetCards->FileListCallbackFunction != NULL) {
  1356. err = (*pNetCards->FileListCallbackFunction)( pNetCards->FileListCallbackContext,
  1357. InfFileName,
  1358. destFileBuffer );
  1359. }
  1360. } else {
  1361. RtlInitUnicodeString( &fileCopy->DestFile, destFileBuffer );
  1362. RtlInitUnicodeString( &fileCopy->SourceFile, sourceFile );
  1363. if (pNetCards->FileListCallbackFunction != NULL) {
  1364. err = (*pNetCards->FileListCallbackFunction)( pNetCards->FileListCallbackContext,
  1365. InfFileName,
  1366. sourceFile );
  1367. }
  1368. }
  1369. destFileBuffer = NULL;
  1370. destFileBufferLength = 0;
  1371. InsertTailList( &pEntry->FileCopyList, &fileCopy->FileCopyListEntry );
  1372. if (err != ERROR_SUCCESS) {
  1373. goto exitGetRegistry;
  1374. }
  1375. OnToNextValue:
  1376. if (SetupFindNextLine( &infContext, &infContext ) == FALSE ) {
  1377. break;
  1378. }
  1379. }
  1380. err = ERROR_SUCCESS;
  1381. exitGetRegistry:
  1382. if ( sourceFileBuffer ) {
  1383. BinlFreeMemory( sourceFileBuffer );
  1384. }
  1385. if ( destFileBuffer ) {
  1386. BinlFreeMemory( destFileBuffer );
  1387. }
  1388. return err;
  1389. }
  1390. // netinf.c eof