Moved a bunch of functions out of libwine/kernel/gdi into USER.
[wine] / loader / resource.c
1 /*
2  * Resources
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include <assert.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <unistd.h>
15 #include "windef.h"
16 #include "winbase.h"
17 #include "wine/winbase16.h"
18 #include "wine/exception.h"
19 #include "ldt.h"
20 #include "global.h"
21 #include "heap.h"
22 #include "callback.h"
23 #include "cursoricon.h"
24 #include "neexe.h"
25 #include "task.h"
26 #include "process.h"
27 #include "module.h"
28 #include "file.h"
29 #include "debugtools.h"
30 #include "winerror.h"
31 #include "winnls.h"
32
33 DEFAULT_DEBUG_CHANNEL(resource);
34
35 #define HRSRC_MAP_BLOCKSIZE 16
36
37 typedef struct _HRSRC_ELEM
38 {
39     HANDLE hRsrc;
40     WORD     type;
41 } HRSRC_ELEM;
42
43 typedef struct _HRSRC_MAP
44 {
45     int nAlloc;
46     int nUsed;
47     HRSRC_ELEM *elem;
48 } HRSRC_MAP;
49
50 /**********************************************************************
51  *          MapHRsrc32To16
52  */
53 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE hRsrc32, WORD type )
54 {
55     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
56     HRSRC_ELEM *newElem;
57     int i;
58
59     /* On first call, initialize HRSRC map */
60     if ( !map )
61     {
62         if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
63                                              sizeof(HRSRC_MAP) ) ) )
64         {
65             ERR("Cannot allocate HRSRC map\n" );
66             return 0;
67         }
68         pModule->hRsrcMap = (LPVOID)map;
69     }
70
71     /* Check whether HRSRC32 already in map */
72     for ( i = 0; i < map->nUsed; i++ )
73         if ( map->elem[i].hRsrc == hRsrc32 )
74             return (HRSRC16)(i + 1);
75
76     /* If no space left, grow table */
77     if ( map->nUsed == map->nAlloc )
78     {
79         if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
80                                                     map->elem, 
81                                                     (map->nAlloc + HRSRC_MAP_BLOCKSIZE) 
82                                                     * sizeof(HRSRC_ELEM) ) ))
83         {
84             ERR("Cannot grow HRSRC map\n" );
85             return 0;
86         }
87         map->elem = newElem;
88         map->nAlloc += HRSRC_MAP_BLOCKSIZE;
89     }
90
91     /* Add HRSRC32 to table */
92     map->elem[map->nUsed].hRsrc = hRsrc32;
93     map->elem[map->nUsed].type  = type;
94     map->nUsed++;
95
96     return (HRSRC16)map->nUsed;
97 }
98
99 /**********************************************************************
100  *          MapHRsrc16To32
101  */
102 static HANDLE MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
103 {
104     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
105     if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
106
107     return map->elem[(int)hRsrc16-1].hRsrc;
108 }
109
110 /**********************************************************************
111  *          MapHRsrc16ToType
112  */
113 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
114 {
115     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
116     if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
117
118     return map->elem[(int)hRsrc16-1].type;
119 }
120
121
122 /* filter for page-fault exceptions */
123 static WINE_EXCEPTION_FILTER(page_fault)
124 {
125     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
126         return EXCEPTION_EXECUTE_HANDLER;
127     return EXCEPTION_CONTINUE_SEARCH;
128 }
129
130 static HRSRC RES_FindResource2( HMODULE hModule, LPCSTR type,
131                                 LPCSTR name, WORD lang, 
132                                 BOOL bUnicode, BOOL bRet16 )
133 {
134     HRSRC hRsrc = 0;
135     HMODULE16 hMod16   = MapHModuleLS( hModule );
136     NE_MODULE *pModule = NE_GetPtr( hMod16 );
137     WINE_MODREF *wm    = pModule && pModule->module32? 
138         MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
139     
140     TRACE("(%08x %s, %08x%s, %08x%s, %04x, %s, %s)\n",
141           hModule,
142           pModule ? (char *)NE_MODULE_NAME(pModule) : "NULL dereference",
143           (UINT)type, HIWORD(type)? (bUnicode? debugstr_w((LPWSTR)type) : debugstr_a(type)) : "",
144           (UINT)name, HIWORD(name)? (bUnicode? debugstr_w((LPWSTR)name) : debugstr_a(name)) : "",
145           lang,
146           bUnicode? "W"  : "A",
147           bRet16?   "NE" : "PE" );
148     
149     if (pModule)
150     {
151         if ( wm )
152         {
153             /* 32-bit PE module */
154             LPWSTR typeStr, nameStr;
155             
156             if ( HIWORD( type ) && !bUnicode )
157                 typeStr = HEAP_strdupAtoW( GetProcessHeap(), 0, type );
158             else
159                 typeStr = (LPWSTR)type;
160             if ( HIWORD( name ) && !bUnicode )
161                 nameStr = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
162             else
163                 nameStr = (LPWSTR)name;
164             
165             hRsrc = PE_FindResourceExW( wm, nameStr, typeStr, lang );
166             
167             if ( HIWORD( type ) && !bUnicode ) 
168                 HeapFree( GetProcessHeap(), 0, typeStr );
169             if ( HIWORD( name ) && !bUnicode ) 
170                 HeapFree( GetProcessHeap(), 0, nameStr );
171             
172             
173             /* If we need to return 16-bit HRSRC, perform conversion */
174             if ( bRet16 )
175                 hRsrc = MapHRsrc32To16( pModule, hRsrc, 
176                                         HIWORD( type )? 0 : LOWORD( type ) );
177         }
178         else
179         {
180             /* 16-bit NE module */
181             LPSTR typeStr, nameStr;
182             
183             if ( HIWORD( type ) && bUnicode )
184                 typeStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)type );
185             else
186                 typeStr = (LPSTR)type;
187             if ( HIWORD( name ) && bUnicode )
188                 nameStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)name );
189             else
190                 nameStr = (LPSTR)name;
191             
192             hRsrc = NE_FindResource( pModule, nameStr, typeStr );
193             
194             if ( HIWORD( type ) && bUnicode ) 
195                 HeapFree( GetProcessHeap(), 0, typeStr );
196             if ( HIWORD( name ) && bUnicode ) 
197                 HeapFree( GetProcessHeap(), 0, nameStr );
198             
199             
200             /* If we need to return 32-bit HRSRC, no conversion is necessary,
201                we simply use the 16-bit HRSRC as 32-bit HRSRC */
202         }
203     }
204     return hRsrc;
205 }
206
207 /**********************************************************************
208  *          RES_FindResource
209  */
210
211 static HRSRC RES_FindResource( HMODULE hModule, LPCSTR type,
212                                LPCSTR name, WORD lang, 
213                                BOOL bUnicode, BOOL bRet16 )
214 {
215     HRSRC hRsrc;
216     __TRY
217     {
218         hRsrc = RES_FindResource2(hModule, type, name, lang, bUnicode, bRet16);
219     }
220     __EXCEPT(page_fault)
221     {
222         WARN("page fault\n");
223         SetLastError(ERROR_INVALID_PARAMETER);
224         return 0;
225     }
226     __ENDTRY
227     return hRsrc;
228 }
229
230 /**********************************************************************
231  *          RES_SizeofResource
232  */
233 static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
234 {
235     DWORD size = 0;
236
237     HMODULE16 hMod16   = MapHModuleLS( hModule );
238     NE_MODULE *pModule = NE_GetPtr( hMod16 );
239     WINE_MODREF *wm    = pModule && pModule->module32? 
240                          MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
241
242     TRACE("(%08x %s, %08x, %s)\n",
243           hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
244
245     if ( !pModule || !hRsrc ) return 0;
246
247     if ( wm )
248     {
249         /* 32-bit PE module */
250
251         /* If we got a 16-bit hRsrc, convert it */
252         HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
253
254         size = PE_SizeofResource( hModule, hRsrc32 );
255     }
256     else
257     {
258         /* 16-bit NE module */
259
260         /* If we got a 32-bit hRsrc, we don't need to convert it */
261
262         size = NE_SizeofResource( pModule, hRsrc );
263     }
264
265     return size;
266 }
267
268 /**********************************************************************
269  *          RES_AccessResource
270  */
271 static HFILE RES_AccessResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
272 {
273     HFILE hFile = HFILE_ERROR;
274
275     HMODULE16 hMod16   = MapHModuleLS( hModule );
276     NE_MODULE *pModule = NE_GetPtr( hMod16 );
277     WINE_MODREF *wm    = pModule && pModule->module32? 
278                          MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
279
280     TRACE("(%08x %s, %08x, %s)\n",
281           hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
282
283     if ( !pModule || !hRsrc ) return HFILE_ERROR;
284
285     if ( wm )
286     {
287         /* 32-bit PE module */
288 #if 0
289         /* If we got a 16-bit hRsrc, convert it */
290         HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
291 #endif
292
293         FIXME("32-bit modules not yet supported.\n" );
294         hFile = HFILE_ERROR;
295
296         /* If we need to return a 16-bit file handle, convert it */
297         if ( bRet16 )
298             hFile = FILE_AllocDosHandle( hFile );
299     }
300     else
301     {
302         /* 16-bit NE module */
303
304         /* If we got a 32-bit hRsrc, we don't need to convert it */
305
306         hFile = NE_AccessResource( pModule, hRsrc );
307
308         /* If we are to return a 32-bit file handle, convert it */
309         if ( !bRet16 )
310             hFile = FILE_GetHandle( hFile );
311     }
312
313     return hFile;
314 }
315
316 /**********************************************************************
317  *          RES_LoadResource
318  */
319 static HGLOBAL RES_LoadResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
320 {
321     HGLOBAL hMem = 0;
322
323     HMODULE16 hMod16   = MapHModuleLS( hModule );
324     NE_MODULE *pModule = NE_GetPtr( hMod16 );
325     WINE_MODREF *wm    = pModule && pModule->module32? 
326                          MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
327
328     TRACE("(%08x %s, %08x, %s)\n",
329           hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
330
331     if ( !pModule || !hRsrc ) return 0;
332
333     if ( wm )
334     {
335         /* 32-bit PE module */
336
337         /* If we got a 16-bit hRsrc, convert it */
338         HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
339
340         hMem = PE_LoadResource( wm, hRsrc32 );
341
342         /* If we need to return a 16-bit resource, convert it */
343         if ( bRet16 )
344         {
345             WORD type   = MapHRsrc16ToType( pModule, hRsrc );
346             DWORD size  = SizeofResource( hModule, hRsrc );
347             LPVOID bits = LockResource( hMem );
348
349             hMem = NE_LoadPEResource( pModule, type, bits, size );
350         }
351     }
352     else
353     {
354         /* 16-bit NE module */
355
356         /* If we got a 32-bit hRsrc, we don't need to convert it */
357
358         hMem = NE_LoadResource( pModule, hRsrc );
359
360         /* If we are to return a 32-bit resource, we should probably
361            convert it but we don't for now.  FIXME !!! */
362     }
363
364     return hMem;
365 }
366
367 /**********************************************************************
368  *          RES_LockResource
369  */
370 static LPVOID RES_LockResource( HGLOBAL handle, BOOL bRet16 )
371 {
372     LPVOID bits = NULL;
373
374     TRACE("(%08x, %s)\n", handle, bRet16? "NE" : "PE" );
375
376     if ( HIWORD( handle ) )
377     {
378         /* 32-bit memory handle */
379
380         if ( bRet16 )
381             FIXME("can't return SEGPTR to 32-bit resource %08x.\n", handle );
382         else
383             bits = (LPVOID)handle;
384     }
385     else
386     {
387         /* 16-bit memory handle */
388
389         /* May need to reload the resource if discarded */
390         SEGPTR segPtr = WIN16_GlobalLock16( handle );
391         
392         if ( bRet16 )
393             bits = (LPVOID)segPtr;
394         else
395             bits = PTR_SEG_TO_LIN( segPtr );
396     }
397
398     return bits;
399 }
400
401 /**********************************************************************
402  *          RES_FreeResource
403  */
404 static BOOL RES_FreeResource( HGLOBAL handle )
405 {
406     HGLOBAL retv = handle;
407
408     TRACE("(%08x)\n", handle );
409
410     if ( HIWORD( handle ) )
411     {
412         /* 32-bit memory handle: nothing to do */
413     }
414     else
415     {
416         /* 16-bit memory handle */
417         NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
418
419         /* Try NE resource first */
420         retv = NE_FreeResource( pModule, handle );
421
422         /* If this failed, call USER.DestroyIcon32; this will check
423            whether it is a shared cursor/icon; if not it will call
424            GlobalFree16() */
425         if ( retv ) {
426             if ( Callout.DestroyIcon32 )
427                 retv = Callout.DestroyIcon32( handle, CID_RESOURCE );
428             else
429                 retv = GlobalFree16( handle );
430         }
431     }
432
433     return (BOOL)retv;
434 }
435
436
437 /**********************************************************************
438  *          FindResource16   (KERNEL.60)
439  */
440 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
441 {
442     LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
443     LPCSTR typeStr = HIWORD(type)? PTR_SEG_TO_LIN(type) : (LPCSTR)type;
444
445     return RES_FindResource( hModule, typeStr, nameStr, 
446                              GetSystemDefaultLangID(), FALSE, TRUE );
447 }
448
449 /**********************************************************************
450  *          FindResourceA    (KERNEL32.128)
451  */
452 HANDLE WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
453 {
454     return RES_FindResource( hModule, type, name, 
455                              GetSystemDefaultLangID(), FALSE, FALSE );
456 }
457
458 /**********************************************************************
459  *          FindResourceExA  (KERNEL32.129)
460  */
461 HANDLE WINAPI FindResourceExA( HMODULE hModule, 
462                                LPCSTR type, LPCSTR name, WORD lang )
463 {
464     return RES_FindResource( hModule, type, name, 
465                              lang, FALSE, FALSE );
466 }
467
468 /**********************************************************************
469  *          FindResourceExW  (KERNEL32.130)
470  */
471 HRSRC WINAPI FindResourceExW( HMODULE hModule, 
472                               LPCWSTR type, LPCWSTR name, WORD lang )
473 {
474     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
475                              lang, TRUE, FALSE );
476 }
477
478 /**********************************************************************
479  *          FindResourceW    (KERNEL32.131)
480  */
481 HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
482 {
483     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
484                              GetSystemDefaultLangID(), TRUE, FALSE );
485 }
486
487 /**********************************************************************
488  *          LoadResource16   (KERNEL.61)
489  */
490 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
491 {
492     return RES_LoadResource( hModule, hRsrc, TRUE );
493 }
494
495 /**********************************************************************
496  *          LoadResource     (KERNEL32.370)
497  */
498 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
499 {
500     return RES_LoadResource( hModule, hRsrc, FALSE );
501 }
502
503 /**********************************************************************
504  *          LockResource16   (KERNEL.62)
505  */
506 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
507 {
508     return (SEGPTR)RES_LockResource( handle, TRUE );
509 }
510 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
511 {
512     return RES_LockResource( handle, FALSE );
513 }
514
515 /**********************************************************************
516  *          LockResource     (KERNEL32.384)
517  */
518 LPVOID WINAPI LockResource( HGLOBAL handle )
519 {
520     return RES_LockResource( handle, FALSE );
521 }
522
523 /**********************************************************************
524  *          FreeResource16   (KERNEL.63)
525  */
526 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
527 {
528     return RES_FreeResource( handle );
529 }
530
531 /**********************************************************************
532  *          FreeResource     (KERNEL32.145)
533  */
534 BOOL WINAPI FreeResource( HGLOBAL handle )
535 {
536     return RES_FreeResource( handle );
537 }
538
539 /**********************************************************************
540  *          AccessResource16 (KERNEL.64)
541  */
542 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
543 {
544     return RES_AccessResource( hModule, hRsrc, TRUE );
545 }
546
547 /**********************************************************************
548  *          AccessResource   (KERNEL32.64)
549  */
550 INT WINAPI AccessResource( HMODULE hModule, HRSRC hRsrc )
551 {
552     return RES_AccessResource( hModule, hRsrc, FALSE );
553 }
554
555 /**********************************************************************
556  *          SizeofResource16 (KERNEL.65)
557  */
558 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
559 {
560     return RES_SizeofResource( hModule, hRsrc, TRUE );
561 }
562
563 /**********************************************************************
564  *          SizeofResource   (KERNEL32.522)
565  */
566 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
567 {
568     return RES_SizeofResource( hModule, hRsrc, FALSE );
569 }
570
571
572
573 /**********************************************************************
574  *      EnumResourceTypesA      (KERNEL32.90)
575  */
576 BOOL WINAPI EnumResourceTypesA( HMODULE hmodule,ENUMRESTYPEPROCA lpfun,
577                                     LONG lParam)
578 {
579         /* FIXME: move WINE_MODREF stuff here */
580     return PE_EnumResourceTypesA(hmodule,lpfun,lParam);
581 }
582
583 /**********************************************************************
584  *      EnumResourceTypesW      (KERNEL32.91)
585  */
586 BOOL WINAPI EnumResourceTypesW( HMODULE hmodule,ENUMRESTYPEPROCW lpfun,
587                                     LONG lParam)
588 {
589         /* FIXME: move WINE_MODREF stuff here */
590     return PE_EnumResourceTypesW(hmodule,lpfun,lParam);
591 }
592
593 /**********************************************************************
594  *      EnumResourceNamesA      (KERNEL32.88)
595  */
596 BOOL WINAPI EnumResourceNamesA( HMODULE hmodule, LPCSTR type,
597                                     ENUMRESNAMEPROCA lpfun, LONG lParam )
598 {
599         /* FIXME: move WINE_MODREF stuff here */
600     return PE_EnumResourceNamesA(hmodule,type,lpfun,lParam);
601 }
602 /**********************************************************************
603  *      EnumResourceNamesW      (KERNEL32.89)
604  */
605 BOOL WINAPI EnumResourceNamesW( HMODULE hmodule, LPCWSTR type,
606                                     ENUMRESNAMEPROCW lpfun, LONG lParam )
607 {
608         /* FIXME: move WINE_MODREF stuff here */
609     return PE_EnumResourceNamesW(hmodule,type,lpfun,lParam);
610 }
611
612 /**********************************************************************
613  *      EnumResourceLanguagesA  (KERNEL32.86)
614  */
615 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmodule, LPCSTR type,
616                                         LPCSTR name, ENUMRESLANGPROCA lpfun,
617                                         LONG lParam)
618 {
619         /* FIXME: move WINE_MODREF stuff here */
620     return PE_EnumResourceLanguagesA(hmodule,type,name,lpfun,lParam);
621 }
622 /**********************************************************************
623  *      EnumResourceLanguagesW  (KERNEL32.87)
624  */
625 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmodule, LPCWSTR type,
626                                         LPCWSTR name, ENUMRESLANGPROCW lpfun,
627                                         LONG lParam)
628 {
629         /* FIXME: move WINE_MODREF stuff here */
630     return PE_EnumResourceLanguagesW(hmodule,type,name,lpfun,lParam);
631 }