Updates and fixes.
[wine/wine64.git] / loader / resource.c
blob6313649e8293368934ba76a25520f59754575ecf
1 /*
2 * Resources
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <assert.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 "windows.h"
16 #include "wine/winuser16.h"
17 #include "gdi.h"
18 #include "global.h"
19 #include "heap.h"
20 #include "neexe.h"
21 #include "task.h"
22 #include "process.h"
23 #include "module.h"
24 #include "file.h"
25 #include "resource.h"
26 #include "debug.h"
27 #include "libres.h"
28 #include "winerror.h"
29 #include "debugstr.h"
31 extern WORD WINE_LanguageId;
33 #define HRSRC_MAP_BLOCKSIZE 16
35 typedef struct _HRSRC_ELEM
37 HANDLE32 hRsrc;
38 WORD type;
39 } HRSRC_ELEM;
41 typedef struct _HRSRC_MAP
43 int nAlloc;
44 int nUsed;
45 HRSRC_ELEM *elem;
46 } HRSRC_MAP;
48 /**********************************************************************
49 * MapHRsrc32To16
51 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE32 hRsrc32, WORD type )
53 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
54 HRSRC_ELEM *newElem;
55 int i;
57 /* On first call, initialize HRSRC map */
58 if ( !map )
60 if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
61 sizeof(HRSRC_MAP) ) ) )
63 ERR( resource, "Cannot allocate HRSRC map\n" );
64 return 0;
66 pModule->hRsrcMap = (LPVOID)map;
69 /* Check whether HRSRC32 already in map */
70 for ( i = 0; i < map->nUsed; i++ )
71 if ( map->elem[i].hRsrc == hRsrc32 )
72 return (HRSRC16)(i + 1);
74 /* If no space left, grow table */
75 if ( map->nUsed == map->nAlloc )
77 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
78 map->elem,
79 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
80 * sizeof(HRSRC_ELEM) ) ))
82 ERR( resource, "Cannot grow HRSRC map\n" );
83 return 0;
85 map->elem = newElem;
86 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
89 /* Add HRSRC32 to table */
90 map->elem[map->nUsed].hRsrc = hRsrc32;
91 map->elem[map->nUsed].type = type;
92 map->nUsed++;
94 return (HRSRC16)map->nUsed;
97 /**********************************************************************
98 * MapHRsrc16To32
100 static HANDLE32 MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
102 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
103 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
105 return map->elem[(int)hRsrc16-1].hRsrc;
108 /**********************************************************************
109 * MapHRsrc16ToType
111 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
113 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
114 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
116 return map->elem[(int)hRsrc16-1].type;
119 /**********************************************************************
120 * FindResource16 (KERNEL.60)
122 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
124 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
125 LPCSTR typeStr = HIWORD(type)? PTR_SEG_TO_LIN(type) : (LPCSTR)type;
127 NE_MODULE *pModule = NE_GetPtr( hModule );
128 if ( !pModule ) return 0;
130 if ( pModule->module32 )
132 HANDLE32 hRsrc32 = FindResource32A( pModule->module32, nameStr, typeStr );
133 return MapHRsrc32To16( pModule, hRsrc32, HIWORD(type)? 0 : type );
136 return NE_FindResource( pModule, nameStr, typeStr );
139 /**********************************************************************
140 * FindResource32A (KERNEL32.128)
142 HANDLE32 WINAPI FindResource32A( HMODULE32 hModule, LPCSTR name, LPCSTR type)
144 return FindResourceEx32A(hModule,type,name,WINE_LanguageId);
147 /**********************************************************************
148 * FindResourceEx32A (KERNEL32.129)
150 HANDLE32 WINAPI FindResourceEx32A( HMODULE32 hModule, LPCSTR type, LPCSTR name,
151 WORD lang
153 LPWSTR xname,xtype;
154 HANDLE32 ret;
156 if (HIWORD((DWORD)name))
157 xname = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
158 else
159 xname = (LPWSTR)name;
160 if (HIWORD((DWORD)type))
161 xtype = HEAP_strdupAtoW( GetProcessHeap(), 0, type);
162 else
163 xtype = (LPWSTR)type;
164 ret = FindResourceEx32W( hModule, xtype, xname, lang );
165 if (HIWORD((DWORD)name)) HeapFree( GetProcessHeap(), 0, xname );
166 if (HIWORD((DWORD)type)) HeapFree( GetProcessHeap(), 0, xtype );
167 return ret;
171 /**********************************************************************
172 * FindResourceEx32W (KERNEL32.130)
174 HRSRC32 WINAPI FindResourceEx32W( HMODULE32 hModule, LPCWSTR type,
175 LPCWSTR name, WORD lang )
177 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
178 HRSRC32 hrsrc;
180 TRACE(resource, "module=%08x(%s) type=%s name=%s\n",
181 hModule, wm->modname,
182 debugres_w (type),
183 debugres_w (name));
185 if (!wm) return (HRSRC32)0;
187 switch (wm->type)
189 case MODULE32_PE:
190 hrsrc = PE_FindResourceEx32W(wm,name,type,lang);
191 break;
193 case MODULE32_ELF:
194 hrsrc = LIBRES_FindResource( hModule, name, type );
195 break;
197 default:
198 ERR(module,"unknown module type %d\n",wm->type);
199 return (HRSRC32)0;
202 if ( !hrsrc )
203 ERR(resource,"0x%08x(%s) %s(%s) not found!\n", hModule,wm->modname, debugres_w (name), debugres_w (type));
205 return hrsrc;
209 /**********************************************************************
210 * FindResource32W (KERNEL32.131)
212 HRSRC32 WINAPI FindResource32W(HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type)
214 return FindResourceEx32W(hModule,type,name,WINE_LanguageId);
217 /**********************************************************************
218 * LoadResource16 (KERNEL.61)
220 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
222 NE_MODULE *pModule = NE_GetPtr( hModule );
223 if ( !pModule ) return 0;
225 if ( pModule->module32 )
227 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
228 WORD type = MapHRsrc16ToType( pModule, hRsrc );
229 HGLOBAL32 image = LoadResource32( pModule->module32, hRsrc32 );
230 DWORD size = SizeofResource32( pModule->module32, hRsrc32 );
231 LPVOID bits = LockResource32( image );
233 return NE_LoadPEResource( pModule, type, bits, size );
236 return NE_LoadResource( pModule, hRsrc );
239 /**********************************************************************
240 * LoadResource32 (KERNEL32.370)
241 * 'loads' a resource. The current implementation just returns a pointer
242 * into the already mapped image.
243 * RETURNS
244 * pointer into the mapped resource of the passed module
246 HGLOBAL32 WINAPI LoadResource32(
247 HINSTANCE32 hModule, /* [in] module handle */
248 HRSRC32 hRsrc ) /* [in] resource handle */
250 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
252 TRACE(resource, "module=%04x res=%04x\n",
253 hModule, hRsrc );
254 if (!hRsrc) {
255 ERR(resource,"hRsrc is 0, return 0.\n");
256 return 0;
258 if (!wm) return 0;
260 switch (wm->type)
262 case MODULE32_PE:
263 return PE_LoadResource32(wm,hRsrc);
265 case MODULE32_ELF:
266 return LIBRES_LoadResource( hModule, hRsrc );
268 default:
269 ERR(resource,"unknown module type %d\n",wm->type);
270 break;
272 return 0;
275 /**********************************************************************
276 * LockResource16 (KERNEL.62)
278 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
280 TRACE( resource, "handle=%04x\n", handle );
281 if (!handle) return (SEGPTR)0;
283 /* May need to reload the resource if discarded */
284 return (SEGPTR)WIN16_GlobalLock16( handle );
286 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
288 return (LPVOID)PTR_SEG_TO_LIN( WIN16_LockResource16( handle ) );
291 /**********************************************************************
292 * LockResource32 (KERNEL32.384)
294 LPVOID WINAPI LockResource32( HGLOBAL32 handle )
296 return (LPVOID)handle;
300 /**********************************************************************
301 * FreeResource16 (KERNEL.63)
303 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
305 NE_MODULE *pModule = NE_GetPtr( FarGetOwner(handle) );
306 if ( !pModule ) return handle;
308 if ( pModule->module32 )
309 return NE_FreePEResource( pModule, handle );
311 return NE_FreeResource( pModule, handle );
314 /**********************************************************************
315 * FreeResource32 (KERNEL32.145)
317 BOOL32 WINAPI FreeResource32( HGLOBAL32 handle )
319 /* no longer used in Win32 */
320 return TRUE;
323 /**********************************************************************
324 * AccessResource16 (KERNEL.64)
326 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
328 NE_MODULE *pModule = NE_GetPtr( hModule );
329 if ( !pModule ) return 0;
331 if ( pModule->module32 )
333 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
334 HFILE32 hFile32 = AccessResource32( pModule->module32, hRsrc32 );
335 return FILE_AllocDosHandle( hFile32 );
338 return NE_AccessResource( pModule, hRsrc );
341 /**********************************************************************
342 * AccessResource32 (KERNEL32.64)
344 INT32 WINAPI AccessResource32( HMODULE32 hModule, HRSRC32 hRsrc )
346 FIXME(resource,"(module=%08x res=%08x),not implemented\n", hModule, hRsrc);
347 return 0;
351 /**********************************************************************
352 * SizeofResource16 (KERNEL.65)
354 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
356 NE_MODULE *pModule = NE_GetPtr( hModule );
357 if ( !pModule ) return 0;
359 if ( pModule->module32 )
361 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
362 return SizeofResource32( hModule, hRsrc32 );
365 return NE_SizeofResource( pModule, hRsrc );
368 /**********************************************************************
369 * SizeofResource32 (KERNEL32.522)
371 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
373 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
375 TRACE(resource, "module=%08x res=%08x\n", hModule, hRsrc );
376 if (!wm) return 0;
378 switch (wm->type)
380 case MODULE32_PE:
381 return PE_SizeofResource32(hModule,hRsrc);
383 case MODULE32_ELF:
384 return LIBRES_SizeofResource( hModule, hRsrc );
386 default:
387 ERR(module,"unknown module type %d\n",wm->type);
388 break;
390 return 0;
394 /**********************************************************************
395 * LoadAccelerators16 [USER.177]
397 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
399 HRSRC16 hRsrc;
401 if (HIWORD(lpTableName))
402 TRACE(accel, "%04x '%s'\n",
403 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
404 else
405 TRACE(accel, "%04x %04x\n",
406 instance, LOWORD(lpTableName) );
408 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
409 WARN(accel, "couldn't find accelerator table resource\n");
410 return 0;
413 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
414 return LoadResource16(instance,hRsrc);
417 /**********************************************************************
418 * LoadAccelerators32W [USER.177]
419 * The image layout seems to look like this (not 100% sure):
420 * 00: BYTE type type of accelerator
421 * 01: BYTE pad (to WORD boundary)
422 * 02: WORD event
423 * 04: WORD IDval
424 * 06: WORD pad (to DWORD boundary)
426 HACCEL32 WINAPI LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
428 HRSRC32 hRsrc;
429 HACCEL32 hMem,hRetval;
430 DWORD size;
432 if (HIWORD(lpTableName))
433 TRACE(accel, "%p '%s'\n",
434 (LPVOID)instance, (char *)( lpTableName ) );
435 else
436 TRACE(accel, "%p 0x%04x\n",
437 (LPVOID)instance, LOWORD(lpTableName) );
439 if (!(hRsrc = FindResource32W( instance, lpTableName, RT_ACCELERATOR32W )))
441 WARN(accel, "couldn't find accelerator table resource\n");
442 hRetval = 0;
444 else {
445 hMem = LoadResource32( instance, hRsrc );
446 size = SizeofResource32( instance, hRsrc );
447 if(size>=sizeof(PE_ACCEL))
449 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
450 LPACCEL16 accel16;
451 int i,nrofaccells = size/sizeof(PE_ACCEL);
453 hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
454 accel16 = (LPACCEL16)GlobalLock16(hRetval);
455 for (i=0;i<nrofaccells;i++) {
456 accel16[i].fVirt = accel_table[i].fVirt;
457 accel16[i].key = accel_table[i].key;
458 accel16[i].cmd = accel_table[i].cmd;
460 accel16[i-1].fVirt |= 0x80;
463 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
464 return hRetval;
467 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
469 LPWSTR uni;
470 HACCEL32 result;
471 if (HIWORD(lpTableName))
472 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
473 else
474 uni = (LPWSTR)lpTableName;
475 result = LoadAccelerators32W(instance,uni);
476 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
477 return result;
480 /**********************************************************************
481 * CopyAcceleratorTable32A (USER32.58)
483 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
485 return CopyAcceleratorTable32W(src, dst, entries);
488 /**********************************************************************
489 * CopyAcceleratorTable32W (USER32.59)
491 * By mortene@pvv.org 980321
493 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
494 INT32 entries)
496 int i,xsize;
497 LPACCEL16 accel = (LPACCEL16)GlobalLock16(src);
498 BOOL32 done = FALSE;
500 /* Do parameter checking to avoid the explosions and the screaming
501 as far as possible. */
502 if((dst && (entries < 1)) || (src == (HACCEL32)NULL) || !accel) {
503 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
504 (LPVOID)src, (LPVOID)dst, entries);
505 return 0;
507 xsize = GlobalSize16(src)/sizeof(ACCEL16);
508 if (xsize>entries) entries=xsize;
510 i=0;
511 while(!done) {
512 /* Spit out some debugging information. */
513 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
514 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
516 /* Copy data to the destination structure array (if dst == NULL,
517 we're just supposed to count the number of entries). */
518 if(dst) {
519 dst[i].fVirt = accel[i].fVirt;
520 dst[i].key = accel[i].key;
521 dst[i].cmd = accel[i].cmd;
523 /* Check if we've reached the end of the application supplied
524 accelerator table. */
525 if(i+1 == entries) {
526 /* Turn off the high order bit, just in case. */
527 dst[i].fVirt &= 0x7f;
528 done = TRUE;
532 /* The highest order bit seems to mark the end of the accelerator
533 resource table, but not always. Use GlobalSize() check too. */
534 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
536 i++;
539 return i;
542 /*********************************************************************
543 * CreateAcceleratorTable (USER32.64)
545 * By mortene@pvv.org 980321
547 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
549 HACCEL32 hAccel;
550 LPACCEL16 accel;
551 int i;
553 /* Do parameter checking just in case someone's trying to be
554 funny. */
555 if(cEntries < 1) {
556 WARN(accel, "Application sent invalid parameters (%p %d).\n",
557 lpaccel, cEntries);
558 SetLastError(ERROR_INVALID_PARAMETER);
559 return (HACCEL32)NULL;
561 FIXME(accel, "should check that the accelerator descriptions are valid,"
562 " return NULL and SetLastError() if not.\n");
565 /* Allocate memory and copy the table. */
566 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
568 TRACE(accel, "handle %x\n", hAccel);
569 if(!hAccel) {
570 ERR(accel, "Out of memory.\n");
571 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
572 return (HACCEL32)NULL;
574 accel = GlobalLock16(hAccel);
575 for (i=0;i<cEntries;i++) {
576 accel[i].fVirt = lpaccel[i].fVirt;
577 accel[i].key = lpaccel[i].key;
578 accel[i].cmd = lpaccel[i].cmd;
580 /* Set the end-of-table terminator. */
581 accel[cEntries-1].fVirt |= 0x80;
583 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
584 return hAccel;
588 /******************************************************************************
589 * DestroyAcceleratorTable [USER32.130]
590 * Destroys an accelerator table
592 * NOTES
593 * By mortene@pvv.org 980321
595 * PARAMS
596 * handle [I] Handle to accelerator table
598 * RETURNS STD
600 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
602 FIXME(accel, "(0x%x): stub\n", handle);
603 /* FIXME: GlobalFree16(handle); */
604 return TRUE;
607 /**********************************************************************
608 * LoadString16
610 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
611 LPSTR buffer, INT16 buflen )
613 HGLOBAL16 hmem;
614 HRSRC16 hrsrc;
615 unsigned char *p;
616 int string_num;
617 int i;
619 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
620 instance, resource_id, (int) buffer, buflen);
622 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
623 if (!hrsrc) return 0;
624 hmem = LoadResource16( instance, hrsrc );
625 if (!hmem) return 0;
627 p = LockResource16(hmem);
628 string_num = resource_id & 0x000f;
629 for (i = 0; i < string_num; i++)
630 p += *p + 1;
632 TRACE(resource, "strlen = %d\n", (int)*p );
634 i = MIN(buflen - 1, *p);
635 if (buffer == NULL)
636 return i;
637 if (i > 0) {
638 memcpy(buffer, p + 1, i);
639 buffer[i] = '\0';
640 } else {
641 if (buflen > 1) {
642 buffer[0] = '\0';
643 return 0;
645 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
647 FreeResource16( hmem );
649 TRACE(resource,"'%s' loaded !\n", buffer);
650 return i;
653 /**********************************************************************
654 * LoadString32W (USER32.376)
656 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
657 LPWSTR buffer, INT32 buflen )
659 HGLOBAL32 hmem;
660 HRSRC32 hrsrc;
661 WCHAR *p;
662 int string_num;
663 int i;
665 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
666 resource_id = (UINT32)(-((INT32)resource_id));
667 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
668 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
670 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
671 RT_STRING32W );
672 if (!hrsrc) return 0;
673 hmem = LoadResource32( instance, hrsrc );
674 if (!hmem) return 0;
676 p = LockResource32(hmem);
677 string_num = resource_id & 0x000f;
678 for (i = 0; i < string_num; i++)
679 p += *p + 1;
681 TRACE(resource, "strlen = %d\n", (int)*p );
683 i = MIN(buflen - 1, *p);
684 if (buffer == NULL)
685 return i;
686 if (i > 0) {
687 memcpy(buffer, p + 1, i * sizeof (WCHAR));
688 buffer[i] = (WCHAR) 0;
689 } else {
690 if (buflen > 1) {
691 buffer[0] = (WCHAR) 0;
692 return 0;
694 #if 0
695 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
696 #endif
699 TRACE(resource,"%s loaded !\n", debugstr_w(buffer));
700 return i;
703 /**********************************************************************
704 * LoadString32A (USER32.375)
706 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
707 LPSTR buffer, INT32 buflen )
709 INT32 retval;
710 LPWSTR buffer2 = NULL;
711 if (buffer && buflen)
712 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
713 retval = LoadString32W(instance,resource_id,buffer2,buflen);
715 if (buffer2)
717 if (retval) {
718 lstrcpynWtoA( buffer, buffer2, buflen );
719 retval = lstrlen32A( buffer );
721 else
722 *buffer = 0;
723 HeapFree( GetProcessHeap(), 0, buffer2 );
725 return retval;
728 /* Messages...used by FormatMessage32* (KERNEL32.something)
730 * They can be specified either directly or using a message ID and
731 * loading them from the resource.
733 * The resourcedata has following format:
734 * start:
735 * 0: DWORD nrofentries
736 * nrofentries * subentry:
737 * 0: DWORD firstentry
738 * 4: DWORD lastentry
739 * 8: DWORD offset from start to the stringentries
741 * (lastentry-firstentry) * stringentry:
742 * 0: WORD len (0 marks end)
743 * 2: WORD unknown (flags?)
744 * 4: CHAR[len-4]
745 * (stringentry i of a subentry refers to the ID 'firstentry+i')
747 * Yes, ANSI strings in win32 resources. Go figure.
750 /**********************************************************************
751 * LoadMessage32A (internal)
753 INT32 WINAPI LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
754 LPSTR buffer, INT32 buflen )
756 HGLOBAL32 hmem;
757 HRSRC32 hrsrc;
758 BYTE *p;
759 int nrofentries,i,slen;
760 struct _subentry {
761 DWORD firstentry;
762 DWORD lastentry;
763 DWORD offset;
764 } *se;
765 struct _stringentry {
766 WORD len;
767 WORD unknown;
768 CHAR str[1];
769 } *stre;
771 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
773 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
774 hrsrc = FindResourceEx32W(instance,RT_MESSAGELIST32W,(LPWSTR)1,lang);
775 if (!hrsrc) return 0;
776 hmem = LoadResource32( instance, hrsrc );
777 if (!hmem) return 0;
779 p = LockResource32(hmem);
780 nrofentries = *(DWORD*)p;
781 stre = NULL;
782 se = (struct _subentry*)(p+4);
783 for (i=nrofentries;i--;) {
784 if ((id>=se->firstentry) && (id<=se->lastentry)) {
785 stre = (struct _stringentry*)(p+se->offset);
786 id -= se->firstentry;
787 break;
789 se++;
791 if (!stre)
792 return 0;
793 for (i=id;i--;) {
794 if (!(slen=stre->len))
795 return 0;
796 stre = (struct _stringentry*)(((char*)stre)+slen);
798 slen=stre->len;
799 TRACE(resource," - strlen=%d\n",slen);
800 i = MIN(buflen - 1, slen);
801 if (buffer == NULL)
802 return slen; /* different to LoadString */
803 if (i>0) {
804 lstrcpyn32A(buffer,stre->str,i);
805 buffer[i]=0;
806 } else {
807 if (buflen>1) {
808 buffer[0]=0;
809 return 0;
812 if (buffer)
813 TRACE(resource,"'%s' copied !\n", buffer);
814 return i;
817 /**********************************************************************
818 * LoadMessage32W (internal)
820 INT32 WINAPI LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
821 LPWSTR buffer, INT32 buflen )
823 INT32 retval;
824 LPSTR buffer2 = NULL;
825 if (buffer && buflen)
826 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
827 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
828 if (buffer)
830 if (retval) {
831 lstrcpynAtoW( buffer, buffer2, buflen );
832 retval = lstrlen32W( buffer );
834 HeapFree( GetProcessHeap(), 0, buffer2 );
836 return retval;
840 /**********************************************************************
841 * EnumResourceTypesA (KERNEL32.90)
843 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
844 LONG lParam)
846 /* FIXME: move WINE_MODREF stuff here */
847 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
850 /**********************************************************************
851 * EnumResourceTypesW (KERNEL32.91)
853 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
854 LONG lParam)
856 /* FIXME: move WINE_MODREF stuff here */
857 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
860 /**********************************************************************
861 * EnumResourceNamesA (KERNEL32.88)
863 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
864 ENUMRESNAMEPROC32A lpfun, LONG lParam )
866 /* FIXME: move WINE_MODREF stuff here */
867 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
869 /**********************************************************************
870 * EnumResourceNamesW (KERNEL32.89)
872 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
873 ENUMRESNAMEPROC32W lpfun, LONG lParam )
875 /* FIXME: move WINE_MODREF stuff here */
876 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
879 /**********************************************************************
880 * EnumResourceLanguagesA (KERNEL32.86)
882 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
883 LPCSTR name, ENUMRESLANGPROC32A lpfun,
884 LONG lParam)
886 /* FIXME: move WINE_MODREF stuff here */
887 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
889 /**********************************************************************
890 * EnumResourceLanguagesW (KERNEL32.87)
892 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
893 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
894 LONG lParam)
896 /* FIXME: move WINE_MODREF stuff here */
897 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);