Release 950403
[wine] / loader / resource.c
1 /*
2 static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
3 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
4 */
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include "arch.h"
13 #include "windows.h"
14 #include "gdi.h"
15 #include "bitmap.h"
16 #include "neexe.h"
17 #include "icon.h"
18 #include "menu.h"
19 #include "accel.h"
20 #include "dlls.h"
21 #include "resource.h"
22 #include "library.h"
23 #include "stddebug.h"
24 #include "debug.h"
25
26 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
27
28 RESOURCE *Top = NULL;
29
30 extern int NE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
31 extern int PE_FindResource(HANDLE, SEGPTR, SEGPTR, RESOURCE *);
32
33 #define PrintId(name) \
34         if (HIWORD((DWORD)name)) \
35                 printf(", '%s'", (char *)PTR_SEG_TO_LIN(name)); \
36         else \
37                 printf(", #%d", LOWORD(name)); 
38
39 /**********************************************************************
40  *                      FindResource    [KERNEL.60]
41  */
42 HANDLE FindResource(HANDLE instance, SEGPTR name, SEGPTR type)
43 {
44         int status;
45         RESOURCE *r;
46         HANDLE rh;
47
48         if(debugging_resource){
49         printf("FindResource(%04X", instance);
50         PrintId(name);
51         PrintId(type);
52         printf(")\n");
53         }
54         
55         /* FIXME: did we already find this one ? */
56
57         if ((rh = GlobalAlloc(GMEM_MOVEABLE, sizeof(RESOURCE))) == 0)
58                 return 0;
59
60         r = (RESOURCE *)GlobalLock(rh);
61         r->next = Top;
62         Top = r;
63         r->info_mem = rh;
64         r->rsc_mem = 0;
65         r->count = 0;
66         if (HIWORD((DWORD)name))
67                 r->name = strdup(PTR_SEG_TO_LIN(name));
68         else
69                 r->name = (LPSTR)name;
70
71         if (HIWORD((DWORD)type))
72                 r->type = strdup(PTR_SEG_TO_LIN(type));
73         else
74                 r->type = (LPSTR)type;
75
76         r->wpnt = GetFileInfo(instance);
77         r->fd = dup(r->wpnt->fd);
78         if (r->wpnt->ne)
79                 status = NE_FindResource(instance, name, type, r);
80         else
81                 status = PE_FindResource(instance, name, type, r);
82
83         if (!status) {
84                 if (HIWORD((DWORD)r->name))
85                         free(r->name);
86
87                 if (HIWORD((DWORD)r->type))
88                         free(r->type);
89                 close(r->fd);
90
91                 Top = r->next;
92                 GlobalUnlock(rh);
93                 return 0;
94         } else
95                 return rh;
96 }
97
98 /**********************************************************************
99  *                      AllocResource   [KERNEL.66]
100  */
101 HANDLE AllocResource(HANDLE instance, HANDLE hResInfo, DWORD dwSize)
102 {
103         RESOURCE *r;
104         int image_size;
105
106         dprintf_resource(stddeb, "AllocResource(%04X, %04X, %08X);\n", 
107                 instance, hResInfo, (int) dwSize);
108
109         if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
110                 return 0;
111     
112         image_size = r->size;
113
114         if (dwSize == 0)
115                 r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
116         else
117                 r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, dwSize);
118
119         GlobalUnlock(hResInfo);
120
121         return r->rsc_mem;
122 }
123 \f
124 /**********************************************************************
125  *                              AccessResource  [KERNEL.64]
126  */
127 int AccessResource(HANDLE instance, HANDLE hResInfo)
128 {
129         int fd;
130         RESOURCE *r;
131
132         dprintf_resource(stddeb, "AccessResource(%04X, %04X);\n", 
133                 instance, hResInfo);
134
135         if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
136                 return -1;
137
138         fd = r->fd;
139         lseek(fd, r->offset, SEEK_SET);
140         GlobalUnlock(hResInfo);
141
142         return fd;
143 }
144 \f
145 /**********************************************************************
146  *                              SizeofResource  [KERNEL.65]
147  */
148 WORD SizeofResource(HANDLE instance, HANDLE hResInfo)
149 {
150         RESOURCE *r;
151         int size;
152         
153         dprintf_resource(stddeb, "SizeofResource(%04X, %04X);\n", 
154                 instance, hResInfo);
155
156         if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
157                 return 0;
158
159         size = r->size;
160         GlobalUnlock(hResInfo);
161
162         return size;
163 }
164
165 /**********************************************************************
166  *                      LoadResource    [KERNEL.61]
167  */
168 HANDLE LoadResource(HANDLE instance, HANDLE hResInfo)
169 {
170     RESOURCE *r;
171     int image_size, fd;
172     void *image;
173     HANDLE h;
174
175     dprintf_resource(stddeb, "LoadResource(%04X, %04X);\n", instance, hResInfo);
176
177     if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
178         return 0;
179     
180     h = r->rsc_mem = AllocResource(instance, hResInfo, 0);
181     image = GlobalLock(h);
182     image_size = r->size;
183     fd = AccessResource(instance, hResInfo);
184
185     if (image == NULL || read(fd, image, image_size) != image_size) {
186         GlobalFree(h);
187         GlobalUnlock(hResInfo);
188         return 0;
189     }
190     r->count++;
191     close(fd);
192     GlobalUnlock(h);
193     GlobalUnlock(hResInfo);
194     return h;
195 }
196
197 /**********************************************************************
198  *                              LockResource    [KERNEL.62]
199  */
200
201 /* 16-bit version */
202 SEGPTR WIN16_LockResource(HANDLE hResData)
203 {
204     return WIN16_GlobalLock(hResData);
205 }
206
207 /* 32-bit version */
208 LPSTR LockResource(HANDLE hResData)
209 {
210     return GlobalLock(hResData);
211 }
212
213 /**********************************************************************
214  *                              FreeResource    [KERNEL.63]
215  */
216 HANDLE FreeResource(HANDLE hResData)
217 {
218     RESOURCE *r, *rp;
219
220     dprintf_resource(stddeb, "FreeResource: handle %04x\n", hResData);
221
222     for (r = rp = Top; r ; r = r->next) {
223         if (r->rsc_mem == hResData) {
224             if (r->count == 0) {
225                     if (rp != r)
226                         rp->next = r->next;
227                     else
228                         Top = r->next;
229
230                     if (HIWORD((DWORD)r->name))
231                         free(r->name);
232                     if (HIWORD((DWORD)r->type))
233                         free(r->type);
234                     GlobalFree(r->rsc_mem);
235                     GlobalFree(r->info_mem);
236                     return 0;
237             } else
238                 r->count--;
239         }
240         rp = r;
241     }
242     return hResData;
243 }
244 \f
245 /**********************************************************************
246  *                      ConvertCoreBitmap
247  */
248 HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image )
249 {
250     BITMAPINFO * bmpInfo;
251     HBITMAP hbitmap;
252     char * bits;
253     int i, size, n_colors;
254    
255     n_colors = 1 << image->bcBitCount;
256     if (image->bcBitCount < 24)
257     {
258         size = sizeof(BITMAPINFOHEADER) + n_colors * sizeof(RGBQUAD);   
259         bits = (char *) (image + 1) + (n_colors * sizeof(RGBTRIPLE));
260     }
261     else
262     {
263         size = sizeof(BITMAPINFOHEADER);
264         bits = (char *) (image + 1);
265     }
266     bmpInfo = (BITMAPINFO *) malloc( size );
267
268     bmpInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
269     bmpInfo->bmiHeader.biWidth         = image->bcWidth;
270     bmpInfo->bmiHeader.biHeight        = image->bcHeight;
271     bmpInfo->bmiHeader.biPlanes        = image->bcPlanes;
272     bmpInfo->bmiHeader.biBitCount      = image->bcBitCount;
273     bmpInfo->bmiHeader.biCompression   = 0;
274     bmpInfo->bmiHeader.biSizeImage     = 0;
275     bmpInfo->bmiHeader.biXPelsPerMeter = 0;
276     bmpInfo->bmiHeader.biYPelsPerMeter = 0;
277     bmpInfo->bmiHeader.biClrUsed       = 0;
278     bmpInfo->bmiHeader.biClrImportant  = 0;
279
280     if (image->bcBitCount < 24)
281     {
282         RGBTRIPLE * oldMap = (RGBTRIPLE *)(image + 1);
283         RGBQUAD * newMap = bmpInfo->bmiColors;
284         for (i = 0; i < n_colors; i++, oldMap++, newMap++)
285         {
286             newMap->rgbRed      = oldMap->rgbtRed;
287             newMap->rgbGreen    = oldMap->rgbtGreen;
288             newMap->rgbBlue     = oldMap->rgbtBlue;
289             newMap->rgbReserved = 0;
290         }
291     }
292
293     hbitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
294                               bits, bmpInfo, DIB_RGB_COLORS );
295     free( bmpInfo );
296     return hbitmap;
297 }
298
299 /**********************************************************************
300  *                      ConvertInfoBitmap
301  */
302 HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image )
303 {
304     char * bits = ((char *)image) + DIB_BitmapInfoSize(image, DIB_RGB_COLORS);
305     return CreateDIBitmap( hdc, &image->bmiHeader, CBM_INIT,
306                            bits, image, DIB_RGB_COLORS );
307
308
309 /**********************************************************************
310  *                      RSC_LoadResource
311  */
312 HANDLE
313 RSC_LoadResource(int instance, SEGPTR rsc_name, SEGPTR type, int *image_size_ret)
314 {
315         HANDLE hResInfo;
316         RESOURCE *r;
317
318         dprintf_resource(stddeb, "RSC_LoadResource: instance = %04x, name = %08lx, type = %08lx\n",
319            instance, rsc_name, type);
320
321         if ((hResInfo = FindResource(instance, rsc_name, type)) == (HANDLE) NULL) {
322                 return (HANDLE)NULL;
323         }
324         r = (RESOURCE *)GlobalLock(hResInfo);
325         if (image_size_ret) 
326                 *image_size_ret = r->size;
327         r->count++;
328         GlobalUnlock(hResInfo);
329         return LoadResource(instance, hResInfo);
330 }
331 \f
332 /**********************************************************************
333  *                      LoadIcon [USER.174]
334  */
335 HICON LoadIcon( HANDLE instance, SEGPTR icon_name )
336 {
337     HICON       hIcon;
338     HANDLE      rsc_mem;
339     WORD        *lp;
340     ICONDESCRIP *lpicodesc;
341     ICONALLOC   *lpico;
342     int         width, height;
343     BITMAPINFO  *bmi;
344     BITMAPINFOHEADER    *bih;
345     RGBQUAD     *rgbq;
346     HDC         hdc;
347     int         image_size;
348
349     if (HIWORD(icon_name))
350         dprintf_resource( stddeb, "LoadIcon: %04x '%s'\n",
351                           instance, (char *)PTR_SEG_TO_LIN( icon_name ) );
352     else
353         dprintf_resource( stddeb, "LoadIcon: %04x %04x\n",
354                           instance, LOWORD(icon_name) );
355     
356     if (!instance)
357     {
358         if (HIWORD((int)icon_name)) return 0; /* FIXME: should handle '#xxx' */
359         return OBM_LoadIcon( LOWORD((int)icon_name) );
360     }
361
362     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
363     rsc_mem = RSC_LoadResource(instance, icon_name,
364                                (SEGPTR) NE_RSCTYPE_GROUP_ICON, &image_size);
365     if (rsc_mem == (HANDLE)NULL) {
366         printf("LoadIcon / Icon %08x not Found !\n", (int) icon_name);
367         ReleaseDC(GetDesktopWindow(), hdc); 
368         return 0;
369         }
370     lp = (WORD *)GlobalLock(rsc_mem);
371     if (lp == NULL) {
372         GlobalFree(rsc_mem);
373         ReleaseDC(GetDesktopWindow(), hdc); 
374         return 0;
375         }
376     lpicodesc = (ICONDESCRIP *)(lp + 3);
377     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
378     if (hIcon == (HICON)NULL) {
379         GlobalFree(rsc_mem);
380         ReleaseDC(GetDesktopWindow(), hdc); 
381         return 0;
382         }
383     lpico = (ICONALLOC *)GlobalLock(hIcon);
384     lpico->descriptor = *lpicodesc;
385     width = lpicodesc->Width;
386     height = lpicodesc->Height;
387     GlobalUnlock(rsc_mem);
388     GlobalFree(rsc_mem);
389     rsc_mem = RSC_LoadResource( instance, 
390                                 MAKEINTRESOURCE(lpicodesc->icoDIBOffset), 
391                                 (SEGPTR) NE_RSCTYPE_ICON, &image_size );
392     if (rsc_mem == (HANDLE)NULL) {
393         printf("LoadIcon / Icon %08lx Bitmaps not Found !\n", icon_name );
394         ReleaseDC(GetDesktopWindow(), hdc); 
395         return 0;
396         }
397     lp = (WORD *)GlobalLock(rsc_mem);
398     if (lp == NULL) {
399         GlobalFree(rsc_mem);
400         ReleaseDC(GetDesktopWindow(), hdc); 
401         return 0;
402         }
403     bmi = (BITMAPINFO *)lp;
404     bih = (BITMAPINFOHEADER *)lp;
405     rgbq = &bmi->bmiColors[0];
406     bih->biHeight = bih->biHeight / 2;
407 /*
408     printf("LoadIcon / image_size=%d width=%d height=%d bih->biBitCount=%d bih->biSizeImage=%ld\n", 
409         image_size, width, height, bih->biBitCount, bih->biSizeImage);
410 */
411     if (bih->biSize == sizeof(BITMAPINFOHEADER))
412         lpico->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)bih);
413     else
414         lpico->hBitmap = 0;
415     bih->biBitCount = 1;
416     bih->biClrUsed = bih->biClrImportant  = 2;
417     rgbq[0].rgbBlue = rgbq[0].rgbGreen = rgbq[0].rgbRed = 0x00;
418     rgbq[1].rgbBlue = rgbq[1].rgbGreen = rgbq[1].rgbRed = 0xff;
419     rgbq[0].rgbReserved = rgbq[1].rgbReserved = 0;
420     if (bih->biSizeImage == 0) {
421         if (bih->biCompression != BI_RGB) {
422             fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
423             GlobalFree(rsc_mem);
424             ReleaseDC(GetDesktopWindow(), hdc); 
425             return 0;
426             }
427         bih->biSizeImage = (bih->biWidth * bih->biHeight * bih->biBitCount
428                             + 7) / 8;
429         }
430     lpico->hBitMask = CreateDIBitmap(hdc, bih, CBM_INIT,
431         (LPSTR)lp + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
432         (BITMAPINFO *)bih, DIB_RGB_COLORS );
433     GlobalUnlock(rsc_mem);
434     GlobalFree(rsc_mem);
435     ReleaseDC(GetDesktopWindow(), hdc);
436     GlobalUnlock(hIcon);
437     dprintf_resource(stddeb,"LoadIcon Alloc hIcon=%X\n", hIcon);
438     return hIcon;
439 }
440 \f
441 /**********************************************************************
442  *                      CreateIcon [USER.407]
443  */
444 HICON CreateIcon(HANDLE hInstance, int nWidth, int nHeight, 
445                  BYTE nPlanes, BYTE nBitsPixel, LPSTR lpANDbits, 
446                  LPSTR lpXORbits)
447 {
448     HICON       hIcon;
449     ICONALLOC   *lpico;
450
451     dprintf_resource(stddeb, "CreateIcon: hInstance = %04x, nWidth = %08x, nHeight = %08x \n",
452             hInstance, nWidth, nHeight);
453     dprintf_resource(stddeb, "  nPlanes = %04x, nBitsPixel = %04x,",nPlanes, nBitsPixel);
454     dprintf_resource(stddeb, " lpANDbits= %04x, lpXORbits = %04x, \n", (int)lpANDbits,
455                 (int)lpXORbits);
456
457     if (hInstance == (HANDLE)NULL) { 
458         printf("CreateIcon / hInstance %04x not Found!\n",hInstance);
459         return 0;
460         }
461     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
462     if (hIcon == (HICON)NULL) {
463         printf("Can't allocate memory for Icon in CreateIcon\n");
464         return 0;
465         }
466     lpico= (ICONALLOC *)GlobalLock(hIcon);
467
468     lpico->descriptor.Width=nWidth;
469     lpico->descriptor.Height=nHeight;
470     lpico->descriptor.ColorCount=16; /* Dummy Value */ 
471     lpico->descriptor.Reserved1=0;
472     lpico->descriptor.Reserved2=nPlanes;
473     lpico->descriptor.Reserved3=nWidth*nHeight;
474
475     /* either nPlanes and/or nBitCount is set to one */
476     lpico->descriptor.icoDIBSize=nWidth*nHeight*nPlanes*nBitsPixel; 
477     lpico->descriptor.icoDIBOffset=0; 
478
479     if( !(lpico->hBitmap=CreateBitmap(nWidth, nHeight, nPlanes, nBitsPixel, 
480                                  lpXORbits)) ) {
481       printf("CreateIcon: couldn't create the XOR bitmap\n");
482       return(0);
483     }
484     
485     /* the AND BitMask is always monochrome */
486     if( !(lpico->hBitMask=CreateBitmap(nWidth, nHeight, 1, 1, lpANDbits)) ) {
487       printf("CreateIcon: couldn't create the AND bitmap\n");
488       return(0);
489     }
490
491     GlobalUnlock(hIcon);
492     dprintf_resource(stddeb, "CreateIcon Alloc hIcon=%X\n", hIcon);
493     return hIcon;
494 }
495 \f
496 /**********************************************************************
497  *                      DestroyIcon [USER.457]
498  */
499 BOOL DestroyIcon(HICON hIcon)
500 {
501     ICONALLOC   *lpico;
502     
503     if (hIcon == (HICON)NULL)
504         return FALSE;
505     lpico = (ICONALLOC *)GlobalLock(hIcon);
506     if (lpico->hBitmap != (HBITMAP)NULL) 
507         DeleteObject(lpico->hBitmap);
508     GlobalFree(hIcon);
509     return TRUE;
510 }
511 \f
512 /**********************************************************************
513  *                      LoadAccelerators        [USER.177]
514  */
515 HANDLE LoadAccelerators(HANDLE instance, SEGPTR lpTableName)
516 {
517     HANDLE      hAccel;
518     HANDLE      rsc_mem;
519     BYTE        *lp;
520     ACCELHEADER *lpAccelTbl;
521     int         i, image_size, n;
522
523     if (HIWORD(lpTableName))
524         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
525                       instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
526     else
527         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
528                        instance, LOWORD(lpTableName) );
529
530     rsc_mem = RSC_LoadResource( instance, lpTableName,
531                                 (SEGPTR) NE_RSCTYPE_ACCELERATOR, &image_size );
532     if (rsc_mem == (HANDLE)NULL) {
533         printf("LoadAccelerators(%08lx) not found!\n", lpTableName );
534         return 0;
535         }
536     lp = (BYTE *)GlobalLock(rsc_mem);
537     if (lp == NULL) {
538         GlobalFree(rsc_mem);
539         return 0;
540         }
541     dprintf_accel(stddeb,"LoadAccelerators / image_size=%d\n", image_size);
542     n = image_size/5;
543     hAccel = GlobalAlloc(GMEM_MOVEABLE, 
544         sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
545     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
546     lpAccelTbl->wCount = 0;
547     for (i = 0; i < n; i++) {
548         lpAccelTbl->tbl[i].type = *(lp++);
549         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
550         lp += 2;
551         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
552         lp += 2;
553         if (lpAccelTbl->tbl[i].wEvent == 0) break;
554         dprintf_accel(stddeb,
555                 "Accelerator #%u / event=%04X id=%04X type=%02X \n", 
556                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
557                 lpAccelTbl->tbl[i].type);
558         lpAccelTbl->wCount++;
559         }
560     GlobalUnlock(hAccel);
561     GlobalUnlock(rsc_mem);
562     GlobalFree(rsc_mem);
563     return hAccel;
564 }
565 \f
566 /**********************************************************************
567  *                      TranslateAccelerator    [USER.178]
568  */
569 int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
570 {
571     ACCELHEADER *lpAccelTbl;
572     int         i;
573     
574     if (hAccel == 0 || msg == NULL) return 0;
575     if (msg->message != WM_KEYDOWN &&
576         msg->message != WM_KEYUP &&
577         msg->message != WM_CHAR) return 0;
578
579     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04X !\n", hAccel);
580
581     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
582     for (i = 0; i < lpAccelTbl->wCount; i++) {
583         if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
584             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
585                 msg->message == WM_KEYDOWN) {
586                 if ((lpAccelTbl->tbl[i].type & SHIFT_ACCEL) &&
587                     !(GetKeyState(VK_SHIFT) & 0xf)) {
588                     GlobalUnlock(hAccel);
589                     return 0;
590                 }
591                 if ((lpAccelTbl->tbl[i].type & CONTROL_ACCEL) &&
592                     !(GetKeyState(VK_CONTROL) & 0xf)) {
593                     GlobalUnlock(hAccel);
594                     return 0;
595                 }
596                 if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) &&
597                     !(GetKeyState(VK_MENU) & 0xf)) {
598                     GlobalUnlock(hAccel);
599                     return 0;
600                 }
601                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
602                 GlobalUnlock(hAccel);
603                 return 1;
604                 }
605             if (msg->message == WM_KEYUP) return 1;
606             }
607         else {
608             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
609                 msg->message == WM_CHAR) {
610                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
611                 GlobalUnlock(hAccel);
612                 return 1;
613                 }
614             }
615         }
616     GlobalUnlock(hAccel);
617     return 0;
618 }
619 \f
620 /**********************************************************************
621  *                                      LoadString
622  */
623 int
624 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
625 {
626     HANDLE hmem, hrsrc;
627     unsigned char *p;
628     int string_num;
629     int i;
630
631     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
632            "length = %d\n", instance, resource_id, (int) buffer, buflen);
633
634     hrsrc = FindResource( instance, (SEGPTR)((resource_id >> 4) + 1),
635                           (SEGPTR) NE_RSCTYPE_STRING );
636     if (!hrsrc) return 0;
637     hmem = LoadResource( instance, hrsrc );
638     if (!hmem) return 0;
639     
640     p = GlobalLock(hmem);
641     string_num = resource_id & 0x000f;
642     for (i = 0; i < string_num; i++)
643         p += *p + 1;
644     
645     i = MIN(buflen - 1, *p);
646         if (i > 0) {
647                 memcpy(buffer, p + 1, i);
648                 buffer[i] = '\0';
649                 }
650         else {
651                 if (buflen > 1) {
652                         buffer[0] = '\0';
653                         return 0;
654                         }
655                 fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
656                 fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
657                 }
658     FreeResource( hrsrc );
659
660     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
661     return i;
662 }
663 \f
664 /**********************************************************************
665  *                      LoadMenu                [USER.150]
666  */
667 HMENU LoadMenu( HINSTANCE instance, SEGPTR menu_name )
668 {
669     HMENU               hMenu;
670     HANDLE              hMenu_desc;
671     MENU_HEADER         *menu_desc;
672
673     if (HIWORD(menu_name))
674         dprintf_resource( stddeb, "LoadMenu(%04x,'%s')\n",
675                           instance, (char *)PTR_SEG_TO_LIN( menu_name ) );
676     else
677         dprintf_resource( stddeb, "LoadMenu(%04x,%04x)\n",
678                           instance, LOWORD(menu_name) );
679
680     if (!menu_name) return 0;
681
682     if (!(hMenu_desc = RSC_LoadResource( instance, menu_name,
683                                          (SEGPTR) NE_RSCTYPE_MENU, NULL )))
684         return 0;
685         
686     menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc);
687     hMenu = LoadMenuIndirect((LPSTR)menu_desc);
688     return hMenu;
689 }
690 \f
691 /**********************************************************************
692  *                                      LoadBitmap
693  */
694 HBITMAP LoadBitmap( HANDLE instance, SEGPTR bmp_name )
695 {
696     HBITMAP hbitmap;
697     HANDLE rsc_mem;
698     HDC hdc;
699     long *lp;
700     int image_size;
701     int size;
702     
703     if (HIWORD(bmp_name))
704         dprintf_resource( stddeb, "LoadBitmap(%04x,'%s')\n",
705                           instance, (char *)PTR_SEG_TO_LIN( bmp_name ) );
706     else
707         dprintf_resource( stddeb, "LoadBitmap(%04x,%04x)\n",
708                           instance, LOWORD( bmp_name ) );
709
710     if (!instance)
711     {
712         if (HIWORD((int)bmp_name)) return 0;  /* FIXME: should handle '#xxx' */
713         return OBM_LoadBitmap( LOWORD((int)bmp_name) );
714     }
715
716     rsc_mem = RSC_LoadResource(instance, bmp_name, (SEGPTR) NE_RSCTYPE_BITMAP, 
717                                &image_size);
718     if (rsc_mem == (HANDLE)NULL) {
719         printf("LoadBitmap(%04x,%08lx)\n", instance, bmp_name);
720         return 0;
721         }
722     lp = (long *) GlobalLock(rsc_mem);
723     if (lp == NULL)
724     {
725         GlobalFree(rsc_mem);
726         return 0;
727     }
728
729     if (!(hdc = GetDC(0))) lp = NULL;
730     size = CONV_LONG (*lp);
731     if (size == sizeof(BITMAPCOREHEADER)){
732         CONV_BITMAPCOREHEADER (lp);
733         hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
734     } else if (size == sizeof(BITMAPINFOHEADER)){
735         CONV_BITMAPINFO (lp);
736         hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
737     } else hbitmap = 0;
738     GlobalFree(rsc_mem);
739     ReleaseDC( 0, hdc );
740     return hbitmap;
741 }