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.

723 lines
17 KiB

  1. #include "pch.h"
  2. #ifdef UNICODE
  3. #error UNICODE not allowed
  4. #endif
  5. #define PNPREPT_HWND (HWND)1
  6. BOOL
  7. WINAPI
  8. MemDb_Entry (
  9. IN HINSTANCE hinstDLL,
  10. IN DWORD dwReason,
  11. IN LPVOID lpv
  12. );
  13. BOOL
  14. WINAPI
  15. MigUtil_Entry (
  16. HINSTANCE hinstDLL,
  17. DWORD fdwReason,
  18. LPVOID lpvReserved
  19. );
  20. VOID
  21. pInitProgBarVars (
  22. VOID
  23. );
  24. INT
  25. pCallMains (
  26. DWORD Reason
  27. )
  28. {
  29. if (!MigUtil_Entry (g_hInst, Reason, NULL)) {
  30. fprintf (stderr, "MigUtil_Entry error!\n");
  31. return 254;
  32. }
  33. if (!MemDb_Entry (g_hInst, Reason, NULL)) {
  34. fprintf (stderr, "MemDb_Entry error!\n");
  35. return 254;
  36. }
  37. if (!HwComp_Entry (g_hInst, Reason, NULL)) {
  38. fprintf (stderr, "HwComp_Entry error!\n");
  39. return 254;
  40. }
  41. pInitProgBarVars();
  42. return 0;
  43. }
  44. BOOL CancelFlag = FALSE;
  45. BOOL *g_CancelFlagPtr = &CancelFlag;
  46. #ifdef PRERELEASE
  47. BOOL g_Stress;
  48. #endif
  49. HANDLE g_hHeap;
  50. HINSTANCE g_hInst;
  51. HINF g_OverrideInf = INVALID_HANDLE_VALUE;
  52. BOOL g_ManualOverrideMode = FALSE;
  53. CHAR g_TempDirBuf[MAX_MBCHAR_PATH]; // location for hwcomp.dat
  54. CHAR g_TempDirWackBuf[MAX_MBCHAR_PATH];
  55. CHAR g_WinDirBuf[MAX_MBCHAR_PATH];
  56. INT g_TempDirWackChars;
  57. PCSTR g_SourceDirectories[MAX_SOURCE_COUNT]; // location of INFs
  58. DWORD g_SourceDirectoryCount;
  59. PSTR g_TempDir;
  60. PSTR g_TempDirWack;
  61. PSTR g_WinDir;
  62. USEROPTIONS g_ConfigOptions; // Needed by migutil. Unused.
  63. extern HWND g_Component, g_SubComponent;
  64. void
  65. HelpAndExit (
  66. void
  67. )
  68. {
  69. fprintf (stderr,
  70. "Command line syntax:\n\n"
  71. "pnprept {-a|-s|-u|-c} [-e<n>] <Inf Dir 1> <Inf Dir 2>\n\n"
  72. "Optional Arguments:\n"
  73. " <Inf Dir 1> - Specifies the directory containing the first set of INFs\n"
  74. " <Inf Dir 2> - Specifies the directory containing the second set of INFs\n"
  75. "\nOutput Options (specify at least one):\n"
  76. " -a - Dumps all devices for both Dir 1 and Dir 2.\n"
  77. " -1 - Dumps devices supported by Dir 1 only (devices unsupported by Dir 2)\n"
  78. " -2 - Dumps devices supported by Dir 2 only (devices unsupported by Dir 1)\n"
  79. " -c - Dumps devices common to Dir 1 and Dir 2\n"
  80. "\nOther Options:\n"
  81. " -i:<path> - Specifies path to win95upg.inf for override list\n"
  82. " -m - Dumps only PNP IDs that are manually overridden (requires -i)\n"
  83. " -e<n> - Puts an equals instead of a tab after column <n>\n"
  84. "\n"
  85. );
  86. exit(255);
  87. }
  88. DWORD g_Mode = 0;
  89. #define MODE_DIR1 0x0001
  90. #define MODE_DIR2 0x0002
  91. #define MAX_SEPARATORS 3
  92. CHAR g_Separators[MAX_SEPARATORS];
  93. LPSTR g_Dir1Path, g_Dir2Path;
  94. VOID
  95. Dump (
  96. DWORD MustHave,
  97. DWORD MustNotHave
  98. )
  99. {
  100. MEMDB_ENUM e, e2;
  101. CHAR PnpOutput[MAX_ENCODED_PNPID_LENGTH];
  102. CHAR DescOutput[MAX_INF_DESCRIPTION*2];
  103. BOOL IsDir1, IsDir2;
  104. LPSTR Dir1File, Dir2File;
  105. GROWBUFFER Dir1List = GROWBUF_INIT;
  106. GROWBUFFER Dir2List = GROWBUF_INIT;
  107. BOOL Dir1Flag, Dir2Flag;
  108. DWORD Flags;
  109. CHAR Node[MEMDB_MAX];
  110. INFCONTEXT ic;
  111. if (!g_ManualOverrideMode) {
  112. printf ("%s%c%s%cPNP ID\tDevice Description%c\n",
  113. g_Dir1Path, g_Separators[0], g_Dir2Path, g_Separators[1], g_Separators[2]);
  114. } else {
  115. printf ("Overridden PNP IDs\n");
  116. }
  117. if (MemDbEnumFirstValue (&e, TEXT("Devices\\*"), MEMDB_THIS_LEVEL_ONLY, MEMDB_ALL_BUT_PROXY)) {
  118. do {
  119. //
  120. // Test this PNP ID to see if it should be displayed
  121. //
  122. if (((e.dwValue & MustHave) == MustHave) &&
  123. ((e.dwValue & MustNotHave) == 0)) {
  124. //
  125. // Prepare display string for PNP ID
  126. //
  127. StringCopyA (PnpOutput, e.szName);
  128. DecodePnpId (PnpOutput);
  129. //
  130. // Is PNP ID suppressed? If so, continue memdb enum.
  131. //
  132. if (g_OverrideInf != INVALID_HANDLE_VALUE) {
  133. if (SetupFindFirstLine (
  134. g_OverrideInf,
  135. "Standard PNP IDs",
  136. PnpOutput,
  137. &ic
  138. )) {
  139. if (g_ManualOverrideMode) {
  140. printf ("%s\n", PnpOutput);
  141. }
  142. continue;
  143. }
  144. }
  145. //
  146. // If only dumping manually overridden PNP IDs, continue.
  147. //
  148. if (g_ManualOverrideMode) {
  149. continue;
  150. }
  151. //
  152. // Enumerate each description for the PNP ID
  153. //
  154. IsDir1 = (e.dwValue & MODE_DIR1) != 0;
  155. IsDir2 = (e.dwValue & MODE_DIR2) != 0;
  156. wsprintf (Node, TEXT("Devices\\%s\\*"), e.szName);
  157. if (MemDbEnumFirstValue (
  158. &e2,
  159. Node,
  160. MEMDB_ALL_SUBLEVELS,
  161. MEMDB_ENDPOINTS_ONLY
  162. )) {
  163. //
  164. // Prepare display string for description by stripping off
  165. // the sequencer and decoding it, then reset INF file name
  166. // buffers.
  167. //
  168. StringCopyA (DescOutput, e2.szName);
  169. *_mbschr (DescOutput, '\\') = 0;
  170. DecodePnpId (DescOutput);
  171. Dir1List.End = 0;
  172. Dir2List.End = 0;
  173. do {
  174. //
  175. // For each description, get the value of the string
  176. // specified by the description sequencer's offset.
  177. //
  178. // We store the file names in a table, so we can organize
  179. // matches correctly. After the table is complete, we
  180. // then dump it out.
  181. //
  182. MemDbBuildKeyFromOffset (e2.dwValue, Node, 1, &Flags);
  183. if (((Flags & MustHave) || !MustHave) &&
  184. ((Flags & MustNotHave) == 0)) {
  185. Dir1Flag = (Flags & MODE_DIR1) != 0;
  186. Dir2Flag = (Flags & MODE_DIR2) != 0;
  187. if (Dir1Flag) {
  188. MultiSzAppend (&Dir1List, Node);
  189. }
  190. if (Dir2Flag) {
  191. MultiSzAppend (&Dir2List, Node);
  192. }
  193. }
  194. } while (MemDbEnumNextValue (&e2));
  195. MultiSzAppend (&Dir1List, "");
  196. MultiSzAppend (&Dir2List, "");
  197. //
  198. // Dump all matches
  199. //
  200. Dir1File = (LPSTR) Dir1List.Buf;
  201. if (!Dir1File) {
  202. Dir1File = "";
  203. }
  204. Dir2File = (LPSTR) Dir2List.Buf;
  205. if (!Dir2File) {
  206. Dir2File = "";
  207. }
  208. while (*Dir1File || *Dir2File) {
  209. printf (
  210. "%s%c%s%c%s%c%s\n",
  211. Dir1File,
  212. g_Separators[0],
  213. Dir2File,
  214. g_Separators[1],
  215. PnpOutput,
  216. g_Separators[2],
  217. DescOutput
  218. );
  219. if (*Dir1File) {
  220. Dir1File = GetEndOfStringA (Dir1File) + 1;
  221. }
  222. if (*Dir2File) {
  223. Dir2File = GetEndOfStringA (Dir2File) + 1;
  224. }
  225. }
  226. }
  227. }
  228. } while (MemDbEnumNextValue (&e));
  229. } else {
  230. printf ("No devices found.\n");
  231. }
  232. FreeGrowBuffer (&Dir1List);
  233. FreeGrowBuffer (&Dir2List);
  234. }
  235. int
  236. __cdecl
  237. main (
  238. int argc,
  239. char *argv[]
  240. )
  241. {
  242. LPSTR Dir1InputPath;
  243. LPSTR Dir2InputPath;
  244. INT i, j;
  245. LONG rc;
  246. INT UIMode;
  247. BOOL AllFlag = FALSE;
  248. BOOL Dir2Only = FALSE;
  249. BOOL Dir1Only = FALSE;
  250. BOOL Common = FALSE;
  251. PCSTR OverrideList = NULL;
  252. DWORD Count;
  253. //
  254. // Init project globals
  255. //
  256. GetTempPathA (MAX_MBCHAR_PATH, g_TempDirBuf);
  257. g_TempDir = g_TempDirBuf;
  258. StringCopyA (g_TempDirWackBuf, g_TempDir);
  259. AppendWack (g_TempDirWackBuf);
  260. g_TempDirWackChars = CharCountA (g_TempDirWackBuf);
  261. g_TempDirWack = g_TempDirWackBuf;
  262. GetWindowsDirectoryA (g_WinDirBuf, MAX_MBCHAR_PATH);
  263. g_WinDir = g_WinDirBuf;
  264. ZeroMemory(&g_ConfigOptions,sizeof(USEROPTIONS));
  265. UIMode = PNPREPT_OUTPUT;
  266. g_Component = NULL;
  267. g_SubComponent = PNPREPT_HWND;
  268. //
  269. // Parse command line
  270. //
  271. Dir1InputPath = NULL;
  272. Dir2InputPath = NULL;
  273. for (i = 0 ; i < MAX_SEPARATORS ; i++) {
  274. g_Separators[i] = '\t';
  275. }
  276. for (i = 1 ; i < argc ; i++) {
  277. if (argv[i][0] == '-' || argv[i][0] == '/') {
  278. switch (tolower (argv[i][1])) {
  279. case 'a':
  280. AllFlag = TRUE;
  281. break;
  282. case '2':
  283. Dir2Only = TRUE;
  284. break;
  285. case '1':
  286. Dir1Only = TRUE;
  287. break;
  288. case 'c':
  289. Common = TRUE;
  290. break;
  291. case 'm':
  292. g_ManualOverrideMode = TRUE;
  293. break;
  294. case 'e':
  295. j = atoi (&argv[i][2]);
  296. if (j < 1 || j > MAX_SEPARATORS) {
  297. HelpAndExit();
  298. }
  299. g_Separators[j] = '=';
  300. break;
  301. case 'i':
  302. if (!argv[i][2] && (i + 1) < argc) {
  303. i++;
  304. OverrideList = argv[i];
  305. } else if (argv[i][2] == ':') {
  306. OverrideList = &argv[i][3];
  307. } else {
  308. HelpAndExit();
  309. }
  310. break;
  311. default:
  312. HelpAndExit();
  313. }
  314. } else {
  315. if (Dir1InputPath && Dir2InputPath) {
  316. HelpAndExit();
  317. } else if (Dir1InputPath) {
  318. Dir2InputPath = argv[i];
  319. } else {
  320. Dir1InputPath = argv[i];
  321. }
  322. }
  323. }
  324. if (!AllFlag && !Dir2Only && !Dir1Only && !Common) {
  325. HelpAndExit();
  326. }
  327. if (g_ManualOverrideMode && !OverrideList) {
  328. HelpAndExit();
  329. }
  330. if (!Dir2InputPath) {
  331. HelpAndExit();
  332. }
  333. //
  334. // Init globals and libs
  335. //
  336. g_hHeap = GetProcessHeap();
  337. g_hInst = GetModuleHandle (NULL);
  338. g_SourceDirectories[0] = Dir1InputPath;
  339. Count = 1;
  340. g_SourceDirectoryCount = Count;
  341. if (pCallMains (DLL_PROCESS_ATTACH)) {
  342. fprintf (stderr, "Initialization error!\n");
  343. return 254;
  344. }
  345. g_Dir1Path = _mbsrchr (Dir1InputPath, '\\');
  346. if (!g_Dir1Path) {
  347. g_Dir1Path = Dir1InputPath;
  348. } else {
  349. g_Dir2Path++;
  350. }
  351. g_Dir2Path = _mbsrchr (Dir2InputPath, '\\');
  352. if (!g_Dir2Path) {
  353. g_Dir2Path = Dir2InputPath;
  354. } else {
  355. g_Dir2Path++;
  356. }
  357. if (StringIMatch (g_Dir1Path, g_Dir2Path)) {
  358. g_Dir1Path = Dir1InputPath;
  359. g_Dir2Path = Dir2InputPath;
  360. }
  361. if (StringIMatch (g_Dir1Path, g_Dir2Path)) {
  362. fprintf (stderr, "Dir 1 and Dir 2 must be different\n");
  363. return 247;
  364. }
  365. if (OverrideList) {
  366. CHAR FullPath[MAX_MBCHAR_PATH];
  367. PSTR DontCare;
  368. if (!SearchPathA (NULL, OverrideList, NULL, MAX_MBCHAR_PATH, FullPath, &DontCare)) {
  369. StringCopyA (FullPath, OverrideList);
  370. }
  371. g_OverrideInf = SetupOpenInfFile (
  372. FullPath,
  373. NULL,
  374. INF_STYLE_OLDNT|INF_STYLE_WIN4,
  375. NULL
  376. );
  377. if (g_OverrideInf == INVALID_HANDLE_VALUE) {
  378. fprintf (stderr, "Cannot open %s\n", FullPath);
  379. return 246;
  380. }
  381. }
  382. __try {
  383. //
  384. // Generate memdb entries for Dir 1 INFs
  385. //
  386. fprintf (stderr, "Processing...\n", Dir1InputPath);
  387. g_Mode = MODE_DIR1;
  388. if (!CreateNtHardwareList (&Dir1InputPath, 1, NULL, UIMode)) {
  389. rc = GetLastError();
  390. fprintf (stderr, "Could not build complete %s device list. Win32 Error Code: %xh\n", Dir1InputPath, rc);
  391. return 1;
  392. } else {
  393. fprintf (stderr, " %s processed\n", Dir1InputPath);
  394. }
  395. //
  396. // Restart hwcomp.lib
  397. //
  398. if (!HwComp_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) {
  399. fprintf (stderr, "Termination error!\n");
  400. return 253;
  401. }
  402. if (!HwComp_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) {
  403. fprintf (stderr, "Initialization error!\n");
  404. return 252;
  405. }
  406. //
  407. // Generate memdb entries for Dir 2 INFs
  408. //
  409. g_Mode = MODE_DIR2;
  410. if (!CreateNtHardwareList (&Dir2InputPath, 1, NULL, UIMode)) {
  411. rc = GetLastError();
  412. fprintf (stderr, "Could not build complete %s device list. Win32 Error Code: %xh\n", Dir2InputPath, rc);
  413. return 2;
  414. } else {
  415. fprintf (stderr, " %s processed\n", Dir2InputPath);
  416. }
  417. //
  418. // Dump output
  419. //
  420. if (AllFlag) {
  421. Dump (0, 0);
  422. }
  423. if (Dir2Only) {
  424. Dump (MODE_DIR2, MODE_DIR1);
  425. }
  426. if (Dir1Only) {
  427. Dump (MODE_DIR1, MODE_DIR2);
  428. }
  429. if (Common) {
  430. Dump (MODE_DIR2|MODE_DIR1, 0);
  431. }
  432. //
  433. // Terminate hwcomp.lib
  434. //
  435. if (pCallMains (DLL_PROCESS_DETACH)) {
  436. fprintf (stderr, "Initialization error!\n");
  437. return 251;
  438. }
  439. fprintf (stderr, "Done\n");
  440. }
  441. __finally {
  442. if (g_OverrideInf != INVALID_HANDLE_VALUE) {
  443. SetupCloseInfFile (g_OverrideInf);
  444. }
  445. }
  446. return 0;
  447. }
  448. BOOL
  449. ProcessPnpId (
  450. IN PCSTR SubComponent
  451. )
  452. {
  453. DWORD Value;
  454. TCHAR Node[MEMDB_MAX];
  455. LPTSTR PnpId, Desc, File;
  456. LPTSTR p;
  457. DWORD FileOffset;
  458. static DWORD d = 0;
  459. if (SubComponent) {
  460. PnpId = (LPTSTR) SubComponent;
  461. p = _tcschr (PnpId, TEXT('\\'));
  462. if (!p) {
  463. return TRUE;
  464. }
  465. *p = 0;
  466. Desc = p+1;
  467. p = _tcschr (Desc, TEXT('\\'));
  468. if (!p) {
  469. return TRUE;
  470. }
  471. *p = 0;
  472. File = p+1;
  473. //
  474. // Add the file (it may already exist) and remember the offset.
  475. // Keep the files in two separate lists.
  476. //
  477. MemDbSetValueEx (
  478. g_Mode == MODE_DIR1 ? TEXT("Dir1") : TEXT("Dir2"),
  479. File,
  480. NULL,
  481. NULL,
  482. g_Mode,
  483. &FileOffset
  484. );
  485. //
  486. // Add the PNP ID and OR the mode
  487. //
  488. wsprintf (Node, TEXT("Devices\\%s"), PnpId);
  489. if (!MemDbGetValue (Node, &Value)) {
  490. Value = 0;
  491. }
  492. Value |= g_Mode;
  493. MemDbSetValue (Node, Value);
  494. //
  495. // Add the description, and attach a sequencer to make sure
  496. // the description is unique. Make the description point
  497. // to the file offset.
  498. //
  499. d++;
  500. wsprintf (Node, TEXT("Devices\\%s\\%s\\%u"), PnpId, Desc, d);
  501. MemDbSetValue (Node, FileOffset);
  502. }
  503. return TRUE;
  504. }
  505. //
  506. // Stubs
  507. //
  508. HWND g_Component;
  509. HWND g_SubComponent;
  510. HANDLE g_ComponentCancelEvent;
  511. HANDLE g_SubComponentCancelEvent;
  512. VOID
  513. pInitProgBarVars (
  514. VOID
  515. )
  516. {
  517. g_Component = NULL;
  518. g_SubComponent = NULL;
  519. g_ComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  520. g_SubComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  521. }
  522. BOOL
  523. ProgressBar_SetWindowStringA (
  524. IN HWND Window,
  525. IN HANDLE CancelEvent,
  526. IN PCSTR Message, OPTIONAL
  527. IN DWORD MessageId OPTIONAL
  528. )
  529. {
  530. return TRUE;
  531. }
  532. BOOL
  533. TickProgressBar (
  534. VOID
  535. )
  536. {
  537. return TRUE;
  538. }
  539. BOOL
  540. TickProgressBarDelta (
  541. IN UINT TickCount
  542. )
  543. {
  544. return TRUE;
  545. }
  546. VOID
  547. InitializeProgressBar (
  548. IN HWND ProgressBar,
  549. IN HWND Component, OPTIONAL
  550. IN HWND SubComponent, OPTIONAL
  551. IN BOOL *CancelFlagPtr OPTIONAL
  552. )
  553. {
  554. return;
  555. }
  556. VOID
  557. TerminateProgressBar (
  558. VOID
  559. )
  560. {
  561. return;
  562. }
  563. VOID
  564. EndSliceProcessing (
  565. VOID
  566. )
  567. {
  568. return;
  569. }
  570. UINT
  571. RegisterProgressBarSlice (
  572. IN UINT InitialEstimate
  573. )
  574. {
  575. return 0;
  576. }
  577. VOID
  578. ReviseSliceEstimate (
  579. IN UINT SliceId,
  580. IN UINT RevisedEstimate
  581. )
  582. {
  583. return;
  584. }
  585. VOID
  586. BeginSliceProcessing (
  587. IN UINT SliceId
  588. )
  589. {
  590. }