Attempt at fixing the MAX_PATH multiple definition problem.
[wine.git] / loader / resource.c
blob1675cadcfa6c719562fbdc395363e51bed244f3e
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=0;
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 } else {
443 hMem = LoadResource32( instance, hRsrc );
444 size = SizeofResource32( instance, hRsrc );
445 if(size>=sizeof(PE_ACCEL))
447 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
448 LPACCEL16 accel16;
449 int i,nrofaccells = size/sizeof(PE_ACCEL);
451 hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
452 accel16 = (LPACCEL16)GlobalLock16(hRetval);
453 for (i=0;i<nrofaccells;i++) {
454 accel16[i].fVirt = accel_table[i].fVirt;
455 accel16[i].key = accel_table[i].key;
456 accel16[i].cmd = accel_table[i].cmd;
458 accel16[i-1].fVirt |= 0x80;
461 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
462 return hRetval;
465 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
467 LPWSTR uni;
468 HACCEL32 result;
469 if (HIWORD(lpTableName))
470 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
471 else
472 uni = (LPWSTR)lpTableName;
473 result = LoadAccelerators32W(instance,uni);
474 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
475 return result;
478 /**********************************************************************
479 * CopyAcceleratorTable32A (USER32.58)
481 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
483 return CopyAcceleratorTable32W(src, dst, entries);
486 /**********************************************************************
487 * CopyAcceleratorTable32W (USER32.59)
489 * By mortene@pvv.org 980321
491 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
492 INT32 entries)
494 int i,xsize;
495 LPACCEL16 accel = (LPACCEL16)GlobalLock16(src);
496 BOOL32 done = FALSE;
498 /* Do parameter checking to avoid the explosions and the screaming
499 as far as possible. */
500 if((dst && (entries < 1)) || (src == (HACCEL32)NULL) || !accel) {
501 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
502 (LPVOID)src, (LPVOID)dst, entries);
503 return 0;
505 xsize = GlobalSize16(src)/sizeof(ACCEL16);
506 if (xsize>entries) entries=xsize;
508 i=0;
509 while(!done) {
510 /* Spit out some debugging information. */
511 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
512 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
514 /* Copy data to the destination structure array (if dst == NULL,
515 we're just supposed to count the number of entries). */
516 if(dst) {
517 dst[i].fVirt = accel[i].fVirt;
518 dst[i].key = accel[i].key;
519 dst[i].cmd = accel[i].cmd;
521 /* Check if we've reached the end of the application supplied
522 accelerator table. */
523 if(i+1 == entries) {
524 /* Turn off the high order bit, just in case. */
525 dst[i].fVirt &= 0x7f;
526 done = TRUE;
530 /* The highest order bit seems to mark the end of the accelerator
531 resource table, but not always. Use GlobalSize() check too. */
532 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
534 i++;
537 return i;
540 /*********************************************************************
541 * CreateAcceleratorTable (USER32.64)
543 * By mortene@pvv.org 980321
545 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
547 HACCEL32 hAccel;
548 LPACCEL16 accel;
549 int i;
551 /* Do parameter checking just in case someone's trying to be
552 funny. */
553 if(cEntries < 1) {
554 WARN(accel, "Application sent invalid parameters (%p %d).\n",
555 lpaccel, cEntries);
556 SetLastError(ERROR_INVALID_PARAMETER);
557 return (HACCEL32)NULL;
559 FIXME(accel, "should check that the accelerator descriptions are valid,"
560 " return NULL and SetLastError() if not.\n");
563 /* Allocate memory and copy the table. */
564 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
566 TRACE(accel, "handle %x\n", hAccel);
567 if(!hAccel) {
568 ERR(accel, "Out of memory.\n");
569 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
570 return (HACCEL32)NULL;
572 accel = GlobalLock16(hAccel);
573 for (i=0;i<cEntries;i++) {
574 accel[i].fVirt = lpaccel[i].fVirt;
575 accel[i].key = lpaccel[i].key;
576 accel[i].cmd = lpaccel[i].cmd;
578 /* Set the end-of-table terminator. */
579 accel[cEntries-1].fVirt |= 0x80;
581 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
582 return hAccel;
586 /******************************************************************************
587 * DestroyAcceleratorTable [USER32.130]
588 * Destroys an accelerator table
590 * NOTES
591 * By mortene@pvv.org 980321
593 * PARAMS
594 * handle [I] Handle to accelerator table
596 * RETURNS STD
598 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
600 FIXME(accel, "(0x%x): stub\n", handle);
601 /* FIXME: GlobalFree16(handle); */
602 return TRUE;
605 /**********************************************************************
606 * LoadString16
608 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
609 LPSTR buffer, INT16 buflen )
611 HGLOBAL16 hmem;
612 HRSRC16 hrsrc;
613 unsigned char *p;
614 int string_num;
615 int i;
617 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
618 instance, resource_id, (int) buffer, buflen);
620 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
621 if (!hrsrc) return 0;
622 hmem = LoadResource16( instance, hrsrc );
623 if (!hmem) return 0;
625 p = LockResource16(hmem);
626 string_num = resource_id & 0x000f;
627 for (i = 0; i < string_num; i++)
628 p += *p + 1;
630 TRACE(resource, "strlen = %d\n", (int)*p );
632 i = MIN(buflen - 1, *p);
633 if (buffer == NULL)
634 return i;
635 if (i > 0) {
636 memcpy(buffer, p + 1, i);
637 buffer[i] = '\0';
638 } else {
639 if (buflen > 1) {
640 buffer[0] = '\0';
641 return 0;
643 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
645 FreeResource16( hmem );
647 TRACE(resource,"'%s' loaded !\n", buffer);
648 return i;
651 /**********************************************************************
652 * LoadString32W (USER32.376)
654 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
655 LPWSTR buffer, INT32 buflen )
657 HGLOBAL32 hmem;
658 HRSRC32 hrsrc;
659 WCHAR *p;
660 int string_num;
661 int i;
663 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
664 resource_id = (UINT32)(-((INT32)resource_id));
665 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
666 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
668 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
669 RT_STRING32W );
670 if (!hrsrc) return 0;
671 hmem = LoadResource32( instance, hrsrc );
672 if (!hmem) return 0;
674 p = LockResource32(hmem);
675 string_num = resource_id & 0x000f;
676 for (i = 0; i < string_num; i++)
677 p += *p + 1;
679 TRACE(resource, "strlen = %d\n", (int)*p );
681 i = MIN(buflen - 1, *p);
682 if (buffer == NULL)
683 return i;
684 if (i > 0) {
685 memcpy(buffer, p + 1, i * sizeof (WCHAR));
686 buffer[i] = (WCHAR) 0;
687 } else {
688 if (buflen > 1) {
689 buffer[0] = (WCHAR) 0;
690 return 0;
692 #if 0
693 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
694 #endif
697 TRACE(resource,"%s loaded !\n", debugstr_w(buffer));
698 return i;
701 /**********************************************************************
702 * LoadString32A (USER32.375)
704 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
705 LPSTR buffer, INT32 buflen )
707 INT32 retval;
708 LPWSTR buffer2 = NULL;
709 if (buffer && buflen)
710 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
711 retval = LoadString32W(instance,resource_id,buffer2,buflen);
713 if (buffer2)
715 if (retval) {
716 lstrcpynWtoA( buffer, buffer2, buflen );
717 retval = lstrlen32A( buffer );
719 else
720 *buffer = 0;
721 HeapFree( GetProcessHeap(), 0, buffer2 );
723 return retval;
726 /* Messages...used by FormatMessage32* (KERNEL32.something)
728 * They can be specified either directly or using a message ID and
729 * loading them from the resource.
731 * The resourcedata has following format:
732 * start:
733 * 0: DWORD nrofentries
734 * nrofentries * subentry:
735 * 0: DWORD firstentry
736 * 4: DWORD lastentry
737 * 8: DWORD offset from start to the stringentries
739 * (lastentry-firstentry) * stringentry:
740 * 0: WORD len (0 marks end)
741 * 2: WORD unknown (flags?)
742 * 4: CHAR[len-4]
743 * (stringentry i of a subentry refers to the ID 'firstentry+i')
745 * Yes, ANSI strings in win32 resources. Go figure.
748 /**********************************************************************
749 * LoadMessage32A (internal)
751 INT32 WINAPI LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
752 LPSTR buffer, INT32 buflen )
754 HGLOBAL32 hmem;
755 HRSRC32 hrsrc;
756 BYTE *p;
757 int nrofentries,i,slen;
758 struct _subentry {
759 DWORD firstentry;
760 DWORD lastentry;
761 DWORD offset;
762 } *se;
763 struct _stringentry {
764 WORD len;
765 WORD unknown;
766 CHAR str[1];
767 } *stre;
769 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
771 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
772 hrsrc = FindResourceEx32W(instance,RT_MESSAGELIST32W,(LPWSTR)1,lang);
773 if (!hrsrc) return 0;
774 hmem = LoadResource32( instance, hrsrc );
775 if (!hmem) return 0;
777 p = LockResource32(hmem);
778 nrofentries = *(DWORD*)p;
779 stre = NULL;
780 se = (struct _subentry*)(p+4);
781 for (i=nrofentries;i--;) {
782 if ((id>=se->firstentry) && (id<=se->lastentry)) {
783 stre = (struct _stringentry*)(p+se->offset);
784 id -= se->firstentry;
785 break;
787 se++;
789 if (!stre)
790 return 0;
791 for (i=id;i--;) {
792 if (!(slen=stre->len))
793 return 0;
794 stre = (struct _stringentry*)(((char*)stre)+slen);
796 slen=stre->len;
797 TRACE(resource," - strlen=%d\n",slen);
798 i = MIN(buflen - 1, slen);
799 if (buffer == NULL)
800 return slen; /* different to LoadString */
801 if (i>0) {
802 lstrcpyn32A(buffer,stre->str,i);
803 buffer[i]=0;
804 } else {
805 if (buflen>1) {
806 buffer[0]=0;
807 return 0;
810 if (buffer)
811 TRACE(resource,"'%s' copied !\n", buffer);
812 return i;
815 /**********************************************************************
816 * LoadMessage32W (internal)
818 INT32 WINAPI LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
819 LPWSTR buffer, INT32 buflen )
821 INT32 retval;
822 LPSTR buffer2 = NULL;
823 if (buffer && buflen)
824 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
825 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
826 if (buffer)
828 if (retval) {
829 lstrcpynAtoW( buffer, buffer2, buflen );
830 retval = lstrlen32W( buffer );
832 HeapFree( GetProcessHeap(), 0, buffer2 );
834 return retval;
838 /**********************************************************************
839 * EnumResourceTypesA (KERNEL32.90)
841 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
842 LONG lParam)
844 /* FIXME: move WINE_MODREF stuff here */
845 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
848 /**********************************************************************
849 * EnumResourceTypesW (KERNEL32.91)
851 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
852 LONG lParam)
854 /* FIXME: move WINE_MODREF stuff here */
855 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
858 /**********************************************************************
859 * EnumResourceNamesA (KERNEL32.88)
861 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
862 ENUMRESNAMEPROC32A lpfun, LONG lParam )
864 /* FIXME: move WINE_MODREF stuff here */
865 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
867 /**********************************************************************
868 * EnumResourceNamesW (KERNEL32.89)
870 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
871 ENUMRESNAMEPROC32W lpfun, LONG lParam )
873 /* FIXME: move WINE_MODREF stuff here */
874 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
877 /**********************************************************************
878 * EnumResourceLanguagesA (KERNEL32.86)
880 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
881 LPCSTR name, ENUMRESLANGPROC32A lpfun,
882 LONG lParam)
884 /* FIXME: move WINE_MODREF stuff here */
885 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
887 /**********************************************************************
888 * EnumResourceLanguagesW (KERNEL32.87)
890 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
891 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
892 LONG lParam)
894 /* FIXME: move WINE_MODREF stuff here */
895 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);