#include "pch.h" #ifdef UNICODE #error UNICODE not allowed #endif #define PNPREPT_HWND (HWND)1 BOOL WINAPI MemDb_Entry ( IN HINSTANCE hinstDLL, IN DWORD dwReason, IN LPVOID lpv ); BOOL WINAPI MigUtil_Entry ( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ); VOID pInitProgBarVars ( VOID ); INT pCallMains ( DWORD Reason ) { if (!MigUtil_Entry (g_hInst, Reason, NULL)) { fprintf (stderr, "MigUtil_Entry error!\n"); return 254; } if (!MemDb_Entry (g_hInst, Reason, NULL)) { fprintf (stderr, "MemDb_Entry error!\n"); return 254; } if (!HwComp_Entry (g_hInst, Reason, NULL)) { fprintf (stderr, "HwComp_Entry error!\n"); return 254; } pInitProgBarVars(); return 0; } BOOL CancelFlag = FALSE; BOOL *g_CancelFlagPtr = &CancelFlag; #ifdef PRERELEASE BOOL g_Stress; #endif HANDLE g_hHeap; HINSTANCE g_hInst; HINF g_OverrideInf = INVALID_HANDLE_VALUE; BOOL g_ManualOverrideMode = FALSE; CHAR g_TempDirBuf[MAX_MBCHAR_PATH]; // location for hwcomp.dat CHAR g_TempDirWackBuf[MAX_MBCHAR_PATH]; CHAR g_WinDirBuf[MAX_MBCHAR_PATH]; INT g_TempDirWackChars; PCSTR g_SourceDirectories[MAX_SOURCE_COUNT]; // location of INFs DWORD g_SourceDirectoryCount; PSTR g_TempDir; PSTR g_TempDirWack; PSTR g_WinDir; USEROPTIONS g_ConfigOptions; // Needed by migutil. Unused. extern HWND g_Component, g_SubComponent; void HelpAndExit ( void ) { fprintf (stderr, "Command line syntax:\n\n" "pnprept {-a|-s|-u|-c} [-e] \n\n" "Optional Arguments:\n" " - Specifies the directory containing the first set of INFs\n" " - Specifies the directory containing the second set of INFs\n" "\nOutput Options (specify at least one):\n" " -a - Dumps all devices for both Dir 1 and Dir 2.\n" " -1 - Dumps devices supported by Dir 1 only (devices unsupported by Dir 2)\n" " -2 - Dumps devices supported by Dir 2 only (devices unsupported by Dir 1)\n" " -c - Dumps devices common to Dir 1 and Dir 2\n" "\nOther Options:\n" " -i: - Specifies path to win95upg.inf for override list\n" " -m - Dumps only PNP IDs that are manually overridden (requires -i)\n" " -e - Puts an equals instead of a tab after column \n" "\n" ); exit(255); } DWORD g_Mode = 0; #define MODE_DIR1 0x0001 #define MODE_DIR2 0x0002 #define MAX_SEPARATORS 3 CHAR g_Separators[MAX_SEPARATORS]; LPSTR g_Dir1Path, g_Dir2Path; VOID Dump ( DWORD MustHave, DWORD MustNotHave ) { MEMDB_ENUM e, e2; CHAR PnpOutput[MAX_ENCODED_PNPID_LENGTH]; CHAR DescOutput[MAX_INF_DESCRIPTION*2]; BOOL IsDir1, IsDir2; LPSTR Dir1File, Dir2File; GROWBUFFER Dir1List = GROWBUF_INIT; GROWBUFFER Dir2List = GROWBUF_INIT; BOOL Dir1Flag, Dir2Flag; DWORD Flags; CHAR Node[MEMDB_MAX]; INFCONTEXT ic; if (!g_ManualOverrideMode) { printf ("%s%c%s%cPNP ID\tDevice Description%c\n", g_Dir1Path, g_Separators[0], g_Dir2Path, g_Separators[1], g_Separators[2]); } else { printf ("Overridden PNP IDs\n"); } if (MemDbEnumFirstValue (&e, TEXT("Devices\\*"), MEMDB_THIS_LEVEL_ONLY, MEMDB_ALL_BUT_PROXY)) { do { // // Test this PNP ID to see if it should be displayed // if (((e.dwValue & MustHave) == MustHave) && ((e.dwValue & MustNotHave) == 0)) { // // Prepare display string for PNP ID // StringCopyA (PnpOutput, e.szName); DecodePnpId (PnpOutput); // // Is PNP ID suppressed? If so, continue memdb enum. // if (g_OverrideInf != INVALID_HANDLE_VALUE) { if (SetupFindFirstLine ( g_OverrideInf, "Standard PNP IDs", PnpOutput, &ic )) { if (g_ManualOverrideMode) { printf ("%s\n", PnpOutput); } continue; } } // // If only dumping manually overridden PNP IDs, continue. // if (g_ManualOverrideMode) { continue; } // // Enumerate each description for the PNP ID // IsDir1 = (e.dwValue & MODE_DIR1) != 0; IsDir2 = (e.dwValue & MODE_DIR2) != 0; wsprintf (Node, TEXT("Devices\\%s\\*"), e.szName); if (MemDbEnumFirstValue ( &e2, Node, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY )) { // // Prepare display string for description by stripping off // the sequencer and decoding it, then reset INF file name // buffers. // StringCopyA (DescOutput, e2.szName); *_mbschr (DescOutput, '\\') = 0; DecodePnpId (DescOutput); Dir1List.End = 0; Dir2List.End = 0; do { // // For each description, get the value of the string // specified by the description sequencer's offset. // // We store the file names in a table, so we can organize // matches correctly. After the table is complete, we // then dump it out. // MemDbBuildKeyFromOffset (e2.dwValue, Node, 1, &Flags); if (((Flags & MustHave) || !MustHave) && ((Flags & MustNotHave) == 0)) { Dir1Flag = (Flags & MODE_DIR1) != 0; Dir2Flag = (Flags & MODE_DIR2) != 0; if (Dir1Flag) { MultiSzAppend (&Dir1List, Node); } if (Dir2Flag) { MultiSzAppend (&Dir2List, Node); } } } while (MemDbEnumNextValue (&e2)); MultiSzAppend (&Dir1List, ""); MultiSzAppend (&Dir2List, ""); // // Dump all matches // Dir1File = (LPSTR) Dir1List.Buf; if (!Dir1File) { Dir1File = ""; } Dir2File = (LPSTR) Dir2List.Buf; if (!Dir2File) { Dir2File = ""; } while (*Dir1File || *Dir2File) { printf ( "%s%c%s%c%s%c%s\n", Dir1File, g_Separators[0], Dir2File, g_Separators[1], PnpOutput, g_Separators[2], DescOutput ); if (*Dir1File) { Dir1File = GetEndOfStringA (Dir1File) + 1; } if (*Dir2File) { Dir2File = GetEndOfStringA (Dir2File) + 1; } } } } } while (MemDbEnumNextValue (&e)); } else { printf ("No devices found.\n"); } FreeGrowBuffer (&Dir1List); FreeGrowBuffer (&Dir2List); } int __cdecl main ( int argc, char *argv[] ) { LPSTR Dir1InputPath; LPSTR Dir2InputPath; INT i, j; LONG rc; INT UIMode; BOOL AllFlag = FALSE; BOOL Dir2Only = FALSE; BOOL Dir1Only = FALSE; BOOL Common = FALSE; PCSTR OverrideList = NULL; DWORD Count; // // Init project globals // GetTempPathA (MAX_MBCHAR_PATH, g_TempDirBuf); g_TempDir = g_TempDirBuf; StringCopyA (g_TempDirWackBuf, g_TempDir); AppendWack (g_TempDirWackBuf); g_TempDirWackChars = CharCountA (g_TempDirWackBuf); g_TempDirWack = g_TempDirWackBuf; GetWindowsDirectoryA (g_WinDirBuf, MAX_MBCHAR_PATH); g_WinDir = g_WinDirBuf; ZeroMemory(&g_ConfigOptions,sizeof(USEROPTIONS)); UIMode = PNPREPT_OUTPUT; g_Component = NULL; g_SubComponent = PNPREPT_HWND; // // Parse command line // Dir1InputPath = NULL; Dir2InputPath = NULL; for (i = 0 ; i < MAX_SEPARATORS ; i++) { g_Separators[i] = '\t'; } for (i = 1 ; i < argc ; i++) { if (argv[i][0] == '-' || argv[i][0] == '/') { switch (tolower (argv[i][1])) { case 'a': AllFlag = TRUE; break; case '2': Dir2Only = TRUE; break; case '1': Dir1Only = TRUE; break; case 'c': Common = TRUE; break; case 'm': g_ManualOverrideMode = TRUE; break; case 'e': j = atoi (&argv[i][2]); if (j < 1 || j > MAX_SEPARATORS) { HelpAndExit(); } g_Separators[j] = '='; break; case 'i': if (!argv[i][2] && (i + 1) < argc) { i++; OverrideList = argv[i]; } else if (argv[i][2] == ':') { OverrideList = &argv[i][3]; } else { HelpAndExit(); } break; default: HelpAndExit(); } } else { if (Dir1InputPath && Dir2InputPath) { HelpAndExit(); } else if (Dir1InputPath) { Dir2InputPath = argv[i]; } else { Dir1InputPath = argv[i]; } } } if (!AllFlag && !Dir2Only && !Dir1Only && !Common) { HelpAndExit(); } if (g_ManualOverrideMode && !OverrideList) { HelpAndExit(); } if (!Dir2InputPath) { HelpAndExit(); } // // Init globals and libs // g_hHeap = GetProcessHeap(); g_hInst = GetModuleHandle (NULL); g_SourceDirectories[0] = Dir1InputPath; Count = 1; g_SourceDirectoryCount = Count; if (pCallMains (DLL_PROCESS_ATTACH)) { fprintf (stderr, "Initialization error!\n"); return 254; } g_Dir1Path = _mbsrchr (Dir1InputPath, '\\'); if (!g_Dir1Path) { g_Dir1Path = Dir1InputPath; } else { g_Dir2Path++; } g_Dir2Path = _mbsrchr (Dir2InputPath, '\\'); if (!g_Dir2Path) { g_Dir2Path = Dir2InputPath; } else { g_Dir2Path++; } if (StringIMatch (g_Dir1Path, g_Dir2Path)) { g_Dir1Path = Dir1InputPath; g_Dir2Path = Dir2InputPath; } if (StringIMatch (g_Dir1Path, g_Dir2Path)) { fprintf (stderr, "Dir 1 and Dir 2 must be different\n"); return 247; } if (OverrideList) { CHAR FullPath[MAX_MBCHAR_PATH]; PSTR DontCare; if (!SearchPathA (NULL, OverrideList, NULL, MAX_MBCHAR_PATH, FullPath, &DontCare)) { StringCopyA (FullPath, OverrideList); } g_OverrideInf = SetupOpenInfFile ( FullPath, NULL, INF_STYLE_OLDNT|INF_STYLE_WIN4, NULL ); if (g_OverrideInf == INVALID_HANDLE_VALUE) { fprintf (stderr, "Cannot open %s\n", FullPath); return 246; } } __try { // // Generate memdb entries for Dir 1 INFs // fprintf (stderr, "Processing...\n", Dir1InputPath); g_Mode = MODE_DIR1; if (!CreateNtHardwareList (&Dir1InputPath, 1, NULL, UIMode)) { rc = GetLastError(); fprintf (stderr, "Could not build complete %s device list. Win32 Error Code: %xh\n", Dir1InputPath, rc); return 1; } else { fprintf (stderr, " %s processed\n", Dir1InputPath); } // // Restart hwcomp.lib // if (!HwComp_Entry (g_hInst, DLL_PROCESS_DETACH, NULL)) { fprintf (stderr, "Termination error!\n"); return 253; } if (!HwComp_Entry (g_hInst, DLL_PROCESS_ATTACH, NULL)) { fprintf (stderr, "Initialization error!\n"); return 252; } // // Generate memdb entries for Dir 2 INFs // g_Mode = MODE_DIR2; if (!CreateNtHardwareList (&Dir2InputPath, 1, NULL, UIMode)) { rc = GetLastError(); fprintf (stderr, "Could not build complete %s device list. Win32 Error Code: %xh\n", Dir2InputPath, rc); return 2; } else { fprintf (stderr, " %s processed\n", Dir2InputPath); } // // Dump output // if (AllFlag) { Dump (0, 0); } if (Dir2Only) { Dump (MODE_DIR2, MODE_DIR1); } if (Dir1Only) { Dump (MODE_DIR1, MODE_DIR2); } if (Common) { Dump (MODE_DIR2|MODE_DIR1, 0); } // // Terminate hwcomp.lib // if (pCallMains (DLL_PROCESS_DETACH)) { fprintf (stderr, "Initialization error!\n"); return 251; } fprintf (stderr, "Done\n"); } __finally { if (g_OverrideInf != INVALID_HANDLE_VALUE) { SetupCloseInfFile (g_OverrideInf); } } return 0; } BOOL ProcessPnpId ( IN PCSTR SubComponent ) { DWORD Value; TCHAR Node[MEMDB_MAX]; LPTSTR PnpId, Desc, File; LPTSTR p; DWORD FileOffset; static DWORD d = 0; if (SubComponent) { PnpId = (LPTSTR) SubComponent; p = _tcschr (PnpId, TEXT('\\')); if (!p) { return TRUE; } *p = 0; Desc = p+1; p = _tcschr (Desc, TEXT('\\')); if (!p) { return TRUE; } *p = 0; File = p+1; // // Add the file (it may already exist) and remember the offset. // Keep the files in two separate lists. // MemDbSetValueEx ( g_Mode == MODE_DIR1 ? TEXT("Dir1") : TEXT("Dir2"), File, NULL, NULL, g_Mode, &FileOffset ); // // Add the PNP ID and OR the mode // wsprintf (Node, TEXT("Devices\\%s"), PnpId); if (!MemDbGetValue (Node, &Value)) { Value = 0; } Value |= g_Mode; MemDbSetValue (Node, Value); // // Add the description, and attach a sequencer to make sure // the description is unique. Make the description point // to the file offset. // d++; wsprintf (Node, TEXT("Devices\\%s\\%s\\%u"), PnpId, Desc, d); MemDbSetValue (Node, FileOffset); } return TRUE; } // // Stubs // HWND g_Component; HWND g_SubComponent; HANDLE g_ComponentCancelEvent; HANDLE g_SubComponentCancelEvent; VOID pInitProgBarVars ( VOID ) { g_Component = NULL; g_SubComponent = NULL; g_ComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL); g_SubComponentCancelEvent = CreateEvent (NULL, FALSE, FALSE, NULL); } BOOL ProgressBar_SetWindowStringA ( IN HWND Window, IN HANDLE CancelEvent, IN PCSTR Message, OPTIONAL IN DWORD MessageId OPTIONAL ) { return TRUE; } BOOL TickProgressBar ( VOID ) { return TRUE; } BOOL TickProgressBarDelta ( IN UINT TickCount ) { return TRUE; } VOID InitializeProgressBar ( IN HWND ProgressBar, IN HWND Component, OPTIONAL IN HWND SubComponent, OPTIONAL IN BOOL *CancelFlagPtr OPTIONAL ) { return; } VOID TerminateProgressBar ( VOID ) { return; } VOID EndSliceProcessing ( VOID ) { return; } UINT RegisterProgressBarSlice ( IN UINT InitialEstimate ) { return 0; } VOID ReviseSliceEstimate ( IN UINT SliceId, IN UINT RevisedEstimate ) { return; } VOID BeginSliceProcessing ( IN UINT SliceId ) { }