Spelling fixes.
[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 "heap.h"
20 #include "callback.h"
21 #include "cursoricon.h"
22 #include "module.h"
23 #include "file.h"
24 #include "debugtools.h"
25 #include "winerror.h"
26 #include "winnls.h"
27
28 DEFAULT_DEBUG_CHANNEL(resource);
29
30 #define HRSRC_MAP_BLOCKSIZE 16
31
32 typedef struct _HRSRC_ELEM
33 {
34     HANDLE hRsrc;
35     WORD     type;
36 } HRSRC_ELEM;
37
38 typedef struct _HRSRC_MAP
39 {
40     int nAlloc;
41     int nUsed;
42     HRSRC_ELEM *elem;
43 } HRSRC_MAP;
44
45 /**********************************************************************
46  *          MapHRsrc32To16
47  */
48 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE hRsrc32, WORD type )
49 {
50     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
51     HRSRC_ELEM *newElem;
52     int i;
53
54     /* On first call, initialize HRSRC map */
55     if ( !map )
56     {
57         if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
58                                              sizeof(HRSRC_MAP) ) ) )
59         {
60             ERR("Cannot allocate HRSRC map\n" );
61             return 0;
62         }
63         pModule->hRsrcMap = (LPVOID)map;
64     }
65
66     /* Check whether HRSRC32 already in map */
67     for ( i = 0; i < map->nUsed; i++ )
68         if ( map->elem[i].hRsrc == hRsrc32 )
69             return (HRSRC16)(i + 1);
70
71     /* If no space left, grow table */
72     if ( map->nUsed == map->nAlloc )
73     {
74         if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 
75                                                     map->elem, 
76                                                     (map->nAlloc + HRSRC_MAP_BLOCKSIZE) 
77                                                     * sizeof(HRSRC_ELEM) ) ))
78         {
79             ERR("Cannot grow HRSRC map\n" );
80             return 0;
81         }
82         map->elem = newElem;
83         map->nAlloc += HRSRC_MAP_BLOCKSIZE;
84     }
85
86     /* Add HRSRC32 to table */
87     map->elem[map->nUsed].hRsrc = hRsrc32;
88     map->elem[map->nUsed].type  = type;
89     map->nUsed++;
90
91     return (HRSRC16)map->nUsed;
92 }
93
94 /**********************************************************************
95  *          MapHRsrc16To32
96  */
97 static HANDLE MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
98 {
99     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
100     if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
101
102     return map->elem[(int)hRsrc16-1].hRsrc;
103 }
104
105 /**********************************************************************
106  *          MapHRsrc16ToType
107  */
108 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
109 {
110     HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
111     if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
112
113     return map->elem[(int)hRsrc16-1].type;
114 }
115
116
117 /* filter for page-fault exceptions */
118 static WINE_EXCEPTION_FILTER(page_fault)
119 {
120     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
121         return EXCEPTION_EXECUTE_HANDLER;
122     return EXCEPTION_CONTINUE_SEARCH;
123 }
124
125 static HRSRC RES_FindResource2( HMODULE hModule, LPCSTR type,
126                                 LPCSTR name, WORD lang, 
127                                 BOOL bUnicode, BOOL bRet16 )
128 {
129     HRSRC hRsrc = 0;
130     
131     TRACE("(%08x, %08x%s, %08x%s, %04x, %s, %s)\n",
132           hModule,
133           (UINT)type, HIWORD(type)? (bUnicode? debugstr_w((LPWSTR)type) : debugstr_a(type)) : "",
134           (UINT)name, HIWORD(name)? (bUnicode? debugstr_w((LPWSTR)name) : debugstr_a(name)) : "",
135           lang,
136           bUnicode? "W"  : "A",
137           bRet16?   "NE" : "PE" );
138
139     if (!HIWORD(hModule))
140     {
141         HMODULE16 hMod16   = MapHModuleLS( hModule );
142         NE_MODULE *pModule = NE_GetPtr( hMod16 );
143         if (!pModule) return 0;
144         if (!pModule->module32)
145         {
146             /* 16-bit NE module */
147             LPSTR typeStr, nameStr;
148             
149             if ( HIWORD( type ) && bUnicode )
150                 typeStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)type );
151             else
152                 typeStr = (LPSTR)type;
153             if ( HIWORD( name ) && bUnicode )
154                 nameStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)name );
155             else
156                 nameStr = (LPSTR)name;
157             
158             hRsrc = NE_FindResource( pModule, nameStr, typeStr );
159             
160             if ( HIWORD( type ) && bUnicode ) 
161                 HeapFree( GetProcessHeap(), 0, typeStr );
162             if ( HIWORD( name ) && bUnicode ) 
163                 HeapFree( GetProcessHeap(), 0, nameStr );
164             
165             /* If we need to return 32-bit HRSRC, no conversion is necessary,
166                we simply use the 16-bit HRSRC as 32-bit HRSRC */
167         }
168         else
169         {
170             /* 32-bit PE module */
171             hRsrc = RES_FindResource2( pModule->module32, type, name, lang, bUnicode, FALSE );
172             /* If we need to return 16-bit HRSRC, perform conversion */
173             if ( bRet16 )
174                 hRsrc = MapHRsrc32To16( pModule, hRsrc, 
175                                         HIWORD( type )? 0 : LOWORD( type ) );
176         }
177     }
178     else
179     {
180         /* 32-bit PE module */
181         LPWSTR typeStr, nameStr;
182             
183         if ( HIWORD( type ) && !bUnicode )
184             typeStr = HEAP_strdupAtoW( GetProcessHeap(), 0, type );
185         else
186             typeStr = (LPWSTR)type;
187         if ( HIWORD( name ) && !bUnicode )
188             nameStr = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
189         else
190             nameStr = (LPWSTR)name;
191
192         /* Here is the real difference between FindResouce and FindResourceEx */
193         if(lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) ||
194                 lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) ||
195                 lang == MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT) ||
196                 lang == MAKELANGID(LANG_NEUTRAL, 3)) /* FIXME: real name? */
197             hRsrc = PE_FindResourceW( hModule, nameStr, typeStr );
198         else
199             hRsrc = PE_FindResourceExW( hModule, nameStr, typeStr, lang );
200             
201         if ( HIWORD( type ) && !bUnicode ) 
202             HeapFree( GetProcessHeap(), 0, typeStr );
203         if ( HIWORD( name ) && !bUnicode ) 
204             HeapFree( GetProcessHeap(), 0, nameStr );
205     }
206     return hRsrc;
207 }
208
209 /**********************************************************************
210  *          RES_FindResource
211  */
212
213 static HRSRC RES_FindResource( HMODULE hModule, LPCSTR type,
214                                LPCSTR name, WORD lang, 
215                                BOOL bUnicode, BOOL bRet16 )
216 {
217     HRSRC hRsrc;
218     __TRY
219     {
220         hRsrc = RES_FindResource2(hModule, type, name, lang, bUnicode, bRet16);
221     }
222     __EXCEPT(page_fault)
223     {
224         WARN("page fault\n");
225         SetLastError(ERROR_INVALID_PARAMETER);
226         return 0;
227     }
228     __ENDTRY
229     return hRsrc;
230 }
231
232 /**********************************************************************
233  *          RES_SizeofResource
234  */
235 static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
236 {
237     if (!hRsrc) return 0;
238
239     TRACE("(%08x, %08x, %s)\n", hModule, hRsrc, bRet16? "NE" : "PE" );
240
241     if (!HIWORD(hModule))
242     {
243         HMODULE16 hMod16   = MapHModuleLS( hModule );
244         NE_MODULE *pModule = NE_GetPtr( hMod16 );
245         if (!pModule) return 0;
246
247         if (!pModule->module32)  /* 16-bit NE module */
248         {
249             /* If we got a 32-bit hRsrc, we don't need to convert it */
250             return NE_SizeofResource( pModule, hRsrc );
251         }
252
253         /* If we got a 16-bit hRsrc, convert it */
254         if (!HIWORD(hRsrc)) hRsrc = MapHRsrc16To32( pModule, hRsrc );
255     }
256
257     /* 32-bit PE module */
258     return PE_SizeofResource( hRsrc );
259 }
260
261 /**********************************************************************
262  *          RES_LoadResource
263  */
264 static HGLOBAL RES_LoadResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
265 {
266     HGLOBAL hMem = 0;
267
268     TRACE("(%08x, %08x, %s)\n", hModule, hRsrc, bRet16? "NE" : "PE" );
269
270     if (!hRsrc) return 0;
271
272     if (!HIWORD(hModule))
273     {
274         HMODULE16 hMod16   = MapHModuleLS( hModule );
275         NE_MODULE *pModule = NE_GetPtr( hMod16 );
276         if (!pModule) return 0;
277         if (!pModule->module32)
278         {
279             /* 16-bit NE module */
280
281             /* If we got a 32-bit hRsrc, we don't need to convert it */
282             hMem = NE_LoadResource( pModule, hRsrc );
283
284             /* If we are to return a 32-bit resource, we should probably
285                convert it but we don't for now.  FIXME !!! */
286             return hMem;
287         }
288         else
289         {
290             /* If we got a 16-bit hRsrc, convert it */
291             HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
292
293             hMem = PE_LoadResource( pModule->module32, hRsrc32 );
294
295             /* If we need to return a 16-bit resource, convert it */
296             if ( bRet16 )
297             {
298                 WORD type   = MapHRsrc16ToType( pModule, hRsrc );
299                 DWORD size  = SizeofResource( hModule, hRsrc );
300                 LPVOID bits = LockResource( hMem );
301
302                 hMem = NE_LoadPEResource( pModule, type, bits, size );
303             }
304         }
305     }
306     else
307     {
308         /* 32-bit PE module */
309         hMem = PE_LoadResource( hModule, hRsrc );
310     }
311
312     return hMem;
313 }
314
315 /**********************************************************************
316  *          FindResource     (KERNEL.60)
317  *          FindResource16   (KERNEL32.@)
318  */
319 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, LPCSTR name, LPCSTR type )
320 {
321     return RES_FindResource( hModule, type, name,
322                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, TRUE );
323 }
324
325 /**********************************************************************
326  *          FindResourceA    (KERNEL32.@)
327  */
328 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
329 {
330     return RES_FindResource( hModule, type, name, 
331                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, FALSE );
332 }
333
334 /**********************************************************************
335  *          FindResourceExA  (KERNEL32.@)
336  */
337 HRSRC WINAPI FindResourceExA( HMODULE hModule, 
338                                LPCSTR type, LPCSTR name, WORD lang )
339 {
340     return RES_FindResource( hModule, type, name, 
341                              lang, FALSE, FALSE );
342 }
343
344 /**********************************************************************
345  *          FindResourceExW  (KERNEL32.@)
346  */
347 HRSRC WINAPI FindResourceExW( HMODULE hModule, 
348                               LPCWSTR type, LPCWSTR name, WORD lang )
349 {
350     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
351                              lang, TRUE, FALSE );
352 }
353
354 /**********************************************************************
355  *          FindResourceW    (KERNEL32.@)
356  */
357 HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
358 {
359     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
360                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), TRUE, FALSE );
361 }
362
363 /**********************************************************************
364  *          LoadResource     (KERNEL.61)
365  *          LoadResource16   (KERNEL32.@)
366  */
367 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
368 {
369     return RES_LoadResource( hModule, hRsrc, TRUE );
370 }
371
372 /**********************************************************************
373  *          LoadResource     (KERNEL32.@)
374  */
375 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
376 {
377     return RES_LoadResource( hModule, hRsrc, FALSE );
378 }
379
380 /**********************************************************************
381  *          LockResource   (KERNEL.62)
382  */
383 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
384 {
385     TRACE("(%04x)\n", handle );
386     /* May need to reload the resource if discarded */
387     return K32WOWGlobalLock16( handle );
388 }
389
390 /**********************************************************************
391  *          LockResource16 (KERNEL32.@)
392  */
393 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
394 {
395     return MapSL( WIN16_LockResource16(handle) );
396 }
397
398 /**********************************************************************
399  *          LockResource     (KERNEL32.@)
400  */
401 LPVOID WINAPI LockResource( HGLOBAL handle )
402 {
403     TRACE("(%08x)\n", handle );
404
405     if (HIWORD( handle ))  /* 32-bit memory handle */
406         return (LPVOID)handle;
407
408     /* 16-bit memory handle */
409     return LockResource16( handle );
410 }
411
412 /**********************************************************************
413  *          FreeResource     (KERNEL.63)
414  *          FreeResource16   (KERNEL32.@)
415  */
416 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
417 {
418     HGLOBAL retv = handle;
419     NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
420
421     TRACE("(%04x)\n", handle );
422
423     /* Try NE resource first */
424     retv = NE_FreeResource( pModule, handle );
425
426     /* If this failed, call USER.DestroyIcon32; this will check
427        whether it is a shared cursor/icon; if not it will call
428        GlobalFree16() */
429     if ( retv )
430     {
431         if ( Callout.DestroyIcon32 )
432             retv = Callout.DestroyIcon32( handle, CID_RESOURCE );
433         else
434             retv = GlobalFree16( handle );
435     }
436     return (BOOL)retv;
437 }
438
439 /**********************************************************************
440  *          FreeResource     (KERNEL32.@)
441  */
442 BOOL WINAPI FreeResource( HGLOBAL handle )
443 {
444     if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
445
446     return FreeResource16( handle );
447 }
448
449 /**********************************************************************
450  *          SizeofResource   (KERNEL.65)
451  *          SizeofResource16 (KERNEL32.@)
452  */
453 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
454 {
455     return RES_SizeofResource( hModule, hRsrc, TRUE );
456 }
457
458 /**********************************************************************
459  *          SizeofResource   (KERNEL32.@)
460  */
461 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
462 {
463     return RES_SizeofResource( hModule, hRsrc, FALSE );
464 }