Leaked source code of windows server 2003
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.

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