Removed some direct accesses to the 16-bit task structure.
[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  *          FindResource16   (KERNEL.60)
317  */
318 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, LPCSTR name, LPCSTR type )
319 {
320     return RES_FindResource( hModule, type, name,
321                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, TRUE );
322 }
323
324 /**********************************************************************
325  *          FindResourceA    (KERNEL32.128)
326  */
327 HRSRC WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
328 {
329     return RES_FindResource( hModule, type, name, 
330                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), FALSE, FALSE );
331 }
332
333 /**********************************************************************
334  *          FindResourceExA  (KERNEL32.129)
335  */
336 HRSRC WINAPI FindResourceExA( HMODULE hModule, 
337                                LPCSTR type, LPCSTR name, WORD lang )
338 {
339     return RES_FindResource( hModule, type, name, 
340                              lang, FALSE, FALSE );
341 }
342
343 /**********************************************************************
344  *          FindResourceExW  (KERNEL32.130)
345  */
346 HRSRC WINAPI FindResourceExW( HMODULE hModule, 
347                               LPCWSTR type, LPCWSTR name, WORD lang )
348 {
349     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
350                              lang, TRUE, FALSE );
351 }
352
353 /**********************************************************************
354  *          FindResourceW    (KERNEL32.131)
355  */
356 HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
357 {
358     return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name, 
359                     MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), TRUE, FALSE );
360 }
361
362 /**********************************************************************
363  *          LoadResource16   (KERNEL.61)
364  */
365 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
366 {
367     return RES_LoadResource( hModule, hRsrc, TRUE );
368 }
369
370 /**********************************************************************
371  *          LoadResource     (KERNEL32.370)
372  */
373 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
374 {
375     return RES_LoadResource( hModule, hRsrc, FALSE );
376 }
377
378 /**********************************************************************
379  *          LockResource16   (KERNEL.62)
380  */
381 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
382 {
383     TRACE("(%04x)\n", handle );
384     /* May need to reload the resource if discarded */
385     return K32WOWGlobalLock16( handle );
386 }
387
388 /**********************************************************************
389  *          LockResource16   (KERNEL but also exported from KERNEL32 in Wine)
390  */
391 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
392 {
393     return MapSL( WIN16_LockResource16(handle) );
394 }
395
396 /**********************************************************************
397  *          LockResource     (KERNEL32.384)
398  */
399 LPVOID WINAPI LockResource( HGLOBAL handle )
400 {
401     TRACE("(%08x)\n", handle );
402
403     if (HIWORD( handle ))  /* 32-bit memory handle */
404         return (LPVOID)handle;
405
406     /* 16-bit memory handle */
407     return LockResource16( handle );
408 }
409
410 /**********************************************************************
411  *          FreeResource16   (KERNEL.63)
412  */
413 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
414 {
415     HGLOBAL retv = handle;
416     NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
417
418     TRACE("(%04x)\n", handle );
419
420     /* Try NE resource first */
421     retv = NE_FreeResource( pModule, handle );
422
423     /* If this failed, call USER.DestroyIcon32; this will check
424        whether it is a shared cursor/icon; if not it will call
425        GlobalFree16() */
426     if ( retv )
427     {
428         if ( Callout.DestroyIcon32 )
429             retv = Callout.DestroyIcon32( handle, CID_RESOURCE );
430         else
431             retv = GlobalFree16( handle );
432     }
433     return (BOOL)retv;
434 }
435
436 /**********************************************************************
437  *          FreeResource     (KERNEL32.145)
438  */
439 BOOL WINAPI FreeResource( HGLOBAL handle )
440 {
441     if (HIWORD(handle)) return 0; /* 32-bit memory handle: nothing to do */
442
443     return FreeResource16( handle );
444 }
445
446 /**********************************************************************
447  *          SizeofResource16 (KERNEL.65)
448  */
449 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
450 {
451     return RES_SizeofResource( hModule, hRsrc, TRUE );
452 }
453
454 /**********************************************************************
455  *          SizeofResource   (KERNEL32.522)
456  */
457 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
458 {
459     return RES_SizeofResource( hModule, hRsrc, FALSE );
460 }