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

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