429 lines
15 KiB
C++
429 lines
15 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 2000
|
|
//
|
|
// File: GrabMI.cpp
|
|
//
|
|
// Contents: Code for generating matching information for files in a given
|
|
// directory and it's subdirectories.
|
|
//
|
|
// History: 18-Jul-00 jdoherty Created.
|
|
// 16-Dec-00 jdoherty Modified to use SDBAPI routines.
|
|
// 29-Dec-00 prashkud Modified to take space in the filepath
|
|
//
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include <windows.h>
|
|
#include <TCHAR.h>
|
|
#include <stdio.h>
|
|
#include <conio.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#include "shimdb.h"
|
|
typedef BOOL
|
|
(SDBAPI*PFNSdbGrabMatchingInfoA)(
|
|
LPCSTR szMatchingPath,
|
|
DWORD dwFilter,
|
|
LPCSTR szFile
|
|
);
|
|
typedef BOOL
|
|
(SDBAPI*PFNSdbGrabMatchingInfoW)(
|
|
LPCWSTR szMatchingPath,
|
|
DWORD dwFilter,
|
|
LPCWSTR szFile
|
|
);
|
|
}
|
|
#endif
|
|
|
|
typedef GMI_RESULT
|
|
(SDBAPI *PFNSdbGrabMatchingInfoExA)(
|
|
LPCSTR szMatchingPath, // path to begin gathering information
|
|
DWORD dwFilterAndFlags, // specifies the types of files to be added to matching
|
|
LPCSTR szFile, // full path to file where information will be stored
|
|
PFNGMIProgressCallback pfnCallback,
|
|
LPVOID lpvCallbackParameter
|
|
);
|
|
|
|
typedef GMI_RESULT
|
|
(SDBAPI *PFNSdbGrabMatchingInfoExW)(
|
|
LPCWSTR szMatchingPath, // path to begin gathering information
|
|
DWORD dwFilterAndFlags, // specifies the types of files to be added to matching
|
|
LPCWSTR szFile, // full path to file where information will be stored
|
|
PFNGMIProgressCallback pfnCallback,
|
|
LPVOID lpvCallbackParameter
|
|
);
|
|
|
|
|
|
//
|
|
// Filters needed for SdbGrabMatchingInfo
|
|
//
|
|
/*
|
|
#define GRABMI_FILTER_NORMAL 0
|
|
#define GRABMI_FILTER_PRIVACY 1
|
|
#define GRABMI_FILTER_DRIVERS 2
|
|
#define GRABMI_FILTER_VERBOSE 3
|
|
#define GRABMI_FILTER_SYSTEM 4
|
|
#define GRABMI_FILTER_THISFILEONLY 5
|
|
*/
|
|
|
|
void ProperUsage();
|
|
|
|
|
|
BOOL CALLBACK _GrabmiCallback(
|
|
LPVOID lpvCallbackParam, // application-defined parameter
|
|
LPCTSTR lpszRoot, // root directory path
|
|
LPCTSTR lpszRelative, // relative path
|
|
PATTRINFO pAttrInfo, // attributes
|
|
LPCWSTR pwszXML // resulting xml
|
|
)
|
|
{
|
|
static int State = 0;
|
|
static TCHAR szIcon[] = TEXT("||//--\\\\");
|
|
State = ++State % (ARRAYSIZE(szIcon)-1);
|
|
_tcprintf(TEXT("%c\r"), szIcon[State]);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
int __cdecl main(int argc, TCHAR* argv[])
|
|
{
|
|
TCHAR szRootDir[MAX_PATH] = {'\0'}; // original root directory for matching
|
|
TCHAR szFile[MAX_PATH] = {'\0'}; // File to store information to
|
|
TCHAR szCommandLine[MAX_PATH]={'\0'}; // command line passed to winexec
|
|
TCHAR szMessage[MAX_PATH]={'\0'}; // error message to display
|
|
DWORD dwFilter = GRABMI_FILTER_NORMAL; // specifies filter for matching
|
|
DWORD dwFilterFlags = 0;
|
|
BOOL bDestinationSelected = FALSE;
|
|
BOOL bDisplayFile = TRUE;
|
|
OSVERSIONINFO VersionInfo;
|
|
int iRetCode = 0;
|
|
BOOL bUseApphelp = FALSE;
|
|
|
|
static int Cnt = 0;
|
|
|
|
PFNSdbGrabMatchingInfoExA pfnGrabA = NULL;
|
|
PFNSdbGrabMatchingInfoExW pfnGrabW = NULL;
|
|
HMODULE hLib;
|
|
|
|
VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
if (GetVersionEx(&VersionInfo) == FALSE) {
|
|
wsprintf (szMessage, TEXT("Unable to get version info.\n"));
|
|
goto eh;
|
|
}
|
|
|
|
// check OS version to load the correct version
|
|
// of sdbapi
|
|
|
|
// set to debug 9x binaries on WinXP
|
|
// VersionInfo.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
|
|
|
|
switch (VersionInfo.dwPlatformId) {
|
|
case VER_PLATFORM_WIN32_NT:
|
|
|
|
if (VersionInfo.dwMajorVersion >= 5) {
|
|
if (VersionInfo.dwMajorVersion == 5) { // Check minor version for WinXP
|
|
bUseApphelp = VersionInfo.dwMinorVersion >= 1;
|
|
} else {
|
|
bUseApphelp = TRUE;
|
|
}
|
|
}
|
|
hLib = LoadLibrary(bUseApphelp ? TEXT("apphelp.dll") : TEXT("sdbapiu.dll"));
|
|
if (hLib == NULL) {
|
|
wsprintf (szMessage, TEXT("Could not load sdbapiu.dll.\n"));
|
|
goto eh;
|
|
}
|
|
pfnGrabW = (PFNSdbGrabMatchingInfoExW)GetProcAddress(hLib, TEXT("SdbGrabMatchingInfoEx"));
|
|
if (pfnGrabW == NULL) {
|
|
wsprintf (szMessage, TEXT("Unable to get proc address for SdbGrabMatchingInfo\n"));
|
|
goto eh;
|
|
}
|
|
break;
|
|
case VER_PLATFORM_WIN32_WINDOWS:
|
|
hLib = LoadLibraryA(TEXT("sdbapi.dll"));
|
|
if (hLib == NULL) {
|
|
wsprintf (szMessage, TEXT("Could not load sdbapi.dll.\n"));
|
|
goto eh;
|
|
}
|
|
|
|
pfnGrabA = (PFNSdbGrabMatchingInfoExA)GetProcAddress(hLib, TEXT("SdbGrabMatchingInfoEx"));
|
|
if (pfnGrabA == NULL) {
|
|
wsprintf (szMessage, TEXT("Unable to get proc address for SdbGrabMatchingInfo\n"));
|
|
goto eh;
|
|
}
|
|
break;
|
|
default:
|
|
wsprintf (szMessage, TEXT("Unknown platform\n"));
|
|
goto eh;
|
|
}
|
|
|
|
// Parse the command line for flags
|
|
if( argc >= 2) {
|
|
int i = 1;
|
|
while (i < argc){
|
|
LPCTSTR pch = argv[i];
|
|
TCHAR ch = *pch;
|
|
if (ch == TEXT('-') || ch == TEXT('/')) {
|
|
ch = *++pch;
|
|
++pch;
|
|
switch(_totupper(ch)) {
|
|
case TEXT('F'):
|
|
if (*pch == TEXT('\0')) {
|
|
++i;
|
|
if (i < argc && _istalnum(*argv[i])) {
|
|
pch = argv[i];
|
|
} else {
|
|
// error - missing filename
|
|
wsprintf (szMessage, TEXT("You must provide a file with a .txt extension to save to.\n") );
|
|
goto HandleUsage;
|
|
}
|
|
}
|
|
|
|
lstrcpy(szFile, pch);
|
|
bDestinationSelected=TRUE;
|
|
break;
|
|
|
|
case TEXT('?'):
|
|
case TEXT('H'): // help ?
|
|
HandleUsage:
|
|
ProperUsage();
|
|
goto eh;
|
|
|
|
case TEXT('D'):
|
|
dwFilter = GRABMI_FILTER_DRIVERS;
|
|
break;
|
|
|
|
case TEXT('O'):
|
|
dwFilter = GRABMI_FILTER_THISFILEONLY;
|
|
break;
|
|
|
|
case TEXT('V'):
|
|
dwFilter = GRABMI_FILTER_VERBOSE;
|
|
break;
|
|
|
|
case TEXT('Q'):
|
|
bDisplayFile = FALSE;
|
|
break;
|
|
|
|
case TEXT('P'):
|
|
dwFilter = GRABMI_FILTER_PRIVACY;
|
|
break;
|
|
|
|
case TEXT('S'):
|
|
dwFilter = GRABMI_FILTER_SYSTEM;
|
|
break;
|
|
|
|
case TEXT('A'):
|
|
dwFilterFlags |= GRABMI_FILTER_APPEND;
|
|
break;
|
|
|
|
case TEXT('N'):
|
|
dwFilterFlags |= GRABMI_FILTER_NOCLOSE;
|
|
break;
|
|
|
|
default:
|
|
// unrecognized arg goes here
|
|
wsprintf(szMessage, TEXT("Unrecognized argument, RTFM: %s\n"), argv[i]);
|
|
goto HandleUsage;
|
|
break;
|
|
}
|
|
} else {
|
|
// unnamed argument
|
|
if (++Cnt > 1) {
|
|
|
|
// error - more than one file specified -- we do not support it for now
|
|
//
|
|
wsprintf(szMessage, TEXT("More than one file specified %s\n"), argv[i]);
|
|
goto HandleUsage;
|
|
}
|
|
|
|
lstrcpy(szRootDir, argv[i]);
|
|
}
|
|
|
|
++i;
|
|
}
|
|
}
|
|
|
|
if (!bDestinationSelected) {
|
|
GetSystemDirectory( szFile, MAX_PATH );
|
|
LPTSTR pchBackslash;
|
|
|
|
pchBackslash = _tcschr(szFile, TEXT('\\'));
|
|
|
|
lstrcpy (pchBackslash, TEXT("\\matchinginfo.txt"));
|
|
bDestinationSelected=TRUE;
|
|
}
|
|
|
|
if ( (_tcsicmp(szRootDir ,TEXT(".")) == 0) || szRootDir[0] == '\0' ) {
|
|
// The root path wasn't specified. Get the current path or
|
|
// the path to the drivers depending on command line
|
|
if (dwFilter == GRABMI_FILTER_DRIVERS && (_tcsicmp(szRootDir ,TEXT(".")) != 0)) {
|
|
GetSystemDirectory( szRootDir, MAX_PATH );
|
|
lstrcat( szRootDir, TEXT("\\drivers") );
|
|
} else {
|
|
GetCurrentDirectory( MAX_PATH, szRootDir );
|
|
}
|
|
}
|
|
|
|
// if we are using sdbapiu.dll we need to call it with
|
|
// unicode parameters
|
|
if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
WCHAR wszRootDir[MAX_PATH] ={'\0'};
|
|
WCHAR wszFile[MAX_PATH] ={'\0'};
|
|
int cchWideChar;
|
|
|
|
cchWideChar = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
szRootDir,
|
|
-1,
|
|
NULL,
|
|
0 );
|
|
//
|
|
// check for error!!!
|
|
//
|
|
if ((DWORD)cchWideChar > MAX_PATH) {
|
|
wsprintf (szMessage, TEXT("Unable to convert szRootDir to wszRootDir.\n"));
|
|
goto eh;
|
|
}
|
|
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
szRootDir,
|
|
-1,
|
|
wszRootDir,
|
|
cchWideChar );
|
|
|
|
cchWideChar = MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
szFile,
|
|
-1,
|
|
NULL,
|
|
0 );
|
|
//
|
|
// check for error!!!
|
|
//
|
|
if ((DWORD)cchWideChar > MAX_PATH) {
|
|
wsprintf (szMessage, TEXT("Unable to convert szFile to wszFile.\n"));
|
|
goto eh;
|
|
}
|
|
|
|
MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
szFile,
|
|
-1,
|
|
wszFile,
|
|
cchWideChar );
|
|
// now make call to SdbGrabMatchingInfo with Unicode parameters
|
|
if ((pfnGrabW (wszRootDir, dwFilter|dwFilterFlags, wszFile, _GrabmiCallback, NULL)) != GMI_SUCCESS) {
|
|
wsprintf (szMessage, TEXT("Unable to grab matching information from %s.\n"), szRootDir);
|
|
goto eh;
|
|
}
|
|
wsprintf (szMessage, TEXT("Matching information retrieved successfully.\n"));
|
|
|
|
|
|
}
|
|
else if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS){
|
|
// otherwise call SdbGrabMatchingInfo as normal
|
|
if ((pfnGrabA (szRootDir, dwFilter|dwFilterFlags, szFile, _GrabmiCallback, NULL)) != GMI_SUCCESS) {
|
|
wsprintf (szMessage, TEXT("Unable to grab matching information from %s.\n"), szRootDir);
|
|
goto eh;
|
|
}
|
|
wsprintf (szMessage, TEXT("Matching information retrieved successfully.\n"));
|
|
}
|
|
else {
|
|
wsprintf (szMessage, TEXT("Unknown OS Platform.\n"));
|
|
goto eh;
|
|
}
|
|
|
|
if (bDisplayFile) {
|
|
|
|
if (VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
|
lstrcpy (szCommandLine, TEXT("notepad "));
|
|
}
|
|
else {
|
|
lstrcpy (szCommandLine, TEXT("write "));
|
|
}
|
|
lstrcat (szCommandLine, szFile);
|
|
|
|
WinExec (szCommandLine, SW_SHOW);
|
|
}
|
|
eh:
|
|
|
|
if (*szMessage) {
|
|
_tprintf (TEXT("%s"), szMessage);
|
|
iRetCode = 1;
|
|
}
|
|
return iRetCode;
|
|
}
|
|
|
|
/*++
|
|
|
|
Function Description:
|
|
|
|
This function simply prints out the proper usage for GrabMI.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
VOID.
|
|
|
|
History:
|
|
|
|
jdoherty Created 8/2/00
|
|
|
|
--*/
|
|
void ProperUsage()
|
|
{
|
|
|
|
_tprintf (TEXT("\nGrabMI can be used in one of the following ways:\n")
|
|
TEXT(" *** The following flags can be used with other flags: \n")
|
|
TEXT(" -f, -a, -n, and -h \n")
|
|
TEXT(" otherwise the last flag specified will be the one used.\n")
|
|
TEXT(" *** By default information will be stored in %%systemdrive%%\\matchinginfo.txt\n\n")
|
|
TEXT(" grabmi [path to start generating info ie. c:\\progs]\n")
|
|
TEXT(" Grabs matching information from the path specified. Limits the\n")
|
|
TEXT(" information gathered to 10 miscellaneous files per directory,\n")
|
|
TEXT(" and includes all files with extensions .icd, .exe, .dll, \n")
|
|
TEXT(" .msi, ._mp\n\n")
|
|
TEXT(" grabmi [-d]\n")
|
|
TEXT(" Grabs matching information from %%windir%%\\system32\\drivers. \n")
|
|
TEXT(" The format of the information is slightly different in this case\n")
|
|
TEXT(" and only information for *.sys files will be grabbed.\n\n")
|
|
TEXT(" grabmi [-f drive:\\filename.txt]\n")
|
|
TEXT(" The matching information is stored in a file specified by the user.\n\n")
|
|
TEXT(" grabmi [-h or -?]\n")
|
|
TEXT(" Displays this help.\n\n")
|
|
TEXT(" grabmi [-o]\n")
|
|
TEXT(" Grabs information for the file specified. If a file was not specified \n")
|
|
TEXT(" the call will fail. If the destination file exists then the information\n")
|
|
TEXT(" will be concatenated to the end of the existing file.\n\n")
|
|
TEXT(" grabmi [-p]\n")
|
|
TEXT(" Grabs information for files with .icd, .exe, .dll, .msi, ._mp extensions. \n")
|
|
TEXT(" No more, no less.\n\n")
|
|
TEXT(" grabmi [-q]\n")
|
|
TEXT(" Grabs matching information and does not display the file when completed.\n\n")
|
|
TEXT(" grabmi [-s]\n")
|
|
TEXT(" Grabs information for the following system files: \n")
|
|
TEXT(" advapi32.dll, gdi32.dll, ntdll.dll, kernel32.dll, winsock.dll\n")
|
|
TEXT(" ole32.dll, oleaut32.dll, shell32.dll, user32.dll, and wininet.dll \n\n")
|
|
TEXT(" grabmi [-v]\n")
|
|
TEXT(" Grabs matching information for all files. \n\n")
|
|
TEXT(" grabmi [-a]\n")
|
|
TEXT(" Appends new matching information to the existing matching\n")
|
|
TEXT(" information file. \n\n")
|
|
TEXT(" grabmi [-n]\n")
|
|
TEXT(" Allows to append more information to the file later (see -a). \n\n")
|
|
TEXT("Grab Matching Information Help\n"));
|
|
return;
|
|
}
|