|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
blres.c
Abstract:
Provides rudimentary resource support for the osloader and setupldr
Author:
John Vert (jvert) 12-Nov-1993
Revision History:
--*/ #include "bootlib.h"
PUCHAR BlpResourceDirectory = NULL; PUCHAR BlpResourceFileOffset = NULL;
//
// private function prototypes
//
PIMAGE_RESOURCE_DIRECTORY BlpFindDirectoryEntry( IN PIMAGE_RESOURCE_DIRECTORY Directory, IN ULONG Id, IN PUCHAR SectionStart );
ARC_STATUS BlInitResources( IN PCHAR StartCommand )
/*++
Routine Description:
Opens the executable that was run and reads the section headers out of the image to determine where the resource section is located in memory.
Arguments:
StartCommand - Supplies the command used to start the program (argv[0])
Return Value:
ESUCCESS if successful
ARC_STATUS if unsuccessful
--*/
{ CHAR DeviceName[80]; PCHAR FileName; PCHAR p; ULONG DeviceId; ULONG FileId; ARC_STATUS Status; UCHAR LocalBuffer[(SECTOR_SIZE * 2) + 256]; PUCHAR LocalPointer; ULONG Count; PIMAGE_FILE_HEADER FileHeader; PIMAGE_OPTIONAL_HEADER OptionalHeader; PIMAGE_DATA_DIRECTORY ResourceDirectory; PIMAGE_SECTION_HEADER SectionHeader; ULONG NumberOfSections; #if defined(_IA64_)
PIMAGE_NT_HEADERS NtHeader; #endif
if (BlpResourceDirectory != NULL) { //
// Already initialized, just return.
//
return(ESUCCESS); } //
// extract device name from the startup path
//
p=strrchr(StartCommand,')'); if (p==NULL) { return(ENODEV); }
strncpy(DeviceName, StartCommand, (ULONG) (p-StartCommand+1)); DeviceName[p-StartCommand+1]='\0';
FileName = p+1; #ifdef ARCI386
FileName++; #endif
//
// Open the device.
//
Status = ArcOpen(DeviceName, ArcOpenReadOnly, &DeviceId); if (Status != ESUCCESS) { return(Status); }
//
// Open the file.
//
Status = BlOpen(DeviceId, FileName, ArcOpenReadOnly, &FileId); if (Status != ESUCCESS) { ArcClose(DeviceId); return(Status); }
//
// Read the first two sectors of the image header from the file.
//
LocalPointer = ALIGN_BUFFER(LocalBuffer); Status = BlRead(FileId, LocalPointer, SECTOR_SIZE*2, &Count); BlClose(FileId); ArcClose(DeviceId);
if (Status != ESUCCESS) { return(Status); }
#if defined(_IA64_)
NtHeader = (PIMAGE_NT_HEADERS) ( (PCHAR) LocalPointer + ((PIMAGE_DOS_HEADER) LocalPointer)->e_lfanew); FileHeader = &(NtHeader->FileHeader); LocalPointer = (PUCHAR) FileHeader; #else
FileHeader = (PIMAGE_FILE_HEADER)LocalPointer; #endif
OptionalHeader = (PIMAGE_OPTIONAL_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER)); NumberOfSections = FileHeader->NumberOfSections; SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)OptionalHeader + FileHeader->SizeOfOptionalHeader);
//
// Find .rsrc section
//
while (NumberOfSections) { if (_stricmp(SectionHeader->Name, ".rsrc")==0) { BlpResourceDirectory = (PUCHAR)((LONG_PTR)((LONG)SectionHeader->VirtualAddress)); BlpResourceFileOffset = (PUCHAR)(ULONG_PTR)SectionHeader->PointerToRawData; #if defined(ARCI386) || defined(_IA64_)
// No startup.com to fix up these values for this ARC PROM.
BlpResourceDirectory += OptionalHeader->ImageBase; BlpResourceFileOffset = (PUCHAR)UlongToPtr(SectionHeader->VirtualAddress); //ResourceDirectory->VirtualAddress;
#endif
if (FileHeader->Machine == IMAGE_FILE_MACHINE_POWERPC) { BlpResourceDirectory += OptionalHeader->ImageBase; }
return(ESUCCESS); }
++SectionHeader; --NumberOfSections; }
return(EBADF); }
PTCHAR BlFindMessage( IN ULONG Id )
/*++
Routine Description:
Looks up a message resource in the given image. Note that this routine ignores the Language ID. It is assumed that the osloader/setupldr only has messages for one language.
Arguments:
Id - Supplies the message ID to look up.
Return Value:
PTCHAR - pointer to the message string.
NULL - failure.
--*/
{ PIMAGE_RESOURCE_DIRECTORY ResourceDirectory; PIMAGE_RESOURCE_DIRECTORY NextDirectory; PMESSAGE_RESOURCE_DATA MessageData; PMESSAGE_RESOURCE_BLOCK MessageBlock; PMESSAGE_RESOURCE_ENTRY MessageEntry; PIMAGE_RESOURCE_DATA_ENTRY DataEntry; ULONG NumberOfBlocks; ULONG Index;
if (BlpResourceDirectory==NULL) { return(NULL); }
ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)BlpResourceDirectory;
//
// Search the directory. We are looking for the type RT_MESSAGETABLE (11)
//
NextDirectory = BlpFindDirectoryEntry(ResourceDirectory, 11, (PUCHAR)ResourceDirectory); if (NextDirectory==NULL) { return(NULL); }
//
// Find the next directory. Should only be one entry here (nameid == 1)
//
NextDirectory = BlpFindDirectoryEntry(NextDirectory, 1, (PUCHAR)ResourceDirectory); if (NextDirectory==NULL) { return(NULL); }
// Find the message table.
// If a dbcs locale is active, then we look for the appropriate
// message table first. Otherwise we just look for the first message table.
//
if(DbcsLangId) { DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)BlpFindDirectoryEntry( NextDirectory, DbcsLangId, (PUCHAR)ResourceDirectory ); } else { DataEntry = NULL; }
if(!DataEntry) { DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)BlpFindDirectoryEntry( NextDirectory, (ULONG)(-1), (PUCHAR)ResourceDirectory ); }
if(!DataEntry) { return(NULL); }
MessageData = (PMESSAGE_RESOURCE_DATA)(BlpResourceDirectory + DataEntry->OffsetToData - BlpResourceFileOffset);
NumberOfBlocks = MessageData->NumberOfBlocks; MessageBlock = MessageData->Blocks; while (NumberOfBlocks--) { if ((Id >= MessageBlock->LowId) && (Id <= MessageBlock->HighId)) {
//
// The requested ID is within this block, scan forward until
// we find it.
//
MessageEntry = (PMESSAGE_RESOURCE_ENTRY)((PCHAR)MessageData + MessageBlock->OffsetToEntries); Index = Id - MessageBlock->LowId; while (Index--) { MessageEntry = (PMESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageEntry + MessageEntry->Length); } return((PTCHAR)MessageEntry->Text); }
//
// Check the next block for this ID.
//
MessageBlock++; }
return(NULL);
}
PIMAGE_RESOURCE_DIRECTORY BlpFindDirectoryEntry( IN PIMAGE_RESOURCE_DIRECTORY Directory, IN ULONG Id, IN PUCHAR SectionStart )
/*++
Routine Description:
Searches through a resource directory for the given ID. Ignores entries with actual names, only searches for ID. If the given ID is -1, the first entry is returned.
Arguments:
Directory - Supplies the resource directory to search.
Id - Supplies the ID to search for. -1 means return the first ID found.
SectionStart - Supplies a pointer to the start of the resource section.
Return Value:
Pointer to the found resource directory.
NULL for failure.
--*/
{ ULONG i; PIMAGE_RESOURCE_DIRECTORY_ENTRY FoundDirectory;
FoundDirectory = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(Directory+1);
//
// Skip entries with names.
//
for (i=0;i<Directory->NumberOfNamedEntries;i++) { ++FoundDirectory; }
//
// Search for matching ID.
//
for (i=0;i<Directory->NumberOfIdEntries;i++) { if ((FoundDirectory->Name == Id) || (Id == (ULONG)-1)) { //
// Found a match.
//
return((PIMAGE_RESOURCE_DIRECTORY)(SectionStart + (FoundDirectory->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)));
} ++FoundDirectory; }
return(NULL); }
|