Release 960717
[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 "global.h"
19 #include "neexe.h"
20 #include "accel.h"
21 #include "module.h"
22 #include "resource.h"
23 #include "stddebug.h"
24 #include "debug.h"
25 #include "libres.h"
26 #include "string32.h"
27 #include "xmalloc.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  *          FindResource16    (KERNEL.60)
38  */
39 HRSRC16 FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
40 {
41     NE_MODULE *pModule;
42
43     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
44     dprintf_resource(stddeb, "FindResource16: module=%04x type=", hModule );
45     PrintId( type );
46     if (HIWORD(name))  /* Check for '#xxx' name */
47     {
48         char *ptr = PTR_SEG_TO_LIN( name );
49         if (ptr[0] == '#') {
50             if (!(name = (SEGPTR)atoi( ptr + 1 ))) return 0;
51         }
52     }
53     dprintf_resource( stddeb, " name=" );
54     PrintId( name );
55     dprintf_resource( stddeb, "\n" );
56     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
57 #ifndef WINELIB
58     if (pModule->flags & NE_FFLAGS_WIN32)
59     {
60         fprintf(stderr,"Don't know how to FindResource16() for Win32 module\n");
61         return 0;
62     }
63     return NE_FindResource( hModule, type, name );
64 #else
65     return LIBRES_FindResource( hModule, name, type );
66 #endif
67 }
68
69
70 /**********************************************************************
71  *          FindResource32A    (KERNEL32.128)
72  */
73 HANDLE32 FindResource32A( HINSTANCE32 hModule, LPCSTR name, LPCSTR type )
74 {
75     LPWSTR xname,xtype;
76     HANDLE32 ret;
77
78     if (HIWORD((DWORD)name)) xname = STRING32_DupAnsiToUni(name);
79     else xname = (LPWSTR)name;
80     if (HIWORD((DWORD)type)) xtype = STRING32_DupAnsiToUni(type);
81     else xtype = (LPWSTR)type;
82     ret = FindResource32W(hModule,xname,xtype);
83     if (HIWORD((DWORD)name)) free(xname);
84     if (HIWORD((DWORD)type)) free(xtype);
85     return ret;
86 }
87
88
89 /**********************************************************************
90  *          FindResource32W    (KERNEL32.131)
91  */
92 HRSRC32 FindResource32W( HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type )
93 {
94 #ifndef WINELIB
95     NE_MODULE *pModule;
96
97     /* Sometimes we get passed hModule = 0x00000000. FIXME: is GetTaskDS()
98      * ok?
99      */
100     if (!hModule) hModule = GetTaskDS();
101     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
102     dprintf_resource(stddeb, "FindResource32W: module=%08x type=", hModule );
103     PrintId( type );
104     dprintf_resource( stddeb, " name=" );
105     PrintId( name );
106     dprintf_resource( stddeb, "\n" );
107     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
108     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;
109     return PE_FindResource32W(hModule,name,type);
110 #else
111     return LIBRES_FindResource( hModule, name, type );
112 #endif
113 }
114
115
116 /**********************************************************************
117  *          LoadResource16    (KERNEL.61)
118  */
119 HGLOBAL16 LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
120 {
121     NE_MODULE *pModule;
122
123     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
124     dprintf_resource(stddeb, "LoadResource16: module=%04x res=%04x\n",
125                      hModule, hRsrc );
126     if (!hRsrc) return 0;
127     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
128 #ifndef WINELIB
129     if (pModule->flags & NE_FFLAGS_WIN32)
130     {
131         fprintf(stderr,"Don't know how to LoadResource16() for Win32 module\n");
132         return 0;
133     }
134     return NE_LoadResource( hModule, hRsrc );
135 #else
136     return LIBRES_LoadResource( hModule, hRsrc );
137 #endif
138 }
139
140 /**********************************************************************
141  *          LoadResource32    (KERNEL32.370)
142  */
143 HGLOBAL32 LoadResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
144 {
145 #ifndef WINELIB
146     NE_MODULE *pModule;
147
148     if (!hModule) hModule = GetTaskDS(); /* FIXME: see FindResource32W */
149     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
150     dprintf_resource(stddeb, "LoadResource32: module=%04x res=%04x\n",
151                      hModule, hRsrc );
152     if (!hRsrc) return 0;
153
154     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
155     if (!(pModule->flags & NE_FFLAGS_WIN32))
156     {
157         fprintf(stderr,"LoadResource32: tried to load a non win32 resource.\n");
158         return 0;  /* FIXME? */
159     }
160     return PE_LoadResource32(hModule,hRsrc);
161 #else
162     return LIBRES_LoadResource( hModule, hRsrc );
163 #endif
164 }
165
166
167 /**********************************************************************
168  *          LockResource    (KERNEL.62)
169  */
170 /* 16-bit version */
171 SEGPTR WIN16_LockResource16(HGLOBAL16 handle)
172 {
173 #ifndef WINELIB
174     HMODULE16 hModule;
175     NE_MODULE *pModule;
176
177     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
178     if (!handle) return (SEGPTR)0;
179     hModule = GetExePtr( handle );
180     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
181     if (pModule->flags & NE_FFLAGS_WIN32)
182     {
183         fprintf(stderr,"Don't know how to LockResource() for Win32 module\n");
184         return 0;
185     }
186     return NE_LockResource( hModule, handle );
187 #else
188     return LIBRES_LockResource( handle );
189 #endif
190 }
191
192 /* WINELIB 16-bit version */
193 LPVOID LockResource16( HGLOBAL16 handle )
194 {
195 #ifndef WINELIB
196     HMODULE16 hModule;
197     NE_MODULE *pModule;
198
199     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
200     if (!handle) return NULL;
201     hModule = GetExePtr( handle );
202     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
203     if (pModule->flags & NE_FFLAGS_WIN32)
204     {
205         fprintf(stderr,"Don't know how to LockResource16() for Win32 module\n");
206         return 0;
207     }
208     return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
209 #else
210     return LIBRES_LockResource( handle );
211 #endif
212 }
213
214
215 /**********************************************************************
216  *          LockResource32    (KERNEL32.384)
217  */
218 LPVOID LockResource32( HGLOBAL32 handle )
219 {
220     return (LPVOID)handle;
221 }
222
223
224 /**********************************************************************
225  *          FreeResource16    (KERNEL.63)
226  */
227 BOOL16 FreeResource16( HGLOBAL16 handle )
228 {
229 #ifndef WINELIB
230     HMODULE16 hModule;
231     NE_MODULE *pModule;
232
233     dprintf_resource(stddeb, "FreeResource16: handle=%04x\n", handle );
234     if (!handle) return FALSE;
235     hModule = GetExePtr( handle );
236     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
237     if (pModule->flags & NE_FFLAGS_WIN32)
238     {
239         fprintf(stderr,"Don't know how to FreeResource16() for Win32 module\n");
240         return 0;
241     }
242     return NE_FreeResource( hModule, handle );
243 #else
244     return LIBRES_FreeResource( handle );
245 #endif
246 }
247
248 /**********************************************************************
249  *          FreeResource32    (KERNEL32.145)
250  */
251 BOOL32 FreeResource32( HGLOBAL32 handle )
252 {
253     /* no longer used in Win32 */
254     return TRUE;
255 }
256
257
258 /**********************************************************************
259  *          AccessResource16    (KERNEL.64)
260  */
261 INT16 AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
262 {
263     NE_MODULE *pModule;
264
265     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
266     dprintf_resource(stddeb, "AccessResource16: module=%04x res=%04x\n",
267                      hModule, hRsrc );
268     if (!hRsrc) return 0;
269     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
270 #ifndef WINELIB
271     if (pModule->flags & NE_FFLAGS_WIN32)
272     {
273         fprintf(stderr,"Don't know how to AccessResource16() for Win32 module\n");
274         return 0;
275     }
276     return NE_AccessResource( hModule, hRsrc );
277 #else
278     return LIBRES_AccessResource( hModule, hRsrc );
279 #endif
280 }
281
282
283 /**********************************************************************
284  *          AccessResource32    (KERNEL32.64)
285  */
286 INT32 AccessResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
287 {
288     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
289     dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
290                      hModule, hRsrc );
291     if (!hRsrc) return 0;
292     fprintf(stderr,"AccessResource32: not implemented\n");
293     return 0;
294 }
295
296
297 /**********************************************************************
298  *          SizeofResource16    (KERNEL.65)
299  */
300 DWORD SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
301 {
302     NE_MODULE *pModule;
303
304     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
305     dprintf_resource(stddeb, "SizeofResource16: module=%04x res=%04x\n",
306                      hModule, hRsrc );
307     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
308 #ifndef WINELIB
309     if (pModule->flags & NE_FFLAGS_WIN32)
310     {
311         fprintf(stderr,"Don't know how to SizeOfResource16() for Win32 module\n");
312         return 0;
313     }
314     return NE_SizeofResource( hModule, hRsrc );
315 #else
316     return LIBRES_SizeofResource( hModule, hRsrc );
317 #endif
318 }
319
320
321 /**********************************************************************
322  *          SizeofResource32    (KERNEL32.522)
323  */
324 DWORD SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
325 {
326     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
327     dprintf_resource(stddeb, "SizeofResource32: module=%04x res=%04x\n",
328                      hModule, hRsrc );
329     fprintf(stderr,"SizeofResource32: not implemented\n");
330     return 0;
331 }
332
333
334 /**********************************************************************
335  *          AllocResource16    (KERNEL.66)
336  */
337 HGLOBAL16 AllocResource16( HMODULE16 hModule, HRSRC16 hRsrc, DWORD size )
338 {
339     NE_MODULE *pModule;
340
341     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
342     dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
343                      hModule, hRsrc, size );
344     if (!hRsrc) return 0;
345     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
346 #ifndef WINELIB
347     if (pModule->flags & NE_FFLAGS_WIN32)
348     {
349         fprintf(stderr,"Don't know how to AllocResource() for Win32 module\n");
350         return 0;
351     }
352     return NE_AllocResource( hModule, hRsrc, size );
353 #else
354     return LIBRES_AllocResource( hModule, hRsrc, size );
355 #endif
356 }
357
358 /**********************************************************************
359  *      DirectResAlloc    (KERNEL.168)
360  *
361  * Check Schulman, p. 232 for details
362  */
363 HANDLE DirectResAlloc(HANDLE hInstance, WORD wType, WORD wSize)
364 {
365     dprintf_resource(stddeb,"DirectResAlloc(%04x,%04x,%04x)\n",
366                      hInstance, wType, wSize );
367     hInstance = GetExePtr(hInstance);
368     if(!hInstance)return 0;
369     if(wType != 0x10)   /* 0x10 is the only observed value, passed from
370                            CreateCursorIndirect. */
371         fprintf(stderr, "DirectResAlloc: wType = %x\n", wType);
372     return GLOBAL_Alloc(GMEM_MOVEABLE, wSize, hInstance, FALSE, FALSE, FALSE);
373 }
374
375
376 /**********************************************************************
377  *                      LoadAccelerators16      [USER.177]
378  */
379 HACCEL16 LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
380 {
381     HACCEL16    hAccel;
382     HGLOBAL16   rsc_mem;
383     HRSRC16 hRsrc;
384     BYTE        *lp;
385     ACCELHEADER *lpAccelTbl;
386     int         i, n;
387
388     if (HIWORD(lpTableName))
389         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
390                       instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
391     else
392         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
393                        instance, LOWORD(lpTableName) );
394
395     if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR )))
396       return 0;
397     if (!(rsc_mem = LoadResource16( instance, hRsrc ))) return 0;
398
399     lp = (BYTE *)LockResource16(rsc_mem);
400     n = SizeofResource16(instance,hRsrc)/sizeof(ACCELENTRY);
401     hAccel = GlobalAlloc16(GMEM_MOVEABLE, 
402         sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
403     lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel);
404     lpAccelTbl->wCount = 0;
405     for (i = 0; i < n; i++) {
406         lpAccelTbl->tbl[i].type = *(lp++);
407         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
408         lp += 2;
409         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
410         lp += 2;
411         if (lpAccelTbl->tbl[i].wEvent == 0) break;
412         dprintf_accel(stddeb,
413                 "Accelerator #%u / event=%04X id=%04X type=%02X \n", 
414                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
415                 lpAccelTbl->tbl[i].type);
416         lpAccelTbl->wCount++;
417         }
418     GlobalUnlock16(hAccel);
419     FreeResource16( rsc_mem );
420     return hAccel;
421 }
422
423 /**********************************************************************
424  *                      LoadAccelerators32W     [USER.177]
425  */
426 HACCEL32 LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
427 {
428 #if 0
429     HACCEL32    hAccel;
430     HGLOBAL32   rsc_mem;
431     HRSRC32 hRsrc;
432     BYTE        *lp;
433     ACCELHEADER *lpAccelTbl;
434     int         i, n;
435
436     if (HIWORD(lpTableName))
437         dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
438                       instance, (char *)( lpTableName ) );
439     else
440         dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
441                        instance, LOWORD(lpTableName) );
442
443     if (!(hRsrc = FindResource32W( instance, lpTableName, 
444                 (LPCWSTR)RT_ACCELERATOR )))
445       return 0;
446     if (!(rsc_mem = LoadResource32( instance, hRsrc ))) return 0;
447
448     lp = (BYTE *)LockResource32(rsc_mem);
449     n = SizeofResource32(instance,hRsrc)/sizeof(ACCELENTRY);
450     hAccel = GlobalAlloc16(GMEM_MOVEABLE, 
451         sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
452     lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel);
453     lpAccelTbl->wCount = 0;
454     for (i = 0; i < n; i++) {
455         lpAccelTbl->tbl[i].type = *(lp++);
456         lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
457         lp += 2;
458         lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
459         lp += 2;
460         if (lpAccelTbl->tbl[i].wEvent == 0) break;
461         dprintf_accel(stddeb,
462                 "Accelerator #%u / event=%04X id=%04X type=%02X \n", 
463                 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, 
464                 lpAccelTbl->tbl[i].type);
465         lpAccelTbl->wCount++;
466         }
467     GlobalUnlock16(hAccel);
468     FreeResource32(rsc_mem);
469     return hAccel;
470 #else
471         fprintf(stderr,"LoadAcceleratorsW: not implemented\n");
472         return 0x100;  /* Return something anyway */
473 #endif
474 }
475
476 HACCEL32 LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
477 {
478         LPWSTR   uni;
479         HACCEL32 result;
480         if (HIWORD(lpTableName))
481                 uni=STRING32_DupAnsiToUni(lpTableName);
482         else
483                 uni=(LPWSTR)lpTableName;
484         result=LoadAccelerators32W(instance,uni);
485         if (HIWORD(uni))
486                 free(uni);
487         return result;
488 }
489
490
491 /**********************************************************************
492  *                      TranslateAccelerator    [USER.178]
493  */
494 int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG16 msg)
495 {
496     ACCELHEADER *lpAccelTbl;
497     int         i;
498     
499     if (hAccel == 0 || msg == NULL) return 0;
500     if (msg->message != WM_KEYDOWN &&
501         msg->message != WM_KEYUP &&
502         msg->message != WM_SYSKEYDOWN &&
503         msg->message != WM_SYSKEYUP &&
504         msg->message != WM_CHAR) return 0;
505
506     dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04x !\n", hAccel);
507
508     lpAccelTbl = (LPACCELHEADER)GlobalLock16(hAccel);
509     for (i = 0; i < lpAccelTbl->wCount; i++) {
510         if(lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
511             if(msg->wParam == lpAccelTbl->tbl[i].wEvent &&
512                (msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN)) {
513                 INT mask = 0;
514
515                 if(GetKeyState(VK_SHIFT) & 0x8000) mask |= SHIFT_ACCEL;
516                 if(GetKeyState(VK_CONTROL) & 0x8000) mask |= CONTROL_ACCEL;
517                 if(GetKeyState(VK_MENU) & 0x8000) mask |= ALT_ACCEL;
518                 if(mask == (lpAccelTbl->tbl[i].type &
519                             (SHIFT_ACCEL | CONTROL_ACCEL | ALT_ACCEL))) {
520                     SendMessage16(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval,
521                                 0x00010000L);
522                     GlobalUnlock16(hAccel);
523                     return 1;
524                 }
525                 if (msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP)
526                     return 1;
527             }
528         }
529         else {
530             if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
531                 msg->message == WM_CHAR) {
532                 SendMessage16(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
533                 GlobalUnlock16(hAccel);
534                 return 1;
535                 }
536             }
537         }
538     GlobalUnlock16(hAccel);
539     return 0;
540 }
541
542 /**********************************************************************
543  *                                      LoadString16
544  */
545 INT16
546 LoadString16(HINSTANCE16 instance,UINT16 resource_id,LPSTR buffer,INT16 buflen)
547 {
548     HGLOBAL16 hmem;
549     HRSRC16 hrsrc;
550     unsigned char *p;
551     int string_num;
552     int i;
553
554     dprintf_resource(stddeb,"LoadString: inst=%04x id=%04x buff=%08x len=%d\n",
555                      instance, resource_id, (int) buffer, buflen);
556
557     hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING );
558     if (!hrsrc) return 0;
559     hmem = LoadResource16( instance, hrsrc );
560     if (!hmem) return 0;
561     
562     p = LockResource16(hmem);
563     string_num = resource_id & 0x000f;
564     for (i = 0; i < string_num; i++)
565         p += *p + 1;
566     
567     dprintf_resource( stddeb, "strlen = %d\n", (int)*p );
568     
569     i = MIN(buflen - 1, *p);
570     if (buffer == NULL)
571         return i;
572     if (i > 0) {
573         memcpy(buffer, p + 1, i);
574         buffer[i] = '\0';
575     } else {
576         if (buflen > 1) {
577             buffer[0] = '\0';
578             return 0;
579         }
580         fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
581         fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
582     }
583     FreeResource16( hmem );
584
585     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
586     return i;
587 }
588
589 /**********************************************************************
590  *      LoadString32W           (USER32.375)
591  */
592 INT32
593 LoadString32W(HINSTANCE32 instance,UINT32 resource_id,LPWSTR buffer,int buflen)
594 {
595     HGLOBAL32 hmem;
596     HRSRC32 hrsrc;
597     WCHAR *p;
598     int string_num;
599     int i;
600
601     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %04x, buffer = %08x, "
602            "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
603
604     hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1), 
605                 (LPCWSTR)RT_STRING );
606     if (!hrsrc) return 0;
607     hmem = LoadResource32( instance, hrsrc );
608     if (!hmem) return 0;
609     
610     p = LockResource32(hmem);
611     string_num = resource_id & 0x000f;
612     for (i = 0; i < string_num; i++)
613         p += *p + 1;
614     
615     dprintf_resource( stddeb, "strlen = %d\n", (int)*p );
616     
617     i = MIN(buflen - 1, *p);
618     if (buffer == NULL)
619         return i;
620     if (i > 0) {
621         memcpy(buffer, p + 1, i * sizeof (WCHAR));
622         buffer[i] = (WCHAR) 0;
623     } else {
624         if (buflen > 1) {
625             buffer[0] = (WCHAR) 0;
626             return 0;
627         }
628 #if 0
629         fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
630         fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
631 #endif
632     }
633 #if 0
634     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
635 #endif
636     return i;
637 }
638
639 /**********************************************************************
640  *      LoadString32A   (USER32.374)
641  */
642 INT32
643 LoadString32A(HINSTANCE32 instance,UINT32 resource_id,LPSTR buffer,int buflen)
644 {
645     LPWSTR buffer2 = (LPWSTR)xmalloc(buflen*2);
646     INT32 retval = LoadString32W(instance,resource_id,buffer2,buflen);
647
648     STRING32_UniToAnsi(buffer,buffer2);
649     free(buffer2);
650     return retval;
651 }
652