mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 14:25:52 +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
|
NTSYSAPI
|
||||||
ULONG
|
PVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlImageRvaToVa(
|
RtlImageRvaToVa(
|
||||||
PIMAGE_NT_HEADERS NtHeader,
|
PIMAGE_NT_HEADERS NtHeader,
|
||||||
|
|
|
@ -36,7 +36,7 @@ KiUserCallbackDispatcher@12
|
||||||
KiUserExceptionDispatcher@8
|
KiUserExceptionDispatcher@8
|
||||||
LdrAccessResource@16
|
LdrAccessResource@16
|
||||||
LdrDisableThreadCalloutsForDll@4
|
LdrDisableThreadCalloutsForDll@4
|
||||||
;LdrEnumResources@20
|
LdrEnumResources@20
|
||||||
LdrFindEntryForAddress@8
|
LdrFindEntryForAddress@8
|
||||||
LdrFindResourceDirectory_U@16
|
LdrFindResourceDirectory_U@16
|
||||||
LdrFindResource_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>rtl</library>
|
||||||
<library>intrlck</library>
|
<library>intrlck</library>
|
||||||
<library>string</library>
|
<library>string</library>
|
||||||
|
<library>pseh</library>
|
||||||
<linkerflag>-lgcc</linkerflag>
|
<linkerflag>-lgcc</linkerflag>
|
||||||
<linkerflag>-nostdlib</linkerflag>
|
<linkerflag>-nostdlib</linkerflag>
|
||||||
<linkerflag>-nostartfiles</linkerflag>
|
<linkerflag>-nostartfiles</linkerflag>
|
||||||
|
@ -23,7 +24,6 @@
|
||||||
<file>dbgui.c</file>
|
<file>dbgui.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="ldr">
|
<directory name="ldr">
|
||||||
<file>res.c</file>
|
|
||||||
<file>startup.c</file>
|
<file>startup.c</file>
|
||||||
<file>utils.c</file>
|
<file>utils.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -328,3 +328,105 @@ RtlpGetAtomEntry(PRTL_ATOM_TABLE AtomTable, ULONG Index)
|
||||||
return NULL;
|
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);
|
return (PVOID)((ULONG_PTR)BaseAddress + Va);
|
||||||
|
|
||||||
/* image mapped as ordinary file, we must find raw pointer */
|
/* 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
|
* @implemented
|
||||||
*/
|
*/
|
||||||
ULONG
|
PVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
RtlImageRvaToVa (
|
RtlImageRvaToVa (
|
||||||
PIMAGE_NT_HEADERS NtHeader,
|
PIMAGE_NT_HEADERS NtHeader,
|
||||||
|
@ -143,7 +143,7 @@ RtlImageRvaToVa (
|
||||||
*SectionHeader = Section;
|
*SectionHeader = Section;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ULONG)((ULONG_PTR)BaseAddress +
|
return (PVOID)((ULONG_PTR)BaseAddress +
|
||||||
Rva +
|
Rva +
|
||||||
Section->PointerToRawData -
|
Section->PointerToRawData -
|
||||||
(ULONG_PTR)Section->VirtualAddress);
|
(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 <reactos/helper.h>
|
||||||
#include "rtlp.h"
|
#include "rtlp.h"
|
||||||
|
|
||||||
|
#include <pseh/pseh.h>
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<define name="NO_RTL_INLINES" />
|
<define name="NO_RTL_INLINES" />
|
||||||
<define name="_NTSYSTEM_" />
|
<define name="_NTSYSTEM_" />
|
||||||
<define name="_NTDLLBUILD_" />
|
<define name="_NTDLLBUILD_" />
|
||||||
|
<define name="_SEH_NO_NATIVE_NLG" />
|
||||||
<include base="rtl">.</include>
|
<include base="rtl">.</include>
|
||||||
<if property="ARCH" value="i386">
|
<if property="ARCH" value="i386">
|
||||||
<directory name="i386">
|
<directory name="i386">
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
<file>random_asm.S</file>
|
<file>random_asm.S</file>
|
||||||
<file>pow_asm.s</file>
|
<file>pow_asm.s</file>
|
||||||
<file>prefetchmemory_asm.s</file>
|
<file>prefetchmemory_asm.s</file>
|
||||||
|
<file>res_asm.s</file>
|
||||||
<file>sin_asm.s</file>
|
<file>sin_asm.s</file>
|
||||||
<file>sqrt_asm.s</file>
|
<file>sqrt_asm.s</file>
|
||||||
<file>tan_asm.s</file>
|
<file>tan_asm.s</file>
|
||||||
|
@ -76,6 +78,7 @@
|
||||||
<file>random.c</file>
|
<file>random.c</file>
|
||||||
<file>rangelist.c</file>
|
<file>rangelist.c</file>
|
||||||
<file>registry.c</file>
|
<file>registry.c</file>
|
||||||
|
<file>res.c</file>
|
||||||
<file>resource.c</file>
|
<file>resource.c</file>
|
||||||
<file>sd.c</file>
|
<file>sd.c</file>
|
||||||
<file>security.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">
|
<directory name="ldr">
|
||||||
<compilationunit name="ldr.c">
|
<compilationunit name="ldr.c">
|
||||||
<file>loader.c</file>
|
<file>loader.c</file>
|
||||||
<file>resource.c</file>
|
|
||||||
<file>rtl.c</file>
|
<file>rtl.c</file>
|
||||||
</compilationunit>
|
</compilationunit>
|
||||||
</directory>
|
</directory>
|
||||||
|
|
|
@ -363,4 +363,55 @@ RtlpCreateUnicodeString(
|
||||||
return TRUE;
|
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 */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue