Release 950430
[wine] / loader / resource.c
1 /*
2  * Resources
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Alexandre Julliard
6  */
7
8 #include <stdio.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 "arch.h"
16 #include "windows.h"
17 #include "gdi.h"
18 #include "bitmap.h"
19 #include "neexe.h"
20 #include "icon.h"
21 #include "accel.h"
22 #include "dlls.h"
23 #include "module.h"
24 #include "resource.h"
25 #include "library.h"
26 #include "stddebug.h"
27 #include "debug.h"
28
29 #define PrintId(name) \
30     if (HIWORD((DWORD)name)) \
31         dprintf_resource( stddeb, "'%s'", (char *)PTR_SEG_TO_LIN(name)); \
32     else \
33         dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
34
35 /**********************************************************************
36  *          FindResource    (KERNEL.60)
37  */
38 HRSRC FindResource( HMODULE hModule, SEGPTR name, SEGPTR type )
39 {
40     WORD *pModule;
41
42     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
43     dprintf_resource(stddeb, "FindResource: module=%04x type=", hModule );
44     PrintId( type );
45     dprintf_resource( stddeb, " name=" );
46     PrintId( name );
47     dprintf_resource( stddeb, "\n" );
48     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
49     switch(*pModule)
50     {
51       case NE_SIGNATURE:
52         return NE_FindResource( hModule, type, name );
53       case PE_SIGNATURE:
54         return 0;
55       default:
56         return 0;
57     }
58 }
59
60
61 /**********************************************************************
62  *          LoadResource    (KERNEL.61)
63  */
64 HGLOBAL LoadResource( HMODULE hModule, HRSRC hRsrc )
65 {
66     WORD *pModule;
67
68     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
69     dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
70                      hModule, hRsrc );
71     if (!hRsrc) return 0;
72     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
73     switch(*pModule)
74     {
75       case NE_SIGNATURE:
76         return NE_LoadResource( hModule, hRsrc );
77       case PE_SIGNATURE:
78         return 0;
79       default:
80         return 0;
81     }
82 }
83
84
85 /**********************************************************************
86  *          LockResource    (KERNEL.62)
87  */
88 /* 16-bit version */
89 SEGPTR WIN16_LockResource( HGLOBAL handle )
90 {
91     HMODULE hModule;
92     WORD *pModule;
93
94     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
95     if (!handle) return (SEGPTR)0;
96     hModule = GetExePtr( handle );
97     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
98     switch(*pModule)
99     {
100       case NE_SIGNATURE:
101         return NE_LockResource( hModule, handle );
102       case PE_SIGNATURE:
103         return 0;
104       default:
105         return 0;
106     }
107 }
108
109 /* 32-bit version */
110 LPSTR LockResource( HGLOBAL handle )
111 {
112     HMODULE hModule;
113     WORD *pModule;
114
115     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
116     if (!handle) return NULL;
117     hModule = GetExePtr( handle );
118     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
119     switch(*pModule)
120     {
121       case NE_SIGNATURE:
122         return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
123       case PE_SIGNATURE:
124         return 0;
125       default:
126         return 0;
127     }
128 }
129
130
131 /**********************************************************************
132  *          FreeResource    (KERNEL.63)
133  */
134 BOOL FreeResource( HGLOBAL handle )
135 {
136     HMODULE hModule;
137     WORD *pModule;
138
139     dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle );
140     if (!handle) return FALSE;
141     hModule = GetExePtr( handle );
142     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
143     switch(*pModule)
144     {
145       case NE_SIGNATURE:
146         return NE_FreeResource( hModule, handle );
147       case PE_SIGNATURE:
148         return FALSE;
149       default:
150         return FALSE;
151     }
152 }
153
154
155 /**********************************************************************
156  *          AccessResource    (KERNEL.64)
157  */
158 int AccessResource( HMODULE hModule, HRSRC hRsrc )
159 {
160     WORD *pModule;
161
162     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
163     dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
164                      hModule, hRsrc );
165     if (!hRsrc) return 0;
166     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
167     switch(*pModule)
168     {
169       case NE_SIGNATURE:
170         return NE_AccessResource( hModule, hRsrc );
171       case PE_SIGNATURE:
172         return 0;
173       default:
174         return 0;
175     }
176 }
177
178
179 /**********************************************************************
180  *          SizeofResource    (KERNEL.65)
181  */
182 DWORD SizeofResource( HMODULE hModule, HRSRC hRsrc )
183 {
184     WORD *pModule;
185
186     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
187     dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
188                      hModule, hRsrc );
189     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
190     switch(*pModule)
191     {
192       case NE_SIGNATURE:
193         return NE_SizeofResource( hModule, hRsrc );
194       case PE_SIGNATURE:
195         return 0;
196       default:
197         return 0;
198     }
199 }
200
201
202 /**********************************************************************
203  *          AllocResource    (KERNEL.66)
204  */
205 HGLOBAL AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
206 {
207     WORD *pModule;
208
209     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
210     dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
211                      hModule, hRsrc, size );
212     if (!hRsrc) return 0;
213     if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
214     switch(*pModule)
215     {
216       case NE_SIGNATURE:
217         return NE_AllocResource( hModule, hRsrc, size );
218       case PE_SIGNATURE:
219         return 0;
220       default:
221         return 0;
222     }
223 }
224
225
226 /**********************************************************************
227  *                      ConvertCoreBitmap
228  */
229 HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image )
230 {
231     BITMAPINFO * bmpInfo;
232     HBITMAP hbitmap;
233     char * bits;
234     int i, size, n_colors;
235    
236     n_colors = 1 << image->bcBitCount;
237     if (image->bcBitCount < 24)
238     {
239         size = sizeof(BITMAPINFOHEADER) + n_colors * sizeof(RGBQUAD);   
240         bits = (char *) (image + 1) + (n_colors * sizeof(RGBTRIPLE));
241     }
242     else
243     {
244         size = sizeof(BITMAPINFOHEADER);
245         bits = (char *) (image + 1);
246     }
247     bmpInfo = (BITMAPINFO *) malloc( size );
248
249     bmpInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
250     bmpInfo->bmiHeader.biWidth         = image->bcWidth;
251     bmpInfo->bmiHeader.biHeight        = image->bcHeight;
252     bmpInfo->bmiHeader.biPlanes        = image->bcPlanes;
253     bmpInfo->bmiHeader.biBitCount      = image->bcBitCount;
254     bmpInfo->bmiHeader.biCompression   = 0;
255     bmpInfo->bmiHeader.biSizeImage     = 0;
256     bmpInfo->bmiHeader.biXPelsPerMeter = 0;
257     bmpInfo->bmiHeader.biYPelsPerMeter = 0;
258     bmpInfo->bmiHeader.biClrUsed       = 0;
259     bmpInfo->bmiHeader.biClrImportant  = 0;
260
261     if (image->bcBitCount < 24)
262     {
263         RGBTRIPLE * oldMap = (RGBTRIPLE *)(image + 1);
264         RGBQUAD * newMap = bmpInfo->bmiColors;
265         for (i = 0; i < n_colors; i++, oldMap++, newMap++)
266         {
267             newMap->rgbRed      = oldMap->rgbtRed;
268             newMap->rgbGreen    = oldMap->rgbtGreen;
269             newMap->rgbBlue     = oldMap->rgbtBlue;
270             newMap->rgbReserved = 0;
271         }
272     }
273
274     hbitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
275                               bits, bmpInfo, DIB_RGB_COLORS );
276     free( bmpInfo );
277     return hbitmap;
278 }
279
280 /**********************************************************************
281  *                      ConvertInfoBitmap
282  */
283 HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image )
284 {
285     char * bits = ((char *)image) + DIB_BitmapInfoSize(image, DIB_RGB_COLORS);
286     return CreateDIBitmap( hdc, &image->bmiHeader, CBM_INIT,
287                            bits, image, DIB_RGB_COLORS );
288
289
290
291 /**********************************************************************
292  *                      LoadIcon [USER.174]
293  */
294 HICON LoadIcon( HANDLE instance, SEGPTR icon_name )
295 {
296     HICON       hIcon;
297     HRSRC       hRsrc;
298     HANDLE      rsc_mem;
299     WORD        *lp;
300     ICONDESCRIP *lpicodesc;
301     ICONALLOC   *lpico;
302     int         width, height;
303     BITMAPINFO  *bmi;
304     BITMAPINFOHEADER    *bih;
305     RGBQUAD     *rgbq;
306     HDC         hdc;
307     BITMAPINFO *pInfo;
308     char *bits;
309     int size;
310
311     if (HIWORD(icon_name))
312         dprintf_resource( stddeb, "LoadIcon: %04x '%s'\n",
313                           instance, (char *)PTR_SEG_TO_LIN( icon_name ) );
314     else
315         dprintf_resource( stddeb, "LoadIcon: %04x %04x\n",
316                           instance, LOWORD(icon_name) );
317     
318     if (!instance)
319     {
320         if (HIWORD((int)icon_name)) return 0; /* FIXME: should handle '#xxx' */
321         return OBM_LoadIcon( LOWORD((int)icon_name) );
322     }
323
324     if (!(hRsrc = FindResource( instance, icon_name, RT_GROUP_ICON))) return 0;
325     rsc_mem = LoadResource( instance, hRsrc );
326     if (rsc_mem == (HANDLE)NULL) {
327         printf("LoadIcon / Icon %08x not Found !\n", (int) icon_name);
328         return 0;
329         }
330     lp = (WORD *)LockResource(rsc_mem);
331     lpicodesc = (ICONDESCRIP *)(lp + 3);
332     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
333     if (hIcon == (HICON)NULL) {
334         FreeResource( rsc_mem );
335         return 0;
336         }
337     lpico = (ICONALLOC *)GlobalLock(hIcon);
338     lpico->descriptor = *lpicodesc;
339     width = lpicodesc->Width;
340     height = lpicodesc->Height;
341     FreeResource( rsc_mem );
342     if (!(hRsrc = FindResource( instance,
343                               MAKEINTRESOURCE(lpico->descriptor.icoDIBOffset), 
344                               RT_ICON ))) return 0;
345     if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
346
347     bmi = (BITMAPINFO *)LockResource(rsc_mem);
348     size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
349     pInfo = (BITMAPINFO *)malloc( size );
350     memcpy( pInfo, bmi, size );
351     bih = &pInfo->bmiHeader;
352     bih->biHeight /= 2;
353
354     if (!(hdc = GetDC( 0 ))) return 0;
355     if (bih->biSize != sizeof(BITMAPINFOHEADER)) return 0;
356     lpico->hBitmap = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
357                                     (char*)bmi + size, pInfo, DIB_RGB_COLORS );
358     if (bih->biSizeImage == 0)
359     {
360         if (bih->biCompression != BI_RGB)
361         {
362             fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
363             FreeResource( rsc_mem );
364             ReleaseDC( 0, hdc); 
365             return 0;
366         }
367         bih->biSizeImage = DIB_GetImageWidthBytes(bih->biWidth,bih->biBitCount)
368                              * bih->biHeight;
369     }
370     bits = (char *)bmi + size +
371              bih->biSizeImage * bih->biBitCount / (bih->biBitCount+1);
372     bih->biBitCount = 1;
373     bih->biClrUsed = bih->biClrImportant = 2;
374     rgbq = &bmi->bmiColors[0];
375     rgbq[0].rgbBlue = rgbq[0].rgbGreen = rgbq[0].rgbRed = 0x00;
376     rgbq[1].rgbBlue = rgbq[1].rgbGreen = rgbq[1].rgbRed = 0xff;
377     rgbq[0].rgbReserved = rgbq[1].rgbReserved = 0;
378     lpico->hBitMask = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT,
379 /*      (LPSTR)bmi + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
380    (LPSTR)lp + bih->biSizeImage + bih->biSize + 4*lpicodesc->ColorCount, */
381                                      bits, pInfo, DIB_RGB_COLORS );
382     FreeResource( rsc_mem );
383     ReleaseDC( 0, hdc);
384     free( pInfo );
385     GlobalUnlock(hIcon);
386     dprintf_resource(stddeb,"LoadIcon Alloc hIcon=%X\n", hIcon);
387     return hIcon;
388 }
389
390
391 /**********************************************************************
392  *                      CreateIcon [USER.407]
393  */
394 HICON CreateIcon(HANDLE hInstance, int nWidth, int nHeight, 
395                  BYTE nPlanes, BYTE nBitsPixel, LPSTR lpANDbits, 
396                  LPSTR lpXORbits)
397 {
398     HICON       hIcon;
399     ICONALLOC   *lpico;
400
401     dprintf_resource(stddeb, "CreateIcon: hInstance = %04x, nWidth = %08x, nHeight = %08x \n",
402             hInstance, nWidth, nHeight);
403     dprintf_resource(stddeb, "  nPlanes = %04x, nBitsPixel = %04x,",nPlanes, nBitsPixel);
404     dprintf_resource(stddeb, " lpANDbits= %04x, lpXORbits = %04x, \n", (int)lpANDbits,
405                 (int)lpXORbits);
406
407     if (hInstance == (HANDLE)NULL) { 
408         printf("CreateIcon / hInstance %04x not Found!\n",hInstance);
409         return 0;
410         }
411     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
412     if (hIcon == (HICON)NULL) {
413         printf("Can't allocate memory for Icon in CreateIcon\n");
414         return 0;
415         }
416     lpico= (ICONALLOC *)GlobalLock(hIcon);
417
418     lpico->descriptor.Width=nWidth;
419     lpico->descriptor.Height=nHeight;
420     lpico->descriptor.ColorCount=16; /* Dummy Value */ 
421     lpico->descriptor.Reserved1=0;
422     lpico->descriptor.Reserved2=nPlanes;
423     lpico->descriptor.Reserved3=nWidth*nHeight;
424
425     /* either nPlanes and/or nBitCount is set to one */
426     lpico->descriptor.icoDIBSize=nWidth*nHeight*nPlanes*nBitsPixel; 
427     lpico->descriptor.icoDIBOffset=0; 
428
429     if( !(lpico->hBitmap=CreateBitmap(nWidth, nHeight, nPlanes, nBitsPixel, 
430                                  lpXORbits)) ) {
431       printf("CreateIcon: couldn't create the XOR bitmap\n");
432       return(0);
433     }
434     
435     /* the AND BitMask is always monochrome */
436     if( !(lpico->hBitMask=CreateBitmap(nWidth, nHeight, 1, 1, lpANDbits)) ) {
437       printf("CreateIcon: couldn't create the AND bitmap\n");
438       return(0);
439     }
440
441     GlobalUnlock(hIcon);
442     dprintf_resource(stddeb, "CreateIcon Alloc hIcon=%X\n", hIcon);
443     return hIcon;
444 }
445 \f
446 /**********************************************************************
447  *                      DestroyIcon [USER.457]
448  */
449 BOOL DestroyIcon(HICON hIcon)
450 {
451     ICONALLOC   *lpico;
452     
453     if (hIcon == (HICON)NULL)
454         return FALSE;
455     lpico = (ICONALLOC *)GlobalLock(hIcon);
456     if (lpico->hBitmap != (HBITMAP)NULL) 
457         DeleteObject(lpico->hBitmap);
458     GlobalFree(hIcon);
459     return TRUE;
460 }
461 \f
462 /**********************************************************************
463  *                      LoadAccelerators        [USER.177]
464  */
465 HANDLE LoadAccelerators(HANDLE instance, SEGPTR lpTableName)
466 {
467     HANDLE      hAccel;
468     HANDLE      rsc_mem;
469     HRSRC hRsrc;
470     BYTE        *lp;
471     ACCELHEADER *lpAccelTbl;
472     int         i, n;
473
474     if (HIWORD(lpTableName))
475         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
476                       instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
477     else
478         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
479                        instance, LOWORD(lpTableName) );
480
481     if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
482       return 0;
483     if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
484
485     lp = (BYTE *)LockResource(rsc_mem);
486     n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
487     hAccel = GlobalAlloc(GMEM_MOVEABLE, 
488         sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
489     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
490     lpAccelTbl->wCount = 0;
491     for (i = 0; i < n; i++) {
492         lpAccelTbl->tbl[i].type = *(lp++);
493         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
494         lp += 2;
495         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
496         lp += 2;
497         if (lpAccelTbl->tbl[i].wEvent == 0) break;
498         dprintf_accel(stddeb,
499                 "Accelerator #%u / event=%04X id=%04X type=%02X \n", 
500                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
501                 lpAccelTbl->tbl[i].type);
502         lpAccelTbl->wCount++;
503         }
504     GlobalUnlock(hAccel);
505     FreeResource( rsc_mem );
506     return hAccel;
507 }
508 \f
509 /**********************************************************************
510  *                      TranslateAccelerator    [USER.178]
511  */
512 int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
513 {
514     ACCELHEADER *lpAccelTbl;
515     int         i;
516     
517     if (hAccel == 0 || msg == NULL) return 0;
518     if (msg->message != WM_KEYDOWN &&
519         msg->message != WM_KEYUP &&
520         msg->message != WM_CHAR) return 0;
521
522     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04X !\n", hAccel);
523
524     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
525     for (i = 0; i < lpAccelTbl->wCount; i++) {
526         if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
527             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
528                 msg->message == WM_KEYDOWN) {
529                 if ((lpAccelTbl->tbl[i].type & SHIFT_ACCEL) &&
530                     !(GetKeyState(VK_SHIFT) & 0xf)) {
531                     GlobalUnlock(hAccel);
532                     return 0;
533                 }
534                 if ((lpAccelTbl->tbl[i].type & CONTROL_ACCEL) &&
535                     !(GetKeyState(VK_CONTROL) & 0xf)) {
536                     GlobalUnlock(hAccel);
537                     return 0;
538                 }
539                 if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) &&
540                     !(GetKeyState(VK_MENU) & 0xf)) {
541                     GlobalUnlock(hAccel);
542                     return 0;
543                 }
544                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
545                 GlobalUnlock(hAccel);
546                 return 1;
547                 }
548             if (msg->message == WM_KEYUP) return 1;
549             }
550         else {
551             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
552                 msg->message == WM_CHAR) {
553                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
554                 GlobalUnlock(hAccel);
555                 return 1;
556                 }
557             }
558         }
559     GlobalUnlock(hAccel);
560     return 0;
561 }
562 \f
563 /**********************************************************************
564  *                                      LoadString
565  */
566 int
567 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
568 {
569     HANDLE hmem, hrsrc;
570     unsigned char *p;
571     int string_num;
572     int i;
573
574     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
575            "length = %d\n", instance, resource_id, (int) buffer, buflen);
576
577     hrsrc = FindResource( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING );
578     if (!hrsrc) return 0;
579     hmem = LoadResource( instance, hrsrc );
580     if (!hmem) return 0;
581     
582     p = LockResource(hmem);
583     string_num = resource_id & 0x000f;
584     for (i = 0; i < string_num; i++)
585         p += *p + 1;
586     
587     i = min(buflen - 1, *p);
588         if (i > 0) {
589                 memcpy(buffer, p + 1, i);
590                 buffer[i] = '\0';
591                 }
592         else {
593                 if (buflen > 1) {
594                         buffer[0] = '\0';
595                         return 0;
596                         }
597                 fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
598                 fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
599                 }
600     FreeResource( hmem );
601
602     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
603     return i;
604 }
605
606
607