Release 960712
[wine] / win32 / resource.c
1 /*
2  * Win32 Resources
3  *
4  * Copyright 1995 Thomas Sandford
5  * Copyright 1996 Martin von Loewis
6  *
7  * Based on the Win16 resource handling code in loader/resource.c
8  * Copyright 1993 Robert J. Amstadt
9  * Copyright 1995 Alexandre Julliard
10  *
11  * This is not even at ALPHA level yet. Don't expect it to work!
12  */
13
14 #include <sys/types.h>
15 #include "wintypes.h"
16 #include "windows.h"
17 #include "kernel32.h"
18 #include "pe_image.h"
19 #include "module.h"
20 #include "handle32.h"
21 #include "libres.h"
22 #include "resource32.h"
23 #include "stackframe.h"
24 #include "neexe.h"
25 #include "accel.h"
26 #include "xmalloc.h"
27 #include "string32.h"
28 #include "stddebug.h"
29 #include "debug.h"
30
31 int language = 0x0409;
32
33 #define PrintIdA(name) \
34     if (HIWORD((DWORD)name)) \
35         dprintf_resource( stddeb, "'%s'", name); \
36     else \
37         dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
38 #define PrintIdW(name)
39 #define PrintId(name)
40
41 /**********************************************************************
42  *          GetResDirEntryW
43  *
44  *      Helper function - goes down one level of PE resource tree
45  *
46  */
47 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryW(PIMAGE_RESOURCE_DIRECTORY resdirptr,
48                                          LPCWSTR name,
49                                          DWORD root)
50 {
51     int entrynum;
52     PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
53         int namelen;
54
55     if (HIWORD(name)) {
56     /* FIXME: what about #xxx names? */
57         entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
58                         (BYTE *) resdirptr + 
59                         sizeof(IMAGE_RESOURCE_DIRECTORY));
60         namelen = lstrlen32W(name);
61         for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
62         {
63                 PIMAGE_RESOURCE_DIR_STRING_U str =
64                 (PIMAGE_RESOURCE_DIR_STRING_U) (root + 
65                         (entryTable[entrynum].Name & 0x7fffffff));
66                 if(namelen != str->Length)
67                         continue;
68                 if(lstrncmpi32W(name,str->NameString,str->Length)==0)
69                         return (PIMAGE_RESOURCE_DIRECTORY) (
70                                 root +
71                                 (entryTable[entrynum].OffsetToData & 0x7fffffff));
72         }
73         return NULL;
74     } else {
75         entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
76                         (BYTE *) resdirptr + 
77                         sizeof(IMAGE_RESOURCE_DIRECTORY) +
78                         resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
79         for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
80             if ((DWORD)entryTable[entrynum].Name == (DWORD)name)
81                 return (PIMAGE_RESOURCE_DIRECTORY) (
82                         root +
83                         (entryTable[entrynum].OffsetToData & 0x7fffffff));
84         return NULL;
85     }
86 }
87
88 /**********************************************************************
89  *          GetResDirEntryA
90  *
91  *      Helper function - goes down one level of PE resource tree
92  *
93  */
94 PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA(PIMAGE_RESOURCE_DIRECTORY resdirptr,
95                                          LPCSTR name,
96                                          DWORD root)
97 {
98         LPWSTR                          xname;
99         PIMAGE_RESOURCE_DIRECTORY       ret;
100
101         if (HIWORD((DWORD)name))
102                 xname   = STRING32_DupAnsiToUni(name);
103         else
104                 xname   = (LPWSTR)name;
105
106         ret=GetResDirEntryW(resdirptr,xname,root);
107         if (HIWORD((DWORD)name))
108                 free(xname);
109         return ret;
110 }
111
112 /**********************************************************************
113  *          FindResourceA    (KERNEL32.128)
114  */
115 HANDLE32 FindResource32A( HINSTANCE hModule, LPCSTR name, LPCSTR type ) {
116         LPWSTR          xname,xtype;
117         HANDLE32        ret;
118
119         if (HIWORD((DWORD)name))
120                 xname = STRING32_DupAnsiToUni(name);
121         else
122                 xname = (LPWSTR)name;
123         if (HIWORD((DWORD)type))
124                 xtype = STRING32_DupAnsiToUni(type);
125         else
126                 xtype = (LPWSTR)type;
127         ret=FindResource32W(hModule,xname,xtype);
128         if (HIWORD((DWORD)name))
129                 free(xname);
130         if (HIWORD((DWORD)type))
131                 free(xtype);
132         return ret;
133 }
134
135 /**********************************************************************
136  *          FindResourceW    (KERNEL32.131)
137  */
138 HANDLE32 FindResource32W( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
139 {
140 #ifndef WINELIB
141     PE_MODULE *pe;
142     NE_MODULE *pModule;
143     PIMAGE_RESOURCE_DIRECTORY resdirptr;
144     DWORD root;
145         HANDLE32 result;
146
147     /* Sometimes we get passed hModule = 0x00000000. FIXME: is GetTaskDS()
148      * ok?
149      */
150     if (!hModule) hModule = GetTaskDS();
151     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
152     dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule );
153     PrintId( type );
154     dprintf_resource( stddeb, " name=" );
155     PrintId( name );
156     dprintf_resource( stddeb, "\n" );
157     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
158     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
159     if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
160
161     resdirptr = (PIMAGE_RESOURCE_DIRECTORY) pe->pe_resource;
162     root = (DWORD) resdirptr;
163     if ((resdirptr = GetResDirEntryW(resdirptr, type, root)) == NULL)
164         return 0;
165     if ((resdirptr = GetResDirEntryW(resdirptr, name, root)) == NULL)
166         return 0;
167     result = (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)language, root);
168         /* Try LANG_NEUTRAL, too */
169     if(!result)
170         return (HANDLE32)GetResDirEntryW(resdirptr, (LPCWSTR)0, root);
171     return result;
172     
173 #else
174     return LIBRES_FindResource( hModule, name, type );
175 #endif
176 }
177
178
179 /**********************************************************************
180  *          LoadResource    (KERNEL32.370)
181  */
182 HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc )
183 {
184 #ifndef WINELIB
185     NE_MODULE *pModule;
186     PE_MODULE *pe;
187
188     if (!hModule) hModule = GetTaskDS(); /* FIXME: see FindResource32W */
189     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
190     dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
191                      hModule, hRsrc );
192     if (!hRsrc) return 0;
193
194     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
195     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
196     if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
197     return (HANDLE32) (pe->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
198 #else
199     return LIBRES_LoadResource( hModule, hRsrc );
200 #endif
201 }
202
203
204 /**********************************************************************
205  *          LockResource    (KERNEL.62)
206  */
207 LPVOID LockResource32( HANDLE32 handle )
208 {
209         return (LPVOID) handle;
210 }
211
212 /**********************************************************************
213  *          FreeResource    (KERNEL.63)
214  */
215 BOOL FreeResource32( HANDLE32 handle )
216 {
217     /* no longer used in Win32 */
218     return TRUE;
219 }
220
221 /**********************************************************************
222  *          AccessResource    (KERNEL.64)
223  */
224 INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc )
225 {
226     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
227     dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
228                      hModule, hRsrc );
229     if (!hRsrc) return 0;
230         fprintf(stderr,"AccessResource32: not implemented\n");
231         return 0;
232 }
233
234
235 /**********************************************************************
236  *          SizeofResource    (KERNEL.65)
237  */
238 DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc )
239 {
240     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
241     dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
242                      hModule, hRsrc );
243         fprintf(stderr,"SizeofResource32: not implemented\n");
244         return 0;
245 }
246
247 /**********************************************************************
248  *                      LoadAccelerators        [USER.177]
249 */
250 HANDLE32 WIN32_LoadAcceleratorsW(HINSTANCE instance, LPCWSTR lpTableName)
251 {
252 #if 0
253     HANDLE32    hAccel;
254     HANDLE32    rsc_mem;
255     HANDLE32 hRsrc;
256     BYTE        *lp;
257     ACCELHEADER *lpAccelTbl;
258     int         i, n;
259
260     if (HIWORD(lpTableName))
261         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
262                       instance, (char *)( lpTableName ) );
263     else
264         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
265                        instance, LOWORD(lpTableName) );
266
267     if (!(hRsrc = FindResource32( instance, lpTableName, 
268                 (LPCWSTR)RT_ACCELERATOR )))
269       return 0;
270     if (!(rsc_mem = LoadResource32( instance, hRsrc ))) return 0;
271
272     lp = (BYTE *)LockResource32(rsc_mem);
273     n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
274     hAccel = GlobalAlloc16(GMEM_MOVEABLE, 
275         sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
276     lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel);
277     lpAccelTbl->wCount = 0;
278     for (i = 0; i < n; i++) {
279         lpAccelTbl->tbl[i].type = *(lp++);
280         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
281         lp += 2;
282         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
283         lp += 2;
284         if (lpAccelTbl->tbl[i].wEvent == 0) break;
285         dprintf_accel(stddeb,
286                 "Accelerator #%u / event=%04X id=%04X type=%02X \n", 
287                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
288                 lpAccelTbl->tbl[i].type);
289         lpAccelTbl->wCount++;
290         }
291     GlobalUnlock16(hAccel);
292     FreeResource( rsc_mem );
293     return hAccel;
294 #else
295         fprintf(stderr,"LoadAcceleratorsW: not implemented\n");
296         return 0x100;  /* Return something anyway */
297 #endif
298 }
299
300 HANDLE32 WIN32_LoadAcceleratorsA(HINSTANCE instance, LPCSTR lpTableName)
301 {
302         LPWSTR          uni;
303         HANDLE32        result;
304         if (HIWORD(lpTableName))
305                 uni=STRING32_DupAnsiToUni(lpTableName);
306         else
307                 uni=(LPWSTR)lpTableName;
308         result=WIN32_LoadAcceleratorsW(instance,uni);
309         if (HIWORD(uni))
310                 free(uni);
311         return result;
312 }
313 \f
314 /**********************************************************************
315  *                                      LoadString
316  */
317 int
318 WIN32_LoadStringW(HINSTANCE instance, DWORD resource_id, LPWSTR buffer, int buflen)
319 {
320     HANDLE32 hmem, hrsrc;
321     WCHAR *p;
322     int string_num;
323     int i;
324
325     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %04x, buffer = %08x, "
326            "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
327
328     hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1), 
329                 (LPCWSTR)RT_STRING );
330     if (!hrsrc) return 0;
331     hmem = LoadResource32( instance, hrsrc );
332     if (!hmem) return 0;
333     
334     p = LockResource32(hmem);
335     string_num = resource_id & 0x000f;
336     for (i = 0; i < string_num; i++)
337         p += *p + 1;
338     
339     dprintf_resource( stddeb, "strlen = %d\n", (int)*p );
340     
341     i = MIN(buflen - 1, *p);
342     if (buffer == NULL)
343         return i;
344     if (i > 0) {
345         memcpy(buffer, p + 1, i * sizeof (WCHAR));
346         buffer[i] = (WCHAR) 0;
347     } else {
348         if (buflen > 1) {
349             buffer[0] = (WCHAR) 0;
350             return 0;
351         }
352 #if 0
353         fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
354         fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
355 #endif
356     }
357     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
358     return i;
359 }
360 \f
361 /**********************************************************************
362  *                                      LoadStringA
363  */
364 int
365 WIN32_LoadStringA(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen)
366 {
367     WCHAR *buffer2 = xmalloc(buflen*2);
368     int retval = WIN32_LoadStringW(instance, resource_id, buffer2, buflen);
369
370     while (*buffer2) 
371         *buffer++ = (char) *buffer2++;
372     *buffer = 0;
373     return retval;
374 }
375
376 HICON LoadIconW32(HINSTANCE hisnt, LPCWSTR lpszIcon)
377
378 {
379         return LoadIcon(0, IDI_APPLICATION);
380 }
381
382 HICON LoadIconA32(HINSTANCE hinst, LPCSTR lpszIcon)
383
384 {
385         return LoadIconW32(hinst, lpszIcon);
386 }
387 /**********************************************************************
388  *          LoadBitmapW
389  */
390 HBITMAP WIN32_LoadBitmapW( HANDLE instance, LPCWSTR name )
391 {
392     HBITMAP hbitmap = 0;
393     HDC hdc;
394     HANDLE32 hRsrc;
395     HANDLE32 handle;
396     BITMAPINFO *info;
397
398     if (!instance)  /* OEM bitmap */
399     {
400         if (HIWORD((int)name)) return 0;
401         return OBM_LoadBitmap( LOWORD((int)name) );
402     }
403
404     if (!(hRsrc = FindResource32W( instance, name, 
405                 (LPWSTR)RT_BITMAP ))) return 0;
406     if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
407
408     info = (BITMAPINFO *)LockResource32( handle );
409     if ((hdc = GetDC(0)) != 0)
410     {
411         char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
412         hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
413                                   bits, info, DIB_RGB_COLORS );
414         ReleaseDC( 0, hdc );
415     }
416     return hbitmap;
417 }
418 /**********************************************************************
419  *          LoadBitmapA
420  */
421 HBITMAP WIN32_LoadBitmapA( HANDLE instance, LPCSTR name )
422 {
423     HBITMAP res;
424     if(!HIWORD(name))
425         res = WIN32_LoadBitmapW(instance,(LPWSTR)name);
426     else{
427         LPWSTR uni=STRING32_DupAnsiToUni(name);
428         res=WIN32_LoadBitmapW(instance,uni);
429         free(uni);
430     }
431     return res;
432 }
433
434 /*****************************************************************
435  *        LoadMenuW                 (USER32.372)
436  */
437 HMENU WIN32_LoadMenuW(HANDLE instance, LPCWSTR name)
438 {
439         HANDLE32 hrsrc;
440         hrsrc=FindResource32W(instance,name,(LPWSTR)RT_MENU);
441         if(!hrsrc)return 0;
442         return LoadMenuIndirect32W( LoadResource32(instance, hrsrc) );
443 }
444
445 /*****************************************************************
446  *        LoadMenuA                 (USER32.370)
447  */
448 HMENU WIN32_LoadMenuA(HANDLE instance,LPCSTR name)
449 {
450         HMENU res;
451         if(!HIWORD(name))
452                 res = WIN32_LoadMenuW(instance,(LPWSTR)name);
453         else{
454                 LPWSTR uni=STRING32_DupAnsiToUni(name);
455                 res=WIN32_LoadMenuW(instance,uni);
456                 free(uni);
457         }
458         return res;
459 }