Release 940201
[wine] / loader / resource.c
1 static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
2 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
3
4 #include <X11/Intrinsic.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include "prototypes.h"
12 #include "windows.h"
13 #include "win.h"
14 #include "gdi.h"
15 #include "wine.h"
16 #include "icon.h"
17 #include "accel.h"
18
19 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
20
21 typedef struct resource_s
22 {
23     struct resource_s *next;
24     HANDLE info_mem;
25     int size_shift;
26     struct resource_nameinfo_s nameinfo;
27     HANDLE rsc_mem;
28 } RESOURCE;
29
30 static int ResourceFd = -1;
31 static HANDLE ResourceInst = 0;
32 static struct w_files *ResourceFileInfo = NULL;
33 static RESOURCE *Top = NULL;
34 extern HINSTANCE hSysRes;
35
36 HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret);
37
38 \f
39 /**********************************************************************
40  *                                      OpenResourceFile
41  */
42 int
43 OpenResourceFile(HANDLE instance)
44 {
45     struct w_files *w;
46     
47     if (ResourceInst == instance)
48         return ResourceFd;
49     
50     w = GetFileInfo(instance);
51     if (w == NULL)
52         return -1;
53     
54     if (ResourceFd >= 0)
55         close(ResourceFd);
56     
57     ResourceInst = instance;
58     ResourceFileInfo = w;
59     ResourceFd = open(w->filename, O_RDONLY);
60     
61     return ResourceFd;
62 }
63 \f
64 /**********************************************************************
65  *                                      ConvertCoreBitmap
66  */
67 HBITMAP
68 ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image )
69 {
70     BITMAPINFO * bmpInfo;
71     HBITMAP hbitmap;
72     char * bits;
73     int i, size, n_colors;
74     
75     n_colors = 1 << image->bcBitCount;
76
77     if (image->bcBitCount < 24)
78     {
79         size = sizeof(BITMAPINFOHEADER) + n_colors * sizeof(RGBQUAD);   
80         bits = (char *) (image + 1) + (n_colors * sizeof(RGBTRIPLE));
81     }
82     else
83     {
84         size = sizeof(BITMAPINFOHEADER);
85         bits = (char *) (image + 1);
86     }
87     bmpInfo = (BITMAPINFO *) malloc( size );
88
89     bmpInfo->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
90     bmpInfo->bmiHeader.biWidth         = image->bcWidth;
91     bmpInfo->bmiHeader.biHeight        = image->bcHeight;
92     bmpInfo->bmiHeader.biPlanes        = image->bcPlanes;
93     bmpInfo->bmiHeader.biBitCount      = image->bcBitCount;
94     bmpInfo->bmiHeader.biCompression   = 0;
95     bmpInfo->bmiHeader.biSizeImage     = 0;
96     bmpInfo->bmiHeader.biXPelsPerMeter = 0;
97     bmpInfo->bmiHeader.biYPelsPerMeter = 0;
98     bmpInfo->bmiHeader.biClrUsed       = 0;
99     bmpInfo->bmiHeader.biClrImportant  = 0;
100
101     if (image->bcBitCount < 24)
102     {
103         RGBTRIPLE * oldMap = (RGBTRIPLE *)(image + 1);
104         RGBQUAD * newMap = bmpInfo->bmiColors;
105         for (i = 0; i < n_colors; i++, oldMap++, newMap++)
106         {
107             newMap->rgbRed      = oldMap->rgbtRed;
108             newMap->rgbGreen    = oldMap->rgbtGreen;
109             newMap->rgbBlue     = oldMap->rgbtBlue;
110             newMap->rgbReserved = 0;
111         }
112     }
113
114     hbitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
115                               bits, bmpInfo, DIB_RGB_COLORS );
116     free( bmpInfo );
117     return hbitmap;
118 }
119
120 /**********************************************************************
121  *                                      ConvertInfoBitmap
122  */
123 HBITMAP
124 ConvertInfoBitmap( HDC hdc, BITMAPINFO * image )
125 {
126     char * bits = ((char *)image) + DIB_BitmapInfoSize(image, DIB_RGB_COLORS);
127     return CreateDIBitmap( hdc, &image->bmiHeader, CBM_INIT,
128                            bits, image, DIB_RGB_COLORS );
129
130 \f
131 /**********************************************************************
132  *                                      FindResourceByNumber
133  */
134 int
135 FindResourceByNumber(struct resource_nameinfo_s *result_p,
136                      int type_id, int resource_id)
137 {
138     struct resource_typeinfo_s typeinfo;
139     struct resource_nameinfo_s nameinfo;
140     unsigned short size_shift;
141     int i;
142     off_t rtoff;
143
144     /*
145      * Move to beginning of resource table.
146      */
147     rtoff = (ResourceFileInfo->mz_header->ne_offset +
148              ResourceFileInfo->ne_header->resource_tab_offset);
149     lseek(ResourceFd, rtoff, SEEK_SET);
150     
151     /*
152      * Read block size.
153      */
154     if (read(ResourceFd, &size_shift, sizeof(size_shift)) != 
155         sizeof(size_shift))
156     {
157         printf("FindResourceByNumber (%s) bad block size !\n", resource_id);
158         return -1;
159     }
160     
161     /*
162      * Find resource.
163      */
164     typeinfo.type_id = 0xffff;
165     while (typeinfo.type_id != 0) {
166         if (read(ResourceFd, &typeinfo, sizeof(typeinfo)) !=
167             sizeof(typeinfo)) {
168             printf("FindResourceByNumber (%X) bad typeinfo size !\n", resource_id);
169             return -1;
170             }
171 #ifdef DEBUG_RESOURCE
172         printf("FindResourceByNumber type=%X count=%d\n", 
173                         typeinfo.type_id, typeinfo.count);
174 #endif
175         if (typeinfo.type_id == 0) break;
176         if (typeinfo.type_id == type_id || type_id == -1) {
177             for (i = 0; i < typeinfo.count; i++) {
178                 if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) != 
179                     sizeof(nameinfo)) {
180                     printf("FindResourceByNumber (%X) bad nameinfo size !\n", resource_id);
181                     return -1;
182                     }
183 #ifdef DEBUG_RESOURCE
184                 printf("FindResource: search type=%X id=%X // type=%X id=%X\n",
185                         type_id, resource_id, typeinfo.type_id, nameinfo.id);
186 #endif
187                 if (nameinfo.id == resource_id) {
188                     memcpy(result_p, &nameinfo, sizeof(nameinfo));
189                     return size_shift;
190                     }
191                 }
192             }
193         else {
194             lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
195             }
196         }
197     return -1;
198 }
199 \f
200 /**********************************************************************
201  *                                      FindResourceByName
202  */
203 int
204 FindResourceByName(struct resource_nameinfo_s *result_p,
205                      int type_id, char *resource_name)
206 {
207     struct resource_typeinfo_s typeinfo;
208     struct resource_nameinfo_s nameinfo;
209     unsigned short size_shift;
210     off_t old_pos, new_pos;
211     unsigned char nbytes;
212     char name[256];
213     int i;
214     off_t rtoff;
215
216     /*
217      * Move to beginning of resource table.
218      */
219     rtoff = (ResourceFileInfo->mz_header->ne_offset +
220              ResourceFileInfo->ne_header->resource_tab_offset);
221     lseek(ResourceFd, rtoff, SEEK_SET);
222     
223     /*
224      * Read block size.
225      */
226     if (read(ResourceFd, &size_shift, sizeof(size_shift)) != 
227         sizeof(size_shift))
228     {
229         printf("FindResourceByName (%s) bad block size !\n", resource_name);
230         return -1;
231     }
232     
233     /*
234      * Find resource.
235      */
236     typeinfo.type_id = 0xffff;
237     while (typeinfo.type_id != 0)
238     {
239         if (read(ResourceFd, &typeinfo, sizeof(typeinfo)) !=
240             sizeof(typeinfo))
241         {
242             printf("FindResourceByName (%s) bad typeinfo size !\n", resource_name);
243             return -1;
244         }
245 #ifdef DEBUG_RESOURCE
246         printf("FindResourceByName typeinfo.type_id=%X type_id=%X\n",
247                         typeinfo.type_id, type_id);
248 #endif
249         if (typeinfo.type_id == 0) break;
250         if (typeinfo.type_id == type_id || type_id == -1)
251         {
252             for (i = 0; i < typeinfo.count; i++)
253             {
254                 if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) != 
255                     sizeof(nameinfo))
256                 {
257                     printf("FindResourceByName (%s) bad nameinfo size !\n", resource_name);
258                     return -1;
259                 }
260
261                 if (nameinfo.id & 0x8000)
262                     continue;
263                 
264                 old_pos = lseek(ResourceFd, 0, SEEK_CUR);
265                 new_pos = rtoff + nameinfo.id;
266                 lseek(ResourceFd, new_pos, SEEK_SET);
267                 read(ResourceFd, &nbytes, 1);
268                 read(ResourceFd, name, nbytes);
269                 lseek(ResourceFd, old_pos, SEEK_SET);
270                 name[nbytes] = '\0';
271 #ifdef DEBUG_RESOURCE
272                 printf("FindResourceByName type_id=%X name='%s' resource_name='%s'\n", 
273                                 typeinfo.type_id, name, resource_name);
274 #endif
275                 if (strcasecmp(name, resource_name) == 0)
276                 {
277                     memcpy(result_p, &nameinfo, sizeof(nameinfo));
278                     return size_shift;
279                 }
280             }
281         }
282         else {
283             lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
284             }
285     }
286     return -1;
287 }
288
289
290 /**********************************************************************
291  *                      LoadIcon [USER.174]
292  */
293 HICON LoadIcon(HANDLE instance, LPSTR icon_name)
294 {
295     HICON       hIcon;
296     HANDLE      rsc_mem;
297     WORD        *lp;
298     ICONDESCRIP *lpicodesc;
299     ICONALLOC   *lpico;
300     int         width, height;
301     BITMAPINFO  *bmi;
302     BITMAPINFOHEADER    *bih;
303     RGBQUAD     *rgbq;
304     HBITMAP     hBitMap;
305     HDC         hMemDC;
306     HDC         hMemDC2;
307     HDC         hdc;
308     int         i, j, image_size;
309 #ifdef DEBUG_RESOURCE
310     printf("LoadIcon: instance = %04x, name = %08x\n",
311            instance, icon_name);
312 #endif
313     
314     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
315     if (instance == (HANDLE)NULL)  instance = hSysRes;
316     rsc_mem = RSC_LoadResource(instance, icon_name, NE_RSCTYPE_GROUP_ICON, 
317                                &image_size);
318     if (rsc_mem == (HANDLE)NULL) {
319         printf("LoadIcon / Icon %04X not Found !\n", icon_name);
320         ReleaseDC(GetDesktopWindow(), hdc); 
321         return 0;
322         }
323     lp = (WORD *)GlobalLock(rsc_mem);
324     if (lp == NULL) {
325         GlobalFree(rsc_mem);
326         ReleaseDC(GetDesktopWindow(), hdc); 
327         return 0;
328         }
329     lpicodesc = (ICONDESCRIP *)(lp + 3);
330     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
331     if (hIcon == (HICON)NULL) {
332         GlobalFree(rsc_mem);
333         ReleaseDC(GetDesktopWindow(), hdc); 
334         return 0;
335         }
336     printf("LoadIcon Alloc hIcon=%X\n", hIcon);
337     lpico = (ICONALLOC *)GlobalLock(hIcon);
338     lpico->descriptor = *lpicodesc;
339     width = lpicodesc->Width;
340     height = lpicodesc->Height;
341     GlobalUnlock(rsc_mem);
342     GlobalFree(rsc_mem);
343     rsc_mem = RSC_LoadResource(instance, 
344         MAKEINTRESOURCE(lpicodesc->icoDIBOffset), 
345         NE_RSCTYPE_ICON, &image_size);
346     if (rsc_mem == (HANDLE)NULL) {
347         printf("LoadIcon / Icon %04X Bitmaps not Found !\n", icon_name);
348         ReleaseDC(GetDesktopWindow(), hdc); 
349         return 0;
350         }
351     lp = (WORD *)GlobalLock(rsc_mem);
352     if (lp == NULL) {
353         GlobalFree(rsc_mem);
354         ReleaseDC(GetDesktopWindow(), hdc); 
355         return 0;
356         }
357     bmi = (BITMAPINFO *)lp;
358     bih = (BITMAPINFOHEADER *)lp;
359     rgbq = &bmi->bmiColors[0];
360     bih->biHeight = bih->biHeight / 2;
361 /*
362     printf("LoadIcon / image_size=%d width=%d height=%d bih->biBitCount=%d bih->biSizeImage=%ld\n", 
363         image_size, width, height, bih->biBitCount, bih->biSizeImage);
364 */
365     if (bih->biSize == sizeof(BITMAPINFOHEADER))
366         lpico->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)bih);
367     else
368         lpico->hBitmap = 0;
369     bih->biBitCount = 1;
370     bih->biClrUsed = bih->biClrImportant  = 2;
371     rgbq[0].rgbBlue     = 0xFF;
372     rgbq[0].rgbGreen    = 0xFF;
373     rgbq[0].rgbRed      = 0xFF;
374     rgbq[0].rgbReserved = 0x00;
375     rgbq[1].rgbBlue     = 0x00;
376     rgbq[1].rgbGreen    = 0x00;
377     rgbq[1].rgbRed      = 0x00;
378     rgbq[1].rgbReserved = 0x00;
379     lpico->hBitMask = CreateDIBitmap(hdc, bih, CBM_INIT,
380         (LPSTR)lp + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
381         (BITMAPINFO *)bih, DIB_RGB_COLORS );
382     GlobalUnlock(rsc_mem);
383     GlobalFree(rsc_mem);
384     hMemDC = CreateCompatibleDC(hdc);
385     hMemDC2 = CreateCompatibleDC(hdc);
386     SelectObject(hMemDC, lpico->hBitmap);
387     SelectObject(hMemDC2, lpico->hBitMask);
388     BitBlt(hMemDC, 0, 0, bih->biWidth, bih->biHeight, hMemDC2, 0, 0, SRCINVERT);
389     DeleteDC(hMemDC);
390     DeleteDC(hMemDC2);
391     ReleaseDC(GetDesktopWindow(), hdc);
392     GlobalUnlock(hIcon);
393     return hIcon;
394 }
395
396
397 /**********************************************************************
398  *                      DestroyIcon [USER.457]
399  */
400 BOOL DestroyIcon(HICON hIcon)
401 {
402     ICONALLOC   *lpico;
403     if (hIcon == (HICON)NULL) return FALSE;
404     lpico = (ICONALLOC *)GlobalLock(hIcon);
405     if (lpico->hBitmap != (HBITMAP)NULL) DeleteObject(lpico->hBitmap);
406     GlobalFree(hIcon);
407     return TRUE;
408 }
409
410
411 /**********************************************************************
412  *                      LoadAccelerators        [USER.177]
413  */
414 HANDLE LoadAccelerators(HANDLE instance, LPSTR lpTableName)
415 {
416     HANDLE      hAccel;
417     HANDLE      rsc_mem;
418     BYTE        *lp;
419     ACCELHEADER *lpAccelTbl;
420     int         i, image_size;
421 #ifdef DEBUG_ACCEL
422     if (((LONG)lpTableName & 0xFFFF0000L) == 0L)
423         printf("LoadAccelerators: instance = %04X, name = %08X\n",
424                         instance, lpTableName);
425     else
426         printf("LoadAccelerators: instance = %04X, name = '%s'\n",
427                         instance, lpTableName);
428 #endif
429     if (instance == (HANDLE)NULL)  instance = hSysRes;
430     rsc_mem = RSC_LoadResource(instance, lpTableName, NE_RSCTYPE_ACCELERATOR, 
431                                &image_size);
432     if (rsc_mem == (HANDLE)NULL) {
433         printf("LoadAccelerators / AccelTable %04X not Found !\n", lpTableName);
434         return 0;
435         }
436     lp = (BYTE *)GlobalLock(rsc_mem);
437     if (lp == NULL) {
438         GlobalFree(rsc_mem);
439         return 0;
440         }
441 #ifdef DEBUG_ACCEL
442     printf("LoadAccelerators / image_size=%d\n", image_size);
443 #endif
444     hAccel = GlobalAlloc(GMEM_MOVEABLE, 
445         sizeof(ACCELHEADER) + sizeof(ACCELENTRY) + image_size);
446     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
447     lpAccelTbl->wCount = 0;
448     for (i = 0; ; i++) {
449         lpAccelTbl->tbl[i].type = *(lp++);
450         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
451         lp += 2;
452         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
453         lp += 2;
454         if (lpAccelTbl->tbl[i].wEvent == 0) break;
455 #ifdef DEBUG_ACCEL
456         printf("Accelerator #%u / event=%04X id=%04X type=%02X \n", 
457                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
458                 lpAccelTbl->tbl[i].type);
459 #endif
460         lpAccelTbl->wCount++;
461         }
462     GlobalUnlock(hAccel);
463     GlobalUnlock(rsc_mem);
464     GlobalFree(rsc_mem);
465     return hAccel;
466 }
467
468 /**********************************************************************
469  *                      TranslateAccelerator    [USER.178]
470  */
471 int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
472 {
473     ACCELHEADER *lpAccelTbl;
474     int         i, image_size;
475     if (hAccel == 0 || msg == NULL) return 0;
476     if (msg->message != WM_KEYDOWN &&
477         msg->message != WM_KEYUP &&
478         msg->message != WM_CHAR) return 0;
479 #ifdef DEBUG_ACCEL
480     printf("TranslateAccelerators hAccel=%04X !\n", hAccel);
481 #endif
482     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
483     for (i = 0; i < lpAccelTbl->wCount; i++) {
484 /*      if (lpAccelTbl->tbl[i].type & SHIFT_ACCEL) { */
485 /*      if (lpAccelTbl->tbl[i].type & CONTROL_ACCEL) { */
486         if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
487             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
488                 msg->message == WM_KEYDOWN) {
489                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
490                 return 1;
491                 }
492             if (msg->message == WM_KEYUP) return 1;
493             }
494         else {
495             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
496                 msg->message == WM_CHAR) {
497                 SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
498                 return 1;
499                 }
500             }
501         }
502     GlobalUnlock(hAccel);
503     return 0;
504 }
505
506 /**********************************************************************
507  *                              FindResource    [KERNEL.60]
508  */
509 HANDLE FindResource(HANDLE instance, LPSTR resource_name, LPSTR type_name)
510 {
511     RESOURCE *r;
512     HANDLE rh;
513
514     if (instance == 0)
515         return 0;
516     
517 #ifdef DEBUG_RESOURCE
518     printf("FindResource hInst=%04X typename=%08X resname=%08X\n", 
519                 instance, type_name, resource_name);
520 #endif
521     if (OpenResourceFile(instance) < 0)
522         return 0;
523     
524     rh = GlobalAlloc(GMEM_MOVEABLE, sizeof(*r));
525     if (rh == 0)
526         return 0;
527     r = (RESOURCE *)GlobalLock(rh);
528
529     r->next = Top;
530     Top = r;
531     r->info_mem = rh;
532     r->rsc_mem = 0;
533
534     if (((int) resource_name & 0xffff0000) == 0)
535     {
536         r->size_shift = FindResourceByNumber(&r->nameinfo, (int)type_name,
537                                              (int) resource_name | 0x8000);
538     }
539     else
540     {
541         r->size_shift = FindResourceByName(&r->nameinfo, (int)type_name, 
542                                            resource_name);
543     }
544     
545     if (r->size_shift == -1)
546     {
547         GlobalFree(rh);
548         return 0;
549     }
550
551     return rh;
552 }
553
554 /**********************************************************************
555  *                              LoadResource    [KERNEL.61]
556  */
557 HANDLE LoadResource(HANDLE instance, HANDLE hResInfo)
558 {
559     RESOURCE *r;
560     int image_size;
561     void *image;
562     HANDLE h;
563
564     if (instance == 0)
565         return 0;
566     
567     if (OpenResourceFile(instance) < 0)
568         return 0;
569
570     r = (RESOURCE *)GlobalLock(hResInfo);
571     if (r == NULL)
572         return 0;
573     
574     image_size = r->nameinfo.length << r->size_shift;
575
576     h = r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
577     image = GlobalLock(h);
578
579     lseek(ResourceFd, ((int) r->nameinfo.offset << r->size_shift), SEEK_SET);
580
581     if (image == NULL || read(ResourceFd, image, image_size) != image_size)
582     {
583         GlobalFree(h);
584         GlobalUnlock(hResInfo);
585         return 0;
586     }
587
588     GlobalUnlock(h);
589     GlobalUnlock(hResInfo);
590     return h;
591 }
592
593 /**********************************************************************
594  *                              LockResource    [KERNEL.62]
595  */
596 LPSTR LockResource(HANDLE hResData)
597 {
598     return GlobalLock(hResData);
599 }
600
601 /**********************************************************************
602  *                              FreeResource    [KERNEL.63]
603  */
604 HANDLE FreeResource(HANDLE hResData)
605 {
606     RESOURCE *r, *rp;
607     
608     for (r = rp = Top; r != NULL; r = r->next)
609     {
610         if (r->info_mem == hResData)
611         {
612             if (rp != NULL)
613                 rp->next = r->next;
614             else
615                 Top = r->next;
616             
617             GlobalFree(r->rsc_mem);
618             GlobalFree(r->info_mem);
619             return 0;
620         }
621     }
622     
623     return hResData;
624 }
625
626 /**********************************************************************
627  *                              AccessResource  [KERNEL.64]
628  */
629 int AccessResource(HANDLE instance, HANDLE hResInfo)
630 {
631     int resfile;
632 #ifdef DEBUG_RESOURCE
633     printf("AccessResource(%04X, %04X);\n", instance, hResInfo);
634 #endif
635 /*
636     resfile = OpenResourceFile(instance);
637     return resfile;
638 */
639     return - 1;
640 }
641
642
643 \f
644 /**********************************************************************
645  *                                      RSC_LoadResource
646  */
647 HANDLE
648 RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret)
649 {
650     struct resource_nameinfo_s nameinfo;
651     HANDLE hmem;
652     void *image;
653     int image_size;
654     int size_shift;
655     
656     /*
657      * Built-in resources
658      */
659     if (instance == 0)
660     {
661         return 0;
662     }
663     else if (OpenResourceFile(instance) < 0)
664         return 0;
665     
666     /*
667      * Get resource by ordinal
668      */
669     if (((int) rsc_name & 0xffff0000) == 0)
670     {
671         size_shift = FindResourceByNumber(&nameinfo, type,
672                                           (int) rsc_name | 0x8000);
673     }
674     /*
675      * Get resource by name
676      */
677     else
678     {
679         size_shift = FindResourceByName(&nameinfo, type, rsc_name);
680     }
681     if (size_shift == -1) {
682         printf("RSC_LoadResource / Resource '%X' not Found !\n", rsc_name);
683         return 0;
684         }
685     /*
686      * Read resource.
687      */
688     lseek(ResourceFd, ((int) nameinfo.offset << size_shift), SEEK_SET);
689
690     image_size = nameinfo.length << size_shift;
691     if (image_size_ret != NULL)
692         *image_size_ret = image_size;
693     hmem = GlobalAlloc(GMEM_MOVEABLE, image_size);
694     image = GlobalLock(hmem);
695     if (image == NULL || read(ResourceFd, image, image_size) != image_size)
696     {
697         GlobalFree(hmem);
698         return 0;
699     }
700
701     GlobalUnlock(hmem);
702     return hmem;
703 }
704 \f
705 /**********************************************************************
706  *                                      LoadString
707  */
708 int
709 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
710 {
711     HANDLE hmem;
712     int rsc_size;
713     unsigned char *p;
714     int string_num;
715     int i;
716
717 #ifdef DEBUG_RESOURCE
718     printf("LoadString: instance = %04x, id = %d, "
719            "buffer = %08x, length = %d\n",
720            instance, resource_id, buffer, buflen);
721 #endif
722
723     hmem = RSC_LoadResource(instance, (char *) ((resource_id >> 4) + 1),
724                             NE_RSCTYPE_STRING, &rsc_size);
725     if (hmem == 0)
726         return 0;
727     
728     p = GlobalLock(hmem);
729     string_num = resource_id & 0x000f;
730     for (i = 0; i < string_num; i++)
731         p += *p + 1;
732     
733     i = MIN(buflen - 1, *p);
734     memcpy(buffer, p + 1, i);
735     buffer[i] = '\0';
736
737     GlobalFree(hmem);
738
739 #ifdef DEBUG_RESOURCE
740     printf("            '%s'\n", buffer);
741 #endif
742     return i;
743 }
744 \f
745 /**********************************************************************
746  *                                      RSC_LoadMenu
747  */
748 HANDLE
749 RSC_LoadMenu(HANDLE instance, LPSTR menu_name)
750 {
751     return RSC_LoadResource(instance, menu_name, NE_RSCTYPE_MENU, NULL);
752 }
753 \f
754 /**********************************************************************
755  *                                      LoadBitmap
756  */
757 HBITMAP
758 LoadBitmap(HANDLE instance, LPSTR bmp_name)
759 {
760     HBITMAP hbitmap;
761     HANDLE rsc_mem;
762     HDC hdc;
763     long *lp;
764     int image_size;
765
766 #ifdef DEBUG_RESOURCE
767     printf("LoadBitmap: instance = %04x, name = %08x\n",
768            instance, bmp_name);
769 #endif
770     if (instance == (HANDLE)NULL)  instance = hSysRes;
771     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
772
773     rsc_mem = RSC_LoadResource(instance, bmp_name, NE_RSCTYPE_BITMAP, 
774                                &image_size);
775     if (rsc_mem == (HANDLE)NULL) {
776         printf("LoadBitmap / BitMap %04X not Found !\n", bmp_name);
777         return 0;
778         }
779     lp = (long *) GlobalLock(rsc_mem);
780     if (lp == NULL)
781     {
782         GlobalFree(rsc_mem);
783         return 0;
784     }
785     if (*lp == sizeof(BITMAPCOREHEADER))
786         hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
787     else if (*lp == sizeof(BITMAPINFOHEADER))
788         hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
789     else hbitmap = 0;
790     GlobalFree(rsc_mem);
791     ReleaseDC( 0, hdc );
792     return hbitmap;
793 }
794
795