Release 980201
[wine/multimedia.git] / loader / pe_resource.c
blob60fa5b8b874da9e6f2850b6f7fe5ce47c104a516
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 = PROCESS_Current();
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->module != 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,
57 BOOL32 allowdefault)
59 int entrynum;
60 LPIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
61 int namelen;
63 if (HIWORD(name)) {
64 if (name[0]=='#') {
65 char buf[10];
67 lstrcpynWtoA(buf,name+1,10);
68 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
70 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
71 (BYTE *) resdirptr +
72 sizeof(IMAGE_RESOURCE_DIRECTORY));
73 namelen = lstrlen32W(name);
74 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
76 LPIMAGE_RESOURCE_DIR_STRING_U str =
77 (LPIMAGE_RESOURCE_DIR_STRING_U) (root +
78 entryTable[entrynum].u1.s.NameOffset);
79 if(namelen != str->Length)
80 continue;
81 if(lstrncmpi32W(name,str->NameString,str->Length)==0)
82 return (LPIMAGE_RESOURCE_DIRECTORY) (
83 root +
84 entryTable[entrynum].u2.s.OffsetToDirectory);
86 return NULL;
87 } else {
88 entryTable = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY) (
89 (BYTE *) resdirptr +
90 sizeof(IMAGE_RESOURCE_DIRECTORY) +
91 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
92 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
93 if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
94 return (LPIMAGE_RESOURCE_DIRECTORY) (
95 root +
96 entryTable[entrynum].u2.s.OffsetToDirectory);
97 /* just use first entry if no default can be found */
98 if (allowdefault && !name && resdirptr->NumberOfIdEntries)
99 return (LPIMAGE_RESOURCE_DIRECTORY) (
100 root +
101 entryTable[0].u2.s.OffsetToDirectory);
102 return NULL;
106 /**********************************************************************
107 * PE_FindResourceEx32W
109 HANDLE32 PE_FindResourceEx32W(
110 HINSTANCE32 hModule,LPCWSTR name,LPCWSTR type,WORD lang
112 LPIMAGE_RESOURCE_DIRECTORY resdirptr;
113 DWORD root;
114 HANDLE32 result;
115 PE_MODREF *pem = HMODULE32toPE_MODREF(hModule);
117 if (!pem || !pem->pe_resource)
118 return 0;
120 resdirptr = pem->pe_resource;
121 root = (DWORD) resdirptr;
122 if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
123 return 0;
124 if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
125 return 0;
126 result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT32)lang, root, FALSE);
127 /* Try LANG_NEUTRAL, too */
128 if(!result)
129 return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root, TRUE);
130 return result;
134 /**********************************************************************
135 * PE_LoadResource32
137 HANDLE32 PE_LoadResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
139 PE_MODREF *pem = HMODULE32toPE_MODREF(hModule);
141 if (!pem || !pem->pe_resource)
142 return 0;
143 if (!hRsrc)
144 return 0;
145 return (HANDLE32) (pem->module + ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
149 /**********************************************************************
150 * PE_SizeofResource32
152 DWORD PE_SizeofResource32( HINSTANCE32 hModule, HANDLE32 hRsrc )
154 /* we don't need hModule */
155 if (!hRsrc)
156 return 0;
157 return ((LPIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
160 /**********************************************************************
161 * PE_EnumResourceTypes32A
163 BOOL32
164 PE_EnumResourceTypes32A(HMODULE32 hmod,ENUMRESTYPEPROC32A lpfun,LONG lparam) {
165 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
166 int i;
167 LPIMAGE_RESOURCE_DIRECTORY resdir;
168 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
169 BOOL32 ret;
170 HANDLE32 heap = GetProcessHeap();
172 if (!pem || !pem->pe_resource)
173 return FALSE;
175 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
176 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
177 ret = FALSE;
178 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
179 LPSTR name;
181 if (HIWORD(et[i].u1.Name))
182 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
183 else
184 name = (LPSTR)et[i].u1.Name;
185 ret = lpfun(hmod,name,lparam);
186 if (HIWORD(name))
187 HeapFree(heap,0,name);
188 if (!ret)
189 break;
191 return ret;
194 /**********************************************************************
195 * PE_EnumResourceTypes32W
197 BOOL32
198 PE_EnumResourceTypes32W(HMODULE32 hmod,ENUMRESTYPEPROC32W lpfun,LONG lparam) {
199 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
200 int i;
201 LPIMAGE_RESOURCE_DIRECTORY resdir;
202 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
203 BOOL32 ret;
205 if (!pem || !pem->pe_resource)
206 return FALSE;
208 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
209 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
210 ret = FALSE;
211 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
212 LPWSTR type;
213 if (HIWORD(et[i].u1.Name))
214 type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
215 else
216 type = (LPWSTR)et[i].u1.Name;
218 ret = lpfun(hmod,type,lparam);
219 if (!ret)
220 break;
222 return ret;
225 /**********************************************************************
226 * PE_EnumResourceNames32A
228 BOOL32
229 PE_EnumResourceNames32A(
230 HMODULE32 hmod,LPCSTR type,ENUMRESNAMEPROC32A lpfun,LONG lparam
232 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
233 int i;
234 LPIMAGE_RESOURCE_DIRECTORY resdir;
235 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
236 BOOL32 ret;
237 HANDLE32 heap = GetProcessHeap();
238 LPWSTR typeW;
240 if (!pem || !pem->pe_resource)
241 return FALSE;
242 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
243 if (HIWORD(type))
244 typeW = HEAP_strdupAtoW(heap,0,type);
245 else
246 typeW = (LPWSTR)type;
247 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
248 if (HIWORD(typeW))
249 HeapFree(heap,0,typeW);
250 if (!resdir)
251 return FALSE;
252 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
253 ret = FALSE;
254 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
255 LPSTR name;
257 if (HIWORD(et[i].u1.Name))
258 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name));
259 else
260 name = (LPSTR)et[i].u1.Name;
261 ret = lpfun(hmod,type,name,lparam);
262 if (HIWORD(name)) HeapFree(heap,0,name);
263 if (!ret)
264 break;
266 return ret;
269 /**********************************************************************
270 * PE_EnumResourceNames32W
272 BOOL32
273 PE_EnumResourceNames32W(
274 HMODULE32 hmod,LPCWSTR type,ENUMRESNAMEPROC32W lpfun,LONG lparam
276 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
277 int i;
278 LPIMAGE_RESOURCE_DIRECTORY resdir;
279 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
280 BOOL32 ret;
282 if (!pem || !pem->pe_resource)
283 return FALSE;
285 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
286 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
287 if (!resdir)
288 return FALSE;
289 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
290 ret = FALSE;
291 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
292 LPWSTR name;
293 if (HIWORD(et[i].u1.Name))
294 name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.Name);
295 else
296 name = (LPWSTR)et[i].u1.Name;
297 ret = lpfun(hmod,type,name,lparam);
298 if (!ret)
299 break;
301 return ret;
304 /**********************************************************************
305 * PE_EnumResourceNames32A
307 BOOL32
308 PE_EnumResourceLanguages32A(
309 HMODULE32 hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROC32A lpfun,
310 LONG lparam
312 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
313 int i;
314 LPIMAGE_RESOURCE_DIRECTORY resdir;
315 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
316 BOOL32 ret;
317 HANDLE32 heap = GetProcessHeap();
318 LPWSTR nameW,typeW;
320 if (!pem || !pem->pe_resource)
321 return FALSE;
323 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
324 if (HIWORD(name))
325 nameW = HEAP_strdupAtoW(heap,0,name);
326 else
327 nameW = (LPWSTR)name;
328 resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource,FALSE);
329 if (HIWORD(nameW))
330 HeapFree(heap,0,nameW);
331 if (!resdir)
332 return FALSE;
333 if (HIWORD(type))
334 typeW = HEAP_strdupAtoW(heap,0,type);
335 else
336 typeW = (LPWSTR)type;
337 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
338 if (HIWORD(typeW))
339 HeapFree(heap,0,typeW);
340 if (!resdir)
341 return FALSE;
342 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
343 ret = FALSE;
344 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
345 /* languages are just ids... I hopem */
346 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
347 if (!ret)
348 break;
350 return ret;
353 /**********************************************************************
354 * PE_EnumResourceLanguages32W
356 BOOL32
357 PE_EnumResourceLanguages32W(
358 HMODULE32 hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROC32W lpfun,
359 LONG lparam
361 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
362 int i;
363 LPIMAGE_RESOURCE_DIRECTORY resdir;
364 LPIMAGE_RESOURCE_DIRECTORY_ENTRY et;
365 BOOL32 ret;
367 if (!pem || !pem->pe_resource)
368 return FALSE;
370 resdir = (LPIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
371 resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource,FALSE);
372 if (!resdir)
373 return FALSE;
374 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
375 if (!resdir)
376 return FALSE;
377 et =(LPIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
378 ret = FALSE;
379 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
380 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
381 if (!ret)
382 break;
384 return ret;