[FREELDR:NTLDR] Improve NLS data loading.

- Use UNICODE_STRINGs wherever possible.
- Retrieve the OEMHAL font file name. TODO: Load it!

- In WinLdrLoadNLSData(), don't open/close each file twice (and showing
  we are loading them twice). Instead, open all files at once (and keep
  them that way), retrieve their sizes and do the calculations, then
  load their respective contents one by one -- giving loading feedback
  only at that point -- and finally close all of them at once.
This commit is contained in:
Hermès Bélusca-Maïto 2022-03-21 23:01:22 +01:00
parent 24cb57fdea
commit 57b9c6b2f2
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 220 additions and 191 deletions

View file

@ -22,60 +22,74 @@ AllocateAndInitLPB(
OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock); OUT PLOADER_PARAMETER_BLOCK* OutLoaderBlock);
static VOID static VOID
SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, PCSTR SearchPath) SetupLdrLoadNlsData(
_Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock,
_In_ HINF InfHandle,
_In_ PCSTR SearchPath)
{ {
BOOLEAN Success;
INFCONTEXT InfContext; INFCONTEXT InfContext;
PCSTR AnsiName, OemName, LangName; PCSTR AnsiData;
UNICODE_STRING AnsiFileName = {0};
UNICODE_STRING OemFileName = {0};
UNICODE_STRING LangFileName = {0}; // CaseTable
UNICODE_STRING OemHalFileName = {0};
/* Get ANSI codepage file */ /* Get ANSI codepage file */
if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext)) if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext) ||
!InfGetDataField(&InfContext, 1, &AnsiData) ||
!RtlCreateUnicodeStringFromAsciiz(&AnsiFileName, AnsiData))
{ {
ERR("Failed to find 'NLS/AnsiCodepage'\n"); ERR("Failed to find or get 'NLS/AnsiCodepage'\n");
return;
}
if (!InfGetDataField(&InfContext, 1, &AnsiName))
{
ERR("Failed to get load options\n");
return; return;
} }
/* Get OEM codepage file */ /* Get OEM codepage file */
if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext)) if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext) ||
!InfGetDataField(&InfContext, 1, &AnsiData) ||
!RtlCreateUnicodeStringFromAsciiz(&OemFileName, AnsiData))
{ {
ERR("Failed to find 'NLS/AnsiCodepage'\n"); ERR("Failed to find or get 'NLS/OemCodepage'\n");
return; goto Quit;
}
if (!InfGetDataField(&InfContext, 1, &OemName))
{
ERR("Failed to get load options\n");
return;
} }
if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext)) /* Get the Unicode case table file */
if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext) ||
!InfGetDataField(&InfContext, 1, &AnsiData) ||
!RtlCreateUnicodeStringFromAsciiz(&LangFileName, AnsiData))
{ {
ERR("Failed to find 'NLS/AnsiCodepage'\n"); ERR("Failed to find or get 'NLS/UnicodeCasetable'\n");
return; goto Quit;
}
if (!InfGetDataField(&InfContext, 1, &LangName))
{
ERR("Failed to get load options\n");
return;
} }
TRACE("NLS data '%s' '%s' '%s'\n", AnsiName, OemName, LangName); /* Get OEM HAL font file */
if (!InfFindFirstLine(InfHandle, "NLS", "OemHalFont", &InfContext) ||
#if DBG !InfGetData(&InfContext, NULL, &AnsiData) ||
!RtlCreateUnicodeStringFromAsciiz(&OemHalFileName, AnsiData))
{ {
BOOLEAN Success = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName); WARN("Failed to find or get 'NLS/OemHalFont'\n");
(VOID)Success; /* Ignore, this is an optional file */
TRACE("NLS data loading %s\n", Success ? "successful" : "failed"); RtlInitEmptyUnicodeString(&OemHalFileName, NULL, 0);
} }
#else
WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
#endif
/* TODO: Load OEM HAL font */ TRACE("NLS data: '%wZ' '%wZ' '%wZ' '%wZ'\n",
// Value "OemHalFont" &AnsiFileName, &OemFileName, &LangFileName, &OemHalFileName);
/* Load NLS data */
Success = WinLdrLoadNLSData(LoaderBlock,
SearchPath,
&AnsiFileName,
&OemFileName,
&LangFileName,
&OemHalFileName);
TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
(VOID)Success;
Quit:
RtlFreeUnicodeString(&OemHalFileName);
RtlFreeUnicodeString(&LangFileName);
RtlFreeUnicodeString(&OemFileName);
RtlFreeUnicodeString(&AnsiFileName);
} }
static static

View file

@ -124,12 +124,16 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
PCSTR SystemPath, PCSTR SystemPath,
PCSTR BootPath, PCSTR BootPath,
USHORT VersionToBoot); USHORT VersionToBoot);
BOOLEAN BOOLEAN
WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, WinLdrLoadNLSData(
IN PCSTR DirectoryPath, _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PCSTR AnsiFileName, _In_ PCSTR DirectoryPath,
IN PCSTR OemFileName, _In_ PCUNICODE_STRING AnsiFileName,
IN PCSTR LanguageFileName); _In_ PCUNICODE_STRING OemFileName,
_In_ PCUNICODE_STRING LangFileName, // CaseTable
_In_ PCUNICODE_STRING OemHalFileName);
BOOLEAN BOOLEAN
WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
PWSTR RegistryPath, PWSTR RegistryPath,

View file

@ -20,12 +20,10 @@ ULONG TotalNLSSize = 0;
static BOOLEAN static BOOLEAN
WinLdrGetNLSNames( WinLdrGetNLSNames(
_Out_z_bytecap_(AnsiNameSize) PSTR AnsiName, _Inout_ PUNICODE_STRING AnsiFileName,
_In_ SIZE_T AnsiNameSize, _Inout_ PUNICODE_STRING OemFileName,
_Out_z_bytecap_(OemNameSize) PSTR OemName, _Inout_ PUNICODE_STRING LangFileName, // CaseTable
_In_ SIZE_T OemNameSize, _Inout_ PUNICODE_STRING OemHalFileName);
_Out_z_bytecap_(LangNameSize) PSTR LangName,
_In_ SIZE_T LangNameSize);
static VOID static VOID
WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead, WinLdrScanRegistry(IN OUT PLIST_ENTRY BootDriverListHead,
@ -178,34 +176,40 @@ BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PCSTR SystemRoot) IN PCSTR SystemRoot)
{ {
BOOLEAN Success; BOOLEAN Success;
DECLARE_UNICODE_STRING_SIZE(AnsiFileName, MAX_PATH);
DECLARE_UNICODE_STRING_SIZE(OemFileName, MAX_PATH);
DECLARE_UNICODE_STRING_SIZE(LangFileName, MAX_PATH); // CaseTable
DECLARE_UNICODE_STRING_SIZE(OemHalFileName, MAX_PATH);
CHAR SearchPath[1024]; CHAR SearchPath[1024];
CHAR AnsiName[256], OemName[256], LangName[256];
/* Scan registry and prepare boot drivers list */ /* Scan registry and prepare boot drivers list */
WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, SystemRoot); WinLdrScanRegistry(&LoaderBlock->BootDriverListHead, SystemRoot);
/* Get names of NLS files */ /* Get names of NLS files */
Success = WinLdrGetNLSNames(AnsiName, sizeof(AnsiName), Success = WinLdrGetNLSNames(&AnsiFileName,
OemName, sizeof(OemName), &OemFileName,
LangName, sizeof(LangName)); &LangFileName,
&OemHalFileName);
if (!Success) if (!Success)
{ {
UiMessageBox("Getting NLS names from registry failed!"); UiMessageBox("Getting NLS names from registry failed!");
return FALSE; return FALSE;
} }
TRACE("NLS data %s %s %s\n", AnsiName, OemName, LangName); TRACE("NLS data: '%wZ' '%wZ' '%wZ' '%wZ'\n",
&AnsiFileName, &OemFileName, &LangFileName, &OemHalFileName);
/* Load NLS data */ /* Load NLS data */
RtlStringCbCopyA(SearchPath, sizeof(SearchPath), SystemRoot); RtlStringCbCopyA(SearchPath, sizeof(SearchPath), SystemRoot);
RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\"); RtlStringCbCatA(SearchPath, sizeof(SearchPath), "system32\\");
Success = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName); Success = WinLdrLoadNLSData(LoaderBlock,
SearchPath,
&AnsiFileName,
&OemFileName,
&LangFileName,
&OemHalFileName);
TRACE("NLS data loading %s\n", Success ? "successful" : "failed"); TRACE("NLS data loading %s\n", Success ? "successful" : "failed");
/* TODO: Load OEM HAL font */
// In HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage,
// REG_SZ value "OEMHAL"
return TRUE; return TRUE;
} }
@ -213,21 +217,17 @@ BOOLEAN WinLdrScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
/* PRIVATE FUNCTIONS ******************************************************/ /* PRIVATE FUNCTIONS ******************************************************/
// Queries registry for those three file names // Queries registry for those three file names
_Use_decl_annotations_
static BOOLEAN static BOOLEAN
WinLdrGetNLSNames( WinLdrGetNLSNames(
_Out_ PSTR AnsiName, _Inout_ PUNICODE_STRING AnsiFileName,
_In_ SIZE_T AnsiNameSize, _Inout_ PUNICODE_STRING OemFileName,
_Out_ PSTR OemName, _Inout_ PUNICODE_STRING LangFileName, // CaseTable
_In_ SIZE_T OemNameSize, _Inout_ PUNICODE_STRING OemHalFileName)
_Out_ PSTR LangName,
_In_ SIZE_T LangNameSize)
{ {
LONG rc = ERROR_SUCCESS; LONG rc;
HKEY hKey; HKEY hKey;
ULONG BufferSize; ULONG BufferSize;
WCHAR szIdBuffer[80]; WCHAR szIdBuffer[80];
WCHAR NameBuffer[80];
/* Open the CodePage key */ /* Open the CodePage key */
rc = RegOpenKey(NULL, rc = RegOpenKey(NULL,
@ -239,47 +239,68 @@ WinLdrGetNLSNames(
return FALSE; return FALSE;
} }
/* Get ANSI codepage */ /* Get ANSI codepage file */
BufferSize = sizeof(szIdBuffer); BufferSize = sizeof(szIdBuffer);
rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize); rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("Couldn't get ACP NLS setting"); //TRACE("Couldn't get ACP NLS setting");
RegCloseKey(hKey); goto Quit;
return FALSE;
} }
BufferSize = sizeof(NameBuffer); BufferSize = AnsiFileName->MaximumLength;
rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize); rc = RegQueryValue(hKey, szIdBuffer, NULL,
(PUCHAR)AnsiFileName->Buffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("ACP NLS Setting exists, but isn't readable"); //TRACE("ACP NLS Setting exists, but isn't readable");
//RegCloseKey(hKey); //goto Quit;
//return FALSE; AnsiFileName->Length = 0;
wcscpy(NameBuffer, L"c_1252.nls"); // HACK: ReactOS bug CORE-6105 RtlAppendUnicodeToString(AnsiFileName, L"c_1252.nls"); // HACK: ReactOS bug CORE-6105
}
else
{
AnsiFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
} }
RtlStringCbPrintfA(AnsiName, AnsiNameSize, "%S", NameBuffer);
/* Get OEM codepage */ /* Get OEM codepage file */
BufferSize = sizeof(szIdBuffer); BufferSize = sizeof(szIdBuffer);
rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize); rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("Couldn't get OEMCP NLS setting"); //TRACE("Couldn't get OEMCP NLS setting");
RegCloseKey(hKey); goto Quit;
return FALSE;
} }
BufferSize = sizeof(NameBuffer); BufferSize = OemFileName->MaximumLength;
rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize); rc = RegQueryValue(hKey, szIdBuffer, NULL,
(PUCHAR)OemFileName->Buffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("OEMCP NLS setting exists, but isn't readable"); //TRACE("OEMCP NLS setting exists, but isn't readable");
//RegCloseKey(hKey); //goto Quit;
//return FALSE; OemFileName->Length = 0;
wcscpy(NameBuffer, L"c_437.nls"); // HACK: ReactOS bug CORE-6105 RtlAppendUnicodeToString(OemFileName, L"c_437.nls"); // HACK: ReactOS bug CORE-6105
}
else
{
OemFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
}
/* Get OEM HAL font file */
BufferSize = OemHalFileName->MaximumLength;
rc = RegQueryValue(hKey, L"OEMHAL", NULL,
(PUCHAR)OemHalFileName->Buffer, &BufferSize);
if (rc != ERROR_SUCCESS)
{
//TRACE("Couldn't get OEMHAL NLS setting");
//goto Quit;
RtlInitEmptyUnicodeString(OemHalFileName, NULL, 0);
}
else
{
OemHalFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
} }
RtlStringCbPrintfA(OemName, OemNameSize, "%S", NameBuffer);
RegCloseKey(hKey); RegCloseKey(hKey);
@ -293,68 +314,71 @@ WinLdrGetNLSNames(
return FALSE; return FALSE;
} }
/* Get the Unicode case table */ /* Get the Unicode case table file */
BufferSize = sizeof(szIdBuffer); BufferSize = sizeof(szIdBuffer);
rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize); rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("Couldn't get Language Default setting"); //TRACE("Couldn't get Language Default setting");
RegCloseKey(hKey); goto Quit;
return FALSE;
} }
BufferSize = sizeof(NameBuffer); BufferSize = LangFileName->MaximumLength;
rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize); rc = RegQueryValue(hKey, szIdBuffer, NULL,
(PUCHAR)LangFileName->Buffer, &BufferSize);
if (rc != ERROR_SUCCESS) if (rc != ERROR_SUCCESS)
{ {
//TRACE("Language Default setting exists, but isn't readable"); //TRACE("Language Default setting exists, but isn't readable");
RegCloseKey(hKey); //goto Quit;
return FALSE; LangFileName->Length = 0;
RtlAppendUnicodeToString(LangFileName, L"l_intl.nls");
}
else
{
LangFileName->Length = (USHORT)BufferSize - sizeof(UNICODE_NULL);
} }
RtlStringCbPrintfA(LangName, LangNameSize, "%S", NameBuffer);
Quit:
RegCloseKey(hKey); RegCloseKey(hKey);
return TRUE; return (rc == ERROR_SUCCESS);
} }
BOOLEAN BOOLEAN
WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, WinLdrLoadNLSData(
IN PCSTR DirectoryPath, _Inout_ PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PCSTR AnsiFileName, _In_ PCSTR DirectoryPath,
IN PCSTR OemFileName, _In_ PCUNICODE_STRING AnsiFileName,
IN PCSTR LanguageFileName) _In_ PCUNICODE_STRING OemFileName,
_In_ PCUNICODE_STRING LangFileName, // CaseTable
_In_ PCUNICODE_STRING OemHalFileName)
{ {
CHAR FileName[255];
ULONG FileId;
ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
ULONG TotalSize;
PVOID NlsDataBase;
PVOID NlsVirtual;
BOOLEAN AnsiEqualsOem = FALSE;
FILEINFORMATION FileInfo;
ULONG BytesRead;
ARC_STATUS Status; ARC_STATUS Status;
FILEINFORMATION FileInfo;
ULONG AnsiFileId = -1, OemFileId = -1, LangFileId = -1;
ULONG AnsiFileSize, OemFileSize, LangFileSize;
ULONG TotalSize;
ULONG BytesRead;
PVOID NlsDataBase, NlsVirtual;
BOOLEAN AnsiEqualsOem = FALSE;
CHAR FileName[MAX_PATH];
/* There may be a case, when OEM and ANSI page coincide */ /* There may be a case, where OEM and ANSI pages coincide */
if (!strcmp(AnsiFileName, OemFileName)) if (RtlCompareUnicodeString(AnsiFileName, OemFileName, TRUE) == 0)
AnsiEqualsOem = TRUE; AnsiEqualsOem = TRUE;
/* Open file with ANSI and store its size */ /* Open file with ANSI and store its size */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), AnsiFileName); DirectoryPath, AnsiFileName);
Status = ArcOpen(FileName, OpenReadOnly, &AnsiFileId);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while opening '%s', Status: %u\n", FileName, Status); WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
Status = ArcGetFileInformation(FileId, &FileInfo); Status = ArcGetFileInformation(AnsiFileId, &FileInfo);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
goto Failure; goto Quit;
AnsiFileSize = FileInfo.EndingAddress.LowPart; AnsiFileSize = FileInfo.EndingAddress.LowPart;
TRACE("AnsiFileSize: %d\n", AnsiFileSize); TRACE("AnsiFileSize: %d\n", AnsiFileSize);
@ -365,146 +389,133 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
} }
else else
{ {
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), OemFileName); DirectoryPath, OemFileName);
Status = ArcOpen(FileName, OpenReadOnly, &OemFileId);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while opening '%s', Status: %u\n", FileName, Status); WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
Status = ArcGetFileInformation(FileId, &FileInfo); Status = ArcGetFileInformation(OemFileId, &FileInfo);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
goto Failure; goto Quit;
OemFileSize = FileInfo.EndingAddress.LowPart; OemFileSize = FileInfo.EndingAddress.LowPart;
} }
TRACE("OemFileSize: %d\n", OemFileSize); TRACE("OemFileSize: %d\n", OemFileSize);
/* And finally open the language codepage file and store its length */ /* Finally open the language codepage file and store its length */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), LanguageFileName); DirectoryPath, LangFileName);
Status = ArcOpen(FileName, OpenReadOnly, &LangFileId);
NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while opening '%s', Status: %u\n", FileName, Status); WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
Status = ArcGetFileInformation(FileId, &FileInfo); Status = ArcGetFileInformation(LangFileId, &FileInfo);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
goto Failure; goto Quit;
LanguageFileSize = FileInfo.EndingAddress.LowPart; LangFileSize = FileInfo.EndingAddress.LowPart;
TRACE("LanguageFileSize: %d\n", LanguageFileSize); TRACE("LangFileSize: %d\n", LangFileSize);
//
// TODO: The OEMHAL file.
//
/* Sum up all three length, having in mind that every one of them /* Sum up all three length, having in mind that every one of them
must start at a page boundary => thus round up each file to a page */ must start at a page boundary => thus round up each file to a page */
TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) + TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
MM_SIZE_TO_PAGES(OemFileSize) + MM_SIZE_TO_PAGES(OemFileSize) +
MM_SIZE_TO_PAGES(LanguageFileSize); MM_SIZE_TO_PAGES(LangFileSize);
/* Store it for later marking the pages as NlsData type */ /* Store it for later marking the pages as NlsData type */
TotalNLSSize = TotalSize; TotalNLSSize = TotalSize;
NlsDataBase = MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData); NlsDataBase = MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData);
if (NlsDataBase == NULL) if (NlsDataBase == NULL)
goto Failure; goto Quit;
NlsVirtual = PaToVa(NlsDataBase); NlsVirtual = PaToVa(NlsDataBase);
LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual; LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
LoaderBlock->NlsData->OemCodePageData = (PVOID)((ULONG_PTR)NlsVirtual +
LoaderBlock->NlsData->OemCodePageData =
(PVOID)((ULONG_PTR)NlsVirtual +
(MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT)); (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((ULONG_PTR)NlsVirtual +
LoaderBlock->NlsData->UnicodeCodePageData =
(PVOID)((ULONG_PTR)NlsVirtual +
(MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) + (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
(MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT)); (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
/* Ansi and OEM data are the same - just set pointers to the same area */ /* ANSI and OEM data are the same - just set pointers to the same area */
if (AnsiEqualsOem) if (AnsiEqualsOem)
LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData; LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
/* Now actually read the data into memory, starting with Ansi file */ /* Now actually read the data into memory, starting with the ANSI file */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), AnsiFileName); DirectoryPath, AnsiFileName);
NtLdrOutputLoadMsg(FileName, NULL); NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId); Status = ArcRead(AnsiFileId,
if (Status != ESUCCESS) VaToPa(LoaderBlock->NlsData->AnsiCodePageData),
{ AnsiFileSize, &BytesRead);
WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure;
}
Status = ArcRead(FileId, VaToPa(LoaderBlock->NlsData->AnsiCodePageData), AnsiFileSize, &BytesRead);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while reading '%s', Status: %u\n", FileName, Status); WARN("Error while reading '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
/* OEM now, if it doesn't equal Ansi of course */ /* OEM now, if it isn't the same as the ANSI one */
if (!AnsiEqualsOem) if (!AnsiEqualsOem)
{ {
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), OemFileName); DirectoryPath, OemFileName);
NtLdrOutputLoadMsg(FileName, NULL); NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId); Status = ArcRead(OemFileId,
if (Status != ESUCCESS) VaToPa(LoaderBlock->NlsData->OemCodePageData),
{ OemFileSize, &BytesRead);
WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure;
}
Status = ArcRead(FileId, VaToPa(LoaderBlock->NlsData->OemCodePageData), OemFileSize, &BytesRead);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while reading '%s', Status: %u\n", FileName, Status); WARN("Error while reading '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
} }
/* Finally the language file */ /* Finally the language file */
RtlStringCbCopyA(FileName, sizeof(FileName), DirectoryPath); RtlStringCbPrintfA(FileName, sizeof(FileName), "%s%wZ",
RtlStringCbCatA(FileName, sizeof(FileName), LanguageFileName); DirectoryPath, LangFileName);
NtLdrOutputLoadMsg(FileName, NULL); NtLdrOutputLoadMsg(FileName, NULL);
Status = ArcOpen(FileName, OpenReadOnly, &FileId); Status = ArcRead(LangFileId,
if (Status != ESUCCESS) VaToPa(LoaderBlock->NlsData->UnicodeCodePageData),
{ LangFileSize, &BytesRead);
WARN("Error while opening '%s', Status: %u\n", FileName, Status);
goto Failure;
}
Status = ArcRead(FileId, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData), LanguageFileSize, &BytesRead);
ArcClose(FileId);
if (Status != ESUCCESS) if (Status != ESUCCESS)
{ {
WARN("Error while reading '%s', Status: %u\n", FileName, Status); WARN("Error while reading '%s', Status: %u\n", FileName, Status);
goto Failure; goto Quit;
} }
// //
// THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK // THIS IS a HACK and should be replaced by actually loading the OEMHAL file!
// Should go to WinLdrLoadOemHalFont(), when it will be implemented
// //
LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData); LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
/* Convert NlsTables address to VA */ /* Convert NlsTables address to VA */
LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData); LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
return TRUE; Quit:
if (LangFileId != -1)
ArcClose(LangFileId);
if (OemFileId != -1)
ArcClose(OemFileId);
if (AnsiFileId != -1)
ArcClose(AnsiFileId);
Failure: if (Status != ESUCCESS)
UiMessageBox("Error reading NLS file %s", FileName); UiMessageBox("Error reading NLS file %s", FileName);
return FALSE;
return (Status == ESUCCESS);
} }
static VOID static VOID