Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

356 lines
8.8 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. blres.c
  5. Abstract:
  6. Provides rudimentary resource support for the osloader and setupldr
  7. Author:
  8. John Vert (jvert) 12-Nov-1993
  9. Revision History:
  10. --*/
  11. #include "bootlib.h"
  12. PUCHAR BlpResourceDirectory = NULL;
  13. PUCHAR BlpResourceFileOffset = NULL;
  14. //
  15. // private function prototypes
  16. //
  17. PIMAGE_RESOURCE_DIRECTORY
  18. BlpFindDirectoryEntry(
  19. IN PIMAGE_RESOURCE_DIRECTORY Directory,
  20. IN ULONG Id,
  21. IN PUCHAR SectionStart
  22. );
  23. ARC_STATUS
  24. BlInitResources(
  25. IN PCHAR StartCommand
  26. )
  27. /*++
  28. Routine Description:
  29. Opens the executable that was run and reads the section headers out of the
  30. image to determine where the resource section is located in memory.
  31. Arguments:
  32. StartCommand - Supplies the command used to start the program (argv[0])
  33. Return Value:
  34. ESUCCESS if successful
  35. ARC_STATUS if unsuccessful
  36. --*/
  37. {
  38. CHAR DeviceName[80];
  39. PCHAR FileName;
  40. PCHAR p;
  41. ULONG DeviceId;
  42. ULONG FileId;
  43. ARC_STATUS Status;
  44. UCHAR LocalBuffer[(SECTOR_SIZE * 2) + 256];
  45. PUCHAR LocalPointer;
  46. ULONG Count;
  47. PIMAGE_FILE_HEADER FileHeader;
  48. PIMAGE_OPTIONAL_HEADER OptionalHeader;
  49. PIMAGE_DATA_DIRECTORY ResourceDirectory;
  50. PIMAGE_SECTION_HEADER SectionHeader;
  51. ULONG NumberOfSections;
  52. #if defined(_IA64_)
  53. PIMAGE_NT_HEADERS NtHeader;
  54. #endif
  55. if (BlpResourceDirectory != NULL) {
  56. //
  57. // Already initialized, just return.
  58. //
  59. return(ESUCCESS);
  60. }
  61. //
  62. // extract device name from the startup path
  63. //
  64. p=strrchr(StartCommand,')');
  65. if (p==NULL) {
  66. return(ENODEV);
  67. }
  68. strncpy(DeviceName, StartCommand, (ULONG) (p-StartCommand+1));
  69. DeviceName[p-StartCommand+1]='\0';
  70. FileName = p+1;
  71. #ifdef ARCI386
  72. FileName++;
  73. #endif
  74. //
  75. // Open the device.
  76. //
  77. Status = ArcOpen(DeviceName, ArcOpenReadOnly, &DeviceId);
  78. if (Status != ESUCCESS) {
  79. return(Status);
  80. }
  81. //
  82. // Open the file.
  83. //
  84. Status = BlOpen(DeviceId,
  85. FileName,
  86. ArcOpenReadOnly,
  87. &FileId);
  88. if (Status != ESUCCESS) {
  89. ArcClose(DeviceId);
  90. return(Status);
  91. }
  92. //
  93. // Read the first two sectors of the image header from the file.
  94. //
  95. LocalPointer = ALIGN_BUFFER(LocalBuffer);
  96. Status = BlRead(FileId, LocalPointer, SECTOR_SIZE*2, &Count);
  97. BlClose(FileId);
  98. ArcClose(DeviceId);
  99. if (Status != ESUCCESS) {
  100. return(Status);
  101. }
  102. #if defined(_IA64_)
  103. NtHeader = (PIMAGE_NT_HEADERS) ( (PCHAR) LocalPointer +
  104. ((PIMAGE_DOS_HEADER) LocalPointer)->e_lfanew);
  105. FileHeader = &(NtHeader->FileHeader);
  106. LocalPointer = (PUCHAR) FileHeader;
  107. #else
  108. FileHeader = (PIMAGE_FILE_HEADER)LocalPointer;
  109. #endif
  110. OptionalHeader = (PIMAGE_OPTIONAL_HEADER)(LocalPointer + sizeof(IMAGE_FILE_HEADER));
  111. NumberOfSections = FileHeader->NumberOfSections;
  112. SectionHeader = (PIMAGE_SECTION_HEADER)((PUCHAR)OptionalHeader +
  113. FileHeader->SizeOfOptionalHeader);
  114. //
  115. // Find .rsrc section
  116. //
  117. while (NumberOfSections) {
  118. if (_stricmp(SectionHeader->Name, ".rsrc")==0) {
  119. BlpResourceDirectory = (PUCHAR)((LONG_PTR)((LONG)SectionHeader->VirtualAddress));
  120. BlpResourceFileOffset = (PUCHAR)(ULONG_PTR)SectionHeader->PointerToRawData;
  121. #if defined(ARCI386) || defined(_IA64_)
  122. // No startup.com to fix up these values for this ARC PROM.
  123. BlpResourceDirectory += OptionalHeader->ImageBase;
  124. BlpResourceFileOffset = (PUCHAR)UlongToPtr(SectionHeader->VirtualAddress); //ResourceDirectory->VirtualAddress;
  125. #endif
  126. if (FileHeader->Machine == IMAGE_FILE_MACHINE_POWERPC) {
  127. BlpResourceDirectory += OptionalHeader->ImageBase;
  128. }
  129. return(ESUCCESS);
  130. }
  131. ++SectionHeader;
  132. --NumberOfSections;
  133. }
  134. return(EBADF);
  135. }
  136. PTCHAR
  137. BlFindMessage(
  138. IN ULONG Id
  139. )
  140. /*++
  141. Routine Description:
  142. Looks up a message resource in the given image. Note that this routine
  143. ignores the Language ID. It is assumed that the osloader/setupldr only
  144. has messages for one language.
  145. Arguments:
  146. Id - Supplies the message ID to look up.
  147. Return Value:
  148. PTCHAR - pointer to the message string.
  149. NULL - failure.
  150. --*/
  151. {
  152. PIMAGE_RESOURCE_DIRECTORY ResourceDirectory;
  153. PIMAGE_RESOURCE_DIRECTORY NextDirectory;
  154. PMESSAGE_RESOURCE_DATA MessageData;
  155. PMESSAGE_RESOURCE_BLOCK MessageBlock;
  156. PMESSAGE_RESOURCE_ENTRY MessageEntry;
  157. PIMAGE_RESOURCE_DATA_ENTRY DataEntry;
  158. ULONG NumberOfBlocks;
  159. ULONG Index;
  160. if (BlpResourceDirectory==NULL) {
  161. return(NULL);
  162. }
  163. ResourceDirectory = (PIMAGE_RESOURCE_DIRECTORY)BlpResourceDirectory;
  164. //
  165. // Search the directory. We are looking for the type RT_MESSAGETABLE (11)
  166. //
  167. NextDirectory = BlpFindDirectoryEntry(ResourceDirectory,
  168. 11,
  169. (PUCHAR)ResourceDirectory);
  170. if (NextDirectory==NULL) {
  171. return(NULL);
  172. }
  173. //
  174. // Find the next directory. Should only be one entry here (nameid == 1)
  175. //
  176. NextDirectory = BlpFindDirectoryEntry(NextDirectory,
  177. 1,
  178. (PUCHAR)ResourceDirectory);
  179. if (NextDirectory==NULL) {
  180. return(NULL);
  181. }
  182. // Find the message table.
  183. // If a dbcs locale is active, then we look for the appropriate
  184. // message table first. Otherwise we just look for the first message table.
  185. //
  186. if(DbcsLangId) {
  187. DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)BlpFindDirectoryEntry(
  188. NextDirectory,
  189. DbcsLangId,
  190. (PUCHAR)ResourceDirectory
  191. );
  192. } else {
  193. DataEntry = NULL;
  194. }
  195. if(!DataEntry) {
  196. DataEntry = (PIMAGE_RESOURCE_DATA_ENTRY)BlpFindDirectoryEntry(
  197. NextDirectory,
  198. (ULONG)(-1),
  199. (PUCHAR)ResourceDirectory
  200. );
  201. }
  202. if(!DataEntry) {
  203. return(NULL);
  204. }
  205. MessageData = (PMESSAGE_RESOURCE_DATA)(BlpResourceDirectory +
  206. DataEntry->OffsetToData -
  207. BlpResourceFileOffset);
  208. NumberOfBlocks = MessageData->NumberOfBlocks;
  209. MessageBlock = MessageData->Blocks;
  210. while (NumberOfBlocks--) {
  211. if ((Id >= MessageBlock->LowId) &&
  212. (Id <= MessageBlock->HighId)) {
  213. //
  214. // The requested ID is within this block, scan forward until
  215. // we find it.
  216. //
  217. MessageEntry = (PMESSAGE_RESOURCE_ENTRY)((PCHAR)MessageData + MessageBlock->OffsetToEntries);
  218. Index = Id - MessageBlock->LowId;
  219. while (Index--) {
  220. MessageEntry = (PMESSAGE_RESOURCE_ENTRY)((PUCHAR)MessageEntry + MessageEntry->Length);
  221. }
  222. return((PTCHAR)MessageEntry->Text);
  223. }
  224. //
  225. // Check the next block for this ID.
  226. //
  227. MessageBlock++;
  228. }
  229. return(NULL);
  230. }
  231. PIMAGE_RESOURCE_DIRECTORY
  232. BlpFindDirectoryEntry(
  233. IN PIMAGE_RESOURCE_DIRECTORY Directory,
  234. IN ULONG Id,
  235. IN PUCHAR SectionStart
  236. )
  237. /*++
  238. Routine Description:
  239. Searches through a resource directory for the given ID. Ignores entries
  240. with actual names, only searches for ID. If the given ID is -1, the
  241. first entry is returned.
  242. Arguments:
  243. Directory - Supplies the resource directory to search.
  244. Id - Supplies the ID to search for. -1 means return the first ID found.
  245. SectionStart - Supplies a pointer to the start of the resource section.
  246. Return Value:
  247. Pointer to the found resource directory.
  248. NULL for failure.
  249. --*/
  250. {
  251. ULONG i;
  252. PIMAGE_RESOURCE_DIRECTORY_ENTRY FoundDirectory;
  253. FoundDirectory = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(Directory+1);
  254. //
  255. // Skip entries with names.
  256. //
  257. for (i=0;i<Directory->NumberOfNamedEntries;i++) {
  258. ++FoundDirectory;
  259. }
  260. //
  261. // Search for matching ID.
  262. //
  263. for (i=0;i<Directory->NumberOfIdEntries;i++) {
  264. if ((FoundDirectory->Name == Id) || (Id == (ULONG)-1)) {
  265. //
  266. // Found a match.
  267. //
  268. return((PIMAGE_RESOURCE_DIRECTORY)(SectionStart +
  269. (FoundDirectory->OffsetToData & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY)));
  270. }
  271. ++FoundDirectory;
  272. }
  273. return(NULL);
  274. }