mirror of
https://github.com/reactos/reactos.git
synced 2025-07-23 11:33:43 +00:00
* Create a branch for USB experiments.
svn path=/branches/usb-experiments/; revision=72629
This commit is contained in:
parent
28d8ba0d3e
commit
0ee830d7a4
23049 changed files with 0 additions and 1313991 deletions
550
boot/environ/lib/misc/resource.c
Normal file
550
boot/environ/lib/misc/resource.c
Normal file
|
@ -0,0 +1,550 @@
|
|||
/*
|
||||
* COPYRIGHT: See COPYING.ARM in the top level directory
|
||||
* PROJECT: ReactOS UEFI Boot Library
|
||||
* FILE: boot/environ/lib/misc/resource.c
|
||||
* PURPOSE: Boot Library Resource Functions
|
||||
* PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "bl.h"
|
||||
|
||||
/* DATA VARIABLES ************************************************************/
|
||||
|
||||
PVOID ResPeImageBase;
|
||||
PVOID ResPeImageEnd;
|
||||
PVOID ResRootDirectory;
|
||||
|
||||
PVOID ResPeImageBasePrimary;
|
||||
PVOID ResPeImageEndPrimary;
|
||||
PVOID ResRootDirectoryPrimary;
|
||||
ULONG_PTR ResRootDirectoryPrimaryOffset;
|
||||
ULONG_PTR ResRootDirectoryOffset;
|
||||
ULONG_PTR ResRootDirectoryFallbackOffset;
|
||||
PVOID ResPeImageBaseFallback;
|
||||
PVOID ResPeImageEndFallback;
|
||||
PVOID ResRootDirectoryFallback;
|
||||
|
||||
BOOLEAN ResLoadedFontFiles;
|
||||
PVOID ResMuiImageBase;
|
||||
ULONG_PTR ResMuiImageSize;
|
||||
|
||||
PWCHAR ResLocale;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
ResSelectLocale (
|
||||
_In_ BOOLEAN Primary
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Check if we're using the primary (MUI) or fallback resources */
|
||||
if (Primary)
|
||||
{
|
||||
/* Use the primary ones */
|
||||
ResRootDirectory = ResRootDirectoryPrimary;
|
||||
ResRootDirectoryOffset = ResRootDirectoryPrimaryOffset;
|
||||
ResPeImageBase = ResPeImageBasePrimary;
|
||||
ResPeImageEnd = ResPeImageEndPrimary;
|
||||
|
||||
/* Register the locale with the display */
|
||||
Status = BlpDisplayRegisterLocale(ResLocale);
|
||||
}
|
||||
|
||||
/* Check if that failed, or if we're using fallback */
|
||||
if (!(Primary) || !(NT_SUCCESS(Status)))
|
||||
{
|
||||
/* Set the fallback pointers */
|
||||
ResRootDirectory = ResRootDirectoryFallback;
|
||||
ResRootDirectoryOffset = ResRootDirectoryFallbackOffset;
|
||||
ResPeImageBase = ResPeImageBaseFallback;
|
||||
ResPeImageEnd = ResPeImageEndFallback;
|
||||
|
||||
/* Register the fallback (America baby!) locale */
|
||||
Status = BlpDisplayRegisterLocale(L"en-US");
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fallback to text mode (yes, this is the API...) */
|
||||
return BlDisplaySetScreenResolution();
|
||||
}
|
||||
}
|
||||
|
||||
/* No fonts loaded -- return failure code */
|
||||
ResLoadedFontFiles = FALSE;
|
||||
return Status;
|
||||
}
|
||||
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY
|
||||
ResFindDirectoryEntry (
|
||||
_In_ PIMAGE_RESOURCE_DIRECTORY Directory,
|
||||
_In_opt_ PUSHORT Id,
|
||||
_In_opt_ PWCHAR Name,
|
||||
_In_ ULONG_PTR SectionStart
|
||||
)
|
||||
{
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY EntryTable, IdEntryTable;
|
||||
ULONG i;
|
||||
SIZE_T NameLength;
|
||||
PIMAGE_RESOURCE_DIRECTORY_STRING NameString;
|
||||
|
||||
/* Are we looking by ID or name? */
|
||||
if (Id)
|
||||
{
|
||||
/* By ID, so were we passed a name? */
|
||||
if (Name)
|
||||
{
|
||||
/* That doesn't make sense */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (!Name)
|
||||
{
|
||||
/* By name, but we weren't given one. Also bad. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the table of names */
|
||||
EntryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(Directory + 1);
|
||||
|
||||
/* Check if we are doing ID lookup instead */
|
||||
if (Id)
|
||||
{
|
||||
/* The IDs come after the names */
|
||||
IdEntryTable = &EntryTable[Directory->NumberOfNamedEntries];
|
||||
|
||||
/* Parse them */
|
||||
for (i = 0; i < Directory->NumberOfIdEntries; i++)
|
||||
{
|
||||
/* Check if the ID matches, or if the wildcard is being used*/
|
||||
if ((IdEntryTable[i].Id == *Id) || (*Id == 0xFFFF))
|
||||
{
|
||||
/* Return a pointer to the data */
|
||||
return (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(SectionStart + IdEntryTable[i].OffsetToDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/* ID was not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Searching by name, so parse them */
|
||||
for (i = 0; i < Directory->NumberOfNamedEntries; i++)
|
||||
{
|
||||
/* Get the name itself and count its length */
|
||||
NameString = (PIMAGE_RESOURCE_DIRECTORY_STRING)(SectionStart + EntryTable[i].NameOffset);
|
||||
NameLength = wcslen(Name);
|
||||
|
||||
/* If the length matches, compare the bytes */
|
||||
if ((NameLength == NameString->Length) &&
|
||||
(RtlCompareMemory(NameString->NameString, Name, NameLength) == NameLength))
|
||||
{
|
||||
/* They both match, so this is our entry. Return it */
|
||||
return (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(SectionStart + EntryTable[i].OffsetToDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
/* Name was not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
ResFindDataEntryFromImage (
|
||||
_In_opt_ PVOID ImageBase,
|
||||
_In_opt_ ULONG ImageSize,
|
||||
_In_ USHORT DirectoryId,
|
||||
_In_ PUSHORT EntryId,
|
||||
_In_ PWCHAR Name,
|
||||
_Out_ PIMAGE_RESOURCE_DATA_ENTRY *DataEntryOut,
|
||||
_Out_ PVOID* ResourceOut
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIMAGE_SECTION_HEADER ResourceSection;
|
||||
PIMAGE_RESOURCE_DIRECTORY ResourceDir, RootDir;
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY DirEntry;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY DataEntry;
|
||||
PVOID Data, DataEnd, ImageEnd;
|
||||
BOOLEAN UseFallbackDirectory;
|
||||
|
||||
/* Assume nothing found */
|
||||
UseFallbackDirectory = TRUE;
|
||||
Status = STATUS_NOT_FOUND;
|
||||
|
||||
/* Are we looking at a particular image? */
|
||||
if (ImageBase)
|
||||
{
|
||||
/* Then make sure we know its size */
|
||||
if (!ImageSize)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Find the resource section for it */
|
||||
ResourceSection = BlImgFindSection(ImageBase, ImageSize);
|
||||
if (!ResourceSection)
|
||||
{
|
||||
return STATUS_INVALID_IMAGE_FORMAT;
|
||||
}
|
||||
|
||||
/* Remember how big the image is, and find the resource directory */
|
||||
ImageEnd = (PVOID)((ULONG_PTR)ImageBase + ImageSize);
|
||||
RootDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG_PTR)ImageBase +
|
||||
ResourceSection->VirtualAddress);
|
||||
if ((PVOID)RootDir < ImageBase)
|
||||
{
|
||||
/* It's out of bounds, so bail out */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* We have a valid directory, don't use fallback for now */
|
||||
UseFallbackDirectory = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are using the current library settings instead */
|
||||
ImageBase = ResPeImageBase;
|
||||
RootDir = ResRootDirectory;
|
||||
ImageEnd = ResPeImageEnd;
|
||||
}
|
||||
|
||||
/* If we don't have a resource directory, there's nothing to find */
|
||||
if (!RootDir)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Try two loops, once for primary, once for fallback */
|
||||
while (1)
|
||||
{
|
||||
/* Find the directory first */
|
||||
ResourceDir = (PIMAGE_RESOURCE_DIRECTORY)ResFindDirectoryEntry(RootDir,
|
||||
&DirectoryId,
|
||||
NULL,
|
||||
(ULONG_PTR)RootDir);
|
||||
if (ResourceDir)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* We didn't find it -- is it time to use the fallback? */
|
||||
if (UseFallbackDirectory)
|
||||
{
|
||||
/* Were were not using the fallback already? */
|
||||
if (RootDir != ResRootDirectoryFallback)
|
||||
{
|
||||
/* Then attempt with the fallback instead*/
|
||||
RootDir = ResRootDirectoryFallback;
|
||||
ImageBase = ResPeImageBaseFallback;
|
||||
ImageEnd = ResPeImageEndFallback;
|
||||
|
||||
/* Making sure we have one... */
|
||||
if (RootDir)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, return failure here */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Now that we are in the right directory, lookup the resource */
|
||||
ResourceDir = (PIMAGE_RESOURCE_DIRECTORY)ResFindDirectoryEntry(ResourceDir,
|
||||
EntryId,
|
||||
Name,
|
||||
(ULONG_PTR)RootDir);
|
||||
if (!ResourceDir)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* The entry is right after */
|
||||
DirEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResourceDir + 1);
|
||||
if ((PVOID)DirEntry < (PVOID)ResourceDir)
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get the data entry for it */
|
||||
DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)((ULONG_PTR)RootDir +
|
||||
DirEntry->OffsetToData);
|
||||
|
||||
/* Check if the data entry is out of bounds */
|
||||
if (((PVOID)DataEntry < ImageBase) || ((PVOID)DataEntry > ImageEnd))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Finally read the data offset */
|
||||
Data = (PVOID)((ULONG_PTR)ImageBase + DataEntry->OffsetToData);
|
||||
|
||||
/* Check if the data is out of bounds */
|
||||
if (((PVOID)Data < ImageBase) || ((PVOID)Data > ImageEnd))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Make sure the data end isn't out of bounds either */
|
||||
DataEnd = (PVOID)((ULONG_PTR)Data + DataEntry->Size);
|
||||
if (((PVOID)DataEnd < ImageBase) || ((PVOID)DataEnd > ImageEnd))
|
||||
{
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* We finally made it. Return the entry and the raw data */
|
||||
*DataEntryOut = DataEntry;
|
||||
*ResourceOut = Data;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PWCHAR
|
||||
BlResourceFindHtml (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY HtmlDataEntry;
|
||||
PWCHAR Stylesheet;
|
||||
|
||||
/* Assume failure */
|
||||
Stylesheet = NULL;
|
||||
|
||||
/* Look for an RT_HTML resource called BOOTMGR.XSL */
|
||||
Status = ResFindDataEntryFromImage(NULL,
|
||||
0,
|
||||
23,
|
||||
NULL,
|
||||
L"BOOTMGR.XSL",
|
||||
&HtmlDataEntry,
|
||||
(PVOID*)&Stylesheet);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Stylesheet;
|
||||
}
|
||||
|
||||
/* Check for Unicode BOM */
|
||||
if (*Stylesheet == 0xFEFF)
|
||||
{
|
||||
/* Overwrite it, and NULL-terminate */
|
||||
RtlMoveMemory(Stylesheet,
|
||||
Stylesheet + 1,
|
||||
HtmlDataEntry->Size - sizeof(WCHAR));
|
||||
Stylesheet[(HtmlDataEntry->Size / sizeof(WCHAR)) - 1] = UNICODE_NULL;
|
||||
}
|
||||
else if (Stylesheet[(HtmlDataEntry->Size / sizeof(WCHAR)) - 1] != UNICODE_NULL)
|
||||
{
|
||||
/* If it's not NULL-terminated, fail */
|
||||
Stylesheet = NULL;
|
||||
}
|
||||
|
||||
/* Return it back */
|
||||
return Stylesheet;
|
||||
}
|
||||
|
||||
PWCHAR
|
||||
BlResourceFindMessage (
|
||||
_In_ ULONG MsgId
|
||||
)
|
||||
{
|
||||
PWCHAR Message;
|
||||
PIMAGE_RESOURCE_DIRECTORY ResourceDir;
|
||||
PIMAGE_RESOURCE_DATA_ENTRY DataEntry;
|
||||
PMESSAGE_RESOURCE_DATA MsgData;
|
||||
PMESSAGE_RESOURCE_ENTRY MsgEntry;
|
||||
ULONG i, j;
|
||||
USHORT Id;
|
||||
PVOID MsgEnd;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Bail out if there's no resource directory */
|
||||
Message = NULL;
|
||||
if (!ResRootDirectory)
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
|
||||
/* Check if we've loaded fonts already */
|
||||
if (!ResLoadedFontFiles)
|
||||
{
|
||||
/* Nope, load them now */
|
||||
Status = BfLoadDeferredFontFiles();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* We failed to load fonts, fallback to fallback locale */
|
||||
Status = ResSelectLocale(FALSE);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Try fonts now */
|
||||
Status = BfLoadDeferredFontFiles();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Still didn't work -- fallback to text mode */
|
||||
EfiPrintf(L"Font loading failed, falling back to text mode\r\n");
|
||||
Status = BlDisplaySetScreenResolution();
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* That didn't work either. F*ck it. */
|
||||
return Message;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have a resource directory, and fonts are loaded */
|
||||
NT_ASSERT(ResRootDirectory != NULL);
|
||||
ResLoadedFontFiles = TRUE;
|
||||
}
|
||||
|
||||
/* Go look for RT_MESSAGETABLE */
|
||||
Id = 11;
|
||||
ResourceDir = (PIMAGE_RESOURCE_DIRECTORY)ResFindDirectoryEntry(ResRootDirectory,
|
||||
&Id,
|
||||
NULL,
|
||||
(ULONG_PTR)ResRootDirectory);
|
||||
if (!ResourceDir)
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
|
||||
/* Go look for the first directory in the table */
|
||||
Id = 1;
|
||||
ResourceDir = (PIMAGE_RESOURCE_DIRECTORY)ResFindDirectoryEntry(ResourceDir,
|
||||
&Id,
|
||||
NULL,
|
||||
(ULONG_PTR)ResRootDirectory);
|
||||
if (!ResourceDir)
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
|
||||
/* Go look for any language entry in the table */
|
||||
Id = -1;
|
||||
DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)ResFindDirectoryEntry(ResourceDir,
|
||||
&Id,
|
||||
NULL,
|
||||
(ULONG_PTR)ResRootDirectory);
|
||||
if (!DataEntry)
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
|
||||
/* Get the message data*/
|
||||
MsgData = (PMESSAGE_RESOURCE_DATA)((ULONG_PTR)ResRootDirectory +
|
||||
DataEntry->OffsetToData -
|
||||
ResRootDirectoryOffset);
|
||||
|
||||
/* Loop through the message blocks */
|
||||
for (j = 0; j < MsgData->NumberOfBlocks; j++)
|
||||
{
|
||||
/* Check if the ID is within this range */
|
||||
if ((MsgId >= MsgData->Blocks[j].LowId) &&
|
||||
(MsgId <= MsgData->Blocks[j].HighId))
|
||||
{
|
||||
/* Get the first entry */
|
||||
MsgEntry = (PMESSAGE_RESOURCE_ENTRY)((ULONG_PTR)MsgData +
|
||||
MsgData->Blocks[j].OffsetToEntries);
|
||||
|
||||
/* Loop till we find the right one */
|
||||
for (i = MsgId - MsgData->Blocks[j].LowId; i; --i)
|
||||
{
|
||||
MsgEntry = (PMESSAGE_RESOURCE_ENTRY)((ULONG_PTR)MsgEntry +
|
||||
MsgEntry->Length);
|
||||
}
|
||||
|
||||
/* Find where this message ends */
|
||||
MsgEnd = (PVOID)((ULONG_PTR)MsgEntry + MsgEntry->Length);
|
||||
|
||||
/* Now make sure that the message is within bounds */
|
||||
if ((MsgEnd >= (PVOID)MsgEntry) &&
|
||||
((PVOID)MsgEntry >= ResPeImageBase) &&
|
||||
(MsgEnd <= ResPeImageEnd))
|
||||
{
|
||||
/* If so, read the text associated with it */
|
||||
Message = (PWCHAR)MsgEntry->Text;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the text, if one was found */
|
||||
return Message;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
BlpResourceInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIMAGE_SECTION_HEADER ResourceSection;
|
||||
PVOID ImageBase;
|
||||
ULONG ImageSize, VRes, HRes;
|
||||
BOOLEAN UsePrimary;
|
||||
|
||||
/* Default to using fallback */
|
||||
UsePrimary = FALSE;
|
||||
|
||||
/* Initialize all globals */
|
||||
ResMuiImageBase = 0;
|
||||
ResMuiImageSize = 0;
|
||||
ResRootDirectoryPrimary = 0;
|
||||
ResRootDirectoryPrimaryOffset = 0;
|
||||
ResPeImageBasePrimary = 0;
|
||||
ResPeImageEndPrimary = 0;
|
||||
ResRootDirectoryFallback = 0;
|
||||
ResRootDirectoryFallbackOffset = 0;
|
||||
ResPeImageBaseFallback = 0;
|
||||
ResPeImageEndFallback = 0;
|
||||
ResRootDirectory = 0;
|
||||
ResRootDirectoryOffset = 0;
|
||||
ResPeImageBase = 0;
|
||||
ResPeImageEnd = 0;
|
||||
ResLoadedFontFiles = 0;
|
||||
|
||||
/* Check if we had allocated a locale already */
|
||||
if (ResLocale)
|
||||
{
|
||||
/* Free it and reset */
|
||||
BlMmFreeHeap(ResLocale);
|
||||
ResLocale = 0;
|
||||
}
|
||||
|
||||
/* Get our base address and size*/
|
||||
Status = BlGetApplicationBaseAndSize(&ImageBase, &ImageSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Find our resource section */
|
||||
ResourceSection = BlImgFindSection(ImageBase, ImageSize);
|
||||
if (ResourceSection)
|
||||
{
|
||||
/* The resource section will be our fallback. Save down its details */
|
||||
ResRootDirectoryFallbackOffset = ResourceSection->VirtualAddress;
|
||||
ResPeImageBaseFallback = ImageBase;
|
||||
ResPeImageEndFallback = (PVOID)((ULONG_PTR)ImageBase + ImageSize);
|
||||
ResRootDirectoryFallback = (PIMAGE_RESOURCE_DIRECTORY)((ULONG_PTR)ImageBase +
|
||||
ResRootDirectoryFallbackOffset);
|
||||
}
|
||||
|
||||
/* Get the current screen resolution and check if we're in graphics mode */
|
||||
Status = BlDisplayGetScreenResolution(&HRes, &VRes);
|
||||
if ((NT_SUCCESS(Status)) && ((HRes != 640) || (VRes != 200)))
|
||||
{
|
||||
/* We are... we should load MUI data */
|
||||
Status = STATUS_NOT_IMPLEMENTED;//ResInitializeMuiResources();
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* And not rely on the fallback */
|
||||
UsePrimary = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the locale resources */
|
||||
return ResSelectLocale(UsePrimary);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue