]> git.sesse.net Git - vlc/blob - loader/pe_resource.c
5e54e5e711d7f287e860ad24e494238679ca244e
[vlc] / loader / pe_resource.c
1 /*
2  * PE (Portable Execute) File Resources
3  * $Id$
4  *
5  * Copyright 1995 Thomas Sandford
6  * Copyright 1996 Martin von Loewis
7  *
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
12  *
13  * Modified for use with MPlayer, detailed CVS changelog at
14  * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
15  *
16  * File now distributed as part of VLC media player with no modifications.
17  *
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.
22  *
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.
27  *
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.
31  */
32 #include "config.h"
33
34 #include <stdlib.h>
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"
41 //#include "task.h"
42 //#include "process.h"
43 //#include "stackframe.h"
44 #include "wine/debugtools.h"
45 #include "ext.h"
46
47 /**********************************************************************
48  *  HMODULE32toPE_MODREF 
49  *
50  * small helper function to get a PE_MODREF from a passed HMODULE32
51  */
52 static PE_MODREF*
53 HMODULE32toPE_MODREF(HMODULE hmod) {
54         WINE_MODREF     *wm;
55
56         wm = MODULE32_LookupHMODULE( hmod );
57         if (!wm || wm->type!=MODULE32_PE)
58                 return NULL;
59         return &(wm->binfmt.pe);
60 }
61
62 /**********************************************************************
63  *          GetResDirEntryW
64  *
65  *      Helper function - goes down one level of PE resource tree
66  *
67  */
68 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr,
69                                            LPCWSTR name,DWORD root,
70                                            WIN_BOOL allowdefault)
71 {
72     int entrynum;
73     PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
74     int namelen;
75
76     if (HIWORD(name)) {
77         if (name[0]=='#') {
78                 char    buf[10];
79
80                 lstrcpynWtoA(buf,name+1,10);
81                 return GetResDirEntryW(resdirptr,(LPCWSTR)atoi(buf),root,allowdefault);
82         }
83         entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
84                         (BYTE *) resdirptr + 
85                         sizeof(IMAGE_RESOURCE_DIRECTORY));
86         namelen = lstrlenW(name);
87         for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
88         {
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)
93                         continue;
94                 if(wcsnicmp(name,str->NameString,str->Length)==0)
95                         return (PIMAGE_RESOURCE_DIRECTORY) (
96                                 root +
97                                 entryTable[entrynum].u2.s.OffsetToDirectory);
98         }
99         return NULL;
100     } else {
101         entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
102                         (BYTE *) resdirptr + 
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) (
108                         root +
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) (
113                         root +
114                         entryTable[0].u2.s.OffsetToDirectory);
115         return NULL;
116     }
117 }
118
119 /**********************************************************************
120  *          GetResDirEntryA
121  */
122 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA( PIMAGE_RESOURCE_DIRECTORY resdirptr,
123                                            LPCSTR name, DWORD root,
124                                            WIN_BOOL allowdefault )
125 {
126     PIMAGE_RESOURCE_DIRECTORY retv;
127     LPWSTR nameW = HIWORD(name)? HEAP_strdupAtoW( GetProcessHeap(), 0, name ) 
128                                : (LPWSTR)name;
129
130     retv = GetResDirEntryW( resdirptr, nameW, root, allowdefault );
131
132     if ( HIWORD(name) ) HeapFree( GetProcessHeap(), 0, nameW );
133
134     return retv;
135 }
136
137 /**********************************************************************
138  *          PE_FindResourceEx32W
139  */
140 HANDLE PE_FindResourceExW(
141         WINE_MODREF *wm,LPCWSTR name,LPCWSTR type,WORD lang
142 ) {
143     PIMAGE_RESOURCE_DIRECTORY resdirptr;
144     DWORD root;
145     HANDLE result;
146     PE_MODREF   *pem = &(wm->binfmt.pe);
147
148     if (!pem || !pem->pe_resource)
149         return 0;
150
151     resdirptr = pem->pe_resource;
152     root = (DWORD) resdirptr;
153     if ((resdirptr = GetResDirEntryW(resdirptr, type, root, FALSE)) == NULL)
154         return 0;
155     if ((resdirptr = GetResDirEntryW(resdirptr, name, root, FALSE)) == NULL)
156         return 0;
157     result = (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)(UINT)lang, root, FALSE);
158         /* Try LANG_NEUTRAL, too */
159     if(!result)
160         return (HANDLE)GetResDirEntryW(resdirptr, (LPCWSTR)0, root, TRUE);
161     return result;
162 }
163
164
165 /**********************************************************************
166  *          PE_LoadResource32
167  */
168 HANDLE PE_LoadResource( WINE_MODREF *wm, HANDLE hRsrc )
169 {
170     if (!hRsrc || !wm || wm->type!=MODULE32_PE)
171         return 0;
172     return (HANDLE) (wm->module + ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
173 }
174
175
176 /**********************************************************************
177  *          PE_SizeofResource32
178  */
179 DWORD PE_SizeofResource( HINSTANCE hModule, HANDLE hRsrc )
180 {
181     /* we don't need hModule */
182     if (!hRsrc)
183          return 0;
184     return ((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->Size;
185 }
186
187 /**********************************************************************
188  *          PE_EnumResourceTypes32A
189  */
190 WIN_BOOL
191 PE_EnumResourceTypesA(HMODULE hmod,ENUMRESTYPEPROCA lpfun,LONG lparam) {
192     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
193     int         i;
194     PIMAGE_RESOURCE_DIRECTORY           resdir;
195     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
196     WIN_BOOL    ret;
197     HANDLE      heap = GetProcessHeap();        
198
199     if (!pem || !pem->pe_resource)
200         return FALSE;
201
202     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
203     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
204     ret = FALSE;
205     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
206         LPSTR   name;
207
208         if (et[i].u1.s.NameIsString)
209                 name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
210         else
211                 name = (LPSTR)(int)et[i].u1.Id;
212         ret = lpfun(hmod,name,lparam);
213         if (HIWORD(name))
214                 HeapFree(heap,0,name);
215         if (!ret)
216                 break;
217     }
218     return ret;
219 }
220
221 /**********************************************************************
222  *          PE_EnumResourceTypes32W
223  */
224 WIN_BOOL
225 PE_EnumResourceTypesW(HMODULE hmod,ENUMRESTYPEPROCW lpfun,LONG lparam) {
226     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
227     int         i;
228     PIMAGE_RESOURCE_DIRECTORY           resdir;
229     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
230     WIN_BOOL    ret;
231
232     if (!pem || !pem->pe_resource)
233         return FALSE;
234
235     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
236     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
237     ret = FALSE;
238     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
239         LPWSTR  type;
240         if (et[i].u1.s.NameIsString)
241                 type = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
242         else
243                 type = (LPWSTR)(int)et[i].u1.Id;
244
245         ret = lpfun(hmod,type,lparam);
246         if (!ret)
247                 break;
248     }
249     return ret;
250 }
251
252 /**********************************************************************
253  *          PE_EnumResourceNames32A
254  */
255 WIN_BOOL
256 PE_EnumResourceNamesA(
257         HMODULE hmod,LPCSTR type,ENUMRESNAMEPROCA lpfun,LONG lparam
258 ) {
259     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
260     int         i;
261     PIMAGE_RESOURCE_DIRECTORY           resdir;
262     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
263     WIN_BOOL    ret;
264     HANDLE      heap = GetProcessHeap();        
265     LPWSTR      typeW;
266
267     if (!pem || !pem->pe_resource)
268         return FALSE;
269     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
270     if (HIWORD(type))
271         typeW = HEAP_strdupAtoW(heap,0,type);
272     else
273         typeW = (LPWSTR)type;
274     resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
275     if (HIWORD(typeW))
276         HeapFree(heap,0,typeW);
277     if (!resdir)
278         return FALSE;
279     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
280     ret = FALSE;
281     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
282         LPSTR   name;
283
284         if (et[i].u1.s.NameIsString)
285             name = HEAP_strdupWtoA(heap,0,(LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset));
286         else
287             name = (LPSTR)(int)et[i].u1.Id;
288         ret = lpfun(hmod,type,name,lparam);
289         if (HIWORD(name)) HeapFree(heap,0,name);
290         if (!ret)
291                 break;
292     }
293     return ret;
294 }
295
296 /**********************************************************************
297  *          PE_EnumResourceNames32W
298  */
299 WIN_BOOL
300 PE_EnumResourceNamesW(
301         HMODULE hmod,LPCWSTR type,ENUMRESNAMEPROCW lpfun,LONG lparam
302 ) {
303     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
304     int         i;
305     PIMAGE_RESOURCE_DIRECTORY           resdir;
306     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
307     WIN_BOOL    ret;
308
309     if (!pem || !pem->pe_resource)
310         return FALSE;
311
312     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
313     resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
314     if (!resdir)
315         return FALSE;
316     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
317     ret = FALSE;
318     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
319         LPWSTR  name;
320         if (et[i].u1.s.NameIsString)
321                 name = (LPWSTR)((LPBYTE)pem->pe_resource+et[i].u1.s.NameOffset);
322         else
323                 name = (LPWSTR)(int)et[i].u1.Id;
324         ret = lpfun(hmod,type,name,lparam);
325         if (!ret)
326                 break;
327     }
328     return ret;
329 }
330
331 /**********************************************************************
332  *          PE_EnumResourceNames32A
333  */
334 WIN_BOOL
335 PE_EnumResourceLanguagesA(
336         HMODULE hmod,LPCSTR name,LPCSTR type,ENUMRESLANGPROCA lpfun,
337         LONG lparam
338 ) {
339     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
340     int         i;
341     PIMAGE_RESOURCE_DIRECTORY           resdir;
342     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
343     WIN_BOOL    ret;
344     HANDLE      heap = GetProcessHeap();        
345     LPWSTR      nameW,typeW;
346
347     if (!pem || !pem->pe_resource)
348         return FALSE;
349
350     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
351     if (HIWORD(name))
352         nameW = HEAP_strdupAtoW(heap,0,name);
353     else
354         nameW = (LPWSTR)name;
355     resdir = GetResDirEntryW(resdir,nameW,(DWORD)pem->pe_resource,FALSE);
356     if (HIWORD(nameW))
357         HeapFree(heap,0,nameW);
358     if (!resdir)
359         return FALSE;
360     if (HIWORD(type))
361         typeW = HEAP_strdupAtoW(heap,0,type);
362     else
363         typeW = (LPWSTR)type;
364     resdir = GetResDirEntryW(resdir,typeW,(DWORD)pem->pe_resource,FALSE);
365     if (HIWORD(typeW))
366         HeapFree(heap,0,typeW);
367     if (!resdir)
368         return FALSE;
369     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
370     ret = FALSE;
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);
374         if (!ret)
375                 break;
376     }
377     return ret;
378 }
379
380 /**********************************************************************
381  *          PE_EnumResourceLanguages32W
382  */
383 WIN_BOOL
384 PE_EnumResourceLanguagesW(
385         HMODULE hmod,LPCWSTR name,LPCWSTR type,ENUMRESLANGPROCW lpfun,
386         LONG lparam
387 ) {
388     PE_MODREF   *pem = HMODULE32toPE_MODREF(hmod);
389     int         i;
390     PIMAGE_RESOURCE_DIRECTORY           resdir;
391     PIMAGE_RESOURCE_DIRECTORY_ENTRY     et;
392     WIN_BOOL    ret;
393
394     if (!pem || !pem->pe_resource)
395         return FALSE;
396
397     resdir = (PIMAGE_RESOURCE_DIRECTORY)pem->pe_resource;
398     resdir = GetResDirEntryW(resdir,name,(DWORD)pem->pe_resource,FALSE);
399     if (!resdir)
400         return FALSE;
401     resdir = GetResDirEntryW(resdir,type,(DWORD)pem->pe_resource,FALSE);
402     if (!resdir)
403         return FALSE;
404     et =(PIMAGE_RESOURCE_DIRECTORY_ENTRY)((LPBYTE)resdir+sizeof(IMAGE_RESOURCE_DIRECTORY));
405     ret = FALSE;
406     for (i=0;i<resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries;i++) {
407         ret = lpfun(hmod,name,type,et[i].u1.Id,lparam);
408         if (!ret)
409                 break;
410     }
411     return ret;
412 }