reactos/reactos/ntoskrnl/ldr/resource.c
Royce Mitchell III 080762083a @implemented and @unimplemented comments for ntoskrnl/ldr/*.c
svn path=/trunk/; revision=5051
2003-07-10 20:34:50 +00:00

190 lines
4.8 KiB
C

/* $Id: resource.c,v 1.5 2003/07/10 20:34:50 royce Exp $
*
* 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 <ddk/ntddk.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;
Data = (ULONG)RtlImageDirectoryEntryToData (BaseAddress,
TRUE,
IMAGE_DIRECTORY_ENTRY_RESOURCE,
&DataSize);
if (Data == 0)
return STATUS_RESOURCE_DATA_NOT_FOUND;
if ((ULONG)BaseAddress & 1)
{
/* loaded as ordinary file */
NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
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 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;
}
/* EOF */