PE_FindExportedFunction: use a binary search for function names.

This commit is contained in:
Alexandre Julliard 1999-12-27 00:25:25 +00:00
parent 8a3edf9b5a
commit bbeaeebb2d

View File

@ -71,7 +71,7 @@ DECLARE_DEBUG_CHANNEL(segment)
/* convert PE image VirtualAddress to Real Address */ /* convert PE image VirtualAddress to Real Address */
#define RVA(x) ((unsigned int)load_addr+(unsigned int)(x)) #define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x)))
#define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta)) #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
@ -105,7 +105,7 @@ void dump_exports( HMODULE hModule )
if (!*function) continue; /* No such function */ if (!*function) continue; /* No such function */
if (TRACE_ON(win32)) if (TRACE_ON(win32))
{ {
DPRINTF( "%4ld %08lx %08x", i + pe_exports->Base, *function, RVA(*function) ); DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) );
/* Check if we have a name for it */ /* Check if we have a name for it */
for (j = 0; j < pe_exports->NumberOfNames; j++) for (j = 0; j < pe_exports->NumberOfNames; j++)
if (ordinal[j] == i) if (ordinal[j] == i)
@ -133,10 +133,10 @@ FARPROC PE_FindExportedFunction(
LPCSTR funcName, /* [in] function name */ LPCSTR funcName, /* [in] function name */
BOOL snoop ) BOOL snoop )
{ {
u_short * ordinal; u_short * ordinals;
u_long * function; u_long * function;
u_char ** name, *ename; u_char ** name, *ename = NULL;
int i; int i, ordinal;
PE_MODREF *pem = &(wm->binfmt.pe); PE_MODREF *pem = &(wm->binfmt.pe);
IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export;
unsigned int load_addr = wm->module; unsigned int load_addr = wm->module;
@ -155,7 +155,7 @@ FARPROC PE_FindExportedFunction(
WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
return NULL; return NULL;
} }
ordinal = (u_short*) RVA(exports->AddressOfNameOrdinals); ordinals= (u_short*) RVA(exports->AddressOfNameOrdinals);
function= (u_long*) RVA(exports->AddressOfFunctions); function= (u_long*) RVA(exports->AddressOfFunctions);
name = (u_char **) RVA(exports->AddressOfNames); name = (u_char **) RVA(exports->AddressOfNames);
forward = NULL; forward = NULL;
@ -164,56 +164,77 @@ FARPROC PE_FindExportedFunction(
rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
if (HIWORD(funcName)) { if (HIWORD(funcName))
for(i=0; i<exports->NumberOfNames; i++) { {
ename=(char*)RVA(*name); /* first try a binary search */
if(!strcmp(ename,funcName)) int min = 0, max = exports->NumberOfNames - 1;
{ while (min <= max)
addr = function[*ordinal]; {
if (!addr) return NULL; int res, pos = (min + max) / 2;
if ((addr < rva_start) || (addr >= rva_end)) ename = RVA(name[pos]);
return snoop? SNOOP_GetProcAddress(wm->module,ename,*ordinal,(FARPROC)RVA(addr)) if (!(res = strcmp( ename, funcName )))
: (FARPROC)RVA(addr); {
forward = (char *)RVA(addr); ordinal = ordinals[pos];
break; goto found;
} }
ordinal++; if (res > 0) max = pos - 1;
name++; else min = pos + 1;
} }
} else { /* now try a linear search in case the names aren't sorted properly */
int i; for (i = 0; i < exports->NumberOfNames; i++)
if (LOWORD(funcName)-exports->Base > exports->NumberOfFunctions) { {
TRACE(" ordinal %d out of range!\n", LOWORD(funcName)); ename = RVA(name[i]);
return NULL; if (!strcmp( ename, funcName ))
} {
addr = function[(int)funcName-exports->Base]; ERR( "%s.%s required a linear search\n", wm->modname, funcName );
if (!addr) return NULL; ordinal = ordinals[i];
ename = ""; goto found;
if (name) { }
for (i=0;i<exports->NumberOfNames;i++) { }
ename = (char*)RVA(*name); return NULL;
if (*ordinal == LOWORD(funcName)-exports->Base)
break;
ordinal++;
name++;
}
if (i==exports->NumberOfNames)
ename = "";
}
if ((addr < rva_start) || (addr >= rva_end))
return snoop? SNOOP_GetProcAddress(wm->module,ename,(DWORD)funcName-exports->Base,(FARPROC)RVA(addr))
: (FARPROC)RVA(addr);
forward = (char *)RVA(addr);
} }
if (forward) else /* find by ordinal */
{
ordinal = LOWORD(funcName) - exports->Base;
if (snoop && name) /* need to find a name for it */
{
for (i = 0; i < exports->NumberOfNames; i++)
if (ordinals[i] == ordinal)
{
ename = RVA(name[i]);
break;
}
}
}
found:
if (ordinal >= exports->NumberOfFunctions)
{
TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
return NULL;
}
addr = function[ordinal];
if (!addr) return NULL;
if ((addr < rva_start) || (addr >= rva_end))
{
FARPROC proc = RVA(addr);
if (snoop)
{
if (!ename) ename = "@";
proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc);
}
return proc;
}
else /* forward entry point */
{ {
WINE_MODREF *wm; WINE_MODREF *wm;
char *forward = RVA(addr);
char module[256]; char module[256];
char *end = strchr(forward, '.'); char *end = strchr(forward, '.');
if (!end) return NULL; if (!end) return NULL;
assert(end-forward<256); if (end - forward >= sizeof(module)) return NULL;
strncpy(module, forward, (end - forward)); memcpy( module, forward, end - forward );
module[end-forward] = 0; module[end-forward] = 0;
if (!(wm = MODULE_FindModule( module ))) if (!(wm = MODULE_FindModule( module )))
{ {
@ -222,7 +243,6 @@ FARPROC PE_FindExportedFunction(
} }
return MODULE_GetProcAddress( wm->module, end + 1, snoop ); return MODULE_GetProcAddress( wm->module, end + 1, snoop );
} }
return NULL;
} }
DWORD fixup_imports( WINE_MODREF *wm ) DWORD fixup_imports( WINE_MODREF *wm )