/* Look up the specified function or ordinal in the exportlist: * If it is a string: * - look up the name in the Name list. * - look up the ordinal with that index. * - use the ordinal as offset into the functionlist * If it is a ordinal: * - use ordinal-pe_export->Base as offset into the functionlist */ FARPROC PE_FindExportedFunction( WINE_MODREF *wm, LPCSTR funcName, WIN_BOOL snoop ) { unsigned short * ordinals; unsigned long * function; unsigned char ** name; const char *ename = NULL; int i, ordinal; PE_MODREF *pem = &(wm->binfmt.pe); IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export; unsigned int load_addr = wm->module; unsigned long rva_start, rva_end, addr; char * forward; if (HIWORD(funcName)) TRACE("(%s)\n",funcName); else TRACE("(%d)\n",(int)funcName); if (!exports) { /* Not a fatal problem, some apps do * GetProcAddress(0,"RegisterPenApp") which triggers this * case. */ WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem); return NULL; } ordinals= (unsigned short*) RVA(exports->AddressOfNameOrdinals); function= (unsigned long*) RVA(exports->AddressOfFunctions); name = (unsigned char **) RVA(exports->AddressOfNames); forward = NULL; rva_start = PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (HIWORD(funcName)) { int min = 0, max = exports->NumberOfNames - 1; while (min <= max) { int res, pos = (min + max) / 2; ename = (const char*) RVA(name[pos]); if (!(res = strcmp( ename, funcName ))) { ordinal = ordinals[pos]; goto found; } if (res > 0) max = pos - 1; else min = pos + 1; } for (i = 0; i < exports->NumberOfNames; i++) { ename = (const char*) RVA(name[i]); if (!strcmp( ename, funcName )) { ERR( "%s.%s required a linear search\n", wm->modname, funcName ); ordinal = ordinals[i]; goto found; } } return NULL; } else { ordinal = LOWORD(funcName) - exports->Base; if (snoop && name) { 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); TRACE("SNOOP_GetProcAddress n/a\n"); } return proc; } else { WINE_MODREF *wm; char *forward = RVA(addr); char module[256]; char *end = strchr(forward, '.'); if (!end) return NULL; if (end - forward >= sizeof(module)) return NULL; memcpy( module, forward, end - forward ); module[end-forward] = 0; if (!(wm = MODULE_FindModule( module ))) { ERR("module not found for forward '%s'\n", forward ); return NULL; } return MODULE_GetProcAddress( wm->module, end + 1, snoop ); } }
/*********************************************************************** * GetProcAddress (KERNEL32.257) */ FARPROC WINAPI GetProcAddress( HMODULE hModule, LPCSTR function ) { return MODULE_GetProcAddress( hModule, function, TRUE ); }