Release 971012
[wine/multimedia.git] / loader / pe_resource.c
blob11ee0037dc3efed7b8912cc78b89a7dcbaab43df
1 /*
2 * PE (Portable Execute) File Resources
4 * Copyright 1995 Thomas Sandford
5 * Copyright 1996 Martin von Loewis
7 * Based on the Win16 resource handling code in loader/resource.c
8 * Copyright 1993 Robert J. Amstadt
9 * Copyright 1995 Alexandre Julliard
10 * Copyright 1997 Marcus Meissner
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include "wintypes.h"
16 #include "windows.h"
17 #include "pe_image.h"
18 #include "module.h"
19 #include "heap.h"
20 #include "task.h"
21 #include "process.h"
22 #include "libres.h"
23 #include "stackframe.h"
24 #include "neexe.h"
25 #include "stddebug.h"
26 #include "debug.h"
28 /**********************************************************************
29 * HMODULE32toPE_MODREF
31 * small helper function to get a PE_MODREF from a passed HMODULE32
33 static PE_MODREF*
34 HMODULE32toPE_MODREF(HMODULE32 hmod) {
35 NE_MODULE *pModule;
36 PDB32 *pdb = (PDB32*)GetCurrentProcessId();
37 PE_MODREF *pem;
39 if (!hmod) hmod = GetTaskDS(); /* FIXME: correct? */
40 hmod = MODULE_HANDLEtoHMODULE32( hmod );
41 if (!hmod) return NULL;
42 if (!(pModule = MODULE_GetPtr( hmod ))) return 0;
43 pem = pdb->modref_list;
44 while (pem && pem->pe_module->mappeddll != hmod)
45 pem=pem->next;
46 return pem;
49 /**********************************************************************
50 * GetResDirEntryW
52 * Helper function - goes down one level of PE resource tree
55 LPIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(LPIMAGE_RESOURCE_DIRECTORY resdirptr,
56 LPCWSTR name,DWORD root)
58 int entrynum;
59 LPIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
60 int namelen;
62 if (HIWORD(name)) {
63 if (name[0]=='#') {
64 char buf[10];
66 lstrcpynWtoA(buf,name+1,10);
67 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root);
69 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
70 (BYTE *) resdirptr +
71 sizeof(IMAGE_RESOURCE_DIRECTORY));
72 namelen = lstrlen32W(name);
73 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
75 LPIMAGE_RESOURCE_DIR_STRING_U str =
76 (LPIMAGE_RESOURCE_DIR_STRING_U) (root +
77 entryTable[entrynum].u1.s.NameOffset);
78 if(namelen != str->Length)
79 continue;
80 if(lstrncmpi32W(name,str->NameString,str->Length)==0)
81 return (LPIMAGE_RESOURCE_DIRECTORY) (
82 root +
83 entryTable[entrynum].u2.s.OffsetToDirectory);
85 return NULL;
86 } else {
87 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
88 (BYTE *) resdirptr +
89 sizeof(IMAGE_RESOURCE_DIRECTORY) +
90 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
91 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
92 if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
93 return (LPIMAGE_RESOURCE_DIRECTORY) (
94 root +
95 entryTable[entrynum].u2.s.OffsetToDirectory);
96 /* just use first entry if no default can be found */
97 if (!name && resdirptr->NumberOfIdEntries)
98 return (LPIMAGE_RESOURCE_DIRECTORY) (
99 root +
100 entryTable[0].u2.s.OffsetToDirectory);
101 return NULL;
105 /**********************************************************************
106 * PE_FindResourceEx32W
108 HANDLE32 PE_FindResourceEx32W(
109 HINSTANCE32 hModule,LPCWSTR name,LPCWSTR type,WORD lang
111 LPIMAGE_RESOURCE_DIRECTORY resdirptr;
112 DWORD root;
113 HANDLE32 result;
114 PE_MODREF *pem = HMODULE32toPE_MODREF(hModule);
116 if (!pem || !pem->pe_resource)
117 return 0;
119 resdirptr = pem->pe_resource;
120 root = (DWORD) resdirptr;
121 if ((resdirptr = GetResDirEntryW(resdirptr, type, root)) == NULL)
122 return 0;
123 if ((resdirptr = GetResDirEntryW(resdirptr, name, root)) == NULL)
124 return 0;
125 result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT32)lang, root);
126 /* Try LANG_NEUTRAL, too */
127 if(!result)
128 return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root);
129 return result;
133 /**********************************************************************
134 * PE_LoadResource32
136 HANDLE32 PE_LoadResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
138 PE_MODREF *pem = HMODULE32toPE_MODREF(hModule);
140 if (!pem || !pem->pe_resource)
141 return 0;
142 if (!hRsrc)
143 return 0;
144 return (HANDLE32) (pem->load_addr+((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
148 /**********************************************************************
149 * PE_SizeofResource32
151 DWORD PE_SizeofResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
153 /* we don't need hModule */
154 if (!hRsrc)
155 return 0;
156 return ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
159 /**********************************************************************
160 * PE_EnumResourceTypes32A
162 BOOL32
163 PE_EnumResourceTypes32A(HMODULE32 hmod,ENUMRESTYPEPROC32A lpfun,LONG lparam) {
164 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
165 int i;
166 LPIMAGE_RESOURCE_DIRECTORY resdir;
167 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
168 BOOL32 ret;
169 HANDLE32 heap = GetProcessHeap();
171 if (!pem || !pem->pe_resource)
172 return FALSE;
174 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
175 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
176 ret = FALSE;
177 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
178 LPSTR name;
180 if (HIWORD(et[i].u1.Name))
181 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
182 else
183 name = (LPSTR)et[i].u1.Name;
184 ret = lpfun(hmod,name,lparam);
185 if (HIWORD(name))
186 HeapFree(heap,0,name);
187 if (!ret)
188 break;
190 return ret;
193 /**********************************************************************
194 * PE_EnumResourceTypes32W
196 BOOL32
197 PE_EnumResourceTypes32W(HMODULE32 hmod,ENUMRESTYPEPROC32W lpfun,LONG lparam) {
198 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
199 int i;
200 LPIMAGE_RESOURCE_DIRECTORY resdir;
201 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
202 BOOL32 ret;
204 if (!pem || !pem->pe_resource)
205 return FALSE;
207 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
208 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
209 ret = FALSE;
210 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
211 LPWSTR type;
212 if (HIWORD(et[i].u1.Name))
213 type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
214 else
215 type = (LPWSTR)et[i].u1.Name;
217 ret = lpfun(hmod,type,lparam);
218 if (!ret)
219 break;
221 return ret;
224 /**********************************************************************
225 * PE_EnumResourceNames32A
227 BOOL32
228 PE_EnumResourceNames32A(
229 HMODULE32 hmod,LPCSTR type,ENUMRESNAMEPROC32A lpfun,LONG lparam
231 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
232 int i;
233 LPIMAGE_RESOURCE_DIRECTORY resdir;
234 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
235 BOOL32 ret;
236 HANDLE32 heap = GetProcessHeap();
237 LPWSTR typeW;
239 if (!pem || !pem->pe_resource)
240 return FALSE;
241 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
242 if (HIWORD(type))
243 typeW = HEAP_strdupAtoW(heap,0,type);
244 else
245 typeW = (LPWSTR)type;
246 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
247 if (HIWORD(typeW))
248 HeapFree(heap,0,typeW);
249 if (!resdir)
250 return FALSE;
251 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
252 ret = FALSE;
253 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
254 LPSTR name;
256 if (HIWORD(et[i].u1.Name))
257 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
258 else
259 name = (LPSTR)et[i].u1.Name;
260 ret = lpfun(hmod,type,name,lparam);
261 if (HIWORD(name)) HeapFree(heap,0,name);
262 if (!ret)
263 break;
265 return ret;
268 /**********************************************************************
269 * PE_EnumResourceNames32W
271 BOOL32
272 PE_EnumResourceNames32W(
273 HMODULE32 hmod,LPCWSTR type,ENUMRESNAMEPROC32W lpfun,LONG lparam
275 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
276 int i;
277 LPIMAGE_RESOURCE_DIRECTORY resdir;
278 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
279 BOOL32 ret;
281 if (!pem || !pem->pe_resource)
282 return FALSE;
284 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
285 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
286 if (!resdir)
287 return FALSE;
288 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
289 ret = FALSE;
290 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
291 LPWSTR name;
292 if (HIWORD(et[i].u1.Name))
293 name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
294 else
295 name = (LPWSTR)et[i].u1.Name;
296 ret = lpfun(hmod,type,name,lparam);
297 if (!ret)
298 break;
300 return ret;
303 /**********************************************************************
304 * PE_EnumResourceNames32A
306 BOOL32
307 PE_EnumResourceLanguages32A(
308 HMODULE32 hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROC32A lpfun,
309 LONG lparam
311 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
312 int i;
313 LPIMAGE_RESOURCE_DIRECTORY resdir;
314 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
315 BOOL32 ret;
316 HANDLE32 heap = GetProcessHeap();
317 LPWSTR nameW,typeW;
319 if (!pem || !pem->pe_resource)
320 return FALSE;
322 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
323 if (HIWORD(name))
324 nameW = HEAP_strdupAtoW(heap,0,name);
325 else
326 nameW = (LPWSTR)name;
327 resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource);
328 if (HIWORD(nameW))
329 HeapFree(heap,0,nameW);
330 if (!resdir)
331 return FALSE;
332 if (HIWORD(type))
333 typeW = HEAP_strdupAtoW(heap,0,type);
334 else
335 typeW = (LPWSTR)type;
336 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource);
337 if (HIWORD(typeW))
338 HeapFree(heap,0,typeW);
339 if (!resdir)
340 return FALSE;
341 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
342 ret = FALSE;
343 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
344 /* languages are just ids... I hopem */
345 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
346 if (!ret)
347 break;
349 return ret;
352 /**********************************************************************
353 * PE_EnumResourceLanguages32W
355 BOOL32
356 PE_EnumResourceLanguages32W(
357 HMODULE32 hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROC32W lpfun,
358 LONG lparam
360 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
361 int i;
362 LPIMAGE_RESOURCE_DIRECTORY resdir;
363 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
364 BOOL32 ret;
366 if (!pem || !pem->pe_resource)
367 return FALSE;
369 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
370 resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource);
371 if (!resdir)
372 return FALSE;
373 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource);
374 if (!resdir)
375 return FALSE;
376 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
377 ret = FALSE;
378 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
379 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
380 if (!ret)
381 break;
383 return ret;