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