3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: lib/ntdll/ldr/res.c
6 * PURPOSE: Resource access for PE executables
7 * PROGRAMMERS: Jean Michault
8 * Rex Jolliff (rex@lvcablemodem.com)
9 * Robert Dickenson (robd@mok.lvcm.com)
17 /* INCLUDES *****************************************************************/
19 #include <reactos/config.h>
20 #include <ddk/ntddk.h>
24 #include <ntdll/ldr.h>
25 #include <ntos/minmax.h>
28 #include <ntdll/ntdll.h>
30 /* PROTOTYPES ****************************************************************/
34 /* FUNCTIONS *****************************************************************/
37 Status = LdrFindResource_U (hModule,
43 LdrFindResource_U(PVOID BaseAddress,
44 PLDR_RESOURCE_INFO ResourceInfo,
46 PIMAGE_RESOURCE_DATA_ENTRY* ResourceDataEntry)
48 PIMAGE_RESOURCE_DIRECTORY ResDir;
49 PIMAGE_RESOURCE_DIRECTORY ResBase;
50 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
51 NTSTATUS Status = STATUS_SUCCESS;
57 //DPRINT("LdrFindResource_U()\n");
58 DPRINT("LdrFindResource_U(%08x, %08x, %d, %08x)\n", BaseAddress, ResourceInfo, Level, ResourceDataEntry);
60 /* Get the pointer to the resource directory */
61 ResDir = (PIMAGE_RESOURCE_DIRECTORY)RtlImageDirectoryEntryToData(BaseAddress,
62 TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
64 return STATUS_RESOURCE_DATA_NOT_FOUND;
67 DPRINT("ResourceDirectory: %x Size: %d\n", (ULONG)ResDir, (int)i);
71 /* Let's go into resource tree */
72 for (i = 0; i < Level; i++) {
73 DPRINT("ResDir: %x Level: %d\n", (ULONG)ResDir, i);
75 Id = ((PULONG)ResourceInfo)[i];
76 // ResourceInfo.Type = (ULONG)lpType;
77 // ResourceInfo.Name = (ULONG)lpName;
78 // ResourceInfo.Language = (ULONG)wLanguage;
80 EntryCount = ResDir->NumberOfNamedEntries;
81 DPRINT(" Id: %d NumberOfNamedEntries: %d\n", Id, EntryCount);
82 ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
83 //DPRINT("ResEntry %x\n", (ULONG)ResEntry);
84 if (Id & 0xFFFF0000) {
85 /* Resource name is a unicode string */
86 DPRINT("ResEntry %x - Resource name is a unicode string\n", (ULONG)ResEntry);
87 DPRINT("EntryCount %d\n", (ULONG)EntryCount);
88 for (; EntryCount--; ResEntry++) {
89 /* Scan entries for equal name */
90 if (ResEntry->Name & 0x80000000) {
91 ws = (PWCHAR)((ULONG)ResBase + (ResEntry->Name & 0x7FFFFFFF));
92 if (!_wcsnicmp((PWCHAR)Id, ws + 1, *ws) &&
93 wcslen((PWCHAR)Id) == (int)*ws) {
99 /* We use ID number instead of string */
100 DPRINT("ResEntry %x - Resource ID number instead of string\n", (ULONG)ResEntry);
101 DPRINT("EntryCount %d\n", (ULONG)EntryCount);
102 ResEntry += EntryCount;
103 EntryCount = ResDir->NumberOfIdEntries;
104 DPRINT("EntryCount %d\n", (ULONG)EntryCount);
105 for (; EntryCount--; ResEntry++) {
106 /* Scan entries for equal name */
107 DPRINT("EntryCount %d ResEntry %x\n", (ULONG)EntryCount, ResEntry);
108 DPRINT("ResEntry->Name %x Id %x\n", (ULONG)ResEntry->Name, Id);
109 if (ResEntry->Name == Id) {
110 DPRINT("ID entry found %x\n", Id);
116 //DPRINT("Error %lu\n", i);
120 DPRINT("Error %lu - STATUS_RESOURCE_TYPE_NOT_FOUND\n", i);
121 return STATUS_RESOURCE_TYPE_NOT_FOUND;
123 DPRINT("Error %lu - STATUS_RESOURCE_NAME_NOT_FOUND\n", i);
124 return STATUS_RESOURCE_NAME_NOT_FOUND;
126 if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
127 /* Use the first available language */
128 ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
131 DPRINT("Error %lu - STATUS_RESOURCE_LANG_NOT_FOUND\n", i);
132 return STATUS_RESOURCE_LANG_NOT_FOUND;
134 DPRINT("Error %lu - STATUS_RESOURCE_DATA_NOT_FOUND\n", i);
135 return STATUS_RESOURCE_DATA_NOT_FOUND;
137 DPRINT("Error %lu - STATUS_INVALID_PARAMETER\n", i);
138 return STATUS_INVALID_PARAMETER;
141 ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResBase +
142 (ResEntry->OffsetToData & 0x7FFFFFFF));
144 DPRINT("ResourceDataEntry: %x\n", (ULONG)ResDir);
146 if (ResourceDataEntry) {
147 *ResourceDataEntry = (PVOID)ResDir;
157 LdrAccessResource(IN PVOID BaseAddress,
158 IN PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry,
159 OUT PVOID* Resource OPTIONAL,
160 OUT PULONG Size OPTIONAL)
162 PIMAGE_SECTION_HEADER Section;
163 PIMAGE_NT_HEADERS NtHeader;
170 if(!ResourceDataEntry)
171 return STATUS_RESOURCE_DATA_NOT_FOUND;
173 Data = (ULONG)RtlImageDirectoryEntryToData(BaseAddress,
174 TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &DataSize);
176 return STATUS_RESOURCE_DATA_NOT_FOUND;
178 if ((ULONG)BaseAddress & 1) {
179 /* loaded as ordinary file */
180 NtHeader = RtlImageNtHeader((PVOID)((ULONG)BaseAddress & ~1UL));
181 Offset = (ULONG)BaseAddress - Data + NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
182 Section = RtlImageRvaToSection(NtHeader, BaseAddress, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress);
183 if (Section == NULL) {
184 return STATUS_RESOURCE_DATA_NOT_FOUND;
186 if (Section->Misc.VirtualSize < ResourceDataEntry->OffsetToData) {
187 SectionRva = RtlImageRvaToSection (NtHeader, BaseAddress, ResourceDataEntry->OffsetToData)->VirtualAddress;
188 SectionVa = RtlImageRvaToVa(NtHeader, BaseAddress, SectionRva, NULL);
189 Offset = SectionRva - SectionVa + Data - Section->VirtualAddress;
193 *Resource = (PVOID)(ResourceDataEntry->OffsetToData - Offset + (ULONG)BaseAddress);
196 *Size = ResourceDataEntry->Size;
198 return STATUS_SUCCESS;
206 LdrFindResourceDirectory_U(IN PVOID BaseAddress,
211 PIMAGE_RESOURCE_DIRECTORY ResDir;
212 PIMAGE_RESOURCE_DIRECTORY_ENTRY ResEntry;
215 NTSTATUS Status = STATUS_SUCCESS;
218 /* Get the pointer to the resource directory */
219 ResDir = (PIMAGE_RESOURCE_DIRECTORY)
220 RtlImageDirectoryEntryToData(BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &i);
221 if (ResDir == NULL) {
222 return STATUS_RESOURCE_DATA_NOT_FOUND;
225 /* Let's go into resource tree */
226 for (i = 0; i < level; i++, name++) {
227 EntryCount = ResDir->NumberOfNamedEntries;
228 ResEntry = (PIMAGE_RESOURCE_DIRECTORY_ENTRY)(ResDir + 1);
229 if ((ULONG)(*name) & 0xFFFF0000) {
230 /* Resource name is a unicode string */
231 for (; EntryCount--; ResEntry++) {
232 /* Scan entries for equal name */
233 if (ResEntry->Name & 0x80000000) {
234 ws = (WCHAR*)((ULONG)ResDir + (ResEntry->Name & 0x7FFFFFFF));
235 if (!wcsncmp(*name, ws + 1, *ws) && wcslen(*name) == (int)*ws) {
241 /* We use ID number instead of string */
242 ResEntry += EntryCount;
243 EntryCount = ResDir->NumberOfIdEntries;
244 for (; EntryCount--; ResEntry++) {
245 /* Scan entries for equal name */
246 if (ResEntry->Name == (ULONG)(*name))
252 return STATUS_RESOURCE_TYPE_NOT_FOUND;
254 return STATUS_RESOURCE_NAME_NOT_FOUND;
256 Status = STATUS_RESOURCE_LANG_NOT_FOUND;
257 /* Just use first language entry */
258 if (ResDir->NumberOfNamedEntries || ResDir->NumberOfIdEntries) {
259 ResEntry = (IMAGE_RESOURCE_DIRECTORY_ENTRY*)(ResDir + 1);
264 return STATUS_RESOURCE_DATA_NOT_FOUND;
266 return STATUS_INVALID_PARAMETER;
269 ResDir = (PIMAGE_RESOURCE_DIRECTORY)((ULONG)ResDir + ResEntry->OffsetToData);
272 *addr = (PVOID)ResDir;