static RcStatus readObjectTable( ExeFileInfo *exe ) /*************************************************/ { RcStatus ret; unsigned objects_size; long file_offset; exe_pe_header *pehdr; pehdr = exe->u.PEInfo.WinHead; if( IS_PE64( *pehdr ) ) { objects_size = PE64( *pehdr ).num_objects * sizeof( pe_object ); file_offset = exe->WinHeadOffset + sizeof( pe_header64 ); } else { objects_size = PE32( *pehdr ).num_objects * sizeof( pe_object ); file_offset = exe->WinHeadOffset + sizeof( pe_header ); } exe->u.PEInfo.Objects = RESALLOC( objects_size ); ret = SeekRead( exe->fid, file_offset, exe->u.PEInfo.Objects, objects_size ); switch( ret ) { case RS_OK: break; case RS_READ_ERROR: RcError( ERR_READING_EXE, exe->name, strerror( errno ) ); break; case RS_READ_INCMPLT: RcError( ERR_UNEXPECTED_EOF, exe->name ); break; default: RcError( ERR_INTERNAL, INTERR_UNKNOWN_RCSTATUS ); break; } CheckDebugOffset( exe ); return( ret ); }
int WRCalcObjTableOffset( WResFileID file, exe_pe_header *hdr ) { uint_16 pe_offset; int offset; bool ok; ok = (ResSeek( file, PE_OFFSET, SEEK_SET ) != -1); if( ok ) { ResReadUint16( &pe_offset, file ); ok = (pe_offset != 0); } if ( ok ) { if( IS_PE64( *hdr ) ) { offset = pe_offset + PE64( *hdr ).nt_hdr_size + offsetof( pe_header64, magic ); } else { offset = pe_offset + PE32( *hdr ).nt_hdr_size + offsetof( pe_header, magic ); } } else { offset = 0; } return( offset ); }
long int WRReadWinNTExeHeader( WResFileID file_handle, exe_pe_header *header ) { long int old_pos; uint_16 offset; bool ok; old_pos = -1; ok = (file_handle != -1 && header != NULL); if( ok ) { ok = ((old_pos = ResSeek( file_handle, 0x18, SEEK_SET )) != -1); } /* check the reloc offset */ if( ok ) { ResReadUint16( &offset, file_handle ); ok = (offset >= 0x0040); } if( ok ) { ok = (ResSeek( file_handle, PE_OFFSET, SEEK_SET ) != -1); } /* check header offset */ if( ok ) { ResReadUint16( &offset, file_handle ); ok = (offset != 0x0000); } if( ok ) { ok = (ResSeek( file_handle, offset, SEEK_SET ) != -1); } if( ok ) { ok = (read( file_handle, &PE32( *header ), sizeof( pe_header ) ) == sizeof( pe_header )); if( ok && IS_PE64( *header ) ) { ok = (ResSeek( file_handle, offset, SEEK_SET ) != -1); if( ok ) { ok = (read( file_handle, &PE64( *header ), sizeof( pe_header64 ) ) == sizeof( pe_header64 )); } } } /* check for valid Win32 EXE */ if( ok ) { ok = WRIsHeaderValidWINNT( header ); } if( old_pos != -1 ) { ok = (ResSeek( file_handle, old_pos, SEEK_SET ) != -1 && ok); } if( !ok ) { WRDisplayErrorMsg( WR_INVALIDNTEXE ); offset = 0; } return( offset ); }
static bool IdentifyWinExeHeader( FILE *fh, bool win16 ) { os2_exe_header os2_hdr; exe_pe_header pe_hdr; uint_16 offset; bool ok; ok = ( fh != NULL ); if( ok ) { ok = ( fseek( fh, 0x18, SEEK_SET ) == 0 ); } /* check the reloc offset */ if( ok ) { ok = ( fread( &offset, 1, sizeof( offset ), fh ) == sizeof( offset ) && offset >= 0x0040 ); } if( ok ) { ok = ( fseek( fh, NH_OFFSET, SEEK_SET ) == 0 ); } /* check the header offset */ if( ok ) { ok = ( fread( &offset, 1, sizeof( offset ), fh ) == sizeof( offset ) && offset != 0 ); } /* seek to the header */ if( ok ) { ok = ( fseek( fh, offset, SEEK_SET ) == 0 ); } if( ok ) { if( win16 ) { ok = ( fread( &os2_hdr, 1, sizeof( os2_hdr ), fh ) == sizeof( os2_hdr )); /* check for valid Win16 EXE */ if( ok ) { return( WRIsHeaderValidWIN16( &os2_hdr ) ); } } else { ok = ( fread( &PE32( pe_hdr ), 1, sizeof( pe_header ), fh ) == sizeof( pe_header ) ); if( ok && IS_PE64( pe_hdr ) ) { /* seek to the header again */ ok = ( fseek( fh, offset, SEEK_SET ) == 0 ); if( ok ) { ok = ( fread( &PE64( pe_hdr ), 1, sizeof( pe_header64 ), fh ) == sizeof( pe_header64 ) ); } } /* check for valid Win32 EXE */ if( ok ) { return( WRIsHeaderValidWINNT( &pe_hdr ) ); } } } return( false ); }
int WRIsHeaderValidWINNT( exe_pe_header *header ) { /* at some point will we have to check the CPUTYPE ????!!!! */ if( IS_PE64( *header ) ) { return( PE64( *header ).signature == PE_SIGNATURE ); } else { return( PE32( *header ).signature == PE_SIGNATURE ); } }
int WRWinNTHeaderHasResourceTable( exe_pe_header *header ) { int num_tables; pe_hdr_table_entry *table; if( IS_PE64( *header ) ) { num_tables = PE64( *header ).num_tables; table = PE64( *header ).table; } else { num_tables = PE32( *header ).num_tables; table = PE32( *header ).table; } return( num_tables > PE_TBL_RESOURCE && table[PE_TBL_RESOURCE].rva != 0 && table[PE_TBL_RESOURCE].size != 0 ); }
int WRReadNTObjectTable( WResFileID file, exe_pe_header *hdr, pe_object **ot ) { int size; int ot_offset; ot_offset = WRCalcObjTableOffset( file, hdr ); if( ot_offset == 0 || ResSeek( file, ot_offset, SEEK_SET ) == -1 ) { return( FALSE ); } if( IS_PE64( *hdr ) ) { size = sizeof( pe_object ) * PE64( *hdr ).num_objects; } else { size = sizeof( pe_object ) * PE32( *hdr ).num_objects; } *ot = (pe_object *)MemAlloc( size ); if( *ot != NULL ) { if( read( file, *ot, size ) != size ) { MemFree( *ot ); *ot = NULL; } } return( *ot != NULL ); }
/* * AccLoadProg - create a new process for debugging */ trap_retval ReqProg_load( void ) { char *parm; char *src; char *dst; char *endsrc; char exe_name[PATH_MAX]; char ch; BOOL rc; int len; MYCONTEXT con; thread_info *ti; HANDLE handle; prog_load_req *acc; prog_load_ret *ret; header_info hi; WORD stack; WORD version; DWORD pid; DWORD pid_started; DWORD cr_flags; char *buff = NULL; size_t nBuffRequired = 0; char *dll_name; char *service_name; char *dll_destination; char *service_parm; acc = GetInPtr( 0 ); ret = GetOutPtr( 0 ); parm = GetInPtr( sizeof( *acc ) ); /* * reset status variables */ LastExceptionCode = -1; DebugString = NULL; DebugeeEnded = FALSE; RemoveAllThreads(); FreeLibList(); DidWaitForDebugEvent = FALSE; DebugeePid = 0; DebugeeTid = 0; SupportingExactBreakpoints = 0; /* * check if pid is specified */ ParseServiceStuff( parm, &dll_name, &service_name, &dll_destination, &service_parm ); pid = 0; src = parm; /* // Just to be really safe! */ nBuffRequired = GetTotalSize() + PATH_MAX + 16; if( NULL == ( buff = malloc( nBuffRequired ) ) ) { ret->err = ERROR_NOT_ENOUGH_MEMORY; return( sizeof( *ret ) ); } if( *src == '#' ) { src++; pid = strtoul( src, &endsrc, 16 ); if( pid == 0 ) { pid = -1; } strcpy( buff, endsrc ); } else { while( isdigit( *src ) ) { src++; } if( *src == 0 && src != parm ) { pid = atoi( parm ); } } /* * get program to debug. If the user has specified a pid, then * skip directly to doing a DebugActiveProcess */ IsWOW = FALSE; #if !defined( MD_x64 ) IsDOS = FALSE; #endif if( pid == 0 ) { if( FindFilePath( parm, exe_name, ExtensionList ) != 0 ) { ret->err = ERROR_FILE_NOT_FOUND; goto error_exit; } /* * Get type of application */ handle = CreateFile( (LPTSTR)exe_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if( handle == INVALID_HANDLE_VALUE ) { ret->err = GetLastError(); goto error_exit; } GetFullPathName( exe_name, MAX_PATH, CurrEXEName, NULL ); /* * get the parm list */ if( strchr( CurrEXEName, ' ' ) != NULL ) { strcpy( buff, "\"" ); strcat( buff, CurrEXEName ); strcat( buff, "\"" ); } else { strcpy( buff, CurrEXEName ); } dst = &buff[strlen( buff )]; src = parm; while( *src != 0 ) { ++src; } // parm layout // <--parameters-->0<--program_name-->0<--arguments-->0 // for( len = GetTotalSize() - sizeof( *acc ) - (src - parm) - 1; len > 0; --len ) { ch = *src; if( ch == 0 ) { ch = ' '; } *dst = ch; ++dst; ++src; } *dst = 0; cr_flags = DEBUG_ONLY_THIS_PROCESS; if( !GetEXEHeader( handle, &hi, &stack ) ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } if( hi.sig == EXE_PE ) { if( IS_PE64( hi.u.peh ) ) { DebugeeSubsystem = PE64( hi.u.peh ).subsystem; } else { DebugeeSubsystem = PE32( hi.u.peh ).subsystem; #if defined( MD_x64 ) IsWOW = TRUE; #endif } if( DebugeeSubsystem == SS_WINDOWS_CHAR ) { cr_flags |= CREATE_NEW_CONSOLE; } #if !defined( MD_x64 ) } else if( hi.sig == EXE_NE ) { IsWOW = TRUE; /* * find out the pid of WOW, if it is already running. */ pVDMEnumProcessWOW( EnumWOWProcessFunc, (LPARAM)&pid ); if( pid != 0 ) { version = LOWORD( GetVersion() ); if( LOBYTE( version ) == 3 && HIBYTE( version ) < 50 ) { int kill = MessageBox( NULL, TRP_NT_wow_warning, TRP_The_WATCOM_Debugger, MB_APPLMODAL + MB_YESNO ); if( kill == IDYES ) { DWORD axs = PROCESS_TERMINATE+STANDARD_RIGHTS_REQUIRED; HANDLE hprocess = OpenProcess( axs, FALSE, pid ); if( hprocess != 0 && TerminateProcess( hprocess, 0 ) ) { CloseHandle( hprocess ); pid = 0; } } } else { cr_flags |= CREATE_SEPARATE_WOW_VDM; pid = 0; // always start a new VDM. } } if( pid != 0 ) { ret->err = GetLastError(); CloseHandle( handle ); goto error_exit; } } else { IsDOS = TRUE; #endif } CloseHandle( handle ); } /* * start the debugee */ pid_started = pid; if( *dll_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_DLLNAME ); strcat( buff, dll_name ); } if( *service_name ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICE ); strcat( buff, service_name ); } if( *dll_destination ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_COPYDIR ); strcat( buff, dll_destination ); } if( *service_parm ) { strcat( buff, LOAD_PROG_STR_DELIM ); strcat( buff, LOAD_PROG_STR_SERVICEPARM ); strcat( buff, service_parm ); } ret->err = StartControlThread( buff, &pid_started, cr_flags ); if( ret->err != 0 ) { goto error_exit; } /* * CREATE_PROCESS_DEBUG_EVENT will always be the first debug event. * If it is not, then something is horribly wrong. */ rc = MyWaitForDebugEvent(); if( !rc || ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) || ( DebugEvent.dwProcessId != pid_started ) ) { ret->err = GetLastError(); goto error_exit; } ProcessInfo.pid = DebugEvent.dwProcessId; ProcessInfo.process_handle = DebugEvent.u.CreateProcessInfo.hProcess; ProcessInfo.base_addr = DebugEvent.u.CreateProcessInfo.lpBaseOfImage; AddProcess( &hi ); AddThread( DebugEvent.dwThreadId, DebugEvent.u.CreateProcessInfo.hThread, DebugEvent.u.CreateProcessInfo.lpStartAddress ); DebugeePid = DebugEvent.dwProcessId; DebugeeTid = DebugEvent.dwThreadId; LastDebugEventTid = DebugEvent.dwThreadId; #if defined( MD_x86 ) #ifdef WOW if( IsWOW ) { ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } if( pid ) { addAllWOWModules(); } else { addKERNEL(); } /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD ) con.SegCs; WOWAppInfo.offset = ( WORD ) con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else if( IsDOS ) { // TODO! Clean up this code ret->flags = 0; //LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; /* * we use our own CS and DS as the Flat CS and DS, for lack * of anything better */ FlatDS = GetDS(); FlatCS = GetCS(); if( !executeUntilVDMStart() ) { ret->err = GetLastError(); goto error_exit; } #if 0 if( pid ) { addAllWOWModules(); } else { addKERNEL(); } #endif /* * we save the starting CS:IP of the WOW app, since we will use * it to force execution of code later */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); WOWAppInfo.segment = ( WORD )con.SegCs; WOWAppInfo.offset = ( WORD )con.Eip; con.SegSs = con.SegDs; // Wow lies about the stack segment. Reset it con.Esp = stack; MySetThreadContext( ti, &con ); } else { #else { #endif #else { #endif LPVOID base; if( pid == 0 ) { base = (LPVOID)DebugEvent.u.CreateProcessInfo.lpStartAddress; } else { base = 0; } ret->flags = LD_FLAG_IS_PROT; ret->err = 0; ret->task_id = DebugeePid; if( executeUntilStart( pid != 0 ) ) { LPVOID old; /* * make the application load our DLL, so that we can have it * run code out of it. One small note: this will not work right * if the app does not load our DLL at the same address the * debugger loaded it at!!! */ ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); old = (LPVOID)AdjustIP( &con, 0 ); if( base != 0 ) { SetIP( &con, base ); } MySetThreadContext( ti, &con ); SetIP( &con, old ); MySetThreadContext( ti, &con ); } ti = FindThread( DebugeeTid ); MyGetThreadContext( ti, &con ); #if defined( MD_x86 ) FlatCS = con.SegCs; FlatDS = con.SegDs; #endif ret->flags |= LD_FLAG_IS_BIG; } ret->flags |= LD_FLAG_HAVE_RUNTIME_DLLS; if( pid != 0 ) { ret->flags |= LD_FLAG_IS_STARTED; } ret->mod_handle = 0; error_exit: if( buff ) { free( buff ); buff = NULL; } return( sizeof( *ret ) ); } trap_retval ReqProg_kill( void ) { prog_kill_ret *ret; ret = GetOutPtr( 0 ); ret->err = 0; DelProcess( TRUE ); StopControlThread(); return( sizeof( *ret ) ); }
int GetModuleName( HANDLE fhdl, char *name ) { header_info hi; pe_object obj; pe_export_directory expdir; DWORD lenread; DWORD export_rva; DWORD i; char buf[_MAX_PATH]; WORD stack; int num_objects; DWORD seek_offset; if( !GetEXEHeader( fhdl, &hi, &stack ) ) { return( FALSE ); } if( hi.sig != EXE_PE ) { return( FALSE ); } seek_offset = SetFilePointer( fhdl, 0, NULL, FILE_CURRENT ); if( seek_offset == INVALID_SET_FILE_POINTER ) { return( FALSE ); } if( IS_PE64( hi.u.peh ) ) { export_rva = PE64( hi.u.peh ).table[PE_TBL_EXPORT].rva; num_objects = PE64( hi.u.peh ).num_objects; seek_offset += PE64( hi.u.peh ).nt_hdr_size + offsetof( pe_header64, magic ) - sizeof( exe_pe_header ); } else { export_rva = PE32( hi.u.peh ).table[PE_TBL_EXPORT].rva; num_objects = PE32( hi.u.peh ).num_objects; seek_offset += PE32( hi.u.peh ).nt_hdr_size + offsetof( pe_header, magic ) - sizeof( exe_pe_header ); } if( num_objects == 0 ) { return( FALSE ); } /* position to begining of object table */ if( SetFilePointer( fhdl, seek_offset, NULL, FILE_BEGIN ) == INVALID_SET_FILE_POINTER ) { return( FALSE ); } for( i = 0; i < num_objects; i++ ) { if( !ReadFile( fhdl, &obj, sizeof( obj ), &lenread, NULL ) || lenread != sizeof( obj ) ) { return( FALSE ); } if( export_rva >= obj.rva && export_rva < obj.rva + obj.physical_size ) { break; } } if( i == num_objects ) { return( FALSE ); } if( !SeekRead( fhdl, obj.physical_offset + export_rva - obj.rva, &expdir, sizeof( expdir ) ) ) { return( FALSE ); } if( !SeekRead( fhdl, obj.physical_offset + expdir.name_rva - obj.rva, buf, _MAX_PATH ) ) { return( FALSE ); } if( SetFilePointer( fhdl, obj.physical_offset + expdir.name_rva - obj.rva, NULL, FILE_BEGIN ) == INVALID_SET_FILE_POINTER ) { return( FALSE ); } if( !ReadFile( fhdl, buf, _MAX_PATH, &lenread, NULL ) ) { return( FALSE ); } memcpy( name, buf, lenread ); name[lenread] = '\0'; return( TRUE ); }
static int openExeFileInfoRO( char *filename, ExeFileInfo *info ) /***************************************************************/ { RcStatus status; exe_pe_header *pehdr; info->Handle = RcOpen( filename, O_RDONLY|O_BINARY ); if( info->Handle == NIL_HANDLE ) { RcError( ERR_CANT_OPEN_FILE, filename, strerror( errno ) ); return( FALSE ); } info->IsOpen = TRUE; info->Type = FindNEPELXHeader( info->Handle, &info->WinHeadOffset ); info->name = filename; switch( info->Type ) { case EXE_TYPE_NE_WIN: case EXE_TYPE_NE_OS2: status = SeekRead( info->Handle, info->WinHeadOffset, &info->u.NEInfo.WinHead, sizeof( os2_exe_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( FALSE ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( os2_exe_header ); } break; case EXE_TYPE_PE: pehdr = &info->u.PEInfo.WinHeadData; info->u.PEInfo.WinHead = pehdr; status = SeekRead( info->Handle, info->WinHeadOffset, &PE32( *pehdr ), sizeof( pe_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( FALSE ); } if( IS_PE64( *pehdr ) ) { status = SeekRead( info->Handle, info->WinHeadOffset, &PE64( *pehdr ), sizeof( pe_header64 ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( FALSE ); } info->DebugOffset = info->WinHeadOffset + sizeof( pe_header64 ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( pe_header ); } break; case EXE_TYPE_LX: status = SeekRead( info->Handle, info->WinHeadOffset, &info->u.LXInfo.OS2Head, sizeof( os2_flat_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( FALSE ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( os2_flat_header ); } break; default: RcError( ERR_NOT_VALID_EXE, filename ); return( FALSE ); break; } RcSeek( info->Handle, 0, SEEK_SET ); return( TRUE ); } /* openExeFileInfoRO */
static bool openExeFileInfoRO( const char *filename, ExeFileInfo *info ) /**********************************************************************/ { RcStatus status; exe_pe_header *pehdr; info->fp = ResOpenFileRO( filename ); if( info->fp == NULL ) { RcError( ERR_CANT_OPEN_FILE, filename, strerror( errno ) ); return( false ); } info->IsOpen = true; info->Type = FindNEPELXHeader( info->fp, &info->WinHeadOffset ); info->name = filename; switch( info->Type ) { case EXE_TYPE_NE_WIN: case EXE_TYPE_NE_OS2: status = SeekRead( info->fp, info->WinHeadOffset, &info->u.NEInfo.WinHead, sizeof( os2_exe_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( false ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( os2_exe_header ); } break; case EXE_TYPE_PE: pehdr = &info->u.PEInfo.WinHeadData; info->u.PEInfo.WinHead = pehdr; status = SeekRead( info->fp, info->WinHeadOffset, &PE32( *pehdr ), sizeof( pe_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( false ); } if( IS_PE64( *pehdr ) ) { status = SeekRead( info->fp, info->WinHeadOffset, &PE64( *pehdr ), sizeof( pe_header64 ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( false ); } info->DebugOffset = info->WinHeadOffset + sizeof( pe_header64 ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( pe_header ); } break; case EXE_TYPE_LX: status = SeekRead( info->fp, info->WinHeadOffset, &info->u.LXInfo.OS2Head, sizeof( os2_flat_header ) ); if( status != RS_OK ) { RcError( ERR_NOT_VALID_EXE, filename ); return( false ); } else { info->DebugOffset = info->WinHeadOffset + sizeof( os2_flat_header ); } break; default: RcError( ERR_NOT_VALID_EXE, filename ); return( false ); break; } return( !RESSEEK( info->fp, 0, SEEK_SET ) ); } /* openExeFileInfoRO */
bool WRLoadWResDirFromWinNTEXE( WResFileID file_handle, WResDir *dir ) { exe_pe_header nt_header; pe_object *otable; uint_32 physical_size; uint_32 physical_offset; int i; bool ok; unsigned_32 resource_rva; ok = (file_handle != -1); if( ok ) { ok = ((*dir = WResInitDir()) != NULL); } if( ok ) { ok = (WRReadWinNTExeHeader( file_handle, &nt_header ) != 0); } /* check if a resource table is present */ if( ok ) { ok = WRWinNTHeaderHasResourceTable( &nt_header ); if( !ok ) { WRDisplayErrorMsg( WR_EXENORES ); return( TRUE ); } } /* read NT object table */ otable = NULL; if( ok ) { ok = WRReadNTObjectTable( file_handle, &nt_header, &otable ); } /* find resource object in object table */ resource_rva = 0; if( ok ) { int num_objects; unsigned_32 file_align; physical_size = 0; physical_offset = 0; if( IS_PE64( nt_header ) ) { resource_rva = PE64( nt_header ).table[PE_TBL_RESOURCE].rva; num_objects = PE64( nt_header ).num_objects; file_align = PE64( nt_header ).file_align; } else { resource_rva = PE32( nt_header ).table[PE_TBL_RESOURCE].rva; num_objects = PE32( nt_header ).num_objects; file_align = PE32( nt_header ).file_align; } for( i = 0; i < num_objects; i++ ) { if( otable[i].rva == resource_rva ) { physical_size = otable[i].physical_size; physical_offset = otable[i].physical_offset; break; } } ok = (physical_size != 0 && physical_offset != 0 && physical_size % file_align == 0 && physical_offset % file_align == 0); } if( otable != NULL ) { MemFree( otable ); } /* read the resource information */ if( ok ) { res_offset = physical_offset; res_rva = resource_rva; ok = WRHandleWinNTTypeDir( file_handle, dir, physical_offset ); } return( ok ); }