windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/tools/pnprept/pnprept.c
2020-09-26 16:20:57 +08:00

724 lines
17 KiB
C

#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>] <Inf Dir 1> <Inf Dir 2>\n\n"
"Optional Arguments:\n"
" <Inf Dir 1> - Specifies the directory containing the first set of INFs\n"
" <Inf Dir 2> - 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:<path> - Specifies path to win95upg.inf for override list\n"
" -m - Dumps only PNP IDs that are manually overridden (requires -i)\n"
" -e<n> - Puts an equals instead of a tab after column <n>\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
)
{
}