|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
GrabMatchingInformation.cpp
Abstract:
Upon ProcessAttach the shim gathers matching information from the current directory.
Notes:
This is a general purpose shim.
History:
20-Oct-2000 jdoherty Created
--*/ #include "precomp.h"
#include <stdio.h>
// This module is *not* DBCS safe, but should only be used by our testers
// We should, eventually, correct this file.
// This module has been given an official blessing to use the str routines.
#include "LegalStr.h"
IMPLEMENT_SHIM_BEGIN(GrabMatchingInformation) #include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN APIHOOK_ENUM_ENTRY(GetCommandLineA) APIHOOK_ENUM_ENTRY(GetCommandLineW) APIHOOK_ENUM_END
BOOL gbCalledHook; LPSTR glpOriginalRootDir; VOID GrabMatchingInformationMain(); BOOL GrabMatchingInfo(LPSTR lpRootDirectory, HANDLE hStorageFile, int nLevel); BOOL GetRelativePath(LPSTR lpPathFromRoot, LPCSTR lpSubDir, LPCSTR lpFileName); VOID AddMatchingFile( LPSTR lpData, LPCSTR pszFullPath, LPCSTR pszRelativePath );
LPSTR APIHOOK(GetCommandLineA)() { if (!gbCalledHook) { int nLength = 0; LPSTR lpCursorEnd; glpOriginalRootDir = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); GetModuleFileNameA( NULL, glpOriginalRootDir, MAX_PATH ); nLength = strlen( glpOriginalRootDir ); lpCursorEnd = &glpOriginalRootDir[nLength-1]; while( --nLength ) { if ( *(lpCursorEnd) == '\\' ) { *(lpCursorEnd) = '\0'; break; } lpCursorEnd--; if (nLength==0) { GetCurrentDirectoryA( MAX_PATH, glpOriginalRootDir ); } } GrabMatchingInformationMain(); ShimFree(glpOriginalRootDir); gbCalledHook = TRUE; } return ORIGINAL_API(GetCommandLineA)(); }
LPWSTR APIHOOK(GetCommandLineW)() { if (!gbCalledHook) { int nLength = 0; LPSTR lpCursorEnd; glpOriginalRootDir = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); GetModuleFileNameA( NULL, glpOriginalRootDir, MAX_PATH ); nLength = strlen( glpOriginalRootDir ); lpCursorEnd = &glpOriginalRootDir[nLength-1]; while( --nLength ) { if ( *(lpCursorEnd) == '\\' ) { *(lpCursorEnd) = '\0'; break; } lpCursorEnd--; if (nLength==0) { GetCurrentDirectoryA( MAX_PATH, glpOriginalRootDir ); } } GrabMatchingInformationMain(); ShimFree(glpOriginalRootDir); gbCalledHook = TRUE; }
return ORIGINAL_API(GetCommandLineW)(); }
VOID GrabMatchingInformationMain() { HANDLE hMutexHandle; LPSTR lpStorageFilePath; LPSTR lpDirInfo; LPSTR lpRootDir; HANDLE hStorageFile; DWORD dwBytesWritten = 0;
lpStorageFilePath = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); lpDirInfo = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); lpRootDir = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR));
// Setup a mutex so only one process at a time can write to the matchinginfo.txt file.
hMutexHandle = CreateMutexA( NULL, FALSE, "MyGrabMIFileMutex" ); WaitForSingleObject( hMutexHandle, INFINITE );
// Build path to where the matching information will be stored.
SHGetSpecialFolderPathA(NULL, lpStorageFilePath, CSIDL_DESKTOPDIRECTORY, TRUE ); strcat( lpStorageFilePath, "\\matchinginfo.txt" );
/*
if ( (strcmp(glpOriginalRootDir ,".") == 0) || (strcmp(glpOriginalRootDir ,"") == 0) ) { GetCurrentDirectoryA( MAX_PATH, glpOriginalRootDir ); } */ // Open matchinginfo.txt on the desktop for write if it exists and set the file pointer to the end
// of the file, create a new file otherwise.
hStorageFile = CreateFileA( lpStorageFilePath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
SetFilePointer( hStorageFile, NULL, NULL, FILE_END );
if (hStorageFile == INVALID_HANDLE_VALUE) { return; } sprintf(lpDirInfo, "<!-- Generating matching information for files in: [ %s ]For Process: [ %s ]-->\r\n", glpOriginalRootDir, GetCommandLineA() ); WriteFile( hStorageFile, lpDirInfo, strlen(lpDirInfo), &dwBytesWritten, NULL ); strcpy(lpRootDir, glpOriginalRootDir);
if (!GrabMatchingInfo(lpRootDir, hStorageFile, 0)) { CloseHandle(hStorageFile); return; }
CloseHandle(hStorageFile);
ShimFree(lpStorageFilePath); ShimFree(lpDirInfo); ShimFree(lpRootDir);
ReleaseMutex( hMutexHandle );
return; }
/*++
This function traverses lpRootDirectory and it's subdirectories while storing the size and checksum for the files in those directories.
--*/ BOOL GrabMatchingInfo(LPSTR lpRootDirectory, HANDLE hStorageFile, int nLevel) {
WIN32_FIND_DATAA FindFileData; HANDLE hSearch; // Search handle returned by FindFirstFile
LPSTR lpSubDir; LPSTR lpFilePath; LPSTR lpData; LPSTR lpPathFromRoot; DWORD dwBytesWritten = 0;
int cbFileCounter = 0; lpSubDir = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); lpFilePath = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); lpData = (LPSTR) ShimMalloc((MAX_PATH*2)*sizeof(LPSTR)); lpPathFromRoot = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR));
// Just repeat displaying a dot so the user knows something is happening.
// USED IN GRABMI
// printf(".");
strcpy (lpSubDir, lpRootDirectory);
strcat(lpRootDirectory, "\\*");
if ( (hSearch=FindFirstFileA( lpRootDirectory, &FindFileData )) == INVALID_HANDLE_VALUE ) { return FALSE; }
BOOL bRepeat = FALSE;
while ( (strcmp( FindFileData.cFileName, "." ) == 0) || (strcmp( FindFileData.cFileName, ".." ) == 0) && !bRepeat ) { FindNextFileA(hSearch, &FindFileData); if ( strcmp( FindFileData.cFileName, ".." ) == 0 ) bRepeat = TRUE; }
if (!FindNextFileA(hSearch, &FindFileData)) { return TRUE; }
do { if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { // Build path for matching file
strcpy(lpFilePath, lpSubDir); strcat(lpFilePath, "\\"); strcat(lpFilePath, FindFileData.cFileName);
ZeroMemory( lpData, (MAX_PATH*2)*sizeof(LPSTR) );
// Determine the relative path for the file from the original root directory.
if (!GetRelativePath(lpPathFromRoot, lpSubDir, FindFileData.cFileName)) strcpy(lpPathFromRoot, FindFileData.cFileName);
// Check to see if there is version information for the specified file and whether it is
// an .exe, .icd, ._MP, or .dll. If so add the information to the file.
if ( stristr(lpFilePath, ".exe") || stristr(lpFilePath, ".icd") || stristr(lpFilePath, "._MP") || stristr(lpFilePath, ".dll") ) { AddMatchingFile( lpData, lpFilePath, lpPathFromRoot ); } else { // Limit the amount of info gathered to 10 files per directory excluding the above file types.
if (cbFileCounter < 10) { cbFileCounter++; AddMatchingFile( lpData, lpFilePath, lpPathFromRoot ); } }
// Write the information stored in lpData to the file
WriteFile( hStorageFile, lpData, strlen(lpData), &dwBytesWritten, NULL ); } } while ( FindNextFileA( hSearch, &FindFileData ) );
/////////////////////////////////////////////////////////////////////////////////
//
// Now go through the directory again and go into the subdirectories
//
/////////////////////////////////////////////////////////////////////////////////
if (strlen(lpRootDirectory) < 4) { if ( (hSearch=FindFirstFileA(lpRootDirectory, &FindFileData)) == INVALID_HANDLE_VALUE) { return FALSE; } } else { if ( (hSearch=FindFirstFileA(lpRootDirectory, &FindFileData)) == INVALID_HANDLE_VALUE) { return FALSE; } FindNextFileA(hSearch, &FindFileData); if (!FindNextFileA(hSearch, &FindFileData)) { FindClose( hSearch ); return TRUE; } }
do { if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && nLevel < 3) { strcat(lpSubDir, "\\"); strcat(lpSubDir, FindFileData.cFileName);
GrabMatchingInfo (lpSubDir, hStorageFile, nLevel+1); lpSubDir[strlen(lpSubDir)-2]='\0';
strcpy(lpSubDir, lpRootDirectory); lpSubDir[strlen(lpSubDir)-2]='\0'; } }while ( FindNextFileA( hSearch, &FindFileData ) );
FindClose(hSearch);
ShimFree(lpSubDir); ShimFree(lpFilePath); ShimFree(lpData); ShimFree(lpPathFromRoot);
return TRUE; }
BOOL GetRelativePath(LPSTR lpPathFromRoot, LPCSTR lpSubDir, LPCSTR lpFileName) {
int difference=(strlen(lpSubDir)-strlen(glpOriginalRootDir)); if (difference) { for (int i=0; i < difference; i++) { lpPathFromRoot[i] = lpSubDir[strlen(glpOriginalRootDir)+i+1]; } strcat(lpPathFromRoot, "\\"); strcat(lpPathFromRoot, lpFileName); difference=0; return TRUE; } return FALSE; }
/*++
AddMatchingFile
Description: Adds a matching file and it's attributes to the tree.
--*/ VOID AddMatchingFile( OUT LPSTR lpData, IN LPCSTR pszFullPath, IN LPCSTR pszRelativePath ) { PATTRINFO pAttrInfo; DWORD dwAttrCount;
LPWSTR pwszFullPath; pwszFullPath = (LPWSTR) ShimMalloc(MAX_PATH*sizeof(LPWSTR)); mbstowcs( pwszFullPath, pszFullPath, MAX_PATH );
//
// Call the attribute manager to get all the attributes for this file.
//
if (SdbGetFileAttributes(pwszFullPath, &pAttrInfo, &dwAttrCount)) { LPSTR lpBuffer; LPWSTR lpwBuffer;
lpBuffer = (LPSTR) ShimMalloc(MAX_PATH*sizeof(LPSTR)); lpwBuffer = (LPWSTR) ShimMalloc(MAX_PATH*sizeof(LPWSTR));
//
// Loop through all the attributes and show the ones that are available.
//
// ZeroMemory( lpData, (MAX_PATH*2)*sizeof(LPSTR) );
sprintf(lpData, "<MATCHING_FILE NAME=\"%s\" ", pszRelativePath); for (DWORD i = 0; i < dwAttrCount; ++i) { if ( SdbFormatAttribute(&pAttrInfo[i], lpwBuffer, MAX_PATH) )//CHARCOUNT(lpwBuffer)))
{ ZeroMemory( lpBuffer, MAX_PATH*sizeof(LPSTR) ); wcstombs( lpBuffer, lpwBuffer, wcslen (lpwBuffer) ); //
// wszBuffer has XML for this attribute
//
strcat( lpData, lpBuffer ); strcat( lpData, " " ); } } strcat( lpData, "/>\r\n" ); ShimFree( lpBuffer ); ShimFree( lpwBuffer ); SdbFreeFileAttributes(pAttrInfo); } ShimFree( pwszFullPath ); }
/*++
Handle DLL_PROCESS_ATTACH and DLL_PROCESS_DETACH in your notify function to do initialization and uninitialization.
IMPORTANT: Make sure you ONLY call NTDLL, KERNEL32 and MSVCRT APIs during DLL_PROCESS_ATTACH notification. No other DLLs are initialized at that point. If your shim cannot initialize properly, return FALSE and none of the APIs specified will be hooked. --*/ BOOL NOTIFY_FUNCTION( DWORD fdwReason) { if (fdwReason == DLL_PROCESS_ATTACH) { gbCalledHook = FALSE;
DPFN( eDbgLevelInfo, "Beginng to Grab Information."); }
return TRUE; }
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineA) APIHOOK_ENTRY(KERNEL32.DLL, GetCommandLineW)
CALL_NOTIFY_FUNCTION
HOOK_END
IMPLEMENT_SHIM_END
|