📄 accmap.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Routines to keep track of loaded modules and address maps.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stdnt.h"
typedef struct lli {
HANDLE file_handle;
LPVOID base;
addr_off code_size;
LPVOID except_base;
addr_off except_size;
char is_16 : 1;
char has_real_filename : 1;
char newly_unloaded : 1;
char newly_loaded : 1;
char filename[MAX_PATH + 1];
char modname[40]; //
} lib_load_info;
typedef struct list {
struct list *next;
int is_16;
int segcount;
addr48_ptr _WCUNALIGNED *segs;
char *filename;
char *modname;
} lib_list_info;
static lib_load_info *moduleInfo;
static DWORD lastLib = 0;
static const char libPrefix[] = "NoName";
static lib_list_info *listInfoHead;
static lib_list_info *listInfoTail;
/*
* freeListItem - free an individual lib list item
*/
static void freeListItem( lib_list_info *curr )
{
LocalFree( curr->filename );
LocalFree( curr->modname );
LocalFree( curr->segs );
LocalFree( curr );
}
/*
* FreeLibList - free the lib list info
*/
void FreeLibList( void )
{
lib_list_info *curr;
lib_list_info *next;
curr = listInfoHead;
while( curr != NULL ) {
next = curr->next;
freeListItem( curr );
curr = next;
}
listInfoHead = NULL;
listInfoTail = NULL;
}
/*
* addModuleToLibList - saves away the information about the current
* module. This is used to dump it out later
* (TrapListLibs calls DoListLibs)
*/
static void addModuleToLibList( DWORD module )
{
lib_list_info *curr;
lib_load_info *lli;
lli = &moduleInfo[module];
curr = listInfoHead;
while( curr != NULL ) {
if( !stricmp( lli->modname, curr->modname ) &&
!stricmp( lli->filename, curr->filename ) ) {
return;
}
curr = curr->next;
}
curr = LocalAlloc( LMEM_FIXED, sizeof( lib_list_info ) );
if( curr == NULL ) {
return;
}
curr->filename = LocalAlloc( LMEM_FIXED, strlen( lli->filename ) + 1 );
if( curr->filename == NULL ) {
LocalFree( curr );
return;
}
strcpy( curr->filename, lli->filename );
curr->modname = LocalAlloc( LMEM_FIXED, strlen( lli->modname ) + 1 );
if( curr->modname == NULL ) {
LocalFree( curr->filename );
LocalFree( curr );
return;
}
strcpy( curr->modname, lli->modname );
curr->segcount = 0;
curr->segs = NULL;
curr->is_16 = lli->is_16;
curr->next = NULL;
if( listInfoHead == NULL ) {
listInfoHead = listInfoTail = curr;
} else {
listInfoTail->next = curr;
listInfoTail = curr;
}
}
/*
* RemoveModuleFromLibList - removes a module from our list once it is
* unloaded or exits
*/
void RemoveModuleFromLibList( char *module, char *filename )
{
lib_list_info *curr;
lib_list_info *prev;
curr = listInfoHead;
prev = NULL;
while( curr != NULL ) {
if( !stricmp( module, curr->modname ) &&
!stricmp( filename, curr->filename ) ) {
if( prev == NULL ) {
listInfoHead = curr->next;
} else {
prev->next = curr->next;
}
if( curr == listInfoTail ) {
listInfoTail = prev;
}
freeListItem( curr );
return;
}
prev = curr;
curr = curr->next;
}
}
/*
* addSegmentToLibList - add a new segment. We keep track of this so that
* we can dump it later.
*/
static void addSegmentToLibList( DWORD module, WORD seg, DWORD off )
{
addr48_ptr *new;
if( listInfoTail == NULL ) {
addModuleToLibList( module );
if( listInfoTail == NULL ) {
return;
}
}
new = LocalAlloc( LMEM_FIXED, ( listInfoTail->segcount + 1 )
* sizeof( addr48_ptr ) );
if( new == NULL ) {
return;
}
if( listInfoTail->segs != NULL ) {
memcpy( new, listInfoTail->segs, sizeof( addr48_ptr )*
listInfoTail->segcount );
}
listInfoTail->segs = new;
listInfoTail->segs[listInfoTail->segcount].segment = seg;
listInfoTail->segs[listInfoTail->segcount].offset = off;
listInfoTail->segcount++;
}
BOOL FindExceptInfo( addr_off off, LPVOID *base, addr_off *size )
{
unsigned i;
lib_load_info *lli;
for( i = 0; i < ModuleTop; ++i ) {
lli = &moduleInfo[0];
if( off >= ( addr_off ) lli->base
&& off < ( addr_off ) lli->base + lli->code_size ) {
/* this is the image */
if( lli->except_size == 0 ) {
return( FALSE );
}
*base = lli->except_base;
*size = lli->except_size;
return( TRUE );
}
}
return( FALSE );
}
static void FillInExceptInfo( lib_load_info *lli )
{
DWORD pe_off;
DWORD bytes;
pe_header hdr;
ReadProcessMemory( ProcessInfo.process_handle,
( LPVOID ) ( ( DWORD ) lli->base + OS2_NE_OFFSET ), &pe_off,
sizeof( pe_off ), &bytes );
ReadProcessMemory( ProcessInfo.process_handle,
( LPVOID ) ( ( DWORD ) lli->base + pe_off ), &hdr,
sizeof( hdr ), &bytes );
lli->code_size = hdr.code_base + hdr.code_size;
lli->except_base = ( LPVOID ) ( ( DWORD ) lli->base +
hdr.table[PE_TBL_EXCEPTION].rva );
lli->except_size = hdr.table[PE_TBL_EXCEPTION].size;
}
/*
* AddProcess - a new process has been created
*/
void AddProcess( header_info *hi )
{
lib_load_info *lli;
moduleInfo = LocalAlloc( LMEM_FIXED, sizeof( lib_load_info ) );
memset( moduleInfo, 0, sizeof( lib_load_info ) );
ModuleTop = 1;
lli = &moduleInfo[0];
if( IsWOW || IsDOS ) {
lli->is_16 = TRUE;
lli->file_handle = 0;
lli->base = 0;
lli->has_real_filename = TRUE;
strcpy( lli->modname, hi->modname );
strcpy( lli->filename, CurrEXEName );
} else {
lli->has_real_filename = FALSE;
lli->is_16 = FALSE;
lli->file_handle = DebugEvent.u.CreateProcessInfo.hFile;
// kludge - NT doesn't give us a handle sometimes
if( lli->file_handle == INVALID_HANDLE_VALUE ) {
lli->file_handle = CreateFile( ( LPTSTR )CurrEXEName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
}
lli->base = DebugEvent.u.CreateProcessInfo.lpBaseOfImage;
FillInExceptInfo( lli );
lli->modname[0] = 0;
lli->filename[0] = 0;
}
}
/*
* NameFromProcess - get fully qualified filename for last DLL
* that was loaded in process. Intended for Win9x.
*/
BOOL NameFromProcess( lib_load_info *lli, DWORD dwPID, char *name )
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
BOOL bSuccess = FALSE;
// Check if we have the KERNEL32 entrypoints.
if( !pCreateToolhelp32Snapshot || !pModule32First || !pModule32Next )
goto error_exit;
// Take a snapshot of all modules in the specified process.
hModuleSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
goto error_exit;
// Set the size of the structure before using it.
me32.dwSize = sizeof( MODULEENTRY32 );
// Attempt to retrieve information about the first module.
if( !pModule32First( hModuleSnap, &me32 ) )
goto error_exit;
// Look for freshly loaded module. Not tested on Win9x.
// Unfortunately in WinXP not all newly loaded modules are in the list.
// This should not be relevant as all NT versions will use the PSAPI method anyway.
// The PSAPI method works reliably but is not available on Win9x.
do {
if( me32.modBaseAddr == lli->base ) {
strcpy( name, me32.szExePath );
bSuccess = TRUE;
break;
}
} while( pModule32Next( hModuleSnap, &me32 ) );
error_exit:
if( hModuleSnap != INVALID_HANDLE_VALUE )
CloseHandle( hModuleSnap );
return( bSuccess );
}
/*
* NameFromHandle - get fully qualified filename from file handle.
* Intended for Windows NT.
*/
BOOL NameFromHandle( HANDLE hFile, char *name )
{
#define BUFSIZE 512
BOOL bSuccess = FALSE;
char pszFilename[MAX_PATH + 1];
HANDLE hFileMap = NULL;
void *pMem = NULL;
char szTemp[BUFSIZE];
DWORD dwFileSizeHi;
DWORD dwFileSizeLo;
name[0] = 0;
// Check if we have the required entrypoints (results depend on OS version).
if( (hFile == INVALID_HANDLE_VALUE) || !pGetMappedFileName || !pQueryDosDevice )
goto error_exit;
// Get the file size.
dwFileSizeLo = GetFileSize( hFile, &dwFileSizeHi );
if( dwFileSizeLo == 0 && dwFileSizeHi == 0 )
goto error_exit;
// Create a file mapping object and map the file.
if( !(hFileMap = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 1, NULL ))
|| !(pMem = MapViewOfFile( hFileMap, FILE_MAP_READ, 0, 0, 1 ))
|| !pGetMappedFileName( GetCurrentProcess(), pMem, pszFilename, MAX_PATH ) ) {
goto error_exit;
}
// Translate path with device name to drive letters.
szTemp[0] = '\0';
if( GetLogicalDriveStrings( BUFSIZE - 1, szTemp ) ) {
char szName[MAX_PATH];
char szDrive[3] = " :";
BOOL bFound = FALSE;
char *p = szTemp;
do {
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if( pQueryDosDevice( szDrive, szName, BUFSIZE ) ) {
UINT uNameLen = strlen( szName );
if( uNameLen < MAX_PATH ) {
bFound = strnicmp( pszFilename, szName, uNameLen ) == 0;
if( bFound ) {
// Reconstruct pszFilename using szTemp
// Replace device path with DOS path
char szTempFile[MAX_PATH];
sprintf( szTempFile, "%s%s", szDrive, pszFilename + uNameLen );
strlcpy( name, szTempFile, MAX_PATH );
bSuccess = TRUE;
}
}
}
// Go to the next NULL character.
while( *p++ )
;
} while( !bFound && *p ); // end of string
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -