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; }