386 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			386 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
| //////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| //  Detour Test Program (symtest.cpp of symtest.exe)
 | |
| //
 | |
| //  Microsoft Research Detours Package
 | |
| //
 | |
| //  Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //
 | |
| 
 | |
| #include <windows.h>
 | |
| #include <stdio.h>
 | |
| #pragma warning(push)
 | |
| #if _MSC_VER > 1400
 | |
| #pragma warning(disable:6102 6103) // /analyze warnings
 | |
| #endif
 | |
| #include <strsafe.h>
 | |
| #pragma warning(pop)
 | |
| #include <detours.h>
 | |
| #include "target.h"
 | |
| 
 | |
| #if (_MSC_VER < 1299)
 | |
| #include <imagehlp.h>
 | |
| typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
 | |
| typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
 | |
| typedef IMAGEHLP_SYMBOL SYMBOL_INFO;
 | |
| typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO;
 | |
| #else
 | |
| #pragma warning(push)
 | |
| #pragma warning(disable:4091) // empty typedef
 | |
| #include <dbghelp.h>
 | |
| #pragma warning(pop)
 | |
| #endif
 | |
| 
 | |
| //////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion);
 | |
| 
 | |
| typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess,
 | |
|                                        IN LPCSTR UserSearchPath,
 | |
|                                        IN BOOL fInvadeProcess);
 | |
| typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions);
 | |
| typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
 | |
| typedef DWORD64 (NTAPI *PF_SymLoadModule64)(IN HANDLE hProcess,
 | |
|                                             IN HANDLE hFile,
 | |
|                                             IN PSTR ImageName,
 | |
|                                             IN PSTR ModuleName,
 | |
|                                             IN DWORD64 BaseOfDll,
 | |
|                                             IN DWORD SizeOfDll);
 | |
| typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(IN HANDLE hProcess,
 | |
|                                             IN DWORD64 qwAddr,
 | |
|                                             OUT PIMAGEHLP_MODULE64 ModuleInfo);
 | |
| typedef BOOL (NTAPI *PF_SymFromName)(IN HANDLE hProcess,
 | |
|                                      IN LPSTR Name,
 | |
|                                      OUT PSYMBOL_INFO Symbol);
 | |
| #if (_MSC_VER < 1299)
 | |
| typedef BOOL (NTAPI *PF_SymRegisterCallback64)();
 | |
| typedef BOOL (NTAPI *PF_SymEnumerateModules64)();
 | |
| typedef BOOL (NTAPI *PF_SymEnumSymbols)();
 | |
| #else
 | |
| typedef BOOL (NTAPI *PF_SymRegisterCallback64)(IN HANDLE hProcess,
 | |
|                                                IN PSYMBOL_REGISTERED_CALLBACK64
 | |
|                                                CallbackFunction,
 | |
|                                                IN ULONG64 UserContext);
 | |
| typedef BOOL (NTAPI *PF_SymEnumerateModules64)(IN HANDLE hProcess,
 | |
|                                                IN PSYM_ENUMMODULES_CALLBACK64
 | |
|                                                EnumModulesCallback,
 | |
|                                                IN PVOID UserContext);
 | |
| typedef BOOL (NTAPI *PF_SymEnumSymbols)(IN HANDLE hProcess,
 | |
|                                         IN ULONG64 BaseOfDll,
 | |
|                                         IN PCSTR Mask,
 | |
|                                         IN PSYM_ENUMERATESYMBOLS_CALLBACK
 | |
|                                         EnumSymbolsCallback,
 | |
|                                         IN PVOID UserContext);
 | |
| #endif
 | |
| 
 | |
| PF_ImagehlpApiVersionEx     pfImagehlpApiVersionEx = NULL;
 | |
| PF_SymInitialize            pfSymInitialize = NULL;
 | |
| PF_SymSetOptions            pfSymSetOptions = NULL;
 | |
| PF_SymGetOptions            pfSymGetOptions = NULL;
 | |
| PF_SymLoadModule64          pfSymLoadModule64 = NULL;
 | |
| PF_SymGetModuleInfo64       pfSymGetModuleInfo64 = NULL;
 | |
| PF_SymFromName              pfSymFromName = NULL;
 | |
| PF_SymRegisterCallback64    pfSymRegisterCallback64 = NULL;
 | |
| PF_SymEnumerateModules64    pfSymEnumerateModules64 = NULL;
 | |
| PF_SymEnumSymbols           pfSymEnumSymbols = NULL;
 | |
| 
 | |
| //////////////////////////////////////////////////////////////////////////////
 | |
| //
 | |
| 
 | |
| #if (_MSC_VER > 1299)
 | |
| static BOOL WINAPI SymEnumerateCallback(
 | |
|                                         PCSTR pszModule,
 | |
|                                         DWORD64 base,
 | |
|                                         PVOID pvUserContext)
 | |
| {
 | |
|     (void)pvUserContext;
 | |
|     printf("  %p: %s\n", (PVOID)base, pszModule);
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static int nSymbolCount = 0;
 | |
| static BOOL WINAPI SymEnumerateSymbols(PSYMBOL_INFO pSym,
 | |
|                                        ULONG size,
 | |
|                                        PVOID pvUserContext)
 | |
| {
 | |
|     (void)size;
 | |
|     (void)pvUserContext;
 | |
|     if (strstr(pSym->Name, "Target") != NULL ||
 | |
|         strstr(pSym->Name, "Hidden") != NULL) {
 | |
|         printf("  %p: %s\n", (PVOID)pSym->Address, pSym->Name);
 | |
|         nSymbolCount++;
 | |
|     }
 | |
|     else if (nSymbolCount < 5) {
 | |
|         printf("  %p: %s\n", (PVOID)pSym->Address, pSym->Name);
 | |
|         nSymbolCount++;
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| static void truncate(PCHAR data)
 | |
| {
 | |
|     size_t len = strlen(data);
 | |
|     if (len > 0 && data[len-1] == '\r') {
 | |
|         data[--len] = '\0';
 | |
|     }
 | |
|     if (len > 0 && data[len-1] == '\n') {
 | |
|         data[--len] = '\0';
 | |
|     }
 | |
| }
 | |
| 
 | |
| BOOL WINAPI CallbackFunction(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 context)
 | |
| {
 | |
|     (void)context;
 | |
| 
 | |
|     switch (action) {
 | |
|       case CBA_DEBUG_INFO:
 | |
|         truncate((PCHAR)data);
 | |
|         printf("::> %s\n", (PCHAR)data);
 | |
|         return TRUE;
 | |
| 
 | |
|       case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
 | |
|         printf("::> proc=%p action=%08lx data=%p\n",
 | |
|                       (PVOID)hProcess,
 | |
|                       action,
 | |
|                       (PVOID)data);
 | |
|         {
 | |
|             PIMAGEHLP_DEFERRED_SYMBOL_LOAD64 pi = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD64)data;
 | |
|             printf("pi->SizeOfStruct = %ld\n", pi->SizeOfStruct);
 | |
|             printf("pi->BaseOfImage  = %p\n", (PVOID)(size_t)pi->BaseOfImage);
 | |
|             printf("pi->CheckSum     = %8lx\n", pi->CheckSum);
 | |
|             printf("pi->FileName     = %p [%s]\n", pi->FileName, pi->FileName);
 | |
|             printf("pi->Reparse      = %d\n", pi->Reparse);
 | |
|         }
 | |
|         return FALSE;
 | |
|       default:
 | |
|         printf("::> proc=%p action=%08lx data=%p\n",
 | |
|                       (PVOID)hProcess,
 | |
|                       action,
 | |
|                       (PVOID)data);
 | |
|         return FALSE;
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int __cdecl main(void)
 | |
| {
 | |
|     printf("symtest.exe: Starting.\n");
 | |
|     fflush(stdout);
 | |
| 
 | |
|     //////////////////////////////////////////////////////// Get the functions.
 | |
|     //
 | |
|     HMODULE hDbgHelp = LoadLibraryA("dbghelp.dll");
 | |
|     if (hDbgHelp == NULL) {
 | |
|         printf("Couldn't load dbghelp.dll");
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
|     pfImagehlpApiVersionEx
 | |
|         = (PF_ImagehlpApiVersionEx)GetProcAddress(hDbgHelp,
 | |
|                                                   "ImagehlpApiVersionEx");
 | |
|     pfSymInitialize
 | |
|         = (PF_SymInitialize)GetProcAddress(hDbgHelp, "SymInitialize");
 | |
|     pfSymSetOptions
 | |
|         = (PF_SymSetOptions)GetProcAddress(hDbgHelp, "SymSetOptions");
 | |
|     pfSymGetOptions
 | |
|         = (PF_SymGetOptions)GetProcAddress(hDbgHelp, "SymGetOptions");
 | |
|     pfSymLoadModule64
 | |
|         = (PF_SymLoadModule64)GetProcAddress(hDbgHelp, "SymLoadModule64");
 | |
|     pfSymGetModuleInfo64
 | |
|         = (PF_SymGetModuleInfo64)GetProcAddress(hDbgHelp, "SymGetModuleInfo64");
 | |
|     pfSymFromName
 | |
|         = (PF_SymFromName)GetProcAddress(hDbgHelp, "SymFromName");
 | |
|     pfSymRegisterCallback64
 | |
|         = (PF_SymRegisterCallback64)GetProcAddress(hDbgHelp, "SymRegisterCallback64");
 | |
|     pfSymEnumerateModules64
 | |
|         = (PF_SymEnumerateModules64)GetProcAddress(hDbgHelp, "SymEnumerateModules64");
 | |
|     pfSymEnumSymbols
 | |
|         = (PF_SymEnumSymbols)GetProcAddress(hDbgHelp, "SymEnumSymbols");
 | |
| 
 | |
|     //////////////////////////////////////////////////////////////////////////////
 | |
|     //
 | |
|     HANDLE hProcess = GetCurrentProcess();
 | |
| 
 | |
|     API_VERSION av;
 | |
|     ZeroMemory(&av, sizeof(av));
 | |
|     av.MajorVersion = API_VERSION_NUMBER;
 | |
| 
 | |
|     pfImagehlpApiVersionEx(&av);
 | |
|     printf("  Version: %d.%d (%d)\n",
 | |
|                   av.MajorVersion,
 | |
|                   av.MinorVersion,
 | |
|                   API_VERSION_NUMBER);
 | |
| 
 | |
|     if (!pfSymInitialize(hProcess, NULL, FALSE)) {
 | |
|         printf("SymInitialize failed: %ld\n", GetLastError());
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
| #if (_MSC_VER > 1299)
 | |
|     pfSymRegisterCallback64(hProcess, CallbackFunction, NULL);
 | |
| #endif
 | |
| 
 | |
|     DWORD dw = pfSymGetOptions();
 | |
|     printf("GetOptions = %08lx\n", dw);
 | |
|     dw &= ~(SYMOPT_CASE_INSENSITIVE |
 | |
|             SYMOPT_UNDNAME |
 | |
|             SYMOPT_DEFERRED_LOADS |
 | |
|             0);
 | |
|     dw |= (
 | |
| #if defined(SYMOPT_EXACT_SYMBOLS)
 | |
|            SYMOPT_EXACT_SYMBOLS |
 | |
| #endif
 | |
| #if defined(SYMOPT_DEBUG)
 | |
|            SYMOPT_DEBUG |
 | |
| #endif
 | |
| #if defined(SYMOPT_NO_UNQUALIFIED_LOADS)
 | |
|            SYMOPT_NO_UNQUALIFIED_LOADS |
 | |
| #endif
 | |
| #if defined(SYMOPT_FAIL_CRITICAL_ERRORS)
 | |
|            SYMOPT_FAIL_CRITICAL_ERRORS |
 | |
| #endif
 | |
| #if defined(SYMOPT_INCLUDE_32BIT_MODULES)
 | |
|            SYMOPT_INCLUDE_32BIT_MODULES |
 | |
| #endif
 | |
|            0);
 | |
|     printf("SetOptions = %08lx\n", dw);
 | |
|     pfSymSetOptions(dw);
 | |
| 
 | |
|     /////////////////////////////////////////////// First, try GetProcAddress.
 | |
|     //
 | |
|     PCHAR pszFile = "target" DETOURS_STRINGIFY(DETOURS_BITS) ".dll";
 | |
|     HMODULE hModule = LoadLibraryA(pszFile);
 | |
|     if (hModule == NULL) {
 | |
|         printf("LoadLibraryA(%s) failed: %ld\n", pszFile, GetLastError());
 | |
|         return 2;
 | |
|     }
 | |
| 
 | |
|     ////////////////////////////////////////////////////// Then try ImageHelp.
 | |
|     //
 | |
| #if (_MSC_VER > 1299)
 | |
| 
 | |
|     //CHAR szFull[MAX_PATH];
 | |
|     //GetModuleFileNameA(hModule, szFull, sizeof(szFull));
 | |
|     printf("SymLoadModule64(%s) will be called.\n", pszFile /*szFull*/);
 | |
|     DWORD64 loaded = pfSymLoadModule64(hProcess, NULL,
 | |
|                                        (PCHAR)pszFile/*szFull*/, NULL,
 | |
|                                        (DWORD64)hModule, 0);
 | |
|     if (loaded == 0) {
 | |
|         printf("SymLoadModule64(%p) failed: %ld\n", hProcess, GetLastError());
 | |
|         printf("\n");
 | |
|     }
 | |
|     else {
 | |
|         printf("SymLoadModule64(%p) succeeded: 0x%p\n", hProcess, (PVOID)loaded);
 | |
|     }
 | |
| 
 | |
|     CHAR szModName[512];
 | |
| 
 | |
|     printf("Modules:\n");
 | |
| // The first parameter of PSYM_ENUMMODULES_CALLBACK64 changed from PSTR to PCSTR
 | |
| // between Windows 2003 and Windows 7. Cast here to work with either.
 | |
|     pfSymEnumerateModules64(hProcess, (PSYM_ENUMMODULES_CALLBACK64)SymEnumerateCallback, NULL);
 | |
|     printf("\n");
 | |
| 
 | |
|     IMAGEHLP_MODULE64 modinfo;
 | |
|     ZeroMemory(&modinfo, sizeof(modinfo));
 | |
|     modinfo.SizeOfStruct = sizeof(modinfo);
 | |
|     if (!pfSymGetModuleInfo64(hProcess, (DWORD64)hModule, &modinfo)) {
 | |
|         printf("SymGetModuleInfo64(%p, %p) [64] failed: %ld\n",
 | |
|                       hProcess, hModule, GetLastError());
 | |
|     }
 | |
|     else {
 | |
|         printf("SymGetModuleInfo64(%p, %p) [64] succeeded: %ld\n",
 | |
|                       hProcess, hModule, GetLastError());
 | |
|         StringCchCopyA(szModName, ARRAYSIZE(szModName), modinfo.ModuleName);
 | |
|         StringCchCatA(szModName, ARRAYSIZE(szModName), "!");
 | |
| 
 | |
|         printf("NumSyms:         %ld\n", modinfo.NumSyms);
 | |
|         printf("SymType:         %d\n", modinfo.SymType);
 | |
|         printf("ModuleName:      %s\n", modinfo.ModuleName);
 | |
|         printf("ImageName:       %s\n", modinfo.ImageName);
 | |
|         printf("LoadedImageName: %s\n", modinfo.LoadedImageName);
 | |
|     }
 | |
| 
 | |
|     printf("\n");
 | |
|     fflush(stdout);
 | |
| 
 | |
|     printf("DLLs:\n");
 | |
|     for (hModule = NULL; (hModule = DetourEnumerateModules(hModule)) != NULL;) {
 | |
|         CHAR szName[MAX_PATH];
 | |
|         GetModuleFileNameA(hModule, szName, sizeof(szName));
 | |
|         printf("  %p: %s\n", hModule, szName);
 | |
|     }
 | |
| 
 | |
|     if (pfSymEnumSymbols == NULL) {
 | |
|         printf("Couldn't find SymEnumSymbols.\n");
 | |
|     }
 | |
|     else {
 | |
|         printf("===Enum===\n");
 | |
|         SetLastError(0);
 | |
|         nSymbolCount = 0;
 | |
|         if (!pfSymEnumSymbols(hProcess, loaded, NULL, SymEnumerateSymbols, NULL)) {
 | |
|             printf("SymEnumSymbols() failed: %ld\n",
 | |
|                           GetLastError());
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Look for specific symbols.
 | |
|     struct CFullSymbol : SYMBOL_INFO {
 | |
|         CHAR szRestOfName[MAX_SYM_NAME];
 | |
|     } symbol;
 | |
|     CHAR szFullName[512];
 | |
| 
 | |
|     // Look for Target
 | |
|     StringCchCopyA(szFullName, ARRAYSIZE(szFullName), szModName);
 | |
|     StringCchCatA(szFullName, ARRAYSIZE(szFullName), "Target");
 | |
|     printf("Symbol: [%s]\n", szFullName);
 | |
| 
 | |
|     ZeroMemory(&symbol, sizeof(symbol));
 | |
|     symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
 | |
| #ifdef DBHLPAPI
 | |
|     symbol.MaxNameLen = MAX_SYM_NAME;
 | |
| #else
 | |
|     symbol.MaxNameLength = MAX_SYM_NAME;
 | |
| #endif
 | |
| 
 | |
|     SetLastError(0);
 | |
|     if (!pfSymFromName(hProcess, szFullName, &symbol)) {
 | |
|         printf("--SymFromName(%s) failed: %ld\n", szFullName, GetLastError());
 | |
|     }
 | |
|     if (symbol.Address != 0) {
 | |
|         printf("--SymFromName(%s) succeeded\n", szFullName);
 | |
|     }
 | |
| 
 | |
|     printf("%s => %p\n\n", szFullName, (PBYTE)symbol.Address);
 | |
| 
 | |
|     // Look for Hidden
 | |
|     StringCchCopyA(szFullName, ARRAYSIZE(szFullName), szModName);
 | |
|     StringCchCatA(szFullName, ARRAYSIZE(szFullName), "Hidden");
 | |
|     printf("Symbol: [%s]\n", szFullName);
 | |
| 
 | |
|     ZeroMemory(&symbol, sizeof(symbol));
 | |
|     symbol.SizeOfStruct = sizeof(SYMBOL_INFO);
 | |
| #ifdef DBHLPAPI
 | |
|     symbol.MaxNameLen = MAX_SYM_NAME;
 | |
| #else
 | |
|     symbol.MaxNameLength = MAX_SYM_NAME;
 | |
| #endif
 | |
| 
 | |
|     SetLastError(0);
 | |
|     if (!pfSymFromName(hProcess, szFullName, &symbol)) {
 | |
|         printf("--SymFromName(%s) failed: %ld\n", szFullName, GetLastError());
 | |
|     }
 | |
|     if (symbol.Address != 0) {
 | |
|         printf("--SymFromName(%s) succeeded\n", szFullName);
 | |
|     }
 | |
| 
 | |
|     printf("%s => %p\n\n", szFullName, (PBYTE)symbol.Address);
 | |
| #endif
 | |
| 
 | |
|     // We call Target once to insure it is loaded.
 | |
|     Target(0);
 | |
|     return 0;
 | |
| }
 | |
| //
 | |
| ///////////////////////////////////////////////////////////////// End of File.
 |