FARPROC
GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
)
{
NTSTATUS Status;
PVOID ProcedureAddress;
STRING ProcedureName;
if ( (ULONG_PTR)lpProcName > 0xffff ) {
RtlInitString(&ProcedureName,lpProcName);
Status = LdrGetProcedureAddress(
BasepMapModuleHandle( hModule, FALSE ),
&ProcedureName,
0L,
&ProcedureAddress
);
}
else {
Status = LdrGetProcedureAddress(
BasepMapModuleHandle( hModule, FALSE ),
NULL,
PtrToUlong((PVOID)lpProcName),
&ProcedureAddress
);
}
if ( !NT_SUCCESS(Status) ) {
BaseSetLastNTError(Status);
return NULL;
}
else {
if ( ProcedureAddress == BasepMapModuleHandle( hModule, FALSE ) ) {
if ( (ULONG_PTR)lpProcName > 0xffff ) {
Status = STATUS_ENTRYPOINT_NOT_FOUND;
}
else {
Status = STATUS_ORDINAL_NOT_FOUND;
}
BaseSetLastNTError(Status);
return NULL;
}
else {
return (FARPROC)ProcedureAddress;
}
}
}
NTSTATUS
LdrGetProcedureAddress (
IN PVOID DllHandle,
IN PANSI_STRING ProcedureName OPTIONAL,
IN ULONG ProcedureNumber OPTIONAL,
OUT PVOID *ProcedureAddress
)
{
return LdrpGetProcedureAddress(DllHandle,ProcedureName,ProcedureNumber,ProcedureAddress,TRUE);
}
NTSTATUS
LdrpGetProcedureAddress (
IN PVOID DllHandle,
IN PANSI_STRING ProcedureName OPTIONAL,
IN ULONG ProcedureNumber OPTIONAL,
OUT PVOID *ProcedureAddress,
IN BOOLEAN RunInitRoutines
)
/*++
Routine Description:
This function locates the address of the specified procedure in the
specified DLL and returns its address.
--*/
{
NTSTATUS st;
UCHAR FunctionNameBuffer[64];
PUCHAR src, dst;
ULONG cb, ExportSize;
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;
IMAGE_THUNK_DATA Thunk;
PVOID ImageBase;
PIMAGE_IMPORT_BY_NAME FunctionName;
PIMAGE_EXPORT_DIRECTORY ExportDirectory;
PLIST_ENTRY Next;
#if defined (WX86)
PTEB Teb;
BOOLEAN Wx86KnownDll = FALSE;
#endif
if (ShowSnaps) {
DbgPrint("LDR: LdrGetProcedureAddress by ");
}
#if defined (WX86)
Teb = NtCurrentTeb();
if (Teb->Wx86Thread.UseKnownWx86Dll) {
Wx86KnownDll = Teb->Wx86Thread.UseKnownWx86Dll;
Teb->Wx86Thread.UseKnownWx86Dll = FALSE;
}
#endif
FunctionName = NULL;
if ( ARGUMENT_PRESENT(ProcedureName) ) {
if (ShowSnaps) {
DbgPrint("NAME - %s/n", ProcedureName->Buffer);
}
//
// BUGBUG need STRING to PSZ
//
if (ProcedureName->Length >= sizeof( FunctionNameBuffer )-1 ) {
FunctionName = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( TEMP_TAG ),ProcedureName->Length+1+sizeof(USHORT));
if ( !FunctionName ) {
return STATUS_INVALID_PARAMETER;
}
} else {
FunctionName = (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer;
}
FunctionName->Hint = 0;
cb = ProcedureName->Length;
src = ProcedureName->Buffer;
dst = FunctionName->Name;
while (cb--) {
*dst++ = *src++;
}
*dst = '{fckeditor}';
//
// Make sure we don't pass in address with high bit set so we
// can still use it as ordinal flag
//
ImageBase = FunctionName;
Thunk.u1.AddressOfData = 0;
} else {
ImageBase = NULL;
if (ShowSnaps) {
DbgPrint("ORDINAL - %lx/n", ProcedureNumber);
}
if (ProcedureNumber) {
Thunk.u1.Ordinal = ProcedureNumber | IMAGE_ORDINAL_FLAG;
} else {
return STATUS_INVALID_PARAMETER;
}
}
if ( LdrpInLdrInit == FALSE ) {
RtlEnterCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
}
try {
if (!LdrpCheckForLoadedDllHandle(DllHandle, &LdrDataTableEntry)) {
st = STATUS_DLL_NOT_FOUND;
return st;
}
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(
LdrDataTableEntry->DllBase,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&ExportSize
);
if (!ExportDirectory) {
return STATUS_PROCEDURE_NOT_FOUND;
}
st = LdrpSnapThunk(LdrDataTableEntry->DllBase,
ImageBase,
&Thunk,
&Thunk,
ExportDirectory,
ExportSize,
FALSE,
NULL
);
if ( RunInitRoutines ) {
PLDR_DATA_TABLE_ENTRY LdrInitEntry;
//
// Look at last entry in init order list. If entry processed
// flag is not set, then a forwarded dll was loaded during the
// getprocaddr call and we need to run init routines
//
Next = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink;
LdrInitEntry = CONTAINING_RECORD(Next, LDR_DATA_TABLE_ENTRY, InInitializationOrderLinks);
if ( !(LdrInitEntry->Flags & LDRP_ENTRY_PROCESSED) ) {
try {
st = LdrpRunInitializeRoutines(NULL);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
st = GetExceptionCode();
}
}
}
if ( NT_SUCCESS(st) ) {
*ProcedureAddress = (PVOID)Thunk.u1.Function;
#if defined (WX86)
// For dlls loaded as a Wx86 plugin ...
if (Wx86ProcessInit && (LdrDataTableEntry->Flags & LDRP_WX86_PLUGIN)) {
PVOID ExportThunk = NULL;
USHORT MachineType = RtlImageNtHeader(LdrDataTableEntry->DllBase)->FileHeader.Machine;
// and the GetProcAddress call is cross-architecture ...
if ((!Wx86KnownDll && (MachineType == IMAGE_FILE_MACHINE_I386))
|| (Wx86KnownDll && (MachineType != IMAGE_FILE_MACHINE_I386))) {
// Thunk the export
st = Wx86ThunkPluginExport(LdrDataTableEntry->DllBase,
FunctionName? FunctionName->Name : NULL,
ProcedureNumber,
(PVOID)(Thunk.u1.Function),
&ExportThunk
);
if (NT_SUCCESS(st) && ExportThunk) {
*ProcedureAddress = ExportThunk;
} else {
// Don't let unthunked cross-architecture addresses get out
*ProcedureAddress = NULL;
st = STATUS_INVALID_IMAGE_FORMAT;
}
}
}
#endif
}
} finally {
if ( FunctionName && (FunctionName != (PIMAGE_IMPORT_BY_NAME) FunctionNameBuffer) ) {
RtlFreeHeap(RtlProcessHeap(),0,FunctionName);
}
if ( LdrpInLdrInit == FALSE ) {
RtlLeaveCriticalSection((PRTL_CRITICAL_SECTION)NtCurrentPeb()->LoaderLock);
}
}
return st;
}