Implemented file sharing checks in the server.
[wine/multimedia.git] / loader / resource.c
blobfe281b1f8388dc31ee3f9546ba0f78d9ca4f9e99
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 "gdi.h"
17 #include "global.h"
18 #include "heap.h"
19 #include "neexe.h"
20 #include "task.h"
21 #include "process.h"
22 #include "module.h"
23 #include "file.h"
24 #include "resource.h"
25 #include "debug.h"
26 #include "libres.h"
27 #include "winerror.h"
28 #include "debugstr.h"
30 extern WORD WINE_LanguageId;
32 #define HRSRC_MAP_BLOCKSIZE 16
34 typedef struct _HRSRC_ELEM
36 HANDLE32 hRsrc;
37 WORD type;
38 } HRSRC_ELEM;
40 typedef struct _HRSRC_MAP
42 int nAlloc;
43 int nUsed;
44 HRSRC_ELEM *elem;
45 } HRSRC_MAP;
47 /**********************************************************************
48 * MapHRsrc32To16
50 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE32 hRsrc32, WORD type )
52 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
53 HRSRC_ELEM *newElem;
54 int i;
56 /* On first call, initialize HRSRC map */
57 if ( !map )
59 if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
60 sizeof(HRSRC_MAP) ) ) )
62 ERR( resource, "Cannot allocate HRSRC map\n" );
63 return 0;
65 pModule->hRsrcMap = (LPVOID)map;
68 /* Check whether HRSRC32 already in map */
69 for ( i = 0; i < map->nUsed; i++ )
70 if ( map->elem[i].hRsrc == hRsrc32 )
71 return (HRSRC16)(i + 1);
73 /* If no space left, grow table */
74 if ( map->nUsed == map->nAlloc )
76 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
77 map->elem,
78 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
79 * sizeof(HRSRC_ELEM) ) ))
81 ERR( resource, "Cannot grow HRSRC map\n" );
82 return 0;
84 map->elem = newElem;
85 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
88 /* Add HRSRC32 to table */
89 map->elem[map->nUsed].hRsrc = hRsrc32;
90 map->elem[map->nUsed].type = type;
91 map->nUsed++;
93 return (HRSRC16)map->nUsed;
96 /**********************************************************************
97 * MapHRsrc16To32
99 static HANDLE32 MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
101 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
102 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
104 return map->elem[(int)hRsrc16-1].hRsrc;
107 /**********************************************************************
108 * MapHRsrc16ToType
110 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
112 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
113 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
115 return map->elem[(int)hRsrc16-1].type;
118 /**********************************************************************
119 * FindResource16 (KERNEL.60)
121 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
123 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
124 LPCSTR typeStr = HIWORD(type)? PTR_SEG_TO_LIN(type) : (LPCSTR)type;
126 NE_MODULE *pModule = NE_GetPtr( hModule );
127 if ( !pModule ) return 0;
129 if ( pModule->module32 )
131 HANDLE32 hRsrc32 = FindResource32A( pModule->module32, nameStr, typeStr );
132 return MapHRsrc32To16( pModule, hRsrc32, HIWORD(type)? 0 : type );
135 return NE_FindResource( pModule, nameStr, typeStr );
138 /**********************************************************************
139 * FindResource32A (KERNEL32.128)
141 HANDLE32 WINAPI FindResource32A( HMODULE32 hModule, LPCSTR name, LPCSTR type)
143 return FindResourceEx32A(hModule,type,name,WINE_LanguageId);
146 /**********************************************************************
147 * FindResourceEx32A (KERNEL32.129)
149 HANDLE32 WINAPI FindResourceEx32A( HMODULE32 hModule, LPCSTR type, LPCSTR name,
150 WORD lang
152 LPWSTR xname,xtype;
153 HANDLE32 ret;
155 if (HIWORD((DWORD)name))
156 xname = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
157 else
158 xname = (LPWSTR)name;
159 if (HIWORD((DWORD)type))
160 xtype = HEAP_strdupAtoW( GetProcessHeap(), 0, type);
161 else
162 xtype = (LPWSTR)type;
163 ret = FindResourceEx32W( hModule, xtype, xname, lang );
164 if (HIWORD((DWORD)name)) HeapFree( GetProcessHeap(), 0, xname );
165 if (HIWORD((DWORD)type)) HeapFree( GetProcessHeap(), 0, xtype );
166 return ret;
170 /**********************************************************************
171 * FindResourceEx32W (KERNEL32.130)
173 HRSRC32 WINAPI FindResourceEx32W( HMODULE32 hModule, LPCWSTR type,
174 LPCWSTR name, WORD lang )
176 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
177 HRSRC32 hrsrc;
179 TRACE(resource, "module=%08x(%s) type=%s name=%s\n",
180 hModule, wm->modname,
181 debugres_w (type),
182 debugres_w (name));
184 if (!wm) return (HRSRC32)0;
186 switch (wm->type)
188 case MODULE32_PE:
189 hrsrc = PE_FindResourceEx32W(wm,name,type,lang);
190 break;
192 case MODULE32_ELF:
193 hrsrc = LIBRES_FindResource( hModule, name, type );
194 break;
196 default:
197 ERR(module,"unknown module type %d\n",wm->type);
198 return (HRSRC32)0;
201 if ( !hrsrc )
202 ERR(resource,"0x%08x(%s) %s(%s) not found!\n", hModule,wm->modname, debugres_w (name), debugres_w (type));
204 return hrsrc;
208 /**********************************************************************
209 * FindResource32W (KERNEL32.131)
211 HRSRC32 WINAPI FindResource32W(HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type)
213 return FindResourceEx32W(hModule,type,name,WINE_LanguageId);
216 /**********************************************************************
217 * LoadResource16 (KERNEL.61)
219 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
221 NE_MODULE *pModule = NE_GetPtr( hModule );
222 if ( !pModule ) return 0;
224 if ( pModule->module32 )
226 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
227 WORD type = MapHRsrc16ToType( pModule, hRsrc );
228 HGLOBAL32 image = LoadResource32( pModule->module32, hRsrc32 );
229 DWORD size = SizeofResource32( pModule->module32, hRsrc32 );
230 LPVOID bits = LockResource32( image );
232 return NE_LoadPEResource( pModule, type, bits, size );
235 return NE_LoadResource( pModule, hRsrc );
238 /**********************************************************************
239 * LoadResource32 (KERNEL32.370)
240 * 'loads' a resource. The current implementation just returns a pointer
241 * into the already mapped image.
242 * RETURNS
243 * pointer into the mapped resource of the passed module
245 HGLOBAL32 WINAPI LoadResource32(
246 HINSTANCE32 hModule, /* [in] module handle */
247 HRSRC32 hRsrc ) /* [in] resource handle */
249 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
251 TRACE(resource, "module=%04x res=%04x\n",
252 hModule, hRsrc );
253 if (!hRsrc) {
254 ERR(resource,"hRsrc is 0, return 0.\n");
255 return 0;
257 if (!wm) return 0;
259 switch (wm->type)
261 case MODULE32_PE:
262 return PE_LoadResource32(wm,hRsrc);
264 case MODULE32_ELF:
265 return LIBRES_LoadResource( hModule, hRsrc );
267 default:
268 ERR(resource,"unknown module type %d\n",wm->type);
269 break;
271 return 0;
274 /**********************************************************************
275 * LockResource16 (KERNEL.62)
277 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
279 TRACE( resource, "handle=%04x\n", handle );
280 if (!handle) return (SEGPTR)0;
282 /* May need to reload the resource if discarded */
283 return (SEGPTR)WIN16_GlobalLock16( handle );
285 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
287 return (LPVOID)PTR_SEG_TO_LIN( WIN16_LockResource16( handle ) );
290 /**********************************************************************
291 * LockResource32 (KERNEL32.384)
293 LPVOID WINAPI LockResource32( HGLOBAL32 handle )
295 return (LPVOID)handle;
299 /**********************************************************************
300 * FreeResource16 (KERNEL.63)
302 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
304 NE_MODULE *pModule = NE_GetPtr( FarGetOwner(handle) );
305 if ( !pModule ) return handle;
307 if ( pModule->module32 )
308 return NE_FreePEResource( pModule, handle );
310 return NE_FreeResource( pModule, handle );
313 /**********************************************************************
314 * FreeResource32 (KERNEL32.145)
316 BOOL32 WINAPI FreeResource32( HGLOBAL32 handle )
318 /* no longer used in Win32 */
319 return TRUE;
322 /**********************************************************************
323 * AccessResource16 (KERNEL.64)
325 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
327 NE_MODULE *pModule = NE_GetPtr( hModule );
328 if ( !pModule ) return 0;
330 if ( pModule->module32 )
332 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
333 HFILE32 hFile32 = AccessResource32( pModule->module32, hRsrc32 );
334 return HFILE32_TO_HFILE16( hFile32 );
337 return NE_AccessResource( pModule, hRsrc );
340 /**********************************************************************
341 * AccessResource32 (KERNEL32.64)
343 INT32 WINAPI AccessResource32( HMODULE32 hModule, HRSRC32 hRsrc )
345 FIXME(resource,"(module=%08x res=%08x),not implemented\n", hModule, hRsrc);
346 return 0;
350 /**********************************************************************
351 * SizeofResource16 (KERNEL.65)
353 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
355 NE_MODULE *pModule = NE_GetPtr( hModule );
356 if ( !pModule ) return 0;
358 if ( pModule->module32 )
360 HANDLE32 hRsrc32 = MapHRsrc16To32( pModule, hRsrc );
361 return SizeofResource32( hModule, hRsrc32 );
364 return NE_SizeofResource( pModule, hRsrc );
367 /**********************************************************************
368 * SizeofResource32 (KERNEL32.522)
370 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
372 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
374 TRACE(resource, "module=%08x res=%08x\n", hModule, hRsrc );
375 if (!wm) return 0;
377 switch (wm->type)
379 case MODULE32_PE:
380 return PE_SizeofResource32(hModule,hRsrc);
382 case MODULE32_ELF:
383 return LIBRES_SizeofResource( hModule, hRsrc );
385 default:
386 ERR(module,"unknown module type %d\n",wm->type);
387 break;
389 return 0;
393 /**********************************************************************
394 * LoadAccelerators16 [USER.177]
396 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
398 HRSRC16 hRsrc;
400 if (HIWORD(lpTableName))
401 TRACE(accel, "%04x '%s'\n",
402 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
403 else
404 TRACE(accel, "%04x %04x\n",
405 instance, LOWORD(lpTableName) );
407 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
408 WARN(accel, "couldn't find accelerator table resource\n");
409 return 0;
412 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
413 return LoadResource16(instance,hRsrc);
416 /**********************************************************************
417 * LoadAccelerators32W [USER.177]
418 * The image layout seems to look like this (not 100% sure):
419 * 00: BYTE type type of accelerator
420 * 01: BYTE pad (to WORD boundary)
421 * 02: WORD event
422 * 04: WORD IDval
423 * 06: WORD pad (to DWORD boundary)
425 HACCEL32 WINAPI LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
427 HRSRC32 hRsrc;
428 HACCEL32 hRetval;
429 DWORD size;
431 if (HIWORD(lpTableName))
432 TRACE(accel, "%p '%s'\n",
433 (LPVOID)instance, (char *)( lpTableName ) );
434 else
435 TRACE(accel, "%p 0x%04x\n",
436 (LPVOID)instance, LOWORD(lpTableName) );
438 if (!(hRsrc = FindResource32W( instance, lpTableName, RT_ACCELERATOR32W )))
440 WARN(accel, "couldn't find accelerator table resource\n");
441 hRetval = 0;
443 else {
444 hRetval = LoadResource32( instance, hRsrc );
445 size = SizeofResource32( instance, hRsrc );
446 if(size>=sizeof(ACCEL32))
448 LPACCEL32 accel_table = (LPACCEL32) hRetval;
449 /* mark last element as such - sometimes it is not marked in image */
450 accel_table[size/sizeof(ACCEL32)-1].fVirt |= 0x80;
454 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
455 return hRetval;
458 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
460 LPWSTR uni;
461 HACCEL32 result;
462 if (HIWORD(lpTableName))
463 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
464 else
465 uni = (LPWSTR)lpTableName;
466 result = LoadAccelerators32W(instance,uni);
467 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
468 return result;
471 /**********************************************************************
472 * CopyAcceleratorTable32A (USER32.58)
474 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
476 return CopyAcceleratorTable32W(src, dst, entries);
479 /**********************************************************************
480 * CopyAcceleratorTable32W (USER32.59)
482 * By mortene@pvv.org 980321
484 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
485 INT32 entries)
487 int i;
488 LPACCEL32 accel = (LPACCEL32)src;
489 BOOL32 done = FALSE;
491 /* Do parameter checking to avoid the explosions and the screaming
492 as far as possible. */
493 if((dst && (entries < 1)) || (src == (HACCEL32)NULL)) {
494 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
495 (LPVOID)src, (LPVOID)dst, entries);
496 return 0;
500 i=0;
501 while(!done) {
502 /* Spit out some debugging information. */
503 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
504 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
506 /* Copy data to the destination structure array (if dst == NULL,
507 we're just supposed to count the number of entries). */
508 if(dst) {
509 memcpy(&dst[i], &accel[i], sizeof(ACCEL32));
511 /* Check if we've reached the end of the application supplied
512 accelerator table. */
513 if(i+1 == entries) {
514 /* Turn off the high order bit, just in case. */
515 dst[i].fVirt &= 0x7f;
516 done = TRUE;
520 /* The highest order bit seems to mark the end of the accelerator
521 resource table. (?) */
522 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
524 i++;
527 return i;
530 /*********************************************************************
531 * CreateAcceleratorTable (USER32.64)
533 * By mortene@pvv.org 980321
535 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
537 HACCEL32 hAccel;
539 /* Do parameter checking just in case someone's trying to be
540 funny. */
541 if(cEntries < 1) {
542 WARN(accel, "Application sent invalid parameters (%p %d).\n",
543 lpaccel, cEntries);
544 SetLastError(ERROR_INVALID_PARAMETER);
545 return (HACCEL32)NULL;
547 FIXME(accel, "should check that the accelerator descriptions are valid,"
548 " return NULL and SetLastError() if not.\n");
551 /* Allocate memory and copy the table. */
552 hAccel = (HACCEL32)HeapAlloc(GetProcessHeap(), 0,
553 cEntries * sizeof(ACCEL32));
554 TRACE(accel, "handle %p\n", (LPVOID)hAccel);
555 if(!hAccel) {
556 ERR(accel, "Out of memory.\n");
557 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
558 return (HACCEL32)NULL;
560 memcpy((LPACCEL32)hAccel, lpaccel, cEntries * sizeof(ACCEL32));
562 /* Set the end-of-table terminator. */
563 ((LPACCEL32)hAccel)[cEntries-1].fVirt |= 0x80;
565 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
566 return hAccel;
570 /******************************************************************************
571 * DestroyAcceleratorTable [USER32.130]
572 * Destroys an accelerator table
574 * NOTES
575 * By mortene@pvv.org 980321
577 * PARAMS
578 * handle [I] Handle to accelerator table
580 * RETURNS STD
582 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
584 FIXME(accel, "(0x%x): stub\n", handle);
587 /* Weird.. I thought this should work. According to the API
588 specification, DestroyAcceleratorTable() should only be called on
589 HACCEL32's made by CreateAcceleratorTable(), but Microsoft Visual
590 Studio 97 calls this function with a series of different handle
591 values without ever calling CreateAcceleratorTable(). Something
592 is very fishy in Denmark... */
593 /* Update: looks like the calls to this function matches the calls
594 to LoadAccelerators() in M$ Visual Studio, except that the handle
595 values are off by some variable size from the HACCEL's returned
596 from LoadAccelerators(). WTH? */
598 /* Parameter checking to avoid any embarassing situations. */
599 #if 0
600 if(!handle) {
601 WARN(accel, "Application sent NULL ptr.\n");
602 SetLastError(ERROR_INVALID_PARAMETER);
603 return FALSE;
606 HeapFree(GetProcessHeap(), 0, (LPACCEL32)handle);
607 #endif
609 return TRUE;
612 /**********************************************************************
613 * LoadString16
615 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
616 LPSTR buffer, INT16 buflen )
618 HGLOBAL16 hmem;
619 HRSRC16 hrsrc;
620 unsigned char *p;
621 int string_num;
622 int i;
624 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
625 instance, resource_id, (int) buffer, buflen);
627 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
628 if (!hrsrc) return 0;
629 hmem = LoadResource16( instance, hrsrc );
630 if (!hmem) return 0;
632 p = LockResource16(hmem);
633 string_num = resource_id & 0x000f;
634 for (i = 0; i < string_num; i++)
635 p += *p + 1;
637 TRACE(resource, "strlen = %d\n", (int)*p );
639 i = MIN(buflen - 1, *p);
640 if (buffer == NULL)
641 return i;
642 if (i > 0) {
643 memcpy(buffer, p + 1, i);
644 buffer[i] = '\0';
645 } else {
646 if (buflen > 1) {
647 buffer[0] = '\0';
648 return 0;
650 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
652 FreeResource16( hmem );
654 TRACE(resource,"'%s' loaded !\n", buffer);
655 return i;
658 /**********************************************************************
659 * LoadString32W (USER32.376)
661 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
662 LPWSTR buffer, INT32 buflen )
664 HGLOBAL32 hmem;
665 HRSRC32 hrsrc;
666 WCHAR *p;
667 int string_num;
668 int i;
670 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
671 resource_id = (UINT32)(-((INT32)resource_id));
672 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
673 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
675 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
676 RT_STRING32W );
677 if (!hrsrc) return 0;
678 hmem = LoadResource32( instance, hrsrc );
679 if (!hmem) return 0;
681 p = LockResource32(hmem);
682 string_num = resource_id & 0x000f;
683 for (i = 0; i < string_num; i++)
684 p += *p + 1;
686 TRACE(resource, "strlen = %d\n", (int)*p );
688 i = MIN(buflen - 1, *p);
689 if (buffer == NULL)
690 return i;
691 if (i > 0) {
692 memcpy(buffer, p + 1, i * sizeof (WCHAR));
693 buffer[i] = (WCHAR) 0;
694 } else {
695 if (buflen > 1) {
696 buffer[0] = (WCHAR) 0;
697 return 0;
699 #if 0
700 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
701 #endif
704 TRACE(resource,"%s loaded !\n", debugstr_w(buffer));
705 return i;
708 /**********************************************************************
709 * LoadString32A (USER32.375)
711 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
712 LPSTR buffer, INT32 buflen )
714 INT32 retval;
715 LPWSTR buffer2 = NULL;
716 if (buffer && buflen)
717 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
718 retval = LoadString32W(instance,resource_id,buffer2,buflen);
720 if (buffer2)
722 if (retval) {
723 lstrcpynWtoA( buffer, buffer2, buflen );
724 retval = lstrlen32A( buffer );
726 else
727 *buffer = 0;
728 HeapFree( GetProcessHeap(), 0, buffer2 );
730 return retval;
733 /* Messages...used by FormatMessage32* (KERNEL32.something)
735 * They can be specified either directly or using a message ID and
736 * loading them from the resource.
738 * The resourcedata has following format:
739 * start:
740 * 0: DWORD nrofentries
741 * nrofentries * subentry:
742 * 0: DWORD firstentry
743 * 4: DWORD lastentry
744 * 8: DWORD offset from start to the stringentries
746 * (lastentry-firstentry) * stringentry:
747 * 0: WORD len (0 marks end)
748 * 2: WORD unknown (flags?)
749 * 4: CHAR[len-4]
750 * (stringentry i of a subentry refers to the ID 'firstentry+i')
752 * Yes, ANSI strings in win32 resources. Go figure.
755 /**********************************************************************
756 * LoadMessage32A (internal)
758 INT32 WINAPI LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
759 LPSTR buffer, INT32 buflen )
761 HGLOBAL32 hmem;
762 HRSRC32 hrsrc;
763 BYTE *p;
764 int nrofentries,i,slen;
765 struct _subentry {
766 DWORD firstentry;
767 DWORD lastentry;
768 DWORD offset;
769 } *se;
770 struct _stringentry {
771 WORD len;
772 WORD unknown;
773 CHAR str[1];
774 } *stre;
776 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
778 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
779 hrsrc = FindResourceEx32W(instance,RT_MESSAGELIST32W,(LPWSTR)1,lang);
780 if (!hrsrc) return 0;
781 hmem = LoadResource32( instance, hrsrc );
782 if (!hmem) return 0;
784 p = LockResource32(hmem);
785 nrofentries = *(DWORD*)p;
786 stre = NULL;
787 se = (struct _subentry*)(p+4);
788 for (i=nrofentries;i--;) {
789 if ((id>=se->firstentry) && (id<=se->lastentry)) {
790 stre = (struct _stringentry*)(p+se->offset);
791 id -= se->firstentry;
792 break;
794 se++;
796 if (!stre)
797 return 0;
798 for (i=id;i--;) {
799 if (!(slen=stre->len))
800 return 0;
801 stre = (struct _stringentry*)(((char*)stre)+slen);
803 slen=stre->len;
804 TRACE(resource," - strlen=%d\n",slen);
805 i = MIN(buflen - 1, slen);
806 if (buffer == NULL)
807 return slen; /* different to LoadString */
808 if (i>0) {
809 lstrcpyn32A(buffer,stre->str,i);
810 buffer[i]=0;
811 } else {
812 if (buflen>1) {
813 buffer[0]=0;
814 return 0;
817 if (buffer)
818 TRACE(resource,"'%s' copied !\n", buffer);
819 return i;
822 /**********************************************************************
823 * LoadMessage32W (internal)
825 INT32 WINAPI LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
826 LPWSTR buffer, INT32 buflen )
828 INT32 retval;
829 LPSTR buffer2 = NULL;
830 if (buffer && buflen)
831 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
832 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
833 if (buffer)
835 if (retval) {
836 lstrcpynAtoW( buffer, buffer2, buflen );
837 retval = lstrlen32W( buffer );
839 HeapFree( GetProcessHeap(), 0, buffer2 );
841 return retval;
845 /**********************************************************************
846 * EnumResourceTypesA (KERNEL32.90)
848 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
849 LONG lParam)
851 /* FIXME: move WINE_MODREF stuff here */
852 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
855 /**********************************************************************
856 * EnumResourceTypesW (KERNEL32.91)
858 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
859 LONG lParam)
861 /* FIXME: move WINE_MODREF stuff here */
862 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
865 /**********************************************************************
866 * EnumResourceNamesA (KERNEL32.88)
868 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
869 ENUMRESNAMEPROC32A lpfun, LONG lParam )
871 /* FIXME: move WINE_MODREF stuff here */
872 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
874 /**********************************************************************
875 * EnumResourceNamesW (KERNEL32.89)
877 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
878 ENUMRESNAMEPROC32W lpfun, LONG lParam )
880 /* FIXME: move WINE_MODREF stuff here */
881 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
884 /**********************************************************************
885 * EnumResourceLanguagesA (KERNEL32.86)
887 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
888 LPCSTR name, ENUMRESLANGPROC32A lpfun,
889 LONG lParam)
891 /* FIXME: move WINE_MODREF stuff here */
892 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
894 /**********************************************************************
895 * EnumResourceLanguagesW (KERNEL32.87)
897 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
898 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
899 LONG lParam)
901 /* FIXME: move WINE_MODREF stuff here */
902 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);