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.

1349 lines
31 KiB

  1. /*++
  2. Driver Match will parse a set of files, remember the list
  3. of drivers in each file, and print the drivers common to
  4. all the XML files.
  5. --*/
  6. #include <nt.h>
  7. #include <ntrtl.h>
  8. #include <nturtl.h>
  9. #include <windows.h>
  10. #include <stdio.h>
  11. #include <conio.h>
  12. #include <stdlib.h>
  13. #include <TCHAR.h>
  14. #include <diamondd.h>
  15. #include <lzexpand.h>
  16. #include <fcntl.h>
  17. #define OSVERSION_TAG L"<OSVER>"
  18. #define DRIVER_TAG L"<DRIVER>"
  19. #define FILENAME_TAG L"<FILENAME>"
  20. #define VERSION_TAG L"<VERSION>"
  21. #define MANUFACT_TAG L"<MANUFACTURER>"
  22. #define MICROSOFT_MANUFACTURER L"Microsoft Corporation"
  23. //
  24. // Info about a specific driver.
  25. //
  26. typedef struct _FILE_ENTRY {
  27. struct _FILE_ENTRY *Next;
  28. PTSTR FileName;
  29. struct _VERSION_ENTRY *VersionList;
  30. //PTSTR FileVersion;
  31. ULONG RefCount;
  32. } FILE_ENTRY, *PFILE_ENTRY;
  33. typedef struct _VERSION_ENTRY {
  34. struct _VERSION_ENTRY *Next;
  35. PFILE_ENTRY FileEntry;
  36. PTSTR FileVersion;
  37. ULONG RefCount;
  38. } VERSION_ENTRY, *PVERSION_ENTRY;
  39. PFILE_ENTRY MasterFileList = NULL;
  40. ULONG FilesProcessed = 0;
  41. BOOLEAN ExcludeMicrosoftDrivers = FALSE;
  42. //
  43. // Diamond stuff so we can crack .CAB files.
  44. //
  45. HFDI FdiContext;
  46. DWORD LastError;
  47. ERF FdiError;
  48. PVOID DecompBuffer = NULL;
  49. ULONG SizeOfFileInDecompressBuffer = 0;
  50. ULONG DecompressBufferSize;
  51. //
  52. // This is the value we return to diamond when it asks us to create
  53. // the target file.
  54. //
  55. #define DECOMP_MAGIC_HANDLE 0x87654
  56. //
  57. // Private malloc/free routines so we can track memory
  58. // if we ever want to.
  59. //
  60. VOID *MyMalloc( size_t Size )
  61. {
  62. PVOID ReturnPtr = NULL;
  63. ReturnPtr = malloc(Size);
  64. if( ReturnPtr ) {
  65. RtlZeroMemory( ReturnPtr, Size );
  66. }
  67. return ReturnPtr;
  68. }
  69. VOID MyFree( PVOID Ptr )
  70. {
  71. free( Ptr );
  72. }
  73. PSTR
  74. UnicodeStringToAnsiString(
  75. PWSTR StringW
  76. )
  77. {
  78. UNICODE_STRING UStr;
  79. ANSI_STRING AStr;
  80. ULONG AnsiLength,Index;
  81. RtlInitUnicodeString(&UStr, StringW);
  82. AnsiLength = RtlUnicodeStringToAnsiSize(&UStr);
  83. AStr.MaximumLength = (USHORT)AnsiLength;
  84. AStr.Length = (USHORT) AnsiLength - 1;
  85. AStr.Buffer = MyMalloc(AStr.MaximumLength);
  86. if (!AStr.Buffer) {
  87. return(NULL);
  88. }
  89. RtlUnicodeToMultiByteN( AStr.Buffer,
  90. AStr.Length,
  91. &Index,
  92. UStr.Buffer,
  93. UStr.Length
  94. );
  95. return(AStr.Buffer);
  96. }
  97. PVOID
  98. DIAMONDAPI
  99. SpdFdiAlloc(
  100. IN ULONG NumberOfBytes
  101. )
  102. /*++
  103. Routine Description:
  104. Callback used by FDICopy to allocate memory.
  105. Arguments:
  106. NumberOfBytes - supplies desired size of block.
  107. Return Value:
  108. Returns pointer to a block of memory or NULL
  109. if memory cannot be allocated.
  110. --*/
  111. {
  112. return(MyMalloc(NumberOfBytes));
  113. }
  114. VOID
  115. DIAMONDAPI
  116. SpdFdiFree(
  117. IN PVOID Block
  118. )
  119. /*++
  120. Routine Description:
  121. Callback used by FDICopy to free a memory block.
  122. The block must have been allocated with SpdFdiAlloc().
  123. Arguments:
  124. Block - supplies pointer to block of memory to be freed.
  125. Return Value:
  126. None.
  127. --*/
  128. {
  129. MyFree(Block);
  130. }
  131. INT_PTR
  132. DIAMONDAPI
  133. SpdFdiOpen(
  134. IN PSTR FileName,
  135. IN int oflag,
  136. IN int pmode
  137. )
  138. /*++
  139. Routine Description:
  140. Callback used by FDICopy to open files.
  141. This routine is capable only of opening existing files.
  142. When making changes here, also take note of other places
  143. that open the file directly (search for SpdFdiOpen)
  144. Arguments:
  145. FileName - supplies name of file to be opened.
  146. oflag - supplies flags for open.
  147. pmode - supplies additional flags for open.
  148. Return Value:
  149. Handle to open file or -1 if error occurs.
  150. --*/
  151. {
  152. HANDLE h;
  153. UNREFERENCED_PARAMETER(pmode);
  154. if(oflag & (_O_WRONLY | _O_RDWR | _O_APPEND | _O_CREAT | _O_TRUNC | _O_EXCL)) {
  155. LastError = ERROR_INVALID_PARAMETER;
  156. return(-1);
  157. }
  158. h = CreateFileA(FileName,
  159. GENERIC_READ,
  160. FILE_SHARE_READ,
  161. NULL,
  162. OPEN_EXISTING,
  163. 0,
  164. NULL);
  165. if(h == INVALID_HANDLE_VALUE) {
  166. LastError = GetLastError();
  167. return(-1);
  168. }
  169. return (INT_PTR)h;
  170. }
  171. UINT
  172. DIAMONDAPI
  173. SpdFdiRead(
  174. IN INT_PTR Handle,
  175. OUT PVOID pv,
  176. IN UINT ByteCount
  177. )
  178. /*++
  179. Routine Description:
  180. Callback used by FDICopy to read from a file.
  181. Arguments:
  182. Handle - supplies handle to open file to be read from.
  183. pv - supplies pointer to buffer to receive bytes we read.
  184. ByteCount - supplies number of bytes to read.
  185. Return Value:
  186. Number of bytes read or -1 if an error occurs.
  187. --*/
  188. {
  189. DWORD d;
  190. HANDLE hFile = (HANDLE)Handle;
  191. DWORD bytes;
  192. UINT rc;
  193. if (Handle == DECOMP_MAGIC_HANDLE) {
  194. return(-1);
  195. }
  196. if(ReadFile(hFile,pv,(DWORD)ByteCount,&bytes,NULL)) {
  197. rc = (UINT)bytes;
  198. } else {
  199. d = GetLastError();
  200. rc = (UINT)(-1);
  201. LastError = d;
  202. }
  203. return rc;
  204. }
  205. UINT
  206. DIAMONDAPI
  207. SpdFdiWrite(
  208. IN INT_PTR Handle,
  209. IN PVOID pv,
  210. IN UINT ByteCount
  211. )
  212. /*++
  213. Routine Description:
  214. Callback used by FDICopy to write to a file.
  215. Arguments:
  216. Handle - supplies handle to open file to be written to.
  217. pv - supplies pointer to buffer containing bytes to write.
  218. ByteCount - supplies number of bytes to write.
  219. Return Value:
  220. Number of bytes written (ByteCount) or -1 if an error occurs.
  221. --*/
  222. {
  223. if (Handle != DECOMP_MAGIC_HANDLE) {
  224. return(-1);
  225. }
  226. //
  227. // Check for overflow.
  228. //
  229. if(SizeOfFileInDecompressBuffer+ByteCount > DecompressBufferSize) {
  230. return((UINT)(-1));
  231. }
  232. RtlCopyMemory(
  233. (PCHAR)DecompBuffer + SizeOfFileInDecompressBuffer,
  234. pv,
  235. ByteCount
  236. );
  237. SizeOfFileInDecompressBuffer += ByteCount;
  238. return(ByteCount);
  239. }
  240. int
  241. DIAMONDAPI
  242. SpdFdiClose(
  243. IN INT_PTR Handle
  244. )
  245. /*++
  246. Routine Description:
  247. Callback used by FDICopy to close files.
  248. Arguments:
  249. Handle - handle of file to close.
  250. Return Value:
  251. 0 (success).
  252. --*/
  253. {
  254. BOOL success = FALSE;
  255. if (Handle != DECOMP_MAGIC_HANDLE) {
  256. CloseHandle((HANDLE)Handle);
  257. }
  258. //
  259. // Always act like we succeeded.
  260. //
  261. return 0;
  262. }
  263. long
  264. DIAMONDAPI
  265. SpdFdiSeek(
  266. IN INT_PTR Handle,
  267. IN long Distance,
  268. IN int SeekType
  269. )
  270. /*++
  271. Routine Description:
  272. Callback used by FDICopy to seek files.
  273. Arguments:
  274. Handle - handle of file to close.
  275. Distance - supplies distance to seek. Interpretation of this
  276. parameter depends on the value of SeekType.
  277. SeekType - supplies a value indicating how Distance is to be
  278. interpreted; one of SEEK_SET, SEEK_CUR, SEEK_END.
  279. Return Value:
  280. New file offset or -1 if an error occurs.
  281. --*/
  282. {
  283. LONG rc;
  284. DWORD d;
  285. HANDLE hFile = (HANDLE)Handle;
  286. DWORD pos_low;
  287. DWORD method;
  288. if (Handle == DECOMP_MAGIC_HANDLE) {
  289. return(-1);
  290. }
  291. switch(SeekType) {
  292. case SEEK_SET:
  293. method = FILE_BEGIN;
  294. break;
  295. case SEEK_CUR:
  296. method = FILE_CURRENT;
  297. break;
  298. case SEEK_END:
  299. method = FILE_END;
  300. break;
  301. default:
  302. return -1;
  303. }
  304. pos_low = SetFilePointer(hFile,(DWORD)Distance,NULL,method);
  305. if(pos_low == INVALID_SET_FILE_POINTER) {
  306. d = GetLastError();
  307. rc = -1L;
  308. LastError = d;
  309. } else {
  310. rc = (long)pos_low;
  311. }
  312. return(rc);
  313. }
  314. BOOL
  315. DiamondInitialize(
  316. VOID
  317. )
  318. /*++
  319. Routine Description:
  320. Per-thread initialization routine for Diamond.
  321. Called once per thread.
  322. Arguments:
  323. None.
  324. Return Value:
  325. Boolean result indicating success or failure.
  326. Failure can be assumed to be out of memory.
  327. --*/
  328. {
  329. BOOL retval = FALSE;
  330. try {
  331. //
  332. // Initialize a diamond context.
  333. //
  334. FdiContext = FDICreate(
  335. SpdFdiAlloc,
  336. SpdFdiFree,
  337. SpdFdiOpen,
  338. SpdFdiRead,
  339. SpdFdiWrite,
  340. SpdFdiClose,
  341. SpdFdiSeek,
  342. cpuUNKNOWN,
  343. &FdiError
  344. );
  345. if(FdiContext) {
  346. retval = TRUE;
  347. }
  348. } except(EXCEPTION_EXECUTE_HANDLER) {
  349. retval = FALSE;
  350. }
  351. return(retval);
  352. }
  353. VOID
  354. DiamondTerminate(
  355. VOID
  356. )
  357. /*++
  358. Routine Description:
  359. Per-thread termination routine for Diamond.
  360. Called internally.
  361. Arguments:
  362. None.
  363. Return Value:
  364. Boolean result indicating success or failure.
  365. Failure can be assumed to be out of memory.
  366. --*/
  367. {
  368. FDIDestroy(FdiContext);
  369. FdiContext = NULL;
  370. }
  371. INT_PTR
  372. DIAMONDAPI
  373. NotifyFunction(
  374. FDINOTIFICATIONTYPE fdint,
  375. PFDINOTIFICATION pfdin)
  376. {
  377. switch(fdint) {
  378. case fdintCOPY_FILE:
  379. if (_strcmpi(pfdin->psz1,"sysdata.xml") == 0) {
  380. DecompressBufferSize = pfdin->cb+2;
  381. DecompBuffer = MyMalloc(DecompressBufferSize);
  382. if (!DecompBuffer) {
  383. return(-1);
  384. }
  385. SizeOfFileInDecompressBuffer = 0;
  386. return(DECOMP_MAGIC_HANDLE);
  387. }
  388. return(0);
  389. break;
  390. case fdintCLOSE_FILE_INFO:
  391. if (pfdin->hf == DECOMP_MAGIC_HANDLE) {
  392. return(TRUE);
  393. }
  394. return(FALSE);
  395. break;
  396. default:
  397. return(0);
  398. }
  399. return(0);
  400. }
  401. BOOL
  402. DiamondExtractFileIntoBuffer(
  403. PTSTR DirectoryName,
  404. PTSTR FileName,
  405. PVOID *Buffer,
  406. PDWORD FileSize
  407. )
  408. {
  409. HANDLE h;
  410. PSTR FileNameA;
  411. PSTR DirectoryNameA;
  412. CHAR File[MAX_PATH];
  413. ULONG i;
  414. #ifdef UNICODE
  415. FileNameA = UnicodeStringToAnsiString(FileName);
  416. DirectoryNameA = UnicodeStringToAnsiString(DirectoryName);
  417. #else
  418. DirectoryNameA = DirectoryName;
  419. FileNameA = FileName;
  420. #endif
  421. strcpy(File, DirectoryNameA);
  422. i = strlen(File);
  423. if (File[i-1] != '\\') {
  424. File[i] = '\\';
  425. File[i+1] = '\0';
  426. }
  427. strcat(File, FileNameA);
  428. h = (HANDLE)SpdFdiOpen(File, 0, 0);
  429. if (h == INVALID_HANDLE_VALUE) {
  430. return(FALSE);
  431. }
  432. SpdFdiSeek( (INT_PTR)h, 0, SEEK_SET );
  433. DecompBuffer = NULL;
  434. LastError = ERROR_SUCCESS;
  435. #if 0
  436. GetCurrentDirectoryA(MAX_PATH,Dir);
  437. i = strlen(Dir);
  438. Dir[i] = '\\';
  439. Dir[i+1] = '\0';
  440. #endif
  441. if (!FDICopy(FdiContext,
  442. FileNameA,
  443. DirectoryNameA,// Dir,//FileNameA,
  444. 0,
  445. NotifyFunction,
  446. NULL,
  447. Buffer)) {
  448. return(FALSE);
  449. }
  450. SpdFdiClose((INT_PTR)h);
  451. #ifdef UNICODE
  452. MyFree(FileNameA);
  453. MyFree(DirectoryNameA);
  454. #endif
  455. if (LastError == ERROR_SUCCESS) {
  456. if (DecompBuffer) {
  457. *Buffer = DecompBuffer;
  458. *FileSize = DecompressBufferSize;
  459. return(TRUE);
  460. } else {
  461. return(FALSE);
  462. }
  463. } else {
  464. return(FALSE);
  465. }
  466. }
  467. void
  468. Usage( char *AppName )
  469. {
  470. if (AppName == NULL) {
  471. return;
  472. }
  473. printf( "\n\n" );
  474. printf( "Usage: %s [-m] <filename>\n", AppName );
  475. printf( " Searchs the given XML files for all the drivers and\n" );
  476. printf( " collates a list of drivers common to all the files.\n" );
  477. printf( "\n" );
  478. printf( " -m (OPTIONAL) Exclude drivers manufactured by Microsoft Corporation.\n" );
  479. printf( "\n" );
  480. printf( " <filename> May contain wildcards. Search this file(s) for drivers.\n" );
  481. printf( "\n" );
  482. printf( " EXAMPLE:\n" );
  483. printf( " %s -m sysdata*.xml\n", AppName );
  484. printf( "\n" );
  485. printf( " This would examine every file which matches the pattern 'sysdata*.xml'\n" );
  486. printf( " and build a list of non-Microsoft drivers which are common to all the files.\n" );
  487. printf( "\n\n" );
  488. }
  489. BOOL
  490. AddDriverEntry(
  491. PWSTR DriverName,
  492. PWSTR DriverVersion
  493. )
  494. /*++
  495. Routine Description:
  496. Insert a driver entry into the MasterFileList. Note that it should be inserted in
  497. ascending order with respect to the FileName.
  498. Arguments:
  499. DriverName Name of the specified driver.
  500. DriverVersion String containing the version of the specified driver.
  501. Return Value:
  502. --*/
  503. {
  504. PFILE_ENTRY LastEntry = NULL;
  505. PFILE_ENTRY ThisEntry = NULL;
  506. PVERSION_ENTRY ThisVEntry = NULL;
  507. PVERSION_ENTRY LastVEntry = NULL;
  508. if( DriverName == NULL ) {
  509. //printf( "AddDriverEntry: Bad incoming parameter\n" );
  510. return(FALSE);
  511. }
  512. //printf( "AddDriverEntry Enter: Adding filename %S\n", DriverName );
  513. if( MasterFileList == NULL ) {
  514. //
  515. // First entry for the machine.
  516. //
  517. //printf( " Adding the very first entry.\n" );
  518. MasterFileList = MyMalloc(sizeof(FILE_ENTRY));
  519. if (!MasterFileList) {
  520. return(FALSE);
  521. }
  522. ThisVEntry = MyMalloc(sizeof(VERSION_ENTRY));
  523. if (!ThisVEntry) {
  524. MyFree(MasterFileList);
  525. MasterFileList = NULL;
  526. return(FALSE);
  527. }
  528. MasterFileList->FileName = DriverName;
  529. MasterFileList->VersionList = ThisVEntry;
  530. MasterFileList->Next = NULL;
  531. MasterFileList->RefCount = 1;
  532. ThisVEntry->FileEntry = MasterFileList;
  533. ThisVEntry->RefCount = 1;
  534. ThisVEntry->FileVersion = DriverVersion;
  535. ThisVEntry->Next = NULL;
  536. return(TRUE);
  537. }
  538. LastEntry = MasterFileList;
  539. ThisEntry = MasterFileList;
  540. //
  541. // Find a spot to add this driver into our list.
  542. //
  543. while( ThisEntry &&
  544. (_wcsicmp(ThisEntry->FileName, DriverName) < 0)) {
  545. //printf( " Checking against filename %S\n", ThisEntry->FileName );
  546. LastEntry = ThisEntry;
  547. ThisEntry = ThisEntry->Next;
  548. }
  549. //
  550. // Handle all the cases that would make use break out of the above loop.
  551. //
  552. if( ThisEntry == NULL ) {
  553. //
  554. // insert at the tail.
  555. //
  556. //printf( " Inserting at the tail of our list.\n" );
  557. LastEntry->Next = MyMalloc(sizeof(FILE_ENTRY));
  558. if (!LastEntry->Next) {
  559. return(FALSE);
  560. }
  561. LastEntry->Next->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
  562. if (!LastEntry->Next->VersionList) {
  563. MyFree(LastEntry->Next);
  564. LastEntry->Next = NULL;
  565. return(FALSE);
  566. }
  567. ThisEntry = LastEntry->Next;
  568. ThisEntry->FileName = DriverName;
  569. ThisEntry->RefCount = 1;
  570. ThisEntry->Next = NULL;
  571. ThisEntry->VersionList->FileVersion = DriverVersion;
  572. ThisEntry->VersionList->FileEntry = ThisEntry;
  573. ThisEntry->VersionList->Next = NULL;
  574. ThisEntry->VersionList->RefCount = 1;
  575. return(TRUE);
  576. }
  577. if( !_wcsicmp(ThisEntry->FileName, DriverName)) {
  578. //printf( " Found a duplicate drivername!\n" );
  579. ThisEntry->RefCount++;
  580. LastVEntry = ThisEntry->VersionList;
  581. ThisVEntry = ThisEntry->VersionList;
  582. //
  583. // Find a spot to add this driver into our list.
  584. //
  585. while( ThisVEntry &&
  586. (_wcsicmp(ThisVEntry->FileVersion, DriverVersion) < 0)) {
  587. //printf( " Checking against version %S\n", ThisVEntry->FileVersion );
  588. LastVEntry = ThisVEntry;
  589. ThisVEntry = ThisVEntry->Next;
  590. }
  591. if (!ThisVEntry) {
  592. //printf( " Inserting version at the tail of our list.\n" );
  593. LastVEntry->Next = MyMalloc(sizeof(VERSION_ENTRY));
  594. if (!LastVEntry->Next) {
  595. MyFree(LastVEntry->Next);
  596. LastVEntry->Next = NULL;
  597. return(FALSE);
  598. }
  599. ThisVEntry = LastVEntry->Next;
  600. ThisVEntry->FileVersion = DriverVersion;
  601. ThisVEntry->FileEntry = ThisEntry;
  602. ThisVEntry->Next = NULL;
  603. ThisVEntry->RefCount = 1;
  604. return(TRUE);
  605. }
  606. if (!_wcsicmp(ThisVEntry->FileVersion, DriverVersion)) {
  607. ThisVEntry->RefCount++;
  608. return(TRUE);
  609. }
  610. if (LastVEntry == ThisVEntry) {
  611. //
  612. // Put it at the very head of the list
  613. //
  614. //printf( " Inserting version at the head of our list.\n" );
  615. ThisVEntry = ThisEntry->VersionList;
  616. ThisEntry->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
  617. if (!ThisEntry->VersionList) {
  618. ThisEntry->VersionList = ThisVEntry;
  619. return(FALSE);
  620. }
  621. ThisEntry->VersionList->FileVersion = DriverVersion;
  622. ThisEntry->VersionList->FileEntry = ThisEntry;
  623. ThisEntry->VersionList->Next = LastVEntry;
  624. ThisEntry->VersionList->RefCount = 1;
  625. return(TRUE);
  626. }
  627. //
  628. // insert between LastEntry and ThisEntry
  629. //
  630. LastVEntry->Next = MyMalloc(sizeof(VERSION_ENTRY));
  631. if (!LastVEntry->Next) {
  632. LastVEntry->Next = ThisVEntry;
  633. return(FALSE);
  634. }
  635. LastVEntry->Next->FileVersion = DriverVersion;
  636. LastVEntry->Next->FileEntry = LastEntry->Next;
  637. LastVEntry->Next->RefCount = 1;
  638. LastVEntry->Next->Next = ThisVEntry;
  639. return(TRUE);
  640. }
  641. if( LastEntry == ThisEntry ) {
  642. //
  643. // Put it at the very head of the list
  644. //
  645. //printf( " Inserting at the head of our list.\n" );
  646. ThisEntry = MasterFileList;
  647. MasterFileList = MyMalloc(sizeof(FILE_ENTRY));
  648. if (!MasterFileList) {
  649. MasterFileList = ThisEntry;
  650. return(FALSE);
  651. }
  652. MasterFileList->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
  653. if (!MasterFileList->VersionList) {
  654. MyFree(MasterFileList);
  655. MasterFileList = ThisEntry;
  656. return(FALSE);
  657. }
  658. ThisEntry = LastEntry;
  659. MasterFileList->FileName = DriverName;
  660. MasterFileList->RefCount = 1;
  661. MasterFileList->Next = LastEntry;
  662. MasterFileList->VersionList->FileVersion = DriverVersion;
  663. MasterFileList->VersionList->FileEntry = MasterFileList;
  664. MasterFileList->VersionList->Next = NULL;
  665. MasterFileList->VersionList->RefCount = 1;
  666. } else {
  667. //
  668. // insert betwee LastEntry and ThisEntry
  669. //
  670. LastEntry->Next = MyMalloc(sizeof(FILE_ENTRY));
  671. if (!LastEntry->Next) {
  672. LastEntry->Next = ThisEntry;
  673. return(FALSE);
  674. }
  675. LastEntry->Next->VersionList = MyMalloc(sizeof(VERSION_ENTRY));
  676. if (!LastEntry->Next->VersionList) {
  677. MyFree(LastEntry->Next);
  678. LastEntry->Next = ThisEntry;
  679. return(FALSE);
  680. }
  681. LastEntry->Next->RefCount = 1;
  682. LastEntry->Next->Next = ThisEntry;
  683. LastEntry->Next->FileName = DriverName;
  684. LastEntry->Next->VersionList->FileVersion = DriverVersion;
  685. LastEntry->Next->VersionList->FileEntry = LastEntry->Next;
  686. LastEntry->Next->VersionList->Next = NULL;
  687. LastEntry->Next->VersionList->RefCount = 1;
  688. //printf( " LastEntry: %S DriverEntry: %S NextEntry: %S\n",LastEntry->FileName, DriverName, ThisEntry->FileName );
  689. }
  690. return(TRUE);
  691. }
  692. PWSTR
  693. ExtractAndDuplicateString(
  694. PWSTR BufferPointer
  695. )
  696. /*++
  697. Routine Description:
  698. Extract a file name from the given buffer, allocate memory and return
  699. a copy of the extracted string.
  700. Arguments:
  701. BufferPointer Pointer to a buffer which is assumed to be the start
  702. of a string. We continue to inspect the incoming
  703. buffer until we get to the start of an XML tag.
  704. At that point, assume the string is ending, copy the
  705. string into a secondary buffer and return that buffer.
  706. N.B. The caller is responsible for freeing the memory
  707. we've allocated!
  708. Return Value:
  709. Pointer to the allocated memory.
  710. NULL if we fail.
  711. --*/
  712. {
  713. PWSTR TmpPtr = NULL;
  714. PWSTR ReturnPtr = NULL;
  715. TmpPtr = BufferPointer;
  716. while( TmpPtr && (*TmpPtr) && (*TmpPtr != L'<') ) {
  717. TmpPtr++;
  718. }
  719. if( *TmpPtr == L'<' ) {
  720. ULONG SizeInBytes;
  721. SizeInBytes = ((TmpPtr - BufferPointer) + 1) * sizeof(WCHAR);
  722. ReturnPtr = MyMalloc( SizeInBytes );
  723. wcsncpy( ReturnPtr, BufferPointer, (TmpPtr - BufferPointer) );
  724. }
  725. return ReturnPtr;
  726. }
  727. BOOL
  728. ProcessFile(
  729. PTSTR DirectoryName,
  730. PTSTR FileName
  731. )
  732. /*++
  733. Routine Description:
  734. Parse through the given file (XML file) and remember all the
  735. driver files specified in it.
  736. Arguments:
  737. DirectoryName Directory file is present in.
  738. FileName Name of the file we'll parse.
  739. Return Value:
  740. TRUE - we successfully inserted the file into our list.
  741. FALSE - we failed.
  742. --*/
  743. {
  744. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  745. PUCHAR FileBuffer = NULL;
  746. ULONG i = 0;
  747. DWORD FileSize = 0;
  748. BOOLEAN b = FALSE;
  749. PWSTR MyPtr;
  750. PWSTR DriverName;
  751. PWSTR DriverVersion;
  752. PWSTR ManufacturerName;
  753. BOOL Status;
  754. if( !FileName ) {
  755. return FALSE;
  756. }
  757. _wcslwr( FileName );
  758. if( wcsstr(FileName,L".cab") ) {
  759. //
  760. // They've sent us a cab. Call special code to crack
  761. // the cab, and extract the xml file into our buffer.
  762. //
  763. if (!DiamondExtractFileIntoBuffer(DirectoryName, FileName, &FileBuffer,&FileSize)) {
  764. return(FALSE);
  765. }
  766. } else {
  767. FileHandle = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
  768. if( FileHandle == INVALID_HANDLE_VALUE) { return(FALSE); }
  769. FileSize = GetFileSize( FileHandle, NULL );
  770. if( FileSize == (DWORD)(-1) ) { return(FALSE); };
  771. FileBuffer = MyMalloc(FileSize + 3);
  772. if( FileBuffer == NULL ) {
  773. // printf( "No System resources!\n" );
  774. return(FALSE);
  775. }
  776. b = (BOOLEAN)ReadFile( FileHandle, FileBuffer, FileSize, &i, NULL );
  777. CloseHandle( FileHandle );
  778. }
  779. //
  780. // We've got the file up in memory (in FileBuffer), now parse it.
  781. //
  782. MyPtr = (PWSTR)FileBuffer;
  783. while( MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(DRIVER_TAG) * sizeof(WCHAR))) ) {
  784. // find the driver tag
  785. if( !_wcsnicmp((MyPtr), DRIVER_TAG, wcslen(DRIVER_TAG)) ) {
  786. // FileName tag.
  787. while( *MyPtr && (_wcsnicmp((MyPtr), FILENAME_TAG, wcslen(FILENAME_TAG))) ) {
  788. if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(FILENAME_TAG) * sizeof(WCHAR)))) {
  789. MyPtr++;
  790. } else {
  791. Status = FALSE;
  792. goto exit;
  793. }
  794. }
  795. MyPtr += wcslen(FILENAME_TAG);
  796. DriverName = ExtractAndDuplicateString( MyPtr );
  797. // printf( "Found Driver name %S\n", DriverName );
  798. // Driver Version
  799. while( *MyPtr && (_wcsnicmp((MyPtr), VERSION_TAG, wcslen(VERSION_TAG))) ) {
  800. if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(VERSION_TAG) * sizeof(WCHAR)))) {
  801. MyPtr++;
  802. } else {
  803. Status = FALSE;
  804. goto exit;
  805. }
  806. }
  807. MyPtr += wcslen(VERSION_TAG);
  808. DriverVersion = ExtractAndDuplicateString( MyPtr );
  809. // printf( " Version: %S\n", DriverVersion );
  810. // Manufacturer
  811. while( *MyPtr && (_wcsnicmp((MyPtr), MANUFACT_TAG, wcslen(MANUFACT_TAG))) ) {
  812. if (MyPtr < (PWSTR)(FileBuffer + FileSize - (wcslen(MANUFACT_TAG) * sizeof(WCHAR)))) {
  813. MyPtr++;
  814. } else {
  815. Status = FALSE;
  816. goto exit;
  817. }
  818. }
  819. MyPtr += wcslen(MANUFACT_TAG);
  820. ManufacturerName = ExtractAndDuplicateString( MyPtr );
  821. //printf( " Manufacturer name %S\n", ManufacturerName );
  822. if( ExcludeMicrosoftDrivers &&
  823. !_wcsicmp(ManufacturerName, MICROSOFT_MANUFACTURER) ) {
  824. // skip it.
  825. // printf( " Skipping Driver: %S\n", DriverName );
  826. if( DriverName ) {
  827. MyFree( DriverName );
  828. }
  829. if( DriverVersion ) {
  830. MyFree( DriverVersion );
  831. }
  832. } else {
  833. // printf( " Addinging Driver: %S\n", DriverName );
  834. AddDriverEntry( DriverName, DriverVersion );
  835. }
  836. MyFree( ManufacturerName );
  837. } else {
  838. if (MyPtr < (PWSTR)(FileBuffer + FileSize)) {
  839. MyPtr++;
  840. } else {
  841. Status = FALSE;
  842. goto exit;
  843. }
  844. }
  845. }
  846. Status = TRUE;
  847. exit:
  848. if( FileBuffer ) {
  849. MyFree( FileBuffer );
  850. }
  851. return(Status);
  852. }
  853. VOID
  854. PrintNode(
  855. PFILE_ENTRY Entry
  856. )
  857. {
  858. PVERSION_ENTRY V;
  859. _tprintf( TEXT("%d %s ("), Entry->RefCount, Entry->FileName);
  860. V = Entry->VersionList;
  861. while (V) {
  862. _tprintf( TEXT("%d %s %c"),
  863. V->RefCount,
  864. V->FileVersion,
  865. V->Next
  866. ? TEXT(',')
  867. : TEXT(')') );
  868. V = V->Next;
  869. }
  870. _tprintf( TEXT("\r\n"));
  871. }
  872. VOID
  873. DumpFileList(
  874. VOID
  875. )
  876. /*++
  877. Routine Description:
  878. Walk our list of files, printing out those which are found on all machines
  879. and those which are not.
  880. Arguments:
  881. NONE.
  882. Return Value:
  883. NONE.
  884. --*/
  885. {
  886. PFILE_ENTRY MyFileEntry;
  887. if( MasterFileList == NULL ) {
  888. return;
  889. }
  890. #if 0
  891. _tprintf( TEXT("\nThe following %sdrivers were NOT found in all machines.\n"),
  892. ExcludeMicrosoftDrivers
  893. ? TEXT("Non-Microsoft ")
  894. : TEXT("") );
  895. MyFileEntry = MasterFileList;
  896. while( MyFileEntry ) {
  897. if( MyFileEntry->RefCount != FilesProcessed ) {
  898. PrintNode(MyFileEntry);
  899. }
  900. MyFileEntry = MyFileEntry->Next;
  901. }
  902. _tprintf( TEXT("\nThe following %sdrivers were found in all machines.\n"),
  903. ExcludeMicrosoftDrivers
  904. ? TEXT("Non-Microsoft ")
  905. : TEXT("") );
  906. MyFileEntry = MasterFileList;
  907. while( MyFileEntry ) {
  908. if( MyFileEntry->RefCount == FilesProcessed ) {
  909. PrintNode(MyFileEntry);
  910. }
  911. MyFileEntry = MyFileEntry->Next;
  912. }
  913. #else
  914. MyFileEntry = MasterFileList;
  915. while( MyFileEntry ) {
  916. PrintNode(MyFileEntry);
  917. MyFileEntry = MyFileEntry->Next;
  918. }
  919. #endif
  920. }
  921. int
  922. __cdecl
  923. main( int argc, char *argv[])
  924. {
  925. WCHAR TmpDirectoryString[MAX_PATH];
  926. WCHAR TmpName[MAX_PATH];
  927. PWSTR p;
  928. HANDLE FindHandle;
  929. WIN32_FIND_DATA FoundData;
  930. DWORD i;
  931. #if 1
  932. HANDLE FileHandle;
  933. DWORD FileSize;
  934. PVOID FileBuffer;
  935. BOOL b;
  936. PSTR DirectoryName,FileName,Ptr,Ptr2;
  937. CHAR OldChar;
  938. WCHAR DName[MAX_PATH];
  939. WCHAR FName[MAX_PATH];
  940. #endif
  941. //
  942. // Load Arguments.
  943. //
  944. if( argc < 2 ) {
  945. Usage( argv[0] );
  946. return 1;
  947. }
  948. if( !_stricmp("/m", argv[1]) || !_stricmp("-m",argv[1]) ) {
  949. printf( "Exculding all Microsoft Drivers.\n" );
  950. ExcludeMicrosoftDrivers = TRUE;
  951. }
  952. #if 0
  953. swprintf( TmpDirectoryString, L"%S", argv[argc-1] );
  954. FindHandle = FindFirstFile( TmpDirectoryString, &FoundData );
  955. if( (FindHandle == INVALID_HANDLE_VALUE) || (FindHandle == NULL) ) {
  956. printf( "Failed to find file: %S\n", TmpDirectoryString );
  957. return 0;
  958. }
  959. p = wcsrchr(TmpDirectoryString, L'\\');
  960. *(p+1) = L'\0';
  961. DiamondInitialize();
  962. //
  963. // Look at every file like this one and populate our driver database.
  964. //
  965. do {
  966. if( !(FoundData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
  967. //printf( " Processing file: %S\n", FoundData.cFileName );
  968. if (ProcessFile( TmpDirectoryString, FoundData.cFileName )) {
  969. FilesProcessed++;
  970. }
  971. }
  972. } while( FindNextFile( FindHandle, &FoundData ) );
  973. #else
  974. DiamondInitialize();
  975. swprintf( TmpDirectoryString, L"%S", argv[argc-1] );
  976. FileHandle = CreateFile( TmpDirectoryString, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL );
  977. if( FileHandle == INVALID_HANDLE_VALUE) { return(FALSE); }
  978. FileSize = GetFileSize( FileHandle, NULL );
  979. if( FileSize == (DWORD)(-1) ) { return(FALSE); };
  980. FileBuffer = MyMalloc(FileSize + 3);
  981. if( FileBuffer == NULL ) {
  982. return -1;
  983. }
  984. b = (BOOLEAN)ReadFile( FileHandle, FileBuffer, FileSize, &i, NULL );
  985. CloseHandle( FileHandle );
  986. Ptr = (PSTR)FileBuffer;
  987. while(Ptr < (PCHAR)FileBuffer + FileSize) {
  988. Ptr2 = DirectoryName = Ptr;
  989. while(*Ptr2 != '\r') {
  990. Ptr2++;
  991. }
  992. Ptr = Ptr2+2;
  993. *Ptr2 = '\0';
  994. Ptr2 = strrchr(DirectoryName, '\\');
  995. Ptr2+=1;
  996. FileName = Ptr2;
  997. OldChar = *Ptr2;
  998. *Ptr2 = '\0';
  999. swprintf( DName, L"%S", DirectoryName );
  1000. *Ptr2 = OldChar;
  1001. swprintf( FName, L"%S", FileName );
  1002. //printf( " Processing file: %s\n", FileName );
  1003. if (ProcessFile( DName, FName )) {
  1004. //printf( " Successfully processed: %s\n", FileName );
  1005. FilesProcessed++;
  1006. } else {
  1007. //printf( " Failed to process: %s\n", FileName );
  1008. }
  1009. }
  1010. #endif
  1011. //
  1012. // Print out one of the lists. They should all be the same.
  1013. //
  1014. printf("Sucessfully processed %d files.\r\n", FilesProcessed);
  1015. DumpFileList();
  1016. DiamondTerminate();
  1017. return 0;
  1018. }