BOOL WINAPI InitializeOls() { if(gInitDll == FALSE) { gIsNT = IsNT(); gIsCpuid = IsCpuid(); if(gIsCpuid) { gIsMsr = IsMsr(); gIsTsc = IsTsc(); } gDllStatus = InitDriverInfo(); if(gDllStatus == OLS_DLL_NO_ERROR) { // Retry, Max 1000ms for(int i = 0; i < 4; i++) { gDllStatus = Initialize(); if(gDllStatus == OLS_DLL_NO_ERROR) { break; } Sleep(100 * i); } } gInitDll = TRUE; } return (BOOL)(gDllStatus == OLS_DLL_NO_ERROR); }
HANDLE SymGetProcessHandle() { if (IsNT()) return GetCurrentProcess(); else return (HANDLE)GetCurrentProcessId(); }
DWORD __stdcall BSUGetModuleBaseName( HANDLE hProcess, HMODULE hModule, LPTSTR lpBaseName, DWORD nSize ) { if ( IsNT() ) { // Call the NT version. It is in NT4ProcessInfo because that is // where all the PSAPI wrappers are kept. return ( NTGetModuleBaseName( hProcess, hModule, lpBaseName, nSize ) ); } return ( Win95GetModuleBaseName( hProcess, hModule, lpBaseName, nSize ) ); }
static BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule, LPCSTR szFunc, PROC paHookFuncs, PROC* paOrigFuncs) { PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PIMAGE_THUNK_DATA pOrigThunk; PIMAGE_THUNK_DATA pRealThunk; if (!IsNT() && ((size_t)hModule >= 0x80000000)) return FALSE; pImportDesc = GetNamedImportDescriptor(hModule, szImportModule); if (pImportDesc == NULL) return FALSE; pOrigThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->OriginalFirstThunk); pRealThunk = MakePtr(PIMAGE_THUNK_DATA, hModule, pImportDesc->FirstThunk); while (pOrigThunk->u1.Function) { if (IMAGE_ORDINAL_FLAG != (pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) { PIMAGE_IMPORT_BY_NAME pByName = MakePtr(PIMAGE_IMPORT_BY_NAME, hModule, pOrigThunk->u1.AddressOfData); BOOL bDoHook; // When hook EditPlus, read pByName->Name[0] will case this dll terminate, so call IsBadReadPtr() here. if (IsBadReadPtr(pByName, sizeof(IMAGE_IMPORT_BY_NAME))) { pOrigThunk++; pRealThunk++; continue; } if ('\0' == pByName->Name[0]) { pOrigThunk++; pRealThunk++; continue; } bDoHook = FALSE; if ((szFunc[0] == pByName->Name[0]) && (_strcmpi(szFunc, (char*)pByName->Name) == 0)) { if (paHookFuncs) bDoHook = TRUE; } if (bDoHook) { MEMORY_BASIC_INFORMATION mbi_thunk; DWORD dwOldProtect; VirtualQuery(pRealThunk, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION)); VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect); if (paOrigFuncs) *paOrigFuncs = (PROC)pRealThunk->u1.Function; pRealThunk->u1.Function = (DWORD)paHookFuncs; VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); return TRUE; } } pOrigThunk++; pRealThunk++; } return FALSE; }
/* A check of the registry which a virus uses */ static int KlezTypeCheck( void ) { HKEY hKey; LONG lResult; TCHAR szKeyName[1024]; DWORD dwIndex, dwCount; FILETIME ft; int viruscount = 0; /* Search a thing registered with Windows Startup */ if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Run"), 0, KEY_READ, &hKey ) != ERROR_SUCCESS ) { return -1; } dwIndex = 0; while( 1 ) { dwCount = sizeof(szKeyName)/sizeof(TCHAR); lResult = RegEnumValue( hKey, dwIndex, szKeyName, &dwCount, 0, NULL, NULL, NULL ); if( lResult != ERROR_SUCCESS ) { break; } viruscount += KlezTypeCheckSub( szKeyName, KEYTYPE_1 ); dwIndex++; } RegCloseKey( hKey ); if( !IsNT() ) { return viruscount; } /* Search a thing registered with WindowsNT Service */ if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("System\\CurrentControlSet\\Services"), 0, KEY_READ, &hKey ) != ERROR_SUCCESS ) { return -1; } dwIndex = 0; while( 1 ) { dwCount = sizeof(szKeyName)/sizeof(TCHAR); lResult = RegEnumKeyEx( hKey, dwIndex, szKeyName, &dwCount, 0, NULL, NULL, &ft ); if( lResult != ERROR_SUCCESS ) { break; } viruscount += KlezTypeCheckSub( szKeyName, KEYTYPE_2 ); dwIndex++; } RegCloseKey( hKey ); return viruscount; }
int SimpleVirusChecker(void) { int viruscount = 0; if( IsNT() < 0 ) return -1; if( ExeRegistryCheck() > 0 ) viruscount++; viruscount += SpecialRegistryCheck(); viruscount += KlezTypeCheck(); return viruscount; }
/* * logSysInfo - record basic system info */ static void logSysInfo( bool wasfault ) { char *str; time_t tod; DWORD ver; SYSTEM_INFO sysinfo; char name[ MAX_COMPUTERNAME_LENGTH + 1 ]; DWORD bufsize; tod = time( NULL ); str = ctime( &tod ); if( wasfault ) { logPrintf( STR_FAULT_FOUND_ON_X, AppName, str ); } else { logPrintf( STR_LOG_TAKEN_ON_X, AppName, str ); } bufsize = sizeof( name ); GetComputerName( name, &bufsize ); logPrintf( STR_COMPUTER_NAME, name ); bufsize = sizeof( name ); GetUserName( name, &bufsize ); logPrintf( STR_USER_NAME, name ); #ifndef _WIN64 ver = GetVersion(); #ifdef CHICAGO // TEMPORARY FIX UNTIL WE CAN CHECK FOR WIN 95 logPrintf( STR_OPERATING_SYSTEM, "Windows 95" ); #else logPrintf( STR_OPERATING_SYSTEM, IsNT( ver ) ? "Windows NT":"Win32s" ); #endif logPrintf( STR_OS_VERSION, (int)GetMajVer( ver ), (int)GetMinVer( ver ) ); #else logPrintf( STR_OPERATING_SYSTEM, "Windows NT 64-bit" ); #endif GetSystemInfo( &sysinfo ); str = SrchMsg( sysinfo.dwProcessorType, ProcessorNames, NULL ); if( str == NULL ) { str = AllocRCString( STR_UNKNOWN ); logPrintf( STR_PROCESSOR_TYPE, str ); FreeRCString( str ); } else { logPrintf( STR_PROCESSOR_TYPE, str ); } logPrintf( STR_NUM_PROCESSORS, sysinfo.dwNumberOfProcessors ); }
DWORD __stdcall BSUGetModuleFileNameEx ( DWORD dwPID , HANDLE hProcess , HMODULE hModule , LPTSTR szFilename , DWORD nSize ) { if ( TRUE == IsNT ( ) ) { return ( NTGetModuleFileNameEx ( dwPID , hProcess , hModule , szFilename , nSize ) ) ; } return ( TLHELPGetModuleFileNameEx ( dwPID , hProcess , hModule , szFilename , nSize ) ) ; }
BOOL BUGSUTIL_DLLINTERFACE __stdcall HookImportedFunctionsByName ( HMODULE hModule , LPCSTR szImportMod , UINT uiCount , LPHOOKFUNCDESCA paHookArray , PROC * paOrigFuncs , LPDWORD pdwHooked ) { // Double check the parameters. ASSERT ( NULL != szImportMod ) ; ASSERT ( 0 != uiCount ) ; ASSERT ( FALSE == IsBadReadPtr ( paHookArray , sizeof (HOOKFUNCDESC) * uiCount )); #ifdef _DEBUG if ( NULL != paOrigFuncs ) { ASSERT ( FALSE == IsBadWritePtr ( paOrigFuncs , sizeof ( PROC ) * uiCount ) ); } if ( NULL != pdwHooked ) { ASSERT ( FALSE == IsBadWritePtr ( pdwHooked , sizeof ( UINT ))); } // Check each function name in the hook array. { for ( UINT i = 0 ; i < uiCount ; i++ ) { ASSERT ( NULL != paHookArray[ i ].szFunc ) ; ASSERT ( '\0' != *paHookArray[ i ].szFunc ) ; // If the proc is not NULL, then it is checked. if ( NULL != paHookArray[ i ].pProc ) { ASSERT ( FALSE == IsBadCodePtr ( paHookArray[i].pProc)); } } } #endif // Do the parameter validation for real. if ( ( 0 == uiCount ) || ( NULL == szImportMod ) || ( TRUE == IsBadReadPtr ( paHookArray , sizeof (HOOKFUNCDESC) * uiCount ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } if ( ( NULL != paOrigFuncs ) && ( TRUE == IsBadWritePtr ( paOrigFuncs , sizeof ( PROC ) * uiCount ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } if ( ( NULL != pdwHooked ) && ( TRUE == IsBadWritePtr ( pdwHooked , sizeof ( UINT ) ) ) ) { SetLastErrorEx ( ERROR_INVALID_PARAMETER , SLE_ERROR ) ; return ( FALSE ) ; } // Is this a system DLL, which Windows95 will not let you patch // since it is above the 2GB line? if ( ( FALSE == IsNT ( ) ) && ( (DWORD)hModule >= 0x80000000 ) ) { SetLastErrorEx ( ERROR_INVALID_HANDLE , SLE_ERROR ) ; return ( FALSE ) ; } // TODO TODO // Should each item in the hook array be checked in release builds? if ( NULL != paOrigFuncs ) { // Set all the values in paOrigFuncs to NULL. memset ( paOrigFuncs , NULL , sizeof ( PROC ) * uiCount ) ; } if ( NULL != pdwHooked ) { // Set the number of functions hooked to zero. *pdwHooked = 0 ; } // Get the specific import descriptor. PIMAGE_IMPORT_DESCRIPTOR pImportDesc = GetNamedImportDescriptor ( hModule , szImportMod ); if ( NULL == pImportDesc ) { // The requested module was not imported. This is not an error. return ( TRUE ) ; } // Get the original thunk information for this DLL. I cannot use // the thunk information stored in the pImportDesc->FirstThunk // because the that is the array that the loader has already // bashed to fix up all the imports. This pointer gives us acess // to the function names. PIMAGE_THUNK_DATA pOrigThunk = MakePtr ( PIMAGE_THUNK_DATA , hModule , pImportDesc->OriginalFirstThunk ) ; // Get the array pointed to by the pImportDesc->FirstThunk. This is // where I will do the actual bash. PIMAGE_THUNK_DATA pRealThunk = MakePtr ( PIMAGE_THUNK_DATA , hModule , pImportDesc->FirstThunk ); // Loop through and look for the one that matches the name. while ( NULL != pOrigThunk->u1.Function ) { // Only look at those that are imported by name, not ordinal. if ( IMAGE_ORDINAL_FLAG != ( pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG )) { // Look get the name of this imported function. PIMAGE_IMPORT_BY_NAME pByName ; pByName = MakePtr ( PIMAGE_IMPORT_BY_NAME , hModule , pOrigThunk->u1.AddressOfData ) ; // If the name starts with NULL, then just skip out now. if ( '\0' == pByName->Name[ 0 ] ) { continue ; } // Determines if we do the hook. BOOL bDoHook = FALSE ; // TODO TODO // Might want to consider bsearch here. // See if the particular function name is in the import // list. It might be good to consider requiring the // paHookArray to be in sorted order so bsearch could be // used so the lookup will be faster. However, the size of // uiCount coming into this function should be rather // small but it is called for each function imported by // szImportMod. for ( UINT i = 0 ; i < uiCount ; i++ ) { if ( ( paHookArray[i].szFunc[0] == pByName->Name[0] ) && ( 0 == _strcmpi ( paHookArray[i].szFunc , (char*)pByName->Name ) ) ) { // If the proc is NULL, kick out, otherwise go // ahead and hook it. if ( NULL != paHookArray[ i ].pProc ) { bDoHook = TRUE ; } break ; } } if ( TRUE == bDoHook ) { // I found it. Now I need to change the protection to // writable before I do the blast. Note that I am now // blasting into the real thunk area! MEMORY_BASIC_INFORMATION mbi_thunk ; VirtualQuery ( pRealThunk , &mbi_thunk , sizeof ( MEMORY_BASIC_INFORMATION ) ) ; VERIFY ( VirtualProtect ( mbi_thunk.BaseAddress , mbi_thunk.RegionSize , PAGE_READWRITE , &mbi_thunk.Protect ) ) ; // Save the original address if requested. if ( NULL != paOrigFuncs ) { paOrigFuncs[i] = (PROC)pRealThunk->u1.Function ; } // Do the actual hook. pRealThunk->u1.Function = (DWORD)paHookArray[i].pProc ; DWORD dwOldProtect ; // Change the protection back to what it was before I // blasted. VERIFY ( VirtualProtect ( mbi_thunk.BaseAddress , mbi_thunk.RegionSize , mbi_thunk.Protect , &dwOldProtect ) ) ; if ( NULL != pdwHooked ) { // Increment the total number hooked. *pdwHooked += 1 ; } } } // Increment both tables. pOrigThunk++ ; pRealThunk++ ; } // All OK, JumpMaster! SetLastError ( ERROR_SUCCESS ) ; return ( TRUE ) ; }
DWORD __stdcall BSUSymInitialize ( DWORD dwPID , HANDLE hProcess , PSTR UserSearchPath , BOOL fInvadeProcess ) { // If this is any flavor of NT or fInvadeProcess is FALSE, just call // SymInitialize itself if ( ( TRUE == IsNT ( ) ) || ( FALSE == fInvadeProcess ) ) { return ( ::SymInitialize ( hProcess , UserSearchPath , fInvadeProcess ) ) ; } else { // This is Win9x and the user wants to invade! // The first step is to initialize the symbol engine. If it // fails, there is not much I can do. BOOL bSymInit = ::SymInitialize ( hProcess , UserSearchPath , fInvadeProcess ) ; ASSERT ( FALSE != bSymInit ) ; if ( FALSE == bSymInit ) { return ( FALSE ) ; } DWORD dwCount ; // Find out how many modules there are. This is a BSU function. if ( FALSE == GetLoadedModules ( dwPID , 0 , NULL , &dwCount ) ) { ASSERT ( !"GetLoadedModules failed" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; return ( FALSE ) ; } // Allocate something big enough to hold the list. HMODULE * paMods = new HMODULE[ dwCount ] ; // Get the list for real. if ( FALSE == GetLoadedModules ( dwPID , dwCount , paMods , &dwCount ) ) { ASSERT ( !"GetLoadedModules failed" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } // The module filename. TCHAR szModName [ MAX_PATH ] ; for ( UINT uiCurr = 0 ; uiCurr < dwCount ; uiCurr++ ) { // Get the module's filename. if ( FALSE == GetModuleFileName ( paMods[ uiCurr ] , szModName , sizeof ( szModName ) ) ) { ASSERT ( !"GetModuleFileName failed!" ) ; // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } // In order to get the symbol engine to work outside a // debugger, it needs a handle to the image. Yes, this // will leak but the OS will close it down when the process // ends. HANDLE hFile = CreateFile ( szModName , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , 0 ) ; // For whatever reason, SymLoadModule can return zero, but // it still loads the modules. Sheez. if ( FALSE == SymLoadModule ( hProcess , hFile , szModName , NULL , (DWORD)paMods[ uiCurr ] , 0 ) ) { // Check the last error value. If it is zero, then all // I can assume is that it worked. DWORD dwLastErr = GetLastError ( ) ; ASSERT ( ERROR_SUCCESS == dwLastErr ) ; if ( ERROR_SUCCESS != dwLastErr ) { // Clean up the symbol engine and leave. VERIFY ( ::SymCleanup ( hProcess ) ) ; // Free the memory that I allocated earlier. delete [] paMods ; return ( FALSE ) ; } } } delete [] paMods ; } return ( TRUE ) ; }
void main ( void ) { // Get the real list of modules. DWORD dwModCount = 0 ; HMODULE * hProcessMods = AllocAndFillProcessModuleList ( GetProcessHeap ( ) , &dwModCount ) ; ASSERT ( NULL != hProcessMods ) ; if ( NULL == hProcessMods ) { _tprintf ( _T ( "Unable to get the process module list.\n" ) ) ; return ; } DWORD dwProcID = GetCurrentProcessId ( ) ; HANDLE hProcHandle = GetCurrentProcess ( ) ; // Do the BSUGetModuleBaseName tests with good data. char szAnsi[ MAX_PATH ] ; DWORD dwRet = BSUGetModuleBaseNameA ( hProcHandle , NULL , szAnsi , MAX_PATH ) ; ASSERT ( 0 != dwRet ) ; if ( 0 == dwRet ) { _tprintf ( _T ( "BSUGetModuleBaseNameA failed!!\n" ) ) ; return ; } _tprintf ( _T ( "BSUGetModuleBaseNameA returned : %S\n" ) , szAnsi ) ; wchar_t szWide[ MAX_PATH ] ; dwRet = BSUGetModuleBaseNameW ( hProcHandle , NULL , szWide , MAX_PATH ) ; ASSERT ( 0 != dwRet ) ; if ( 0 == dwRet ) { _tprintf ( _T ( "BSUGetModuleBaseNameW failed!!\n" ) ) ; return ; } _tprintf ( _T ( "BSUGetModuleBaseNameW returned : %s\n" ) , szWide ) ; //////////////////////////////////////////////////////// dwRet = BSUGetModuleFileNameExA ( dwProcID , hProcHandle , hProcessMods[ 0 ] , szAnsi , MAX_PATH ) ; ASSERT ( 0 != dwRet ) ; if ( 0 == dwRet ) { _tprintf ( _T ( "BSUGetModuleFileNameExA failed!!\n" ) ) ; return ; } _tprintf ( _T ( "BSUGetModuleFileNameExA returned : %S\n" ) , szAnsi ) ; dwRet = BSUGetModuleFileNameExW ( dwProcID , hProcHandle , hProcessMods[ 0 ] , szWide , MAX_PATH ) ; ASSERT ( 0 != dwRet ) ; if ( 0 == dwRet ) { _tprintf ( _T ( "BSUGetModuleFileNameExW failed!!\n" ) ) ; return ; } _tprintf ( _T ( "BSUGetModuleFileNameExW returned : %s\n" ) , szWide ) ; //////////////////////////////////////////////////////// BSUSetCurrentThreadNameW ( _T ( "Wide Thread Name" ) ) ; BSUSetCurrentThreadNameA ( "Ansi Thread Name" ) ; //////////////////////////////////////////////////////// _tprintf ( _T ( "IsNT = %d\n" ) , IsNT ( ) ) ; _tprintf ( _T ( "IsNT4 = %d\n" ) , IsNT4 ( ) ) ; _tprintf ( _T ( "IsW2K = %d\n" ) , IsW2K ( ) ) ; _tprintf ( _T ( "IsXP = %d\n" ) , IsXP ( ) ) ; _tprintf ( _T ( "IsServer2003 = %d\n" ) , IsServer2003 ( ) ) ; _tprintf ( _T ( "IsW2KorBetter = %d\n" ) , IsW2KorBetter ( ) ) ; _tprintf ( _T ( "IsXPorBetter = %d\n" ) , IsXPorBetter ( ) ) ; _tprintf ( _T ( "IsServer2003orBetter = %d\n" ) , IsServer2003orBetter ( ) ) ; //////////////////////////////////////////////////////// BOOL bRet = BSUSymInitializeA ( dwProcID , hProcHandle , NULL , TRUE ) ; ASSERT ( TRUE == bRet ) ; if ( FALSE == bRet ) { _tprintf ( _T ( "BSUSymInitializeA failed!!\n" ) ) ; return ; } SymCleanup ( hProcHandle ) ; bRet = BSUSymInitializeW ( dwProcID , hProcHandle , NULL , TRUE ) ; ASSERT ( TRUE == bRet ) ; if ( FALSE == bRet ) { _tprintf ( _T ( "BSUSymInitializeW failed!!\n" ) ) ; return ; } SymCleanup ( hProcHandle ) ; //////////////////////////////////////////////////////// int iCount = GetSuperAssertionCount ( ) ; if ( 0 != iCount ) { _tprintf ( _T ( "One of the tests failed!!\n" ) ) ; } DiagOutputW ( _T ( "All done!\n" ) ) ; MemStressInitializeA ( "BSU_Is_Tests.exe" ) ; MemStressTerminate ( ) ; // Get rid of the allocate list of modules. HeapFree ( GetProcessHeap ( ) , 0 , hProcessMods ) ; }
/// Format of error report. BUGTRAP_REPORTFORMAT g_eReportFormat = BTRF_XML; /// Address of error handler called before BugTrap dialog. BT_ErrHandler g_pfnPreErrHandler = NULL; /// User-defined parameter of error handler called before BugTrap dialog. INT_PTR g_nPreErrHandlerParam = 0; /// Address of error handler called after BugTrap dialog. BT_ErrHandler g_pfnPostErrHandler = NULL; /// User-defined parameter of error handler called after BugTrap dialog. INT_PTR g_nPostErrHandlerParam = 0; /// Pointer to the exception information. PEXCEPTION_POINTERS g_pExceptionPointers = NULL; /// Exception thread ID. DWORD g_dwExceptionThreadID = 0; /// True if application runs on Windows NT platform. BOOL g_bWinNT = IsNT(); /// Custom resources manager. CResManager* g_pResManager = NULL; /// Pointer to Simple MAPI session object. CMapiSession* g_pMapiSession = NULL; /// Pointer to symbolic engine. CSymEngine* g_pSymEngine = NULL; /// Pointer to process enumerator. CEnumProcess* g_pEnumProc = NULL; /// Array of custom log file names attached to the report. CArray<CLogLink*, CDynamicTraits<CLogLink*> > g_arrLogLinks; /// User defined message printed to the log file. CStrHolder g_strUserMessage; /// 1st introduction message displayed on the dialog. CStrHolder g_strFirstIntroMesage; /// 2nd introduction message displayed on the dialog.
bool dbgsymengine::guard::init() { if (!m_ref) { m_ref = -1; HANDLE hProc = SymGetProcessHandle(); DWORD dwPid = GetCurrentProcessId(); // initializes SymSetOptions (SymGetOptions()|SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); // SymSetOptions (SYMOPT_UNDNAME|SYMOPT_LOAD_LINES); if (::SymInitialize(hProc, 0, TRUE)) { // enumerate modules if (IsNT()) { typedef BOOL (WINAPI *ENUMPROCESSMODULES)(HANDLE, HMODULE*, DWORD, LPDWORD); HINSTANCE hInst = LoadLibrary( "psapi.dll" ); if (hInst) { ENUMPROCESSMODULES fnEnumProcessModules = (ENUMPROCESSMODULES)GetProcAddress(hInst, "EnumProcessModules"); DWORD cbNeeded = 0; if (fnEnumProcessModules && fnEnumProcessModules(GetCurrentProcess(), 0, 0, &cbNeeded) && cbNeeded) { HMODULE * pmod = (HMODULE *)alloca(cbNeeded); DWORD cb = cbNeeded; if (fnEnumProcessModules(GetCurrentProcess(), pmod, cb, &cbNeeded)) { m_ref = 0; for (unsigned i = 0; i < cb / sizeof (HMODULE); ++i) { if (!load_module(hProc, pmod[i])) { // m_ref = -1; // break; _ASSERTE(0); } } } } else { _ASSERTE(0); } VERIFY(FreeLibrary(hInst)); } else { _ASSERTE(0); } } else { typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD, DWORD); typedef BOOL (WINAPI *MODULEWALK)(HANDLE, LPMODULEENTRY32); HMODULE hMod = GetModuleHandle("kernel32"); CREATESNAPSHOT fnCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress(hMod, "CreateToolhelp32Snapshot"); MODULEWALK fnModule32First = (MODULEWALK)GetProcAddress(hMod, "Module32First"); MODULEWALK fnModule32Next = (MODULEWALK)GetProcAddress(hMod, "Module32Next"); if (fnCreateToolhelp32Snapshot && fnModule32First && fnModule32Next) { HANDLE hModSnap = fnCreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid); if (hModSnap) { MODULEENTRY32 me32 = {0}; me32.dwSize = sizeof(MODULEENTRY32); if (fnModule32First(hModSnap, &me32)) { m_ref = 0; do { if (!load_module(hProc, me32.hModule)) { // m_ref = -1; // break; } } while(fnModule32Next(hModSnap, &me32)); } VERIFY(CloseHandle(hModSnap)); } } } if (m_ref == -1) { VERIFY(SymCleanup(SymGetProcessHandle())); } } else { _ASSERTE(0); } } if (m_ref == -1) return false; if (0 == m_ref) ++m_ref; // lock it once // ++m_ref; return true; }