Made sleep_on usable from all requests.
[wine/multimedia.git] / loader / resource.c
blob4967f294a579f6700f717167d47a824c26bbbaa0
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 "winbase.h"
16 #include "windef.h"
17 #include "winuser.h"
18 #include "wine/winbase16.h"
19 #include "wine/winuser16.h"
20 #include "ldt.h"
21 #include "global.h"
22 #include "heap.h"
23 #include "callback.h"
24 #include "cursoricon.h"
25 #include "neexe.h"
26 #include "task.h"
27 #include "process.h"
28 #include "module.h"
29 #include "file.h"
30 #include "debugtools.h"
31 #include "libres.h"
32 #include "winerror.h"
33 #include "debugstr.h"
34 #include "winnls.h"
36 DEFAULT_DEBUG_CHANNEL(resource)
37 DECLARE_DEBUG_CHANNEL(accel)
39 extern WORD WINE_LanguageId;
41 #define HRSRC_MAP_BLOCKSIZE 16
43 typedef struct _HRSRC_ELEM
45 HANDLE hRsrc;
46 WORD type;
47 } HRSRC_ELEM;
49 typedef struct _HRSRC_MAP
51 int nAlloc;
52 int nUsed;
53 HRSRC_ELEM *elem;
54 } HRSRC_MAP;
56 /**********************************************************************
57 * MapHRsrc32To16
59 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE hRsrc32, WORD type )
61 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
62 HRSRC_ELEM *newElem;
63 int i;
65 /* On first call, initialize HRSRC map */
66 if ( !map )
68 if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
69 sizeof(HRSRC_MAP) ) ) )
71 ERR("Cannot allocate HRSRC map\n" );
72 return 0;
74 pModule->hRsrcMap = (LPVOID)map;
77 /* Check whether HRSRC32 already in map */
78 for ( i = 0; i < map->nUsed; i++ )
79 if ( map->elem[i].hRsrc == hRsrc32 )
80 return (HRSRC16)(i + 1);
82 /* If no space left, grow table */
83 if ( map->nUsed == map->nAlloc )
85 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
86 map->elem,
87 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
88 * sizeof(HRSRC_ELEM) ) ))
90 ERR("Cannot grow HRSRC map\n" );
91 return 0;
93 map->elem = newElem;
94 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
97 /* Add HRSRC32 to table */
98 map->elem[map->nUsed].hRsrc = hRsrc32;
99 map->elem[map->nUsed].type = type;
100 map->nUsed++;
102 return (HRSRC16)map->nUsed;
105 /**********************************************************************
106 * MapHRsrc16To32
108 static HANDLE MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
110 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
111 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
113 return map->elem[(int)hRsrc16-1].hRsrc;
116 /**********************************************************************
117 * MapHRsrc16ToType
119 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
121 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
122 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
124 return map->elem[(int)hRsrc16-1].type;
128 /**********************************************************************
129 * RES_FindResource
131 static HRSRC RES_FindResource( HMODULE hModule, LPCSTR type,
132 LPCSTR name, WORD lang,
133 BOOL bUnicode, BOOL bRet16 )
135 HRSRC hRsrc = 0;
137 HMODULE16 hMod16 = MapHModuleLS( hModule );
138 NE_MODULE *pModule = NE_GetPtr( hMod16 );
139 WINE_MODREF *wm = pModule && pModule->module32?
140 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
142 TRACE("(%08x %s, %08x%s, %08x%s, %04x, %s, %s)\n",
143 hModule,
144 pModule ? (char *)NE_MODULE_NAME(pModule) : "NULL dereference",
145 (UINT)type, HIWORD(type)? (bUnicode? debugstr_w((LPWSTR)type) : debugstr_a(type)) : "",
146 (UINT)name, HIWORD(name)? (bUnicode? debugstr_w((LPWSTR)name) : debugstr_a(name)) : "",
147 lang,
148 bUnicode? "W" : "A",
149 bRet16? "NE" : "PE" );
151 if ( !pModule ) return 0;
153 if ( wm )
155 /* 32-bit PE/ELF module */
156 LPWSTR typeStr, nameStr;
158 if ( HIWORD( type ) && !bUnicode )
159 typeStr = HEAP_strdupAtoW( GetProcessHeap(), 0, type );
160 else
161 typeStr = (LPWSTR)type;
162 if ( HIWORD( name ) && !bUnicode )
163 nameStr = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
164 else
165 nameStr = (LPWSTR)name;
167 switch ( wm->type )
169 case MODULE32_PE:
170 hRsrc = PE_FindResourceExW( wm, nameStr, typeStr, lang );
171 break;
173 case MODULE32_ELF:
174 hRsrc = LIBRES_FindResource( hModule, nameStr, typeStr );
175 break;
177 default:
178 ERR("unknown module type %d\n", wm->type );
179 break;
182 if ( HIWORD( type ) && !bUnicode )
183 HeapFree( GetProcessHeap(), 0, typeStr );
184 if ( HIWORD( name ) && !bUnicode )
185 HeapFree( GetProcessHeap(), 0, nameStr );
188 /* If we need to return 16-bit HRSRC, perform conversion */
189 if ( bRet16 )
190 hRsrc = MapHRsrc32To16( pModule, hRsrc,
191 HIWORD( type )? 0 : LOWORD( type ) );
193 else
195 /* 16-bit NE module */
196 LPSTR typeStr, nameStr;
198 if ( HIWORD( type ) && bUnicode )
199 typeStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)type );
200 else
201 typeStr = (LPSTR)type;
202 if ( HIWORD( name ) && bUnicode )
203 nameStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)name );
204 else
205 nameStr = (LPSTR)name;
207 hRsrc = NE_FindResource( pModule, nameStr, typeStr );
209 if ( HIWORD( type ) && bUnicode )
210 HeapFree( GetProcessHeap(), 0, typeStr );
211 if ( HIWORD( name ) && bUnicode )
212 HeapFree( GetProcessHeap(), 0, nameStr );
215 /* If we need to return 32-bit HRSRC, no conversion is necessary,
216 we simply use the 16-bit HRSRC as 32-bit HRSRC */
219 return hRsrc;
222 /**********************************************************************
223 * RES_SizeofResource
225 static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
227 DWORD size = 0;
229 HMODULE16 hMod16 = MapHModuleLS( hModule );
230 NE_MODULE *pModule = NE_GetPtr( hMod16 );
231 WINE_MODREF *wm = pModule && pModule->module32?
232 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
234 TRACE("(%08x %s, %08x, %s)\n",
235 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
237 if ( !pModule || !hRsrc ) return 0;
239 if ( wm )
241 /* 32-bit PE/ELF module */
243 /* If we got a 16-bit hRsrc, convert it */
244 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
246 switch ( wm->type )
248 case MODULE32_PE:
249 size = PE_SizeofResource( hModule, hRsrc32 );
250 break;
252 case MODULE32_ELF:
253 size = LIBRES_SizeofResource( hModule, hRsrc32 );
254 break;
256 default:
257 ERR("unknown module type %d\n", wm->type );
258 break;
261 else
263 /* 16-bit NE module */
265 /* If we got a 32-bit hRsrc, we don't need to convert it */
267 size = NE_SizeofResource( pModule, hRsrc );
270 return size;
273 /**********************************************************************
274 * RES_AccessResource
276 static HFILE RES_AccessResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
278 HFILE hFile = HFILE_ERROR;
280 HMODULE16 hMod16 = MapHModuleLS( hModule );
281 NE_MODULE *pModule = NE_GetPtr( hMod16 );
282 WINE_MODREF *wm = pModule && pModule->module32?
283 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
285 TRACE("(%08x %s, %08x, %s)\n",
286 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
288 if ( !pModule || !hRsrc ) return HFILE_ERROR;
290 if ( wm )
292 /* 32-bit PE/ELF module */
293 #if 0
294 /* If we got a 16-bit hRsrc, convert it */
295 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
296 #endif
298 FIXME("32-bit modules not yet supported.\n" );
299 hFile = HFILE_ERROR;
301 /* If we need to return a 16-bit file handle, convert it */
302 if ( bRet16 )
303 hFile = FILE_AllocDosHandle( hFile );
305 else
307 /* 16-bit NE module */
309 /* If we got a 32-bit hRsrc, we don't need to convert it */
311 hFile = NE_AccessResource( pModule, hRsrc );
313 /* If we are to return a 32-bit file handle, convert it */
314 if ( !bRet16 )
315 hFile = FILE_GetHandle( hFile );
318 return hFile;
321 /**********************************************************************
322 * RES_LoadResource
324 static HGLOBAL RES_LoadResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
326 HGLOBAL hMem = 0;
328 HMODULE16 hMod16 = MapHModuleLS( hModule );
329 NE_MODULE *pModule = NE_GetPtr( hMod16 );
330 WINE_MODREF *wm = pModule && pModule->module32?
331 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
333 TRACE("(%08x %s, %08x, %s)\n",
334 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
336 if ( !pModule || !hRsrc ) return 0;
338 if ( wm )
340 /* 32-bit PE/ELF module */
342 /* If we got a 16-bit hRsrc, convert it */
343 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
345 switch ( wm->type )
347 case MODULE32_PE:
348 hMem = PE_LoadResource( wm, hRsrc32 );
349 break;
351 case MODULE32_ELF:
352 hMem = LIBRES_LoadResource( hModule, hRsrc32 );
353 break;
355 default:
356 ERR("unknown module type %d\n", wm->type );
357 break;
360 /* If we need to return a 16-bit resource, convert it */
361 if ( bRet16 )
363 WORD type = MapHRsrc16ToType( pModule, hRsrc );
364 DWORD size = SizeofResource( hModule, hRsrc );
365 LPVOID bits = LockResource( hMem );
367 hMem = NE_LoadPEResource( pModule, type, bits, size );
370 else
372 /* 16-bit NE module */
374 /* If we got a 32-bit hRsrc, we don't need to convert it */
376 hMem = NE_LoadResource( pModule, hRsrc );
378 /* If we are to return a 32-bit resource, we should probably
379 convert it but we don't for now. FIXME !!! */
382 return hMem;
385 /**********************************************************************
386 * RES_LockResource
388 static LPVOID RES_LockResource( HGLOBAL handle, BOOL bRet16 )
390 LPVOID bits = NULL;
392 TRACE("(%08x, %s)\n", handle, bRet16? "NE" : "PE" );
394 if ( HIWORD( handle ) )
396 /* 32-bit memory handle */
398 if ( bRet16 )
399 FIXME("can't return SEGPTR to 32-bit resource %08x.\n", handle );
400 else
401 bits = (LPVOID)handle;
403 else
405 /* 16-bit memory handle */
407 /* May need to reload the resource if discarded */
408 SEGPTR segPtr = WIN16_GlobalLock16( handle );
410 if ( bRet16 )
411 bits = (LPVOID)segPtr;
412 else
413 bits = PTR_SEG_TO_LIN( segPtr );
416 return bits;
419 /**********************************************************************
420 * RES_FreeResource
422 static BOOL RES_FreeResource( HGLOBAL handle )
424 HGLOBAL retv = handle;
426 TRACE("(%08x)\n", handle );
428 if ( HIWORD( handle ) )
430 /* 32-bit memory handle: nothing to do */
432 else
434 /* 16-bit memory handle */
435 NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
437 /* Try NE resource first */
438 retv = NE_FreeResource( pModule, handle );
440 /* If this failed, call USER.DestroyIcon32; this will check
441 whether it is a shared cursor/icon; if not it will call
442 GlobalFree16() */
443 if ( retv ) {
444 if ( Callout.DestroyIcon32 )
445 retv = Callout.DestroyIcon32( handle, CID_RESOURCE );
446 else
447 retv = GlobalFree16( handle );
451 return (BOOL)retv;
455 /**********************************************************************
456 * FindResource16 (KERNEL.60)
458 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
460 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
461 LPCSTR typeStr = HIWORD(type)? PTR_SEG_TO_LIN(type) : (LPCSTR)type;
463 return RES_FindResource( hModule, typeStr, nameStr,
464 WINE_LanguageId, FALSE, TRUE );
467 /**********************************************************************
468 * FindResourceA (KERNEL32.128)
470 HANDLE WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
472 return RES_FindResource( hModule, type, name,
473 WINE_LanguageId, FALSE, FALSE );
476 /**********************************************************************
477 * FindResourceExA (KERNEL32.129)
479 HANDLE WINAPI FindResourceExA( HMODULE hModule,
480 LPCSTR type, LPCSTR name, WORD lang )
482 return RES_FindResource( hModule, type, name,
483 lang, FALSE, FALSE );
486 /**********************************************************************
487 * FindResourceExW (KERNEL32.130)
489 HRSRC WINAPI FindResourceExW( HMODULE hModule,
490 LPCWSTR type, LPCWSTR name, WORD lang )
492 return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
493 lang, TRUE, FALSE );
496 /**********************************************************************
497 * FindResourceW (KERNEL32.131)
499 HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
501 return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
502 WINE_LanguageId, TRUE, FALSE );
505 /**********************************************************************
506 * LoadResource16 (KERNEL.61)
508 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
510 return RES_LoadResource( hModule, hRsrc, TRUE );
513 /**********************************************************************
514 * LoadResource (KERNEL32.370)
516 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
518 return RES_LoadResource( hModule, hRsrc, FALSE );
521 /**********************************************************************
522 * LockResource16 (KERNEL.62)
524 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
526 return (SEGPTR)RES_LockResource( handle, TRUE );
528 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
530 return RES_LockResource( handle, FALSE );
533 /**********************************************************************
534 * LockResource (KERNEL32.384)
536 LPVOID WINAPI LockResource( HGLOBAL handle )
538 return RES_LockResource( handle, FALSE );
541 /**********************************************************************
542 * FreeResource16 (KERNEL.63)
544 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
546 return RES_FreeResource( handle );
549 /**********************************************************************
550 * FreeResource (KERNEL32.145)
552 BOOL WINAPI FreeResource( HGLOBAL handle )
554 return RES_FreeResource( handle );
557 /**********************************************************************
558 * AccessResource16 (KERNEL.64)
560 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
562 return RES_AccessResource( hModule, hRsrc, TRUE );
565 /**********************************************************************
566 * AccessResource (KERNEL32.64)
568 INT WINAPI AccessResource( HMODULE hModule, HRSRC hRsrc )
570 return RES_AccessResource( hModule, hRsrc, FALSE );
573 /**********************************************************************
574 * SizeofResource16 (KERNEL.65)
576 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
578 return RES_SizeofResource( hModule, hRsrc, TRUE );
581 /**********************************************************************
582 * SizeofResource (KERNEL32.522)
584 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
586 return RES_SizeofResource( hModule, hRsrc, FALSE );
591 /**********************************************************************
592 * LoadAccelerators16 [USER.177]
594 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
596 HRSRC16 hRsrc;
598 if (HIWORD(lpTableName))
599 TRACE_(accel)("%04x '%s'\n",
600 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
601 else
602 TRACE_(accel)("%04x %04x\n",
603 instance, LOWORD(lpTableName) );
605 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
606 WARN_(accel)("couldn't find accelerator table resource\n");
607 return 0;
610 TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
611 return LoadResource16(instance,hRsrc);
614 /**********************************************************************
615 * LoadAccelerators32W [USER.177]
616 * The image layout seems to look like this (not 100% sure):
617 * 00: BYTE type type of accelerator
618 * 01: BYTE pad (to WORD boundary)
619 * 02: WORD event
620 * 04: WORD IDval
621 * 06: WORD pad (to DWORD boundary)
623 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
625 HRSRC hRsrc;
626 HACCEL hMem,hRetval=0;
627 DWORD size;
629 if (HIWORD(lpTableName))
630 TRACE_(accel)("%p '%s'\n",
631 (LPVOID)instance, (char *)( lpTableName ) );
632 else
633 TRACE_(accel)("%p 0x%04x\n",
634 (LPVOID)instance, LOWORD(lpTableName) );
636 if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
638 WARN_(accel)("couldn't find accelerator table resource\n");
639 } else {
640 hMem = LoadResource( instance, hRsrc );
641 size = SizeofResource( instance, hRsrc );
642 if(size>=sizeof(PE_ACCEL))
644 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
645 LPACCEL16 accel16;
646 int i,nrofaccells = size/sizeof(PE_ACCEL);
648 hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
649 accel16 = (LPACCEL16)GlobalLock16(hRetval);
650 for (i=0;i<nrofaccells;i++) {
651 accel16[i].fVirt = accel_table[i].fVirt;
652 accel16[i].key = accel_table[i].key;
653 accel16[i].cmd = accel_table[i].cmd;
655 accel16[i-1].fVirt |= 0x80;
658 TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
659 return hRetval;
662 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
664 LPWSTR uni;
665 HACCEL result;
666 if (HIWORD(lpTableName))
667 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
668 else
669 uni = (LPWSTR)lpTableName;
670 result = LoadAcceleratorsW(instance,uni);
671 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
672 return result;
675 /**********************************************************************
676 * CopyAcceleratorTable32A (USER32.58)
678 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
680 return CopyAcceleratorTableW(src, dst, entries);
683 /**********************************************************************
684 * CopyAcceleratorTable32W (USER32.59)
686 * By mortene@pvv.org 980321
688 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
689 INT entries)
691 int i,xsize;
692 LPACCEL16 accel = (LPACCEL16)GlobalLock16(src);
693 BOOL done = FALSE;
695 /* Do parameter checking to avoid the explosions and the screaming
696 as far as possible. */
697 if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel) {
698 WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
699 (LPVOID)src, (LPVOID)dst, entries);
700 return 0;
702 xsize = GlobalSize16(src)/sizeof(ACCEL16);
703 if (xsize>entries) entries=xsize;
705 i=0;
706 while(!done) {
707 /* Spit out some debugging information. */
708 TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
709 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
711 /* Copy data to the destination structure array (if dst == NULL,
712 we're just supposed to count the number of entries). */
713 if(dst) {
714 dst[i].fVirt = accel[i].fVirt;
715 dst[i].key = accel[i].key;
716 dst[i].cmd = accel[i].cmd;
718 /* Check if we've reached the end of the application supplied
719 accelerator table. */
720 if(i+1 == entries) {
721 /* Turn off the high order bit, just in case. */
722 dst[i].fVirt &= 0x7f;
723 done = TRUE;
727 /* The highest order bit seems to mark the end of the accelerator
728 resource table, but not always. Use GlobalSize() check too. */
729 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
731 i++;
734 return i;
737 /*********************************************************************
738 * CreateAcceleratorTable (USER32.64)
740 * By mortene@pvv.org 980321
742 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
744 HACCEL hAccel;
745 LPACCEL16 accel;
746 int i;
748 /* Do parameter checking just in case someone's trying to be
749 funny. */
750 if(cEntries < 1) {
751 WARN_(accel)("Application sent invalid parameters (%p %d).\n",
752 lpaccel, cEntries);
753 SetLastError(ERROR_INVALID_PARAMETER);
754 return (HACCEL)NULL;
756 FIXME_(accel)("should check that the accelerator descriptions are valid,"
757 " return NULL and SetLastError() if not.\n");
760 /* Allocate memory and copy the table. */
761 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
763 TRACE_(accel)("handle %x\n", hAccel);
764 if(!hAccel) {
765 ERR_(accel)("Out of memory.\n");
766 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
767 return (HACCEL)NULL;
769 accel = GlobalLock16(hAccel);
770 for (i=0;i<cEntries;i++) {
771 accel[i].fVirt = lpaccel[i].fVirt;
772 accel[i].key = lpaccel[i].key;
773 accel[i].cmd = lpaccel[i].cmd;
775 /* Set the end-of-table terminator. */
776 accel[cEntries-1].fVirt |= 0x80;
778 TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
779 return hAccel;
782 /*********************************************************************
783 * CreateAcceleratorTableW (USER32.64)
787 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
789 HACCEL hAccel;
790 LPACCEL16 accel;
791 int i;
792 char ckey;
794 /* Do parameter checking just in case someone's trying to be
795 funny. */
796 if(cEntries < 1) {
797 WARN_(accel)("Application sent invalid parameters (%p %d).\n",
798 lpaccel, cEntries);
799 SetLastError(ERROR_INVALID_PARAMETER);
800 return (HACCEL)NULL;
802 FIXME_(accel)("should check that the accelerator descriptions are valid,"
803 " return NULL and SetLastError() if not.\n");
806 /* Allocate memory and copy the table. */
807 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
809 TRACE_(accel)("handle %x\n", hAccel);
810 if(!hAccel) {
811 ERR_(accel)("Out of memory.\n");
812 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
813 return (HACCEL)NULL;
815 accel = GlobalLock16(hAccel);
818 for (i=0;i<cEntries;i++) {
819 accel[i].fVirt = lpaccel[i].fVirt;
820 if( !(accel[i].fVirt & FVIRTKEY) ) {
821 ckey = (char) lpaccel[i].key;
822 if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
823 WARN_(accel)("Error converting ASCII accelerator table to Unicode");
825 else
826 accel[i].key = lpaccel[i].key;
827 accel[i].cmd = lpaccel[i].cmd;
830 /* Set the end-of-table terminator. */
831 accel[cEntries-1].fVirt |= 0x80;
833 TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
834 return hAccel;
837 /******************************************************************************
838 * DestroyAcceleratorTable [USER32.130]
839 * Destroys an accelerator table
841 * NOTES
842 * By mortene@pvv.org 980321
844 * PARAMS
845 * handle [I] Handle to accelerator table
847 * RETURNS STD
849 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
851 return GlobalFree16(handle);
854 /**********************************************************************
855 * LoadString16
857 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
858 LPSTR buffer, INT16 buflen )
860 HGLOBAL16 hmem;
861 HRSRC16 hrsrc;
862 unsigned char *p;
863 int string_num;
864 int i;
866 TRACE("inst=%04x id=%04x buff=%08x len=%d\n",
867 instance, resource_id, (int) buffer, buflen);
869 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
870 if (!hrsrc) return 0;
871 hmem = LoadResource16( instance, hrsrc );
872 if (!hmem) return 0;
874 p = LockResource16(hmem);
875 string_num = resource_id & 0x000f;
876 for (i = 0; i < string_num; i++)
877 p += *p + 1;
879 TRACE("strlen = %d\n", (int)*p );
881 if (buffer == NULL) return *p;
882 i = MIN(buflen - 1, *p);
883 if (i > 0) {
884 memcpy(buffer, p + 1, i);
885 buffer[i] = '\0';
886 } else {
887 if (buflen > 1) {
888 buffer[0] = '\0';
889 return 0;
891 WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
893 FreeResource16( hmem );
895 TRACE("'%s' loaded !\n", buffer);
896 return i;
899 /**********************************************************************
900 * LoadString32W (USER32.376)
902 INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
903 LPWSTR buffer, INT buflen )
905 HGLOBAL hmem;
906 HRSRC hrsrc;
907 WCHAR *p;
908 int string_num;
909 int i;
911 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
912 resource_id = (UINT)(-((INT)resource_id));
913 TRACE("instance = %04x, id = %04x, buffer = %08x, "
914 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
916 /* Use bits 4 - 19 (incremented by 1) as resourceid, mask out
917 * 20 - 31. */
918 hrsrc = FindResourceW( instance, (LPCWSTR)(((resource_id>>4)&0xffff)+1),
919 RT_STRINGW );
920 if (!hrsrc) return 0;
921 hmem = LoadResource( instance, hrsrc );
922 if (!hmem) return 0;
924 p = LockResource(hmem);
925 string_num = resource_id & 0x000f;
926 for (i = 0; i < string_num; i++)
927 p += *p + 1;
929 TRACE("strlen = %d\n", (int)*p );
931 if (buffer == NULL) return *p;
932 i = MIN(buflen - 1, *p);
933 if (i > 0) {
934 memcpy(buffer, p + 1, i * sizeof (WCHAR));
935 buffer[i] = (WCHAR) 0;
936 } else {
937 if (buflen > 1) {
938 buffer[0] = (WCHAR) 0;
939 return 0;
941 #if 0
942 WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
943 #endif
946 TRACE("%s loaded !\n", debugstr_w(buffer));
947 return i;
950 /**********************************************************************
951 * LoadString32A (USER32.375)
953 INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id,
954 LPSTR buffer, INT buflen )
956 INT retval;
957 LPWSTR buffer2 = NULL;
958 if (buffer && buflen)
959 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
960 retval = LoadStringW(instance,resource_id,buffer2,buflen);
962 if (buffer2)
964 if (retval) {
965 lstrcpynWtoA( buffer, buffer2, buflen );
966 retval = lstrlenA( buffer );
968 else
969 *buffer = 0;
970 HeapFree( GetProcessHeap(), 0, buffer2 );
972 return retval;
975 /* Messages...used by FormatMessage32* (KERNEL32.something)
977 * They can be specified either directly or using a message ID and
978 * loading them from the resource.
980 * The resourcedata has following format:
981 * start:
982 * 0: DWORD nrofentries
983 * nrofentries * subentry:
984 * 0: DWORD firstentry
985 * 4: DWORD lastentry
986 * 8: DWORD offset from start to the stringentries
988 * (lastentry-firstentry) * stringentry:
989 * 0: WORD len (0 marks end)
990 * 2: WORD flags
991 * 4: CHAR[len-4]
992 * (stringentry i of a subentry refers to the ID 'firstentry+i')
994 * Yes, ANSI strings in win32 resources. Go figure.
997 /**********************************************************************
998 * LoadMessage32A (internal)
1000 INT WINAPI LoadMessageA( HMODULE instance, UINT id, WORD lang,
1001 LPSTR buffer, INT buflen )
1003 HGLOBAL hmem;
1004 HRSRC hrsrc;
1005 PMESSAGE_RESOURCE_DATA mrd;
1006 PMESSAGE_RESOURCE_BLOCK mrb;
1007 PMESSAGE_RESOURCE_ENTRY mre;
1008 int i,slen;
1010 TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
1012 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
1013 hrsrc = FindResourceExW(instance,RT_MESSAGELISTW,(LPWSTR)1,lang);
1014 if (!hrsrc) return 0;
1015 hmem = LoadResource( instance, hrsrc );
1016 if (!hmem) return 0;
1018 mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
1019 mre = NULL;
1020 mrb = &(mrd->Blocks[0]);
1021 for (i=mrd->NumberOfBlocks;i--;) {
1022 if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
1023 mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
1024 id -= mrb->LowId;
1025 break;
1027 mrb++;
1029 if (!mre)
1030 return 0;
1031 for (i=id;i--;) {
1032 if (!mre->Length)
1033 return 0;
1034 mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+(mre->Length));
1036 slen=mre->Length;
1037 TRACE(" - strlen=%d\n",slen);
1038 i = MIN(buflen - 1, slen);
1039 if (buffer == NULL)
1040 return slen;
1041 if (i>0) {
1042 lstrcpynA(buffer,(char*)mre->Text,i);
1043 buffer[i]=0;
1044 } else {
1045 if (buflen>1) {
1046 buffer[0]=0;
1047 return 0;
1050 if (buffer)
1051 TRACE("'%s' copied !\n", buffer);
1052 return i;
1055 /**********************************************************************
1056 * LoadMessage32W (internal)
1058 INT WINAPI LoadMessageW( HMODULE instance, UINT id, WORD lang,
1059 LPWSTR buffer, INT buflen )
1061 INT retval;
1062 LPSTR buffer2 = NULL;
1063 if (buffer && buflen)
1064 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
1065 retval = LoadMessageA(instance,id,lang,buffer2,buflen);
1066 if (buffer)
1068 if (retval) {
1069 lstrcpynAtoW( buffer, buffer2, buflen );
1070 retval = lstrlenW( buffer );
1072 HeapFree( GetProcessHeap(), 0, buffer2 );
1074 return retval;
1078 /**********************************************************************
1079 * EnumResourceTypesA (KERNEL32.90)
1081 BOOL WINAPI EnumResourceTypesA( HMODULE hmodule,ENUMRESTYPEPROCA lpfun,
1082 LONG lParam)
1084 /* FIXME: move WINE_MODREF stuff here */
1085 return PE_EnumResourceTypesA(hmodule,lpfun,lParam);
1088 /**********************************************************************
1089 * EnumResourceTypesW (KERNEL32.91)
1091 BOOL WINAPI EnumResourceTypesW( HMODULE hmodule,ENUMRESTYPEPROCW lpfun,
1092 LONG lParam)
1094 /* FIXME: move WINE_MODREF stuff here */
1095 return PE_EnumResourceTypesW(hmodule,lpfun,lParam);
1098 /**********************************************************************
1099 * EnumResourceNamesA (KERNEL32.88)
1101 BOOL WINAPI EnumResourceNamesA( HMODULE hmodule, LPCSTR type,
1102 ENUMRESNAMEPROCA lpfun, LONG lParam )
1104 /* FIXME: move WINE_MODREF stuff here */
1105 return PE_EnumResourceNamesA(hmodule,type,lpfun,lParam);
1107 /**********************************************************************
1108 * EnumResourceNamesW (KERNEL32.89)
1110 BOOL WINAPI EnumResourceNamesW( HMODULE hmodule, LPCWSTR type,
1111 ENUMRESNAMEPROCW lpfun, LONG lParam )
1113 /* FIXME: move WINE_MODREF stuff here */
1114 return PE_EnumResourceNamesW(hmodule,type,lpfun,lParam);
1117 /**********************************************************************
1118 * EnumResourceLanguagesA (KERNEL32.86)
1120 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmodule, LPCSTR type,
1121 LPCSTR name, ENUMRESLANGPROCA lpfun,
1122 LONG lParam)
1124 /* FIXME: move WINE_MODREF stuff here */
1125 return PE_EnumResourceLanguagesA(hmodule,type,name,lpfun,lParam);
1127 /**********************************************************************
1128 * EnumResourceLanguagesW (KERNEL32.87)
1130 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmodule, LPCWSTR type,
1131 LPCWSTR name, ENUMRESLANGPROCW lpfun,
1132 LONG lParam)
1134 /* FIXME: move WINE_MODREF stuff here */
1135 return PE_EnumResourceLanguagesW(hmodule,type,name,lpfun,lParam);