reactos/reactos/subsys/win32k/ldr/loader.c
Gé van Geldorp b17d0f5101 - Implement NULL module case for EngFindImageProcAddress
- Add stubs for EngFindImageProcAddress()able not present yet

svn path=/trunk/; revision=9079
2004-04-11 09:09:38 +00:00

277 lines
9.7 KiB
C

/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: loader.c,v 1.16 2004/04/11 09:09:38 gvg Exp $
*
*/
#include <ddk/ntddk.h>
#include <ddk/winddi.h>
#include <ddk/ntapi.h>
#define NDEBUG
#include <debug.h>
#ifdef __USE_W32API
PIMAGE_NT_HEADERS STDCALL
RtlImageNtHeader(IN PVOID BaseAddress);
#endif
/*
* This is copied from ntdll... It's needed for loading keyboard dlls.
*/
PVOID
STDCALL
RtlImageDirectoryEntryToData (
PVOID BaseAddress,
BOOLEAN bFlag,
ULONG Directory,
PULONG Size
)
{
PIMAGE_NT_HEADERS NtHeader;
PIMAGE_SECTION_HEADER SectionHeader;
ULONG Va;
ULONG Count;
NtHeader = RtlImageNtHeader (BaseAddress);
if (NtHeader == NULL)
return NULL;
if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
if (Va == 0)
return NULL;
if (Size)
*Size = NtHeader->OptionalHeader.DataDirectory[Directory].Size;
if (bFlag)
return (PVOID)(BaseAddress + Va);
/* image mapped as ordinary file, we must find raw pointer */
SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1);
Count = NtHeader->FileHeader.NumberOfSections;
while (Count--)
{
if (SectionHeader->VirtualAddress == Va)
return (PVOID)(BaseAddress + SectionHeader->PointerToRawData);
SectionHeader++;
}
return NULL;
}
/*
* Blatantly stolen from ldr/utils.c in ntdll. I can't link ntdll from
* here, though.
*/
NTSTATUS STDCALL
LdrGetProcedureAddress (IN PVOID BaseAddress,
IN PANSI_STRING Name,
IN ULONG Ordinal,
OUT PVOID *ProcedureAddress)
{
PIMAGE_EXPORT_DIRECTORY ExportDir;
PUSHORT OrdinalPtr;
PULONG NamePtr;
PULONG AddressPtr;
ULONG i = 0;
DPRINT("LdrGetProcedureAddress (BaseAddress %x Name %Z Ordinal %lu ProcedureAddress %x)\n",
BaseAddress, Name, Ordinal, ProcedureAddress);
/* Get the pointer to the export directory */
ExportDir = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData (BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT,
&i);
DPRINT("ExportDir %x i %lu\n", ExportDir, i);
if (!ExportDir || !i || !ProcedureAddress)
{
return STATUS_INVALID_PARAMETER;
}
AddressPtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfFunctions);
if (Name && Name->Length)
{
/* by name */
OrdinalPtr = (PUSHORT)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNameOrdinals);
NamePtr = (PULONG)((ULONG)BaseAddress + (ULONG)ExportDir->AddressOfNames);
for( i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
{
if (!_strnicmp(Name->Buffer, (char*)(BaseAddress + *NamePtr), Name->Length))
{
*ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[*OrdinalPtr]);
return STATUS_SUCCESS;
}
}
DPRINT1("LdrGetProcedureAddress: Can't resolve symbol '%Z'\n", Name);
}
else
{
/* by ordinal */
Ordinal &= 0x0000FFFF;
if (Ordinal - ExportDir->Base < ExportDir->NumberOfFunctions)
{
*ProcedureAddress = (PVOID)((ULONG)BaseAddress + (ULONG)AddressPtr[Ordinal - ExportDir->Base]);
return STATUS_SUCCESS;
}
DPRINT1("LdrGetProcedureAddress: Can't resolve symbol @%d\n", Ordinal);
}
return STATUS_PROCEDURE_NOT_FOUND;
}
PVOID STDCALL
EngFindImageProcAddress(IN HANDLE Module,
IN LPSTR ProcName)
{
PVOID Function;
NTSTATUS Status;
ANSI_STRING ProcNameString;
unsigned i;
static struct
{
PCSTR ProcName;
PVOID ProcAddress;
}
Win32kExports[] =
{
{ "BRUSHOBJ_hGetColorTransform", BRUSHOBJ_hGetColorTransform },
{ "EngAlphaBlend", EngAlphaBlend },
{ "EngClearEvent", EngClearEvent },
{ "EngControlSprites", EngControlSprites },
{ "EngCreateEvent", EngCreateEvent },
{ "EngDeleteEvent", EngDeleteEvent },
{ "EngDeleteFile", EngDeleteFile },
{ "EngDeleteSafeSemaphore", EngDeleteSafeSemaphore },
{ "EngDeleteWnd", EngDeleteWnd },
{ "EngDitherColor", EngDitherColor },
{ "EngGetPrinterDriver", EngGetPrinterDriver },
{ "EngGradientFill", EngGradientFill },
{ "EngHangNotification", EngHangNotification },
{ "EngInitializeSafeSemaphore", EngInitializeSafeSemaphore },
{ "EngLockDirectDrawSurface", EngLockDirectDrawSurface },
{ "EngLpkInstalled", EngLpkInstalled },
{ "EngMapEvent", EngMapEvent },
{ "EngMapFile", EngMapFile },
{ "EngMapFontFileFD", EngMapFontFileFD },
{ "EngModifySurface", EngModifySurface },
{ "EngMovePointer", EngMovePointer },
{ "EngPlgBlt", EngPlgBlt },
{ "EngQueryDeviceAttribute", EngQueryDeviceAttribute },
{ "EngQueryPalette", EngQueryPalette },
{ "EngQuerySystemAttribute", EngQuerySystemAttribute },
{ "EngReadStateEvent", EngReadStateEvent },
{ "EngRestoreFloatingPointState", EngRestoreFloatingPointState },
{ "EngSaveFloatingPointState", EngSaveFloatingPointState },
{ "EngSetEvent", EngSetEvent },
{ "EngSetPointerShape", EngSetPointerShape },
{ "EngSetPointerTag", EngSetPointerTag },
{ "EngStretchBltROP", EngStretchBltROP },
{ "EngTransparentBlt", EngTransparentBlt },
{ "EngUnlockDirectDrawSurface", EngUnlockDirectDrawSurface },
{ "EngUnmapEvent", EngUnmapEvent },
{ "EngUnmapFile", EngUnmapFile },
{ "EngUnmapFontFileFD", EngUnmapFontFileFD },
{ "EngWaitForSingleObject", EngWaitForSingleObject },
{ "FONTOBJ_pfdg", FONTOBJ_pfdg },
{ "FONTOBJ_pjOpenTypeTablePointer", FONTOBJ_pjOpenTypeTablePointer },
{ "FONTOBJ_pQueryGlyphAttrs", FONTOBJ_pQueryGlyphAttrs },
{ "FONTOBJ_pwszFontFilePaths", FONTOBJ_pwszFontFilePaths },
{ "HeapVidMemAllocAligned", HeapVidMemAllocAligned },
{ "HT_Get8BPPMaskPalette", HT_Get8BPPMaskPalette },
{ "STROBJ_bEnumPositionsOnly", STROBJ_bEnumPositionsOnly },
{ "STROBJ_bGetAdvanceWidths", STROBJ_bGetAdvanceWidths },
{ "STROBJ_fxBreakExtra", STROBJ_fxBreakExtra },
{ "STROBJ_fxCharacterExtra", STROBJ_fxCharacterExtra },
{ "VidMemFree", VidMemFree },
{ "XLATEOBJ_hGetColorTransform", XLATEOBJ_hGetColorTransform }
};
if (NULL == Module)
{
DPRINT("Looking for win32k export %s\n", ProcName);
for (i = 0; i < sizeof(Win32kExports) / sizeof(Win32kExports[0]); i++)
{
if (0 == strcmp(ProcName, Win32kExports[i].ProcName))
{
DPRINT("Found it index %u address %p\n", i, Win32kExports[i].ProcName);
return Win32kExports[i].ProcAddress;
}
}
return NULL;
}
RtlInitAnsiString(&ProcNameString, ProcName);
Status = LdrGetProcedureAddress(Module,
&ProcNameString,
0,
&Function);
if (!NT_SUCCESS(Status))
{
return(NULL);
}
return(Function);
}
/*
* @implemented
*/
HANDLE
STDCALL
EngLoadImage (LPWSTR DriverName)
{
SYSTEM_LOAD_IMAGE GdiDriverInfo;
NTSTATUS Status;
RtlInitUnicodeString(&GdiDriverInfo.ModuleName, DriverName);
Status = ZwSetSystemInformation(SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE));
if (!NT_SUCCESS(Status)) return NULL;
return (HANDLE)GdiDriverInfo.ModuleBase;
}
/*
* @unimplemented
*/
HANDLE
STDCALL
EngLoadModule(LPWSTR ModuleName)
{
SYSTEM_LOAD_IMAGE GdiDriverInfo;
NTSTATUS Status;
// FIXME: should load as readonly
RtlInitUnicodeString (&GdiDriverInfo.ModuleName, ModuleName);
Status = ZwSetSystemInformation (SystemLoadImage, &GdiDriverInfo, sizeof(SYSTEM_LOAD_IMAGE));
if (!NT_SUCCESS(Status)) return NULL;
return (HANDLE)GdiDriverInfo.ModuleBase;
}
/* EOF */