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