mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
- 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:
parent
234544358a
commit
84649db0e9
13 changed files with 481 additions and 622 deletions
|
@ -2092,7 +2092,7 @@ RtlImageDirectoryEntryToData(
|
|||
);
|
||||
|
||||
NTSYSAPI
|
||||
ULONG
|
||||
PVOID
|
||||
NTAPI
|
||||
RtlImageRvaToVa(
|
||||
PIMAGE_NT_HEADERS NtHeader,
|
||||
|
|
|
@ -36,7 +36,7 @@ KiUserCallbackDispatcher@12
|
|||
KiUserExceptionDispatcher@8
|
||||
LdrAccessResource@16
|
||||
LdrDisableThreadCalloutsForDll@4
|
||||
;LdrEnumResources@20
|
||||
LdrEnumResources@20
|
||||
LdrFindEntryForAddress@8
|
||||
LdrFindResourceDirectory_U@16
|
||||
LdrFindResource_U@16
|
||||
|
|
|
@ -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 */
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
20
reactos/lib/rtl/i386/res_asm.s
Normal file
20
reactos/lib/rtl/i386/res_asm.s
Normal 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
|
|
@ -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
297
reactos/lib/rtl/res.c
Normal 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;
|
||||
}
|
|
@ -23,4 +23,6 @@
|
|||
#include <reactos/helper.h>
|
||||
#include "rtlp.h"
|
||||
|
||||
#include <pseh/pseh.h>
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
|
@ -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>
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue