Release 970305
[wine/multimedia.git] / loader / pe_resource.c
blob2d2bbaff92162f35d95b58f47752bdb5874e2883
1 #ifndef WINELIB
2 /*
3 * PE (Portable Execute) File Resources
5 * Copyright 1995 Thomas Sandford
6 * Copyright 1996 Martin von Loewis
8 * Based on the Win16 resource handling code in loader/resource.c
9 * Copyright 1993 Robert J. Amstadt
10 * Copyright 1995 Alexandre Julliard
11 * Copyright 1997 Marcus Meissner
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include "wintypes.h"
17 #include "windows.h"
18 #include "pe_image.h"
19 #include "module.h"
20 #include "heap.h"
21 #include "libres.h"
22 #include "stackframe.h"
23 #include "neexe.h"
24 #include "stddebug.h"
25 #include "debug.h"
27 /**********************************************************************
28 * HMODULE32toPE_MODULE
30 * small helper function to get a PE_MODULE from a passed HMODULE32
32 static PE_MODULE*
33 HMODULE32toPE_MODULE(HMODULE32 hmod) {
34 NE_MODULE *pModule;
36 if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
37 hmod = GetExePtr( hmod ); /* In case we were passed an hInstance */
39 if (!(pModule = MODULE_GetPtr( hmod ))) return 0;
40 if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;
41 return pModule->pe_module;
44 /**********************************************************************
45 * GetResDirEntryW
47 * Helper function - goes down one level of PE resource tree
50 LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(LPIMAGE_RESOURCE_DIRECTORY resdirptr,
51 LPCWSTR name,DWORD root)
53 int entrynum;
54 LPIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
55 int namelen;
57 if (HIWORD(name)) {
58 if (name[0]=='#') {
59 char buf[10];
61 lstrcpynWtoA(buf,name+1,10);
62 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root);
64 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
65 (BYTE *) resdirptr +
66 sizeof(IMAGE_RESOURCE_DIRECTORY));
67 namelen = lstrlen32W(name);
68 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
70 LPIMAGE_RESOURCE_DIR_STRING_U str =
71 (LPIMAGE_RESOURCE_DIR_STRING_U) (root +
72 entryTable[entrynum].u1.s.NameOffset);
73 if(namelen != str->Length)
74 continue;
75 if(lstrncmpi32W(name,str->NameString,str->Length)==0)
76 return (LPIMAGE_RESOURCE_DIRECTORY) (
77 root +
78 entryTable[entrynum].u2.s.OffsetToDirectory);
80 return NULL;
81 } else {
82 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
83 (BYTE *) resdirptr +
84 sizeof(IMAGE_RESOURCE_DIRECTORY) +
85 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
86 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
87 if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
88 return (LPIMAGE_RESOURCE_DIRECTORY) (
89 root +
90 entryTable[entrynum].u2.s.OffsetToDirectory);
91 /* just use first entry if no default can be found */
92 if (!name && resdirptr->NumberOfIdEntries)
93 return (LPIMAGE_RESOURCE_DIRECTORY) (
94 root +
95 entryTable[0].u2.s.OffsetToDirectory);
96 return NULL;
100 /**********************************************************************
101 * PE_FindResourceEx32W
103 HANDLE32 PE_FindResourceEx32W(
104 HINSTANCE32 hModule,LPCWSTR name,LPCWSTR type,WORD lang
106 LPIMAGE_RESOURCE_DIRECTORY resdirptr;
107 DWORD root;
108 HANDLE32 result;
109 PE_MODULE *pe = HMODULE32toPE_MODULE(hModule);
111 if (!pe || !pe->pe_resource)
112 return 0;
114 resdirptr = pe->pe_resource;
115 root = (DWORD) resdirptr;
116 if ((resdirptr = GetResDirEntryW(resdirptr, type, root)) == NULL)
117 return 0;
118 if ((resdirptr = GetResDirEntryW(resdirptr, name, root)) == NULL)
119 return 0;
120 result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT32)lang, root);
121 /* Try LANG_NEUTRAL, too */
122 if(!result)
123 return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root);
124 return result;
128 /**********************************************************************
129 * PE_LoadResource32
131 HANDLE32 PE_LoadResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
133 PE_MODULE *pe = HMODULE32toPE_MODULE(hModule);
135 if (!pe || !pe->pe_resource)
136 return 0;
137 if (!hRsrc)
138 return 0;
139 return (HANDLE32) (pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
143 /**********************************************************************
144 * PE_SizeofResource32
146 void
147 _check_ptr(DWORD x,DWORD start,LPDWORD lastmax) {
148 if ((x>start) && (x<*lastmax))
149 *lastmax=x;
152 static void
153 walk_resdir(DWORD loadaddr,DWORD rootresdir,DWORD xres,DWORD data,DWORD lvl,LPDWORD max){
154 LPIMAGE_RESOURCE_DIRECTORY resdir;
155 LPIMAGE_RESOURCE_DATA_ENTRY dataent;
156 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
157 int i;
159 if (lvl==3) {
160 dataent = (LPIMAGE_RESOURCE_DATA_ENTRY)(rootresdir+xres);
161 _check_ptr(loadaddr+dataent->OffsetToData,data,max);
162 return;
164 resdir = (LPIMAGE_RESOURCE_DIRECTORY)(rootresdir+xres);
165 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
166 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++)
167 walk_resdir(loadaddr,rootresdir,(lvl==2)?et[i].u2.OffsetToData:et[i].u2.s.OffsetToDirectory,data,lvl+1,max);
170 DWORD PE_SizeofResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
172 PE_MODULE *pe = HMODULE32toPE_MODULE(hModule);
173 DWORD max,data;
174 IMAGE_DATA_DIRECTORY dir;
176 if (!pe || !pe->pe_resource)
177 return 0;
178 if (!hRsrc) return 0;
180 max=(DWORD)-1;
181 dir=pe->pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
182 if(dir.Size)
183 max=(DWORD)pe->pe_resource+dir.Size;
185 data=((DWORD)pe->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
186 walk_resdir(pe->load_addr,(DWORD)pe->pe_resource,0,data,0,&max);
187 return max-data;
190 /**********************************************************************
191 * PE_EnumResourceTypes32A
193 BOOL32
194 PE_EnumResourceTypes32A(HMODULE32 hmod,ENUMRESTYPEPROC32A lpfun,LONG lparam) {
195 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
196 int i;
197 LPIMAGE_RESOURCE_DIRECTORY resdir;
198 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
199 BOOL32 ret;
200 HANDLE32 heap = GetProcessHeap();
202 if (!pe || !pe->pe_resource)
203 return FALSE;
205 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
206 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
207 ret = FALSE;
208 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
209 LPSTR name;
211 if (HIWORD(et[i].u1.Name))
212 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
213 else
214 name = (LPSTR)et[i].u1.Name;
215 ret = lpfun(hmod,name,lparam);
216 if (HIWORD(name))
217 HeapFree(heap,0,name);
218 if (!ret)
219 break;
221 return ret;
224 /**********************************************************************
225 * PE_EnumResourceTypes32W
227 BOOL32
228 PE_EnumResourceTypes32W(HMODULE32 hmod,ENUMRESTYPEPROC32W lpfun,LONG lparam) {
229 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
230 int i;
231 LPIMAGE_RESOURCE_DIRECTORY resdir;
232 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
233 BOOL32 ret;
235 if (!pe || !pe->pe_resource)
236 return FALSE;
238 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
239 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
240 ret = FALSE;
241 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
242 LPWSTR type;
243 if (HIWORD(et[i].u1.Name))
244 type = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
245 else
246 type = (LPWSTR)et[i].u1.Name;
248 ret = lpfun(hmod,type,lparam);
249 if (!ret)
250 break;
252 return ret;
255 /**********************************************************************
256 * PE_EnumResourceNames32A
258 BOOL32
259 PE_EnumResourceNames32A(
260 HMODULE32 hmod,LPCSTR type,ENUMRESNAMEPROC32A lpfun,LONG lparam
262 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
263 int i;
264 LPIMAGE_RESOURCE_DIRECTORY resdir;
265 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
266 BOOL32 ret;
267 HANDLE32 heap = GetProcessHeap();
268 LPWSTR typeW;
270 if (!pe || !pe->pe_resource)
271 return FALSE;
272 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
273 if (HIWORD(type))
274 typeW = HEAP_strdupAtoW(heap,0,type);
275 else
276 typeW = (LPWSTR)type;
277 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
278 if (HIWORD(typeW))
279 HeapFree(heap,0,typeW);
280 if (!resdir)
281 return FALSE;
282 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
283 ret = FALSE;
284 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
285 LPSTR name;
287 if (HIWORD(et[i].u1.Name))
288 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name));
289 else
290 name = (LPSTR)et[i].u1.Name;
291 ret = lpfun(hmod,type,name,lparam);
292 if (HIWORD(name)) HeapFree(heap,0,name);
293 if (!ret)
294 break;
296 return ret;
299 /**********************************************************************
300 * PE_EnumResourceNames32W
302 BOOL32
303 PE_EnumResourceNames32W(
304 HMODULE32 hmod,LPCWSTR type,ENUMRESNAMEPROC32W lpfun,LONG lparam
306 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
307 int i;
308 LPIMAGE_RESOURCE_DIRECTORY resdir;
309 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
310 BOOL32 ret;
312 if (!pe || !pe->pe_resource)
313 return FALSE;
315 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
316 resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
317 if (!resdir)
318 return FALSE;
319 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
320 ret = FALSE;
321 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
322 LPWSTR name;
323 if (HIWORD(et[i].u1.Name))
324 name = (LPWSTR)((LPBYTE)pe->pe_resource+et[i].u1.Name);
325 else
326 name = (LPWSTR)et[i].u1.Name;
327 ret = lpfun(hmod,type,name,lparam);
328 if (!ret)
329 break;
331 return ret;
334 /**********************************************************************
335 * PE_EnumResourceNames32A
337 BOOL32
338 PE_EnumResourceLanguages32A(
339 HMODULE32 hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROC32A lpfun,
340 LONG lparam
342 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
343 int i;
344 LPIMAGE_RESOURCE_DIRECTORY resdir;
345 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
346 BOOL32 ret;
347 HANDLE32 heap = GetProcessHeap();
348 LPWSTR nameW,typeW;
350 if (!pe || !pe->pe_resource)
351 return FALSE;
353 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
354 if (HIWORD(name))
355 nameW = HEAP_strdupAtoW(heap,0,name);
356 else
357 nameW = (LPWSTR)name;
358 resdir = GetResDirEntryW(resdir,nameW,(DWORD)pe->pe_resource);
359 if (HIWORD(nameW))
360 HeapFree(heap,0,nameW);
361 if (!resdir)
362 return FALSE;
363 if (HIWORD(type))
364 typeW = HEAP_strdupAtoW(heap,0,type);
365 else
366 typeW = (LPWSTR)type;
367 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pe->pe_resource);
368 if (HIWORD(typeW))
369 HeapFree(heap,0,typeW);
370 if (!resdir)
371 return FALSE;
372 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
373 ret = FALSE;
374 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
375 /* languages are just ids... I hope */
376 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
377 if (!ret)
378 break;
380 return ret;
383 /**********************************************************************
384 * PE_EnumResourceLanguages32W
386 BOOL32
387 PE_EnumResourceLanguages32W(
388 HMODULE32 hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROC32W lpfun,
389 LONG lparam
391 PE_MODULE *pe = HMODULE32toPE_MODULE(hmod);
392 int i;
393 LPIMAGE_RESOURCE_DIRECTORY resdir;
394 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
395 BOOL32 ret;
397 if (!pe || !pe->pe_resource)
398 return FALSE;
400 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pe->pe_resource;
401 resdir = GetResDirEntryW(resdir,name,(DWORD)pe->pe_resource);
402 if (!resdir)
403 return FALSE;
404 resdir = GetResDirEntryW(resdir,type,(DWORD)pe->pe_resource);
405 if (!resdir)
406 return FALSE;
407 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
408 ret = FALSE;
409 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
410 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
411 if (!ret)
412 break;
414 return ret;
416 #endif