2 * 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
13 * Modified for use with MPlayer, detailed CVS changelog at
14 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
16 * File now distributed as part of VLC media player with no modifications.
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
35 #include <sys/types.h>
36 #include "wine/winestring.h"
37 #include "wine/windef.h"
38 #include "wine/pe_image.h"
39 #include "wine/module.h"
40 #include "wine/heap.h"
42 //#include "process.h"
43 //#include "stackframe.h"
44 #include "wine/debugtools.h"
47 /**********************************************************************
48 * HMODULE32toPE_MODREF
50 * small helper function to get a PE_MODREF from a passed HMODULE32
53 HMODULE32toPE_MODREF(HMODULE hmod) {
56 wm = MODULE32_LookupHMODULE( hmod );
57 if (!wm || wm->type!=MODULE32_PE)
59 return &(wm->binfmt.pe);
62 /**********************************************************************
65 * Helper function - goes down one level of PE resource tree
68 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr,
69 LPCWSTR name,DWORD root,
70 WIN_BOOL allowdefault)
73 PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
80 lstrcpynWtoA(buf,name+1,10);
81 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
83 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
85 sizeof(IMAGE_RESOURCE_DIRECTORY));
86 namelen = lstrlenW(name);
87 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
89 PIMAGE_RESOURCE_DIR_STRING_U str =
90 (PIMAGE_RESOURCE_DIR_STRING_U) (root +
91 entryTable[entrynum].u1.s.NameOffset);
92 if(namelen != str->Length)
94 if(wcsnicmp(name,str->NameString,str->Length)==0)
95 return (PIMAGE_RESOURCE_DIRECTORY) (
97 entryTable[entrynum].u2.s.OffsetToDirectory);
101 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
103 sizeof(IMAGE_RESOURCE_DIRECTORY) +
104 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
105 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
106 if ((DWORD)entryTable[entrynum].u1.Name == (DWORD)name)
107 return (PIMAGE_RESOURCE_DIRECTORY) (
109 entryTable[entrynum].u2.s.OffsetToDirectory);
110 /* just use first entry if no default can be found */
111 if (allowdefault && !name && resdirptr->NumberOfIdEntries)
112 return (PIMAGE_RESOURCE_DIRECTORY) (
114 entryTable[0].u2.s.OffsetToDirectory);
119 /**********************************************************************
122 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA( PIMAGE_RESOURCE_DIRECTORY resdirptr,
123 LPCSTR name, DWORD root,
124 WIN_BOOL allowdefault )
126 PIMAGE_RESOURCE_DIRECTORY retv;
127 LPWSTR nameW = HIWORD(name)? HEAP_strdupAtoW( GetProcessHeap(), 0, name )
130 retv = GetResDirEntryW( resdirptr, nameW, root, allowdefault );
132 if ( HIWORD(name) ) HeapFree( GetProcessHeap(), 0, nameW );
137 /**********************************************************************
138 * PE_FindResourceEx32W
140 HANDLE PE_FindResourceExW(
141 WINE_MODREF *wm,LPCWSTR name,LPCWSTR type,WORD lang
143 PIMAGE_RESOURCE_DIRECTORY resdirptr;
146 PE_MODREF *pem = &(wm->binfmt.pe);
148 if (!pem || !pem->pe_resource)
151 resdirptr = pem->pe_resource;
152 root = (DWORD) resdirptr;
153 if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
155 if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
157 result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE);
158 /* Try LANG_NEUTRAL, too */
160 return (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)0, root, TRUE);
165 /**********************************************************************
168 HANDLE PE_LoadResource( WINE_MODREF *wm, HANDLE hRsrc )
170 if (!hRsrc || !wm || wm->type!=MODULE32_PE)
172 return (HANDLE) (wm->module + ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
176 /**********************************************************************
177 * PE_SizeofResource32
179 DWORD PE_SizeofResource( HINSTANCE hModule, HANDLE hRsrc )
181 /* we don't need hModule */
184 return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
187 /**********************************************************************
188 * PE_EnumResourceTypes32A
191 PE_EnumResourceTypesA(HMODULE hmod,ENUMRESTYPEPROCA lpfun,LONG lparam) {
192 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
194 PIMAGE_RESOURCE_DIRECTORY resdir;
195 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
197 HANDLE heap = GetProcessHeap();
199 if (!pem || !pem->pe_resource)
202 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
203 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
205 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
208 if (et[i].u1.s.NameIsString)
209 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
211 name = (LPSTR)(int)et[i].u1.Id;
212 ret = lpfun(hmod,name,lparam);
214 HeapFree(heap,0,name);
221 /**********************************************************************
222 * PE_EnumResourceTypes32W
225 PE_EnumResourceTypesW(HMODULE hmod,ENUMRESTYPEPROCW lpfun,LONG lparam) {
226 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
228 PIMAGE_RESOURCE_DIRECTORY resdir;
229 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
232 if (!pem || !pem->pe_resource)
235 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
236 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
238 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
240 if (et[i].u1.s.NameIsString)
241 type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
243 type = (LPWSTR)(int)et[i].u1.Id;
245 ret = lpfun(hmod,type,lparam);
252 /**********************************************************************
253 * PE_EnumResourceNames32A
256 PE_EnumResourceNamesA(
257 HMODULE hmod,LPCSTR type,ENUMRESNAMEPROCA lpfun,LONG lparam
259 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
261 PIMAGE_RESOURCE_DIRECTORY resdir;
262 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
264 HANDLE heap = GetProcessHeap();
267 if (!pem || !pem->pe_resource)
269 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
271 typeW = HEAP_strdupAtoW(heap,0,type);
273 typeW = (LPWSTR)type;
274 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
276 HeapFree(heap,0,typeW);
279 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
281 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
284 if (et[i].u1.s.NameIsString)
285 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
287 name = (LPSTR)(int)et[i].u1.Id;
288 ret = lpfun(hmod,type,name,lparam);
289 if (HIWORD(name)) HeapFree(heap,0,name);
296 /**********************************************************************
297 * PE_EnumResourceNames32W
300 PE_EnumResourceNamesW(
301 HMODULE hmod,LPCWSTR type,ENUMRESNAMEPROCW lpfun,LONG lparam
303 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
305 PIMAGE_RESOURCE_DIRECTORY resdir;
306 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
309 if (!pem || !pem->pe_resource)
312 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
313 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
316 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
318 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
320 if (et[i].u1.s.NameIsString)
321 name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
323 name = (LPWSTR)(int)et[i].u1.Id;
324 ret = lpfun(hmod,type,name,lparam);
331 /**********************************************************************
332 * PE_EnumResourceNames32A
335 PE_EnumResourceLanguagesA(
336 HMODULE hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROCA lpfun,
339 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
341 PIMAGE_RESOURCE_DIRECTORY resdir;
342 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
344 HANDLE heap = GetProcessHeap();
347 if (!pem || !pem->pe_resource)
350 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
352 nameW = HEAP_strdupAtoW(heap,0,name);
354 nameW = (LPWSTR)name;
355 resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource,FALSE);
357 HeapFree(heap,0,nameW);
361 typeW = HEAP_strdupAtoW(heap,0,type);
363 typeW = (LPWSTR)type;
364 resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
366 HeapFree(heap,0,typeW);
369 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
371 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
372 /* languages are just ids... I hopem */
373 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
380 /**********************************************************************
381 * PE_EnumResourceLanguages32W
384 PE_EnumResourceLanguagesW(
385 HMODULE hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROCW lpfun,
388 PE_MODREF *pem = HMODULE32toPE_MODREF(hmod);
390 PIMAGE_RESOURCE_DIRECTORY resdir;
391 PIMAGE_RESOURCE_DIRECTORY_ENTRY et;
394 if (!pem || !pem->pe_resource)
397 resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
398 resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource,FALSE);
401 resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
404 et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
406 for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
407 ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);