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