- fixed definition of RtlImageRvaToVa

- imported the Ldr resource functions from wine and share them in lib/rtl

svn path=/trunk/; revision=19987
This commit is contained in:
Thomas Bluemel 2005-12-08 23:55:34 +00:00
parent 234544358a
commit 84649db0e9
13 changed files with 481 additions and 622 deletions

View file

@ -2092,7 +2092,7 @@ RtlImageDirectoryEntryToData(
);
NTSYSAPI
ULONG
PVOID
NTAPI
RtlImageRvaToVa(
PIMAGE_NT_HEADERS NtHeader,

View file

@ -36,7 +36,7 @@ KiUserCallbackDispatcher@12
KiUserExceptionDispatcher@8
LdrAccessResource@16
LdrDisableThreadCalloutsForDll@4
;LdrEnumResources@20
LdrEnumResources@20
LdrFindEntryForAddress@8
LdrFindResourceDirectory_U@16
LdrFindResource_U@16

View file

@ -1,387 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: lib/ntdll/ldr/res.c
* PURPOSE: Resource access for PE executables
* PROGRAMMERS: Jean Michault
* Rex Jolliff (rex@lvcablemodem.com)
* Robert Dickenson (robd@mok.lvcm.com)
* NOTES: Parts based on Wine code
* Copyright 1995 Thomas Sandford
* Copyright 1996 Martin von Loewis
* Copyright 2003 Alexandre Julliard
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard
* Copyright 1997 Marcus Meissner
*/
/*
* TODO:
* - any comments ??
*/
/* INCLUDES *****************************************************************/
#include <ntdll.h>
#define NDEBUG
#include <debug.h>
/* PROTOTYPES ****************************************************************/
/* FUNCTIONS *****************************************************************/
static PIMAGE_RESOURCE_DIRECTORY_ENTRY FASTCALL
FindEntryById(PIMAGE_RESOURCE_DIRECTORY ResDir,
ULONG Id)
{
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
LONG low, high, mid, result;
/* We use ID number instead of string */
ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1) + ResDir->NumberOfNamedEntries;
DPRINT("ResEntry %x - Resource ID number instead of string\n", (ULONG)ResEntry);
DPRINT("EntryCount %d\n", (ULONG)ResDir->NumberOfIdEntries);
low = 0;
high = ResDir->NumberOfIdEntries - 1;
mid = high/2;
while( low <= high ) {
result = Id - ResEntry[mid].Name;
if(result == 0)
return ResEntry + mid;
if(result < 0)
high = mid - 1;
else
low = mid + 1;
mid = (low + high)/2;
}
return NULL;
}
static int FASTCALL
PushLanguage(WORD *list, int pos, WORD lang)
{
int i;
for (i = 0; i < pos; i++) {
if (list[i] == lang) {
return pos;
}
}
list[pos++] = lang;
return pos;
}
/*
Status = LdrFindResource_U (hModule,
&ResourceInfo,
RESOURCE_DATA_LEVEL,
&ResourceDataEntry);
*/
NTSTATUS NTAPI
LdrFindResource_U(PVOID BaseAddress,
PLDR_RESOURCE_INFO ResourceInfo,
ULONG Level,
PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
{
PIMAGE_RESOURCE_DIRECTORY ResDir;
PIMAGE_RESOURCE_DIRECTORY ResBase;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
NTSTATUS Status = STATUS_SUCCESS;
PWCHAR ws;
ULONG i;
ULONG Id;
LONG low, high, mid, result;
WORD list[9]; /* list of languages to try */
int j, pos = 0;
LCID UserLCID, SystemLCID;
LANGID UserLangID, SystemLangID;
BOOLEAN MappedAsDataFile;
MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress);
DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry);
/* Get the pointer to the resource directory */
ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
! MappedAsDataFile, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
if (ResDir == NULL) {
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
DPRINT("ResourceDirectory: %x Size: %d\n", (ULONG)ResDir, (int)i);
ResBase = ResDir;
/* Let's go into resource tree */
for (i = 0; i < (2 < Level ? 2 : Level); i++) {
DPRINT("ResDir: %x Level: %d\n", (ULONG)ResDir, i);
Id = ((PULONG)ResourceInfo)[i];
if (Id & 0xFFFF0000) {
/* Resource name is a unicode string */
ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
DPRINT("ResEntry %x - Resource name is a unicode string\n", (ULONG)ResEntry);
DPRINT("EntryCount %d\n", (ULONG)ResDir->NumberOfNamedEntries);
low = 0;
high = ResDir->NumberOfNamedEntries - 1;
mid = high/2;
while( low <= high ) {
/* Does we need check if it's named entry, think not */
ws = (PWCHAR)((ULONG)ResBase + (ResEntry[mid].Name & 0x7FFFFFFF));
result = _wcsnicmp((PWCHAR)Id, ws + 1, *ws);
/* Need double check for lexical & length */
if(result == 0) {
result = (wcslen((PWCHAR)Id) - (int)*ws);
if(result == 0) {
ResEntry += mid;
goto found;
}
}
if(result < 0)
high = mid - 1;
else
low = mid + 1;
mid = (low + high)/2;
}
} else {
/* We use ID number instead of string */
ResEntry = FindEntryById(ResDir, Id);
if (NULL != ResEntry) goto found;
}
switch (i) {
case 0:
DPRINT("Error %lu - STATUS_RESOURCE_TYPE_NOT_FOUND\n", i);
return STATUS_RESOURCE_TYPE_NOT_FOUND;
case 1:
DPRINT("Error %lu - STATUS_RESOURCE_NAME_NOT_FOUND\n", i);
return STATUS_RESOURCE_NAME_NOT_FOUND;
case 2:
if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
/* Use the first available language */
ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
break;
}
DPRINT("Error %lu - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
return STATUS_RESOURCE_LANG_NOT_FOUND;
case 3:
DPRINT("Error %lu - STATUS_RESOURCE_DATA_NOT_FOUND\n", i);
return STATUS_RESOURCE_DATA_NOT_FOUND;
default:
DPRINT("Error %lu - STATUS_INVALID_PARAMETER\n", i);
return STATUS_INVALID_PARAMETER;
}
found:;
ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
(ResEntry->OffsetToData & 0x7FFFFFFF));
}
if (3 <= Level) {
/* 1. specified language */
pos = PushLanguage(list, pos, ResourceInfo->Language );
/* 2. specified language with neutral sublanguage */
pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(ResourceInfo->Language), SUBLANG_NEUTRAL));
/* 3. neutral language with neutral sublanguage */
pos = PushLanguage(list, pos, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
/* if no explicitly specified language, try some defaults */
if (LANG_NEUTRAL == PRIMARYLANGID(ResourceInfo->Language)) {
/* user defaults, unless SYS_DEFAULT sublanguage specified */
if (SUBLANG_SYS_DEFAULT != SUBLANGID(ResourceInfo->Language)) {
NtQueryDefaultLocale(TRUE, &UserLCID);
UserLangID = LANGIDFROMLCID(UserLCID);
/* 4. current thread locale language */
pos = PushLanguage(list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale));
/* 5. user locale language */
pos = PushLanguage(list, pos, UserLangID);
/* 6. user locale language with neutral sublanguage */
pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(UserLangID),
SUBLANG_NEUTRAL));
}
/* now system defaults */
NtQueryDefaultLocale(FALSE, &SystemLCID);
SystemLangID = LANGIDFROMLCID(SystemLCID);
/* 7. system locale language */
pos = PushLanguage(list, pos, SystemLangID);
/* 8. system locale language with neutral sublanguage */
pos = PushLanguage(list, pos, MAKELANGID(PRIMARYLANGID(SystemLangID),
SUBLANG_NEUTRAL));
/* 9. English */
pos = PushLanguage(list, pos, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
}
ResEntry = NULL;
for (j = 0; NULL == ResEntry && j < pos; j++)
ResEntry = FindEntryById(ResDir, list[j]);
if (NULL == ResEntry) {
if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
/* Use the first available language */
ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
} else {
DPRINT("Error - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
return STATUS_RESOURCE_LANG_NOT_FOUND;
}
}
ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
(ResEntry->OffsetToData & 0x7FFFFFFF));
if (3 < Level) {
DPRINT("Error - STATUS_INVALID_PARAMETER\n", i);
return STATUS_INVALID_PARAMETER;
}
}
DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
if (ResourceDataEntry) {
*ResourceDataEntry = (PVOID)ResDir;
}
return Status;
}
/*
* @implemented
*/
NTSTATUS NTAPI
LdrAccessResource(IN PVOID BaseAddress,
IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
OUT PVOID* Resource OPTIONAL,
OUT PULONG Size OPTIONAL)
{
PIMAGE_SECTION_HEADER Section;
PIMAGE_NT_HEADERS NtHeader;
ULONG SectionRva;
ULONG SectionVa;
ULONG DataSize;
ULONG Offset = 0;
ULONG Data;
BOOLEAN MappedAsDataFile;
if(!ResourceDataEntry)
return STATUS_RESOURCE_DATA_NOT_FOUND;
MappedAsDataFile = LdrMappedAsDataFile(&BaseAddress);
Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress,
TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize);
if (Data == 0) {
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
if (MappedAsDataFile) {
/* loaded as ordinary file */
NtHeader = RtlImageNtHeader(BaseAddress);
Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
if (Section == NULL) {
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) {
SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
}
}
if (Resource) {
*Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
}
if (Size) {
*Size = ResourceDataEntry->Size;
}
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS NTAPI
LdrFindResourceDirectory_U(IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO info,
IN ULONG level,
OUT PIMAGE_RESOURCE_DIRECTORY* addr)
{
PIMAGE_RESOURCE_DIRECTORY ResDir;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
ULONG EntryCount;
ULONG i;
NTSTATUS Status = STATUS_SUCCESS;
WCHAR* ws;
PWCHAR* name = (PWCHAR*) info;
/* Get the pointer to the resource directory */
ResDir = (PIMAGE_RESOURCE_DIRECTORY)
RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
if (ResDir == NULL) {
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
/* Let's go into resource tree */
for (i = 0; i < level; i++, name++) {
EntryCount = ResDir->NumberOfNamedEntries;
ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
if ((ULONG)(*name) & 0xFFFF0000) {
/* Resource name is a unicode string */
for (; EntryCount--; ResEntry++) {
/* Scan entries for equal name */
if (ResEntry->Name & 0x80000000) {
ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
if (!wcsncmp(*name, ws + 1, *ws) && wcslen(*name) == (int)*ws) {
goto found;
}
}
}
} else {
/* We use ID number instead of string */
ResEntry += EntryCount;
EntryCount = ResDir->NumberOfIdEntries;
for (; EntryCount--; ResEntry++) {
/* Scan entries for equal name */
if (ResEntry->Name == (ULONG)(*name))
goto found;
}
}
switch (i) {
case 0:
return STATUS_RESOURCE_TYPE_NOT_FOUND;
case 1:
return STATUS_RESOURCE_NAME_NOT_FOUND;
case 2:
Status = STATUS_RESOURCE_LANG_NOT_FOUND;
/* Just use first language entry */
if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
break;
}
return Status;
case 3:
return STATUS_RESOURCE_DATA_NOT_FOUND;
default:
return STATUS_INVALID_PARAMETER;
}
found:;
ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
}
if (addr) {
*addr = (PVOID)ResDir;
}
return Status;
}
/* EOF */

View file

@ -11,6 +11,7 @@
<library>rtl</library>
<library>intrlck</library>
<library>string</library>
<library>pseh</library>
<linkerflag>-lgcc</linkerflag>
<linkerflag>-nostdlib</linkerflag>
<linkerflag>-nostartfiles</linkerflag>
@ -23,7 +24,6 @@
<file>dbgui.c</file>
</directory>
<directory name="ldr">
<file>res.c</file>
<file>startup.c</file>
<file>utils.c</file>
</directory>

View file

@ -328,3 +328,105 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
return NULL;
}
/*
* Ldr Resource support code
*/
IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
LPCWSTR name, void *root,
int want_dir );
IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
WORD id, void *root, int want_dir );
IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
void *root, int want_dir );
int push_language( USHORT *list, ULONG pos, WORD lang );
/**********************************************************************
* find_entry
*
* Find a resource entry
*/
NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
ULONG level, void **ret, int want_dir )
{
ULONG size;
void *root;
IMAGE_RESOURCE_DIRECTORY *resdirptr;
USHORT list[9]; /* list of languages to try */
int i, pos = 0;
LCID user_lcid, system_lcid;
root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
resdirptr = root;
if (!level--) goto done;
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
return STATUS_RESOURCE_TYPE_NOT_FOUND;
if (!level--) return STATUS_SUCCESS;
resdirptr = *ret;
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
return STATUS_RESOURCE_NAME_NOT_FOUND;
if (!level--) return STATUS_SUCCESS;
if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
/* 1. specified language */
pos = push_language( list, pos, info->Language );
/* 2. specified language with neutral sublanguage */
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(info->Language), SUBLANG_NEUTRAL ) );
/* 3. neutral language with neutral sublanguage */
pos = push_language( list, pos, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) );
/* if no explicitly specified language, try some defaults */
if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
{
/* user defaults, unless SYS_DEFAULT sublanguage specified */
if (SUBLANGID(info->Language) != SUBLANG_SYS_DEFAULT)
{
/* 4. current thread locale language */
pos = push_language( list, pos, LANGIDFROMLCID(NtCurrentTeb()->CurrentLocale) );
if (NT_SUCCESS(NtQueryDefaultLocale(TRUE, &user_lcid)))
{
/* 5. user locale language */
pos = push_language( list, pos, LANGIDFROMLCID(user_lcid) );
/* 6. user locale language with neutral sublanguage */
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(user_lcid), SUBLANG_NEUTRAL ) );
}
}
/* now system defaults */
if (NT_SUCCESS(NtQueryDefaultLocale(FALSE, &system_lcid)))
{
/* 7. system locale language */
pos = push_language( list, pos, LANGIDFROMLCID( system_lcid ) );
/* 8. system locale language with neutral sublanguage */
pos = push_language( list, pos, MAKELANGID( PRIMARYLANGID(system_lcid), SUBLANG_NEUTRAL ) );
}
/* 9. English */
pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
}
resdirptr = *ret;
for (i = 0; i < pos; i++)
if ((*ret = find_entry_by_id( resdirptr, list[i], root, want_dir ))) return STATUS_SUCCESS;
/* if no explicitly specified language, return the first entry */
if (PRIMARYLANGID(info->Language) == LANG_NEUTRAL)
{
if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
}
return STATUS_RESOURCE_LANG_NOT_FOUND;
done:
*ret = resdirptr;
return STATUS_SUCCESS;
}

View file

@ -0,0 +1,20 @@
#include <ndk/asm.h>
.intel_syntax noprefix
/*
* On x86, Shrinker, an executable compressor, depends on the
* "call access_resource" instruction being there.
*/
.globl _LdrAccessResource@16
_LdrAccessResource@16:
push ebp
mov ebp, esp
sub esp, 4
push [ebp + 24]
push [ebp + 20]
push [ebp + 16]
push [ebp + 12]
push [ebp + 8]
call _LdrpAccessResource@16
leave
ret 16

View file

@ -80,7 +80,7 @@ RtlImageDirectoryEntryToData (
return (PVOID)((ULONG_PTR)BaseAddress + Va);
/* image mapped as ordinary file, we must find raw pointer */
return (PVOID)RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
return RtlImageRvaToVa (NtHeader, BaseAddress, Va, NULL);
}
@ -117,7 +117,7 @@ RtlImageRvaToSection (
/*
* @implemented
*/
ULONG
PVOID
NTAPI
RtlImageRvaToVa (
PIMAGE_NT_HEADERS NtHeader,
@ -143,7 +143,7 @@ RtlImageRvaToVa (
*SectionHeader = Section;
}
return (ULONG)((ULONG_PTR)BaseAddress +
return (PVOID)((ULONG_PTR)BaseAddress +
Rva +
Section->PointerToRawData -
(ULONG_PTR)Section->VirtualAddress);

297
reactos/lib/rtl/res.c Normal file
View file

@ -0,0 +1,297 @@
/*
* PE file resources
*
* Copyright 1995 Thomas Sandford
* Copyright 1996 Martin von Loewis
* Copyright 2003 Alexandre Julliard
* Copyright 1993 Robert J. Amstadt
* Copyright 1997 Marcus Meissner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
ULONG level, void **ret, int want_dir );
/* FUNCTIONS ****************************************************************/
_SEH_FILTER(page_fault)
{
if (_SEH_GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ||
_SEH_GetExceptionCode() == EXCEPTION_PRIV_INSTRUCTION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
/**********************************************************************
* is_data_file_module
*
* Check if a module handle is for a LOAD_LIBRARY_AS_DATAFILE module.
*/
static int is_data_file_module( PVOID BaseAddress )
{
return (ULONG_PTR)BaseAddress & 1;
}
/**********************************************************************
* push_language
*
* push a language in the list of languages to try
*/
int push_language( USHORT *list, ULONG pos, WORD lang )
{
int i;
for (i = 0; i < pos; i++) if (list[i] == lang) return pos;
list[pos++] = lang;
return pos;
}
/**********************************************************************
* find_first_entry
*
* Find the first suitable entry in a resource directory
*/
IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
void *root, int want_dir )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
int pos;
for (pos = 0; pos < dir->NumberOfNamedEntries + dir->NumberOfIdEntries; pos++)
{
if (!entry[pos].DataIsDirectory == !want_dir)
return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
}
return NULL;
}
/**********************************************************************
* find_entry_by_id
*
* Find an entry by id in a resource directory
*/
IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
WORD id, void *root, int want_dir )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
int min, max, pos;
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
min = dir->NumberOfNamedEntries;
max = min + dir->NumberOfIdEntries - 1;
while (min <= max)
{
pos = (min + max) / 2;
if (entry[pos].Id == id)
{
if (!entry[pos].DataIsDirectory == !want_dir)
{
DPRINT("root %p dir %p id %04x ret %p\n",
root, dir, id, (const char*)root + entry[pos].OffsetToDirectory);
return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
}
break;
}
if (entry[pos].Id > id) max = pos - 1;
else min = pos + 1;
}
DPRINT("root %p dir %p id %04x not found\n", root, dir, id );
return NULL;
}
/**********************************************************************
* find_entry_by_name
*
* Find an entry by name in a resource directory
*/
IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
LPCWSTR name, void *root,
int want_dir )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
const IMAGE_RESOURCE_DIR_STRING_U *str;
int min, max, res, pos, namelen;
if (!((ULONG_PTR)name & 0xFFFF0000)) return find_entry_by_id( dir, (ULONG_PTR)name & 0xFFFF, root, want_dir );
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
namelen = wcslen(name);
min = 0;
max = dir->NumberOfNamedEntries - 1;
while (min <= max)
{
pos = (min + max) / 2;
str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const char *)root + entry[pos].NameOffset);
res = wcsncmp( name, str->NameString, str->Length );
if (!res && namelen == str->Length)
{
if (!entry[pos].DataIsDirectory == !want_dir)
{
DPRINT("root %p dir %p name %ws ret %p\n",
root, dir, name, (const char*)root + entry[pos].OffsetToDirectory);
return (IMAGE_RESOURCE_DIRECTORY *)((char *)root + entry[pos].OffsetToDirectory);
}
break;
}
if (res < 0) max = pos - 1;
else min = pos + 1;
}
DPRINT("root %p dir %p name %ws not found\n", root, dir, name);
return NULL;
}
#ifdef __i386__
NTSTATUS NTAPI LdrpAccessResource( PVOID BaseAddress, IMAGE_RESOURCE_DATA_ENTRY *entry,
void **ptr, ULONG *size )
#else
static NTSTATUS LdrpAccessResource( PVOID BaseAddress, IMAGE_RESOURCE_DATA_ENTRY *entry,
void **ptr, ULONG *size )
#endif
{
NTSTATUS status = STATUS_SUCCESS;
_SEH_TRY
{
ULONG dirsize;
if (!RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &dirsize ))
status = STATUS_RESOURCE_DATA_NOT_FOUND;
else
{
if (ptr)
{
if (is_data_file_module(BaseAddress))
{
PVOID mod = (PVOID)((ULONG_PTR)BaseAddress & ~1);
*ptr = RtlImageRvaToVa( RtlImageNtHeader(mod), mod, entry->OffsetToData, NULL );
}
else *ptr = (char *)BaseAddress + entry->OffsetToData;
}
if (size) *size = entry->Size;
}
}
_SEH_EXCEPT(page_fault)
{
status = _SEH_GetExceptionCode();
}
_SEH_END;
return status;
}
/*
* @implemented
*/
NTSTATUS NTAPI
LdrFindResource_U(PVOID BaseAddress,
PLDR_RESOURCE_INFO ResourceInfo,
ULONG Level,
PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
{
void *res;
NTSTATUS status = STATUS_SUCCESS;
_SEH_TRY
{
if (ResourceInfo)
{
DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
BaseAddress, (LPCWSTR)ResourceInfo->Type,
Level > 1 ? (LPCWSTR)ResourceInfo->Name : L"",
Level > 2 ? ResourceInfo->Language : 0, Level );
}
status = find_entry( BaseAddress, ResourceInfo, Level, &res, FALSE );
if (status == STATUS_SUCCESS) *ResourceDataEntry = res;
}
_SEH_EXCEPT(page_fault)
{
status = _SEH_GetExceptionCode();
}
_SEH_END;
return status;
}
#ifndef __i386__
/*
* @implemented
*/
NTSTATUS NTAPI
LdrAccessResource(IN PVOID BaseAddress,
IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
OUT PVOID* Resource OPTIONAL,
OUT PULONG Size OPTIONAL)
{
return LdrpAccessResource( BaseAddress, ResourceDataEntry, Resource, Size );
}
#endif
/*
* @implemented
*/
NTSTATUS NTAPI
LdrFindResourceDirectory_U(IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO info,
IN ULONG level,
OUT PIMAGE_RESOURCE_DIRECTORY* addr)
{
void *res;
NTSTATUS status = STATUS_SUCCESS;
_SEH_TRY
{
if (info)
{
DPRINT( "module %p type %ws name %ws lang %04lx level %ld\n",
BaseAddress, (LPCWSTR)info->Type,
level > 1 ? (LPCWSTR)info->Name : L"",
level > 2 ? info->Language : 0, level );
}
status = find_entry( BaseAddress, info, level, &res, TRUE );
if (status == STATUS_SUCCESS) *addr = res;
}
_SEH_EXCEPT(page_fault)
{
status = _SEH_GetExceptionCode();
}
_SEH_END;
return status;
}
/*
* @unimplemented
*/
NTSTATUS NTAPI
LdrEnumResources(IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO ResourceInfo,
IN ULONG Level,
IN OUT PULONG ResourceCount,
OUT PVOID Resources OPTIONAL)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}

View file

@ -23,4 +23,6 @@
#include <reactos/helper.h>
#include "rtlp.h"
#include <pseh/pseh.h>
/* EOF */

View file

@ -5,6 +5,7 @@
<define name="NO_RTL_INLINES" />
<define name="_NTSYSTEM_" />
<define name="_NTDLLBUILD_" />
<define name="_SEH_NO_NATIVE_NLG" />
<include base="rtl">.</include>
<if property="ARCH" value="i386">
<directory name="i386">
@ -36,6 +37,7 @@
<file>random_asm.S</file>
<file>pow_asm.s</file>
<file>prefetchmemory_asm.s</file>
<file>res_asm.s</file>
<file>sin_asm.s</file>
<file>sqrt_asm.s</file>
<file>tan_asm.s</file>
@ -76,6 +78,7 @@
<file>random.c</file>
<file>rangelist.c</file>
<file>registry.c</file>
<file>res.c</file>
<file>resource.c</file>
<file>sd.c</file>
<file>security.c</file>

View file

@ -1,228 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/resource.c
* PURPOSE: Resource loader
*
* PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
/*
* @implemented
*/
NTSTATUS STDCALL
LdrAccessResource(IN PVOID BaseAddress,
IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
OUT PVOID *Resource OPTIONAL,
OUT PULONG Size OPTIONAL)
{
PIMAGE_SECTION_HEADER Section;
PIMAGE_NT_HEADERS NtHeader;
ULONG SectionRva;
ULONG SectionVa;
ULONG DataSize;
ULONG Offset = 0;
ULONG Data;
if(!ResourceDataEntry)
return STATUS_RESOURCE_DATA_NOT_FOUND;
Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_RESOURCE,
&DataSize);
if (Data == 0)
return STATUS_RESOURCE_DATA_NOT_FOUND;
if ((ULONG_PTR)BaseAddress & 1)
{
/* loaded as ordinary file */
NtHeader = RtlImageNtHeader((PVOID)((ULONG_PTR)BaseAddress & ~1));
Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
Section = RtlImageRvaToSection (NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
if (Section == NULL)
{
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData)
{
SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
}
}
if (Resource)
{
*Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + ((ULONG_PTR)BaseAddress & ~1));
}
if (Size)
{
*Size = ResourceDataEntry->Size;
}
return STATUS_SUCCESS;
}
/*
* @implemented
*/
NTSTATUS STDCALL
LdrFindResource_U(PVOID BaseAddress,
PLDR_RESOURCE_INFO ResourceInfo,
ULONG Level,
PIMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry)
{
PIMAGE_RESOURCE_DIRECTORY ResDir;
PIMAGE_RESOURCE_DIRECTORY ResBase;
PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
NTSTATUS Status = STATUS_SUCCESS;
ULONG EntryCount;
PWCHAR ws;
ULONG i;
ULONG Id;
DPRINT ("LdrFindResource_U()\n");
/* Get the pointer to the resource directory */
ResDir = (PIMAGE_RESOURCE_DIRECTORY)
RtlImageDirectoryEntryToData (BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_RESOURCE,
&i);
if (ResDir == NULL)
{
return STATUS_RESOURCE_DATA_NOT_FOUND;
}
DPRINT("ResourceDirectory: %x\n", (ULONG)ResDir);
ResBase = ResDir;
/* Let's go into resource tree */
for (i = 0; i < Level; i++)
{
DPRINT("ResDir: %x\n", (ULONG)ResDir);
Id = ((PULONG)ResourceInfo)[i];
EntryCount = ResDir->NumberOfNamedEntries;
ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
DPRINT("ResEntry %x\n", (ULONG)ResEntry);
if (Id & 0xFFFF0000)
{
/* Resource name is a unicode string */
for (; EntryCount--; ResEntry++)
{
/* Scan entries for equal name */
if (ResEntry->Name & 0x80000000)
{
ws = (PWCHAR)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
if (!wcsncmp((PWCHAR)Id, ws + 1, *ws ) &&
wcslen((PWCHAR)Id) == (ULONG)*ws )
{
goto found;
}
}
}
}
else
{
/* We use ID number instead of string */
ResEntry += EntryCount;
EntryCount = ResDir->NumberOfIdEntries;
for (; EntryCount--; ResEntry++)
{
/* Scan entries for equal name */
if (ResEntry->Name == Id)
{
DPRINT("ID entry found %x\n", Id);
goto found;
}
}
}
DPRINT("Error %lu\n", i);
switch (i)
{
case 0:
return STATUS_RESOURCE_TYPE_NOT_FOUND;
case 1:
return STATUS_RESOURCE_NAME_NOT_FOUND;
case 2:
if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries)
{
/* Use the first available language */
ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
break;
}
return STATUS_RESOURCE_LANG_NOT_FOUND;
case 3:
return STATUS_RESOURCE_DATA_NOT_FOUND;
default:
return STATUS_INVALID_PARAMETER;
}
found:;
ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
(ResEntry->OffsetToData & 0x7FFFFFFF));
}
DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
if (ResourceDataEntry)
{
*ResourceDataEntry = (PVOID)ResDir;
}
return Status;
}
/* STUBS */
/*
* @unimplemented
*/
NTSTATUS
STDCALL
LdrFindResourceDirectory_U(
IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO ResourceInfo,
IN ULONG Level,
OUT PIMAGE_RESOURCE_DIRECTORY *ResourceDirectory
)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS
STDCALL
LdrEnumResources(
IN PVOID BaseAddress,
IN PLDR_RESOURCE_INFO ResourceInfo,
IN ULONG Level,
IN OUT PULONG ResourceCount,
OUT PVOID Resources OPTIONAL
)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */

View file

@ -226,7 +226,6 @@
<directory name="ldr">
<compilationunit name="ldr.c">
<file>loader.c</file>
<file>resource.c</file>
<file>rtl.c</file>
</compilationunit>
</directory>

View file

@ -363,4 +363,55 @@ RtlpCreateUnicodeString(
return TRUE;
}
/*
* Ldr Resource support code
*/
IMAGE_RESOURCE_DIRECTORY *find_entry_by_name( IMAGE_RESOURCE_DIRECTORY *dir,
LPCWSTR name, void *root,
int want_dir );
IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( IMAGE_RESOURCE_DIRECTORY *dir,
WORD id, void *root, int want_dir );
IMAGE_RESOURCE_DIRECTORY *find_first_entry( IMAGE_RESOURCE_DIRECTORY *dir,
void *root, int want_dir );
/**********************************************************************
* find_entry
*
* Find a resource entry
*/
NTSTATUS find_entry( PVOID BaseAddress, LDR_RESOURCE_INFO *info,
ULONG level, void **ret, int want_dir )
{
ULONG size;
void *root;
IMAGE_RESOURCE_DIRECTORY *resdirptr;
root = RtlImageDirectoryEntryToData( BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size );
if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND;
resdirptr = root;
if (!level--) goto done;
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Type, root, want_dir || level )))
return STATUS_RESOURCE_TYPE_NOT_FOUND;
if (!level--) return STATUS_SUCCESS;
resdirptr = *ret;
if (!(*ret = find_entry_by_name( resdirptr, (LPCWSTR)info->Name, root, want_dir || level )))
return STATUS_RESOURCE_NAME_NOT_FOUND;
if (!level--) return STATUS_SUCCESS;
if (level) return STATUS_INVALID_PARAMETER; /* level > 3 */
resdirptr = *ret;
if ((*ret = find_first_entry( resdirptr, root, want_dir ))) return STATUS_SUCCESS;
return STATUS_RESOURCE_DATA_NOT_FOUND;
done:
*ret = resdirptr;
return STATUS_SUCCESS;
}
/* EOF */