837 lines
25 KiB
C
837 lines
25 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1989-2000 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
grabmiapi.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Code for generating matching information for files in a given
|
||
|
directory and its subdirectories.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
jdoherty created sometime in 2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
several people contributed (vadimb, clupu, ...)
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "sdbp.h"
|
||
|
#include <time.h>
|
||
|
#include <shlwapi.h>
|
||
|
|
||
|
#define MAX_MISC_FILES_PER_LEVEL 10
|
||
|
#define MAX_LEVELS_OF_DIRECTORIES 3
|
||
|
|
||
|
static UCHAR UNICODE_MARKER[2] = { 0xFF, 0xFE }; // will hold special characters to specify
|
||
|
// a UNICODE File
|
||
|
|
||
|
|
||
|
TCHAR* g_szFilterDesc[] = {
|
||
|
TEXT("GRABMI_FILTER_NORMAL"),
|
||
|
TEXT("GRABMI_FILTER_PRIVACY"),
|
||
|
TEXT("GRABMI_FILTER_DRIVERS"),
|
||
|
TEXT("GRABMI_FILTER_VERBOSE"),
|
||
|
TEXT("GRABMI_FILTER_SYSTEM"),
|
||
|
TEXT("GRABMI_FILTER_THISFILEONLY"),
|
||
|
};
|
||
|
|
||
|
TCHAR* g_szGrabmiFilterNormal[] = {
|
||
|
TEXT(".exe"),
|
||
|
TEXT(".icd"),
|
||
|
TEXT("._mp"),
|
||
|
TEXT(".msi"),
|
||
|
TEXT(".dll")
|
||
|
};
|
||
|
|
||
|
TCHAR* g_szGrabmiFilterSystem[] = {
|
||
|
TEXT("ntdll.dll"),
|
||
|
TEXT("user32.dll"),
|
||
|
TEXT("kernel32.dll"),
|
||
|
TEXT("gdi32.dll"),
|
||
|
TEXT("wininet.dll"),
|
||
|
TEXT("winsock.dll"),
|
||
|
TEXT("advapi32.dll"),
|
||
|
TEXT("shell32.dll"),
|
||
|
TEXT("ole32.dll"),
|
||
|
TEXT("advapi32.dll"),
|
||
|
TEXT("oleaut32.dll"),
|
||
|
TEXT("repcrt32.dll"),
|
||
|
};
|
||
|
|
||
|
typedef struct tagRECINFO {
|
||
|
|
||
|
LPVOID lpvCallbackParameter;
|
||
|
PFNGMIProgressCallback pfnCallback;
|
||
|
|
||
|
ULONG MaxFiles; // limit the number of files
|
||
|
ULONG FileCount; // count the files
|
||
|
BOOL bNewStorageFile;
|
||
|
|
||
|
} RECINFO, *PRECINFO;
|
||
|
|
||
|
#define GRABMI_FLAGS_MASK 0xFFFF0000
|
||
|
|
||
|
GMI_RESULT
|
||
|
SdbpGrabMatchingInfoDir(
|
||
|
HANDLE hStorageFile, // handle to a file we are writing
|
||
|
PRECINFO pinfo, // pointer to extra info
|
||
|
DWORD dwFilterAndFlags, // specifies the types of files to be added for matching
|
||
|
LPCTSTR lpszRoot, // root directory for our search (pointer to the buffer)
|
||
|
LPTSTR lpszOriginalExe, // never null -- pointer to the relative portion,
|
||
|
LPTSTR lpszRelative, // never null -- pointer to the relative portion,
|
||
|
int nLevel // current directory level for matching information
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Function Name:
|
||
|
SdbpGrabMatchingInfoDir
|
||
|
|
||
|
Function Description:
|
||
|
|
||
|
This function traverses a directory and its subdirectories gathering matching
|
||
|
information and writes it to the specified file.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOL: TRUE if Successful
|
||
|
|
||
|
History:
|
||
|
|
||
|
04/26/2001 jdoherty Created
|
||
|
|
||
|
SdbpGrabMatchingInfoDir pointer definition:
|
||
|
c:\foo\bar\soap\relativepath\
|
||
|
^- lpszRoot ^- lpszRelative
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HANDLE hSearch = INVALID_HANDLE_VALUE; // handle for FindFileFirst and FindFileNext
|
||
|
WIN32_FIND_DATA FindFileData; // structure containing file information
|
||
|
LPTSTR lpchFilePart; // points to a file part in szSearchPath
|
||
|
LPTSTR pchExt; // extension of current file
|
||
|
LPTSTR lpReplaceChar; // pointer to character to be replaced
|
||
|
|
||
|
BOOL bMiscFile;
|
||
|
INT nch, nchBuffer, i;
|
||
|
INT nLen;
|
||
|
INT cbFileCounter = 0; // running count of misc files added to matching.
|
||
|
int cbMultiByte = 0; // The amount of MultiByte chars converting.
|
||
|
int cchWideChar = 0; // The amount of WideChars converted.
|
||
|
DWORD dwBufferSize = 4096; // initialize me with the alloc size for lpData
|
||
|
LPTSTR lpData = NULL; // INITIALIZE ME WITH MALLOC!!!
|
||
|
LPTSTR lpBuffer = NULL; // points within lpData
|
||
|
LPWSTR lpUnicodeBuffer = NULL; // INITIALIZE ME WITH MALLOC!!!
|
||
|
BOOL bThisFileOnlyDone = FALSE;
|
||
|
DWORD dwFilter = (dwFilterAndFlags & ~GRABMI_FLAGS_MASK);
|
||
|
DWORD dwFilterFlags = (dwFilterAndFlags & GRABMI_FLAGS_MASK);
|
||
|
PATTRINFO pAttrInfo; // attribute information structure
|
||
|
DWORD dwBytesWritten = 0;
|
||
|
DWORD dwAttributes;
|
||
|
DWORD dwAttrCount;
|
||
|
GMI_RESULT Result = GMI_FAILED; // these two variables control return Result
|
||
|
// is set as a return from callback or nested call
|
||
|
//
|
||
|
// Only want to grab information for the file(s) specified which
|
||
|
// should reside in the root directory specified.
|
||
|
//
|
||
|
if (nLevel != 0 &&
|
||
|
(dwFilter == GRABMI_FILTER_THISFILEONLY ||
|
||
|
dwFilter == GRABMI_FILTER_SYSTEM)) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
lpData = (LPTSTR)SdbAlloc(dwBufferSize * sizeof(TCHAR));
|
||
|
|
||
|
if (lpData == NULL) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInfoDir",
|
||
|
"Unable to allocate %d bytes.\n",
|
||
|
dwBufferSize * sizeof(TCHAR)));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32A_MODE
|
||
|
lpUnicodeBuffer = (LPWSTR)SdbAlloc(dwBufferSize * sizeof(WCHAR));
|
||
|
|
||
|
if (lpUnicodeBuffer == NULL) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInfoDir",
|
||
|
"Unable to allocate %d bytes.\n",
|
||
|
dwBufferSize * sizeof(WCHAR)));
|
||
|
goto eh;
|
||
|
}
|
||
|
#endif // WIN32A_MODE
|
||
|
|
||
|
lpchFilePart = lpszRelative + _tcslen(lpszRelative);
|
||
|
|
||
|
assert(lpchFilePart == lpszRoot || *(lpchFilePart-1) == TEXT('\\'));
|
||
|
|
||
|
if (dwFilter == GRABMI_FILTER_THISFILEONLY) {
|
||
|
_tcscpy(lpchFilePart, lpszOriginalExe);
|
||
|
} else {
|
||
|
_tcscpy(lpchFilePart, TEXT("*"));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Pass one. Grab all the file matching info we can.
|
||
|
//
|
||
|
hSearch = FindFirstFile(lpszRoot, &FindFileData);
|
||
|
|
||
|
if (hSearch == INVALID_HANDLE_VALUE) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInfoDir",
|
||
|
"FindFirstFile Failed on [%s].\n",
|
||
|
lpszRoot));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Comment in hStorage file where the root of the matching information is
|
||
|
//
|
||
|
if (nLevel == 0 && pinfo->bNewStorageFile) {
|
||
|
*lpchFilePart = TEXT('\0');
|
||
|
nch = _sntprintf(lpData,
|
||
|
dwBufferSize,
|
||
|
TEXT("<?xml version=\"1.0\" encoding=\"UTF-16\"?>\r\n<DATABASE>\r\n"));
|
||
|
if (nch < 0) {
|
||
|
//
|
||
|
// lpData is too small to store information
|
||
|
//
|
||
|
DBGPRINT((sdlError, "SdbpGrabMatchingInforDir", "lpData is too small\n"));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
#ifndef WIN32A_MODE
|
||
|
lpUnicodeBuffer = lpData;
|
||
|
#else
|
||
|
cchWideChar = MultiByteToWideChar(CP_ACP,
|
||
|
0,
|
||
|
lpData,
|
||
|
-1,
|
||
|
lpUnicodeBuffer,
|
||
|
dwBufferSize);
|
||
|
|
||
|
if (cchWideChar == 0) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInforDir",
|
||
|
"lpUnicodeBuffer is too small for conversion\n"));
|
||
|
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
WriteFile(hStorageFile, UNICODE_MARKER, 2, &dwBytesWritten, NULL);
|
||
|
|
||
|
WriteFile(hStorageFile,
|
||
|
lpUnicodeBuffer,
|
||
|
wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
|
||
|
&dwBytesWritten,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
if (nLevel == 0) {
|
||
|
if (dwFilter == GRABMI_FILTER_SYSTEM) {
|
||
|
_tcscpy (lpszOriginalExe, TEXT("SYSTEM INFO"));
|
||
|
}
|
||
|
|
||
|
nch = _sntprintf(lpData, dwBufferSize, TEXT("<EXE NAME=\""));
|
||
|
|
||
|
if (nch < 0) {
|
||
|
DBGPRINT((sdlError, "SdbpGrabMatchingInforDir", "lpData is to small\n"));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
if (!SdbpSanitizeXML(lpData + nch, dwBufferSize - nch, lpszOriginalExe)) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
// if we are here, we need to attach a few more things
|
||
|
nLen = _tcslen(lpData);
|
||
|
nch = _sntprintf(lpData + nLen, dwBufferSize - nLen, TEXT("\" FILTER=\"%s\">\r\n"),
|
||
|
g_szFilterDesc[dwFilter]);
|
||
|
if (nch < 0) {
|
||
|
goto eh;
|
||
|
}
|
||
|
nch += nLen;
|
||
|
|
||
|
#ifndef WIN32A_MODE
|
||
|
lpUnicodeBuffer = lpData;
|
||
|
#else
|
||
|
cchWideChar = MultiByteToWideChar(CP_ACP,
|
||
|
0,
|
||
|
lpData,
|
||
|
-1,
|
||
|
lpUnicodeBuffer,
|
||
|
dwBufferSize);
|
||
|
if (cchWideChar == 0) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInforDir",
|
||
|
"lpUnicodeBuffer is too small for conversion\n"));
|
||
|
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
#endif // WIN32A_MODE
|
||
|
|
||
|
WriteFile(hStorageFile,
|
||
|
lpUnicodeBuffer,
|
||
|
wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
|
||
|
&dwBytesWritten,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
switch (dwFilter) {
|
||
|
|
||
|
case GRABMI_FILTER_PRIVACY:
|
||
|
case GRABMI_FILTER_THISFILEONLY:
|
||
|
case GRABMI_FILTER_SYSTEM:
|
||
|
cbFileCounter = MAX_MISC_FILES_PER_LEVEL;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
//
|
||
|
// Check for directories including . and ..
|
||
|
//
|
||
|
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make a relative path with our buffer
|
||
|
//
|
||
|
_tcscpy(lpchFilePart, FindFileData.cFileName);
|
||
|
|
||
|
//
|
||
|
// lpszRelative points to the relative path
|
||
|
// lpszRoot points to the full path
|
||
|
bMiscFile = FALSE;
|
||
|
|
||
|
//
|
||
|
// Check to see if there is version information for the specified file and whether
|
||
|
// it is a .exe, .icd, ._MP, .msi, or .dll. If so print the information to the file.
|
||
|
// Otherwise, add the information if cbFileCounter is less than MAX_MISC_FILES_PER_LEVEL.
|
||
|
//
|
||
|
pchExt = PathFindExtension(lpszRoot);
|
||
|
|
||
|
switch (dwFilter) {
|
||
|
|
||
|
case GRABMI_FILTER_NORMAL:
|
||
|
case GRABMI_FILTER_PRIVACY:
|
||
|
for (i = 0; i < ARRAYSIZE(g_szGrabmiFilterNormal); i++) {
|
||
|
if (_tcsicmp(pchExt, g_szGrabmiFilterNormal[i]) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
bMiscFile = (i >= ARRAYSIZE(g_szGrabmiFilterNormal));
|
||
|
break;
|
||
|
|
||
|
case GRABMI_FILTER_SYSTEM:
|
||
|
for (i = 0; i < ARRAYSIZE(g_szGrabmiFilterSystem); i++) {
|
||
|
if (_tcsicmp(FindFileData.cFileName, g_szGrabmiFilterSystem[i]) == 0) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
bMiscFile = (i >= ARRAYSIZE(g_szGrabmiFilterSystem));
|
||
|
break;
|
||
|
|
||
|
case GRABMI_FILTER_THISFILEONLY:
|
||
|
bMiscFile = _tcsicmp(FindFileData.cFileName, lpszOriginalExe);
|
||
|
break;
|
||
|
|
||
|
case GRABMI_FILTER_DRIVERS:
|
||
|
bMiscFile = _tcsicmp(pchExt, TEXT(".sys"));
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (bMiscFile) {
|
||
|
if (cbFileCounter < MAX_MISC_FILES_PER_LEVEL) {
|
||
|
++cbFileCounter;
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// List relative data here
|
||
|
//
|
||
|
lpBuffer = lpData;
|
||
|
|
||
|
if (dwFilter == GRABMI_FILTER_DRIVERS) {
|
||
|
nch = _sntprintf(lpBuffer, dwBufferSize, TEXT(" <SYS NAME=\""));
|
||
|
} else {
|
||
|
nch = _sntprintf(lpBuffer, dwBufferSize, TEXT(" <MATCHING_FILE NAME=\""));
|
||
|
}
|
||
|
|
||
|
if (nch < 0) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
if (!SdbpSanitizeXML(lpBuffer + nch, dwBufferSize - nch, lpszRelative)) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
nLen = _tcslen(lpBuffer);
|
||
|
nch = _sntprintf(lpBuffer + nLen, dwBufferSize - nLen, TEXT("\" "));
|
||
|
|
||
|
if (nch < 0) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now we add the length -- and we're ready
|
||
|
//
|
||
|
nch += nLen;
|
||
|
|
||
|
lpBuffer += nch;
|
||
|
nchBuffer = nch; // amount of characters in lpBuffer already
|
||
|
|
||
|
//
|
||
|
// Call the attribute manager to get all the attributes for this file.
|
||
|
//
|
||
|
pAttrInfo = NULL;
|
||
|
|
||
|
if (SdbGetFileAttributes(lpszRoot, &pAttrInfo, &dwAttrCount)) {
|
||
|
|
||
|
//
|
||
|
// Loop through all the attributes and add the ones that are available.
|
||
|
//
|
||
|
TCHAR lpszAttr[MAX_PATH*2];
|
||
|
|
||
|
for (i = 0; (DWORD)i < dwAttrCount; ++i) {
|
||
|
|
||
|
if (SdbFormatAttribute(&pAttrInfo[i], lpBuffer, dwBufferSize - nchBuffer)) {
|
||
|
//
|
||
|
// lpBuffer has XML for this attribute
|
||
|
//
|
||
|
|
||
|
// insert space
|
||
|
nch = _tcslen(lpBuffer) + 1; // for space
|
||
|
|
||
|
if (dwFilter == GRABMI_FILTER_DRIVERS) {
|
||
|
switch (pAttrInfo[i].tAttrID) {
|
||
|
|
||
|
case TAG_BIN_PRODUCT_VERSION:
|
||
|
case TAG_UPTO_BIN_PRODUCT_VERSION:
|
||
|
case TAG_LINK_DATE:
|
||
|
case TAG_UPTO_LINK_DATE:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (nchBuffer + nch >= (int)dwBufferSize) {
|
||
|
//
|
||
|
// lpBuffer is not large enough to hold the information
|
||
|
//
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGetMatchingInfoDir",
|
||
|
"lpBuffer is too small to handle attributes for %s.\n",
|
||
|
lpszRelative));
|
||
|
}
|
||
|
|
||
|
_tcscat(lpBuffer, TEXT(" "));
|
||
|
|
||
|
lpBuffer += nch;
|
||
|
|
||
|
nchBuffer += nch;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
nch = _sntprintf(lpBuffer, dwBufferSize, TEXT("/>\r\n"));
|
||
|
|
||
|
if (nch < 0) {
|
||
|
//
|
||
|
// Buffer is too small.
|
||
|
//
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfoDir",
|
||
|
"lpBuffer is too small to handle attributes for %s.\n",
|
||
|
lpszRelative));
|
||
|
continue;
|
||
|
}
|
||
|
//
|
||
|
// Check to see if using unicode or not. If not, convert
|
||
|
// to unicode.
|
||
|
//
|
||
|
#ifndef WIN32A_MODE
|
||
|
lpUnicodeBuffer = lpData;
|
||
|
#else
|
||
|
cchWideChar = MultiByteToWideChar(CP_ACP,
|
||
|
0,
|
||
|
lpData,
|
||
|
-1,
|
||
|
lpUnicodeBuffer,
|
||
|
dwBufferSize);
|
||
|
if (cchWideChar == 0) {
|
||
|
//
|
||
|
// buffer is not large enough for conversion
|
||
|
//
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbpGrabMatchingInforDir",
|
||
|
"lpUnicodeBuffer is not large enough for conversion\n"));
|
||
|
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
#endif // WIN32A_MODE
|
||
|
|
||
|
if (pinfo->pfnCallback) {
|
||
|
if (!pinfo->pfnCallback(pinfo->lpvCallbackParameter,
|
||
|
lpszRoot, // give straight name
|
||
|
lpszRelative, // relative name
|
||
|
pAttrInfo, // pointer to the attributes
|
||
|
lpUnicodeBuffer)) { // xml output
|
||
|
Result = GMI_CANCELLED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WriteFile(hStorageFile,
|
||
|
lpUnicodeBuffer,
|
||
|
wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
|
||
|
&dwBytesWritten,
|
||
|
NULL);
|
||
|
|
||
|
if (pAttrInfo) {
|
||
|
SdbFreeFileAttributes(pAttrInfo);
|
||
|
pAttrInfo = NULL; // make sure we do not free it twice
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check to see whether we have reached the file limit
|
||
|
//
|
||
|
if (pinfo->MaxFiles && ++pinfo->FileCount >= pinfo->MaxFiles && Result != GMI_CANCELLED) {
|
||
|
Result = GMI_SUCCESS; // limit reached, grabmi cancelled
|
||
|
nLevel = MAX_LEVELS_OF_DIRECTORIES; // this is so that we bail out
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FindNextFile(hSearch, &FindFileData) && (Result != GMI_CANCELLED));
|
||
|
|
||
|
FindClose(hSearch);
|
||
|
hSearch = INVALID_HANDLE_VALUE;
|
||
|
|
||
|
if (Result == GMI_CANCELLED) {
|
||
|
goto CloseTags;
|
||
|
}
|
||
|
|
||
|
if (dwFilter != GRABMI_FILTER_SYSTEM && dwFilter != GRABMI_FILTER_THISFILEONLY) {
|
||
|
if (nLevel >= MAX_LEVELS_OF_DIRECTORIES || (dwFilterFlags & GRABMI_FILTER_NORECURSE)) {
|
||
|
Result = GMI_SUCCESS; // not a failure, just a limiting case
|
||
|
goto eh; // done
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Replace the filename in szSearchFile with "*" -- hack!
|
||
|
//
|
||
|
_tcscpy(lpchFilePart, TEXT("*"));
|
||
|
|
||
|
hSearch = FindFirstFile(lpszRoot, &FindFileData);
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE == hSearch) {
|
||
|
//
|
||
|
// lpszRoot does not contain any matching files
|
||
|
//
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfoDir",
|
||
|
"%s contains no matching files!\n",
|
||
|
lpszRoot));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now go through the subdirectories and grab that information.
|
||
|
//
|
||
|
do {
|
||
|
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ((_tcscmp(FindFileData.cFileName, TEXT(".")) == 0) ||
|
||
|
(_tcscmp( FindFileData.cFileName, TEXT("..")) == 0)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Form relative path here by copying lpszRelative and appending cFileName and '\\'
|
||
|
//
|
||
|
_tcscpy(lpchFilePart, FindFileData.cFileName);
|
||
|
_tcscat(lpchFilePart, TEXT("\\"));
|
||
|
|
||
|
//
|
||
|
// Recusive call. Check return result for having been cancelled !!!
|
||
|
//
|
||
|
Result = SdbpGrabMatchingInfoDir(hStorageFile,
|
||
|
pinfo,
|
||
|
dwFilterAndFlags,
|
||
|
lpszRoot,
|
||
|
NULL,
|
||
|
lpszRelative,
|
||
|
nLevel + 1);
|
||
|
|
||
|
if (Result == GMI_CANCELLED) {
|
||
|
//
|
||
|
// We are cancelled. Write out a valid database code to close
|
||
|
// this if we have the option set.
|
||
|
//
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FindNextFile(hSearch, &FindFileData));
|
||
|
|
||
|
}
|
||
|
|
||
|
CloseTags:
|
||
|
//
|
||
|
// This is where we close the tags if instructed to do so
|
||
|
//
|
||
|
if (nLevel == 0) {
|
||
|
wcscpy (lpUnicodeBuffer, L"</EXE>\r\n");
|
||
|
|
||
|
if (!(dwFilterFlags & GRABMI_FILTER_NOCLOSE)) {
|
||
|
wcscat(lpUnicodeBuffer, L"</DATABASE>\r\n");
|
||
|
}
|
||
|
|
||
|
WriteFile(hStorageFile,
|
||
|
lpUnicodeBuffer,
|
||
|
wcslen(lpUnicodeBuffer) * sizeof(WCHAR),
|
||
|
&dwBytesWritten,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check how we got here -- was it via the cancel route ?
|
||
|
//
|
||
|
if (Result == GMI_CANCELLED) {
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Information gathered successfully.
|
||
|
//
|
||
|
Result = GMI_SUCCESS;
|
||
|
|
||
|
eh:
|
||
|
|
||
|
if (INVALID_HANDLE_VALUE != hSearch) {
|
||
|
FindClose(hSearch);
|
||
|
}
|
||
|
if (lpData != NULL) {
|
||
|
SdbFree(lpData);
|
||
|
}
|
||
|
|
||
|
#ifdef WIN32A_MODE
|
||
|
if (lpUnicodeBuffer != NULL) {
|
||
|
SdbFree(lpUnicodeBuffer);
|
||
|
}
|
||
|
#endif // WIN32A_MODE
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
SDBAPI
|
||
|
SdbGrabMatchingInfo(
|
||
|
LPCTSTR szMatchingPath,
|
||
|
DWORD dwFilter,
|
||
|
LPCTSTR szFile
|
||
|
)
|
||
|
{
|
||
|
return SdbGrabMatchingInfoEx(szMatchingPath, dwFilter, szFile, NULL, NULL) == GMI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
GMI_RESULT
|
||
|
SDBAPI
|
||
|
SdbGrabMatchingInfoEx(
|
||
|
LPCTSTR szMatchingPath, // path to begin gathering information
|
||
|
DWORD dwFilterAndFlags, // specifies the types of files to be added to matching
|
||
|
LPCTSTR szFile, // full path to file where information will be stored
|
||
|
PFNGMIProgressCallback pfnCallback,
|
||
|
LPVOID lpvCallbackParameter
|
||
|
)
|
||
|
{
|
||
|
HANDLE hStorageFile = INVALID_HANDLE_VALUE;
|
||
|
LPTSTR lpRootDirectory = NULL;
|
||
|
LPTSTR pchBackslash;
|
||
|
LPTSTR lpRelative;
|
||
|
TCHAR szOriginalExe[MAX_PATH] = {TEXT("Exe Not Specified")};
|
||
|
int nDirLen, nLevel = 0;
|
||
|
DWORD dwAttributes;
|
||
|
GMI_RESULT Result = GMI_FAILED;
|
||
|
DWORD dwFilter = (dwFilterAndFlags & ~GRABMI_FLAGS_MASK);
|
||
|
DWORD dwFilterFlags = (dwFilterAndFlags & GRABMI_FLAGS_MASK);
|
||
|
RECINFO info;
|
||
|
|
||
|
//
|
||
|
// Check to see if dwFilter is a know value
|
||
|
//
|
||
|
if (dwFilter != GRABMI_FILTER_NORMAL &&
|
||
|
dwFilter != GRABMI_FILTER_PRIVACY &&
|
||
|
dwFilter != GRABMI_FILTER_DRIVERS &&
|
||
|
dwFilter != GRABMI_FILTER_VERBOSE &&
|
||
|
dwFilter != GRABMI_FILTER_SYSTEM &&
|
||
|
dwFilter != GRABMI_FILTER_THISFILEONLY) {
|
||
|
|
||
|
//
|
||
|
// Unknown filter specified.
|
||
|
//
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfo",
|
||
|
"dwFilter is not a recognized filter.\n"));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
RtlZeroMemory(&info, sizeof(info));
|
||
|
|
||
|
info.pfnCallback = pfnCallback;
|
||
|
info.lpvCallbackParameter = lpvCallbackParameter;
|
||
|
info.MaxFiles = (dwFilterFlags & GRABMI_FILTER_LIMITFILES) ? GRABMI_IMPOSED_FILE_LIMIT : 0;
|
||
|
info.FileCount = 0;
|
||
|
info.bNewStorageFile = TRUE;
|
||
|
|
||
|
lpRootDirectory = (LPTSTR)SdbAlloc(4096 * sizeof(TCHAR));
|
||
|
|
||
|
if (lpRootDirectory == NULL) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfo",
|
||
|
"Unable to allocate memory for lpRootDirectory."));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
if (dwFilter == GRABMI_FILTER_SYSTEM) {
|
||
|
GetSystemDirectory (lpRootDirectory, MAX_PATH);
|
||
|
_tcscat (lpRootDirectory, TEXT("\\"));
|
||
|
|
||
|
} else {
|
||
|
dwAttributes = GetFileAttributes(szMatchingPath);
|
||
|
|
||
|
if (dwAttributes == (DWORD)-1) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfo",
|
||
|
"GetFileAttributes failed or %s is not a valid path",
|
||
|
szMatchingPath));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
_tcscpy (lpRootDirectory, szMatchingPath);
|
||
|
nDirLen = _tcslen(lpRootDirectory);
|
||
|
|
||
|
//
|
||
|
// See if location specified exists and if so determine
|
||
|
// whether its a file or directory
|
||
|
//
|
||
|
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
|
//
|
||
|
// Is this a directory ?
|
||
|
//
|
||
|
if (nDirLen > 0 && lpRootDirectory[nDirLen-1] != TEXT('\\')) {
|
||
|
_tcscat(lpRootDirectory, TEXT("\\"));
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// A path containing a file name was passed as szMatchingPath.
|
||
|
// Determine what the containing dir is.
|
||
|
//
|
||
|
pchBackslash = _tcsrchr(lpRootDirectory, TEXT('\\'));
|
||
|
|
||
|
if (NULL == pchBackslash) {
|
||
|
_tcscpy (szOriginalExe, lpRootDirectory);
|
||
|
GetCurrentDirectory (MAX_PATH*16, lpRootDirectory);
|
||
|
_tcscat (lpRootDirectory, TEXT("\\"));
|
||
|
|
||
|
} else {
|
||
|
pchBackslash = CharNext(pchBackslash);
|
||
|
_tcscpy (szOriginalExe, pchBackslash);
|
||
|
*pchBackslash = TEXT('\0');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lpRelative = lpRootDirectory + _tcslen(lpRootDirectory);
|
||
|
|
||
|
//
|
||
|
// Check to see if szOriginalExe is not NULL if
|
||
|
// GRABMI_FILTER_THISFILEONLY was selected.
|
||
|
//
|
||
|
if (dwFilter == GRABMI_FILTER_THISFILEONLY && szOriginalExe == '\0' ) {
|
||
|
DBGPRINT((sdlError,
|
||
|
"SdbGrabMatchingInfo",
|
||
|
"GRABMI_FILTER_THISFILEONLY specified but passed in a directory: %s.",
|
||
|
lpRootDirectory));
|
||
|
goto eh;
|
||
|
|
||
|
} else if (dwFilterFlags & GRABMI_FILTER_APPEND) {
|
||
|
//
|
||
|
// Open the file where the information will be stored.
|
||
|
//
|
||
|
hStorageFile = CreateFile(szFile,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
OPEN_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
|
||
|
if (ERROR_ALREADY_EXISTS == GetLastError()) {
|
||
|
SetFilePointer (hStorageFile, 0, NULL, FILE_END);
|
||
|
info.bNewStorageFile = FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// Open the file where the information will be stored.
|
||
|
//
|
||
|
hStorageFile = CreateFile(szFile,
|
||
|
GENERIC_WRITE,
|
||
|
0,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
if (hStorageFile == INVALID_HANDLE_VALUE) {
|
||
|
DBGPRINT((sdlError, "SdbGrabMatchingInfo", "Unable to open the storage file."));
|
||
|
goto eh;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Call the API which does the bulk of the work
|
||
|
//
|
||
|
Result = SdbpGrabMatchingInfoDir(hStorageFile,
|
||
|
&info,
|
||
|
dwFilterAndFlags,
|
||
|
lpRootDirectory,
|
||
|
szOriginalExe,
|
||
|
lpRelative,
|
||
|
nLevel);
|
||
|
|
||
|
eh:
|
||
|
|
||
|
if (hStorageFile != INVALID_HANDLE_VALUE) {
|
||
|
CloseHandle(hStorageFile);
|
||
|
}
|
||
|
|
||
|
if (lpRootDirectory) {
|
||
|
SdbFree(lpRootDirectory);
|
||
|
}
|
||
|
|
||
|
return Result;
|
||
|
}
|
||
|
|