Allow the size of bitmaps to be changed after toolbar buttons have
[wine.git] / loader / resource.c
blob71a55243f298cbdd2a52f5ee28f19ca0faa74dee
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 "wingdi.h"
18 #include "winuser.h"
19 #include "wine/winbase16.h"
20 #include "wine/winuser16.h"
21 #include "wine/exception.h"
22 #include "ldt.h"
23 #include "global.h"
24 #include "heap.h"
25 #include "callback.h"
26 #include "cursoricon.h"
27 #include "neexe.h"
28 #include "task.h"
29 #include "process.h"
30 #include "module.h"
31 #include "file.h"
32 #include "debugtools.h"
33 #include "winerror.h"
34 #include "winnls.h"
36 DEFAULT_DEBUG_CHANNEL(resource);
37 DECLARE_DEBUG_CHANNEL(accel);
39 #define HRSRC_MAP_BLOCKSIZE 16
41 typedef struct _HRSRC_ELEM
43 HANDLE hRsrc;
44 WORD type;
45 } HRSRC_ELEM;
47 typedef struct _HRSRC_MAP
49 int nAlloc;
50 int nUsed;
51 HRSRC_ELEM *elem;
52 } HRSRC_MAP;
54 /**********************************************************************
55 * MapHRsrc32To16
57 static HRSRC16 MapHRsrc32To16( NE_MODULE *pModule, HANDLE hRsrc32, WORD type )
59 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
60 HRSRC_ELEM *newElem;
61 int i;
63 /* On first call, initialize HRSRC map */
64 if ( !map )
66 if ( !(map = (HRSRC_MAP *)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
67 sizeof(HRSRC_MAP) ) ) )
69 ERR("Cannot allocate HRSRC map\n" );
70 return 0;
72 pModule->hRsrcMap = (LPVOID)map;
75 /* Check whether HRSRC32 already in map */
76 for ( i = 0; i < map->nUsed; i++ )
77 if ( map->elem[i].hRsrc == hRsrc32 )
78 return (HRSRC16)(i + 1);
80 /* If no space left, grow table */
81 if ( map->nUsed == map->nAlloc )
83 if ( !(newElem = (HRSRC_ELEM *)HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
84 map->elem,
85 (map->nAlloc + HRSRC_MAP_BLOCKSIZE)
86 * sizeof(HRSRC_ELEM) ) ))
88 ERR("Cannot grow HRSRC map\n" );
89 return 0;
91 map->elem = newElem;
92 map->nAlloc += HRSRC_MAP_BLOCKSIZE;
95 /* Add HRSRC32 to table */
96 map->elem[map->nUsed].hRsrc = hRsrc32;
97 map->elem[map->nUsed].type = type;
98 map->nUsed++;
100 return (HRSRC16)map->nUsed;
103 /**********************************************************************
104 * MapHRsrc16To32
106 static HANDLE MapHRsrc16To32( NE_MODULE *pModule, HRSRC16 hRsrc16 )
108 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
109 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
111 return map->elem[(int)hRsrc16-1].hRsrc;
114 /**********************************************************************
115 * MapHRsrc16ToType
117 static WORD MapHRsrc16ToType( NE_MODULE *pModule, HRSRC16 hRsrc16 )
119 HRSRC_MAP *map = (HRSRC_MAP *)pModule->hRsrcMap;
120 if ( !map || !hRsrc16 || (int)hRsrc16 > map->nUsed ) return 0;
122 return map->elem[(int)hRsrc16-1].type;
126 /* filter for page-fault exceptions */
127 static WINE_EXCEPTION_FILTER(page_fault)
129 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
130 return EXCEPTION_EXECUTE_HANDLER;
131 return EXCEPTION_CONTINUE_SEARCH;
134 static HRSRC RES_FindResource2( HMODULE hModule, LPCSTR type,
135 LPCSTR name, WORD lang,
136 BOOL bUnicode, BOOL bRet16 )
138 HRSRC hRsrc = 0;
139 HMODULE16 hMod16 = MapHModuleLS( hModule );
140 NE_MODULE *pModule = NE_GetPtr( hMod16 );
141 WINE_MODREF *wm = pModule && pModule->module32?
142 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
144 TRACE("(%08x %s, %08x%s, %08x%s, %04x, %s, %s)\n",
145 hModule,
146 pModule ? (char *)NE_MODULE_NAME(pModule) : "NULL dereference",
147 (UINT)type, HIWORD(type)? (bUnicode? debugstr_w((LPWSTR)type) : debugstr_a(type)) : "",
148 (UINT)name, HIWORD(name)? (bUnicode? debugstr_w((LPWSTR)name) : debugstr_a(name)) : "",
149 lang,
150 bUnicode? "W" : "A",
151 bRet16? "NE" : "PE" );
153 if (pModule)
155 if ( wm )
157 /* 32-bit PE module */
158 LPWSTR typeStr, nameStr;
160 if ( HIWORD( type ) && !bUnicode )
161 typeStr = HEAP_strdupAtoW( GetProcessHeap(), 0, type );
162 else
163 typeStr = (LPWSTR)type;
164 if ( HIWORD( name ) && !bUnicode )
165 nameStr = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
166 else
167 nameStr = (LPWSTR)name;
169 hRsrc = PE_FindResourceExW( wm, nameStr, typeStr, lang );
171 if ( HIWORD( type ) && !bUnicode )
172 HeapFree( GetProcessHeap(), 0, typeStr );
173 if ( HIWORD( name ) && !bUnicode )
174 HeapFree( GetProcessHeap(), 0, nameStr );
177 /* If we need to return 16-bit HRSRC, perform conversion */
178 if ( bRet16 )
179 hRsrc = MapHRsrc32To16( pModule, hRsrc,
180 HIWORD( type )? 0 : LOWORD( type ) );
182 else
184 /* 16-bit NE module */
185 LPSTR typeStr, nameStr;
187 if ( HIWORD( type ) && bUnicode )
188 typeStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)type );
189 else
190 typeStr = (LPSTR)type;
191 if ( HIWORD( name ) && bUnicode )
192 nameStr = HEAP_strdupWtoA( GetProcessHeap(), 0, (LPCWSTR)name );
193 else
194 nameStr = (LPSTR)name;
196 hRsrc = NE_FindResource( pModule, nameStr, typeStr );
198 if ( HIWORD( type ) && bUnicode )
199 HeapFree( GetProcessHeap(), 0, typeStr );
200 if ( HIWORD( name ) && bUnicode )
201 HeapFree( GetProcessHeap(), 0, nameStr );
204 /* If we need to return 32-bit HRSRC, no conversion is necessary,
205 we simply use the 16-bit HRSRC as 32-bit HRSRC */
208 return hRsrc;
211 /**********************************************************************
212 * RES_FindResource
215 static HRSRC RES_FindResource( HMODULE hModule, LPCSTR type,
216 LPCSTR name, WORD lang,
217 BOOL bUnicode, BOOL bRet16 )
219 HRSRC hRsrc;
220 __TRY
222 hRsrc = RES_FindResource2(hModule, type, name, lang, bUnicode, bRet16);
224 __EXCEPT(page_fault)
226 WARN("page fault\n");
227 SetLastError(ERROR_INVALID_PARAMETER);
228 return 0;
230 __ENDTRY
231 return hRsrc;
234 /**********************************************************************
235 * RES_SizeofResource
237 static DWORD RES_SizeofResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
239 DWORD size = 0;
241 HMODULE16 hMod16 = MapHModuleLS( hModule );
242 NE_MODULE *pModule = NE_GetPtr( hMod16 );
243 WINE_MODREF *wm = pModule && pModule->module32?
244 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
246 TRACE("(%08x %s, %08x, %s)\n",
247 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
249 if ( !pModule || !hRsrc ) return 0;
251 if ( wm )
253 /* 32-bit PE module */
255 /* If we got a 16-bit hRsrc, convert it */
256 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
258 size = PE_SizeofResource( hModule, hRsrc32 );
260 else
262 /* 16-bit NE module */
264 /* If we got a 32-bit hRsrc, we don't need to convert it */
266 size = NE_SizeofResource( pModule, hRsrc );
269 return size;
272 /**********************************************************************
273 * RES_AccessResource
275 static HFILE RES_AccessResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
277 HFILE hFile = HFILE_ERROR;
279 HMODULE16 hMod16 = MapHModuleLS( hModule );
280 NE_MODULE *pModule = NE_GetPtr( hMod16 );
281 WINE_MODREF *wm = pModule && pModule->module32?
282 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
284 TRACE("(%08x %s, %08x, %s)\n",
285 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
287 if ( !pModule || !hRsrc ) return HFILE_ERROR;
289 if ( wm )
291 /* 32-bit PE module */
292 #if 0
293 /* If we got a 16-bit hRsrc, convert it */
294 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
295 #endif
297 FIXME("32-bit modules not yet supported.\n" );
298 hFile = HFILE_ERROR;
300 /* If we need to return a 16-bit file handle, convert it */
301 if ( bRet16 )
302 hFile = FILE_AllocDosHandle( hFile );
304 else
306 /* 16-bit NE module */
308 /* If we got a 32-bit hRsrc, we don't need to convert it */
310 hFile = NE_AccessResource( pModule, hRsrc );
312 /* If we are to return a 32-bit file handle, convert it */
313 if ( !bRet16 )
314 hFile = FILE_GetHandle( hFile );
317 return hFile;
320 /**********************************************************************
321 * RES_LoadResource
323 static HGLOBAL RES_LoadResource( HMODULE hModule, HRSRC hRsrc, BOOL bRet16 )
325 HGLOBAL hMem = 0;
327 HMODULE16 hMod16 = MapHModuleLS( hModule );
328 NE_MODULE *pModule = NE_GetPtr( hMod16 );
329 WINE_MODREF *wm = pModule && pModule->module32?
330 MODULE32_LookupHMODULE( pModule->module32 ) : NULL;
332 TRACE("(%08x %s, %08x, %s)\n",
333 hModule, NE_MODULE_NAME(pModule), hRsrc, bRet16? "NE" : "PE" );
335 if ( !pModule || !hRsrc ) return 0;
337 if ( wm )
339 /* 32-bit PE module */
341 /* If we got a 16-bit hRsrc, convert it */
342 HRSRC hRsrc32 = HIWORD(hRsrc)? hRsrc : MapHRsrc16To32( pModule, hRsrc );
344 hMem = PE_LoadResource( wm, hRsrc32 );
346 /* If we need to return a 16-bit resource, convert it */
347 if ( bRet16 )
349 WORD type = MapHRsrc16ToType( pModule, hRsrc );
350 DWORD size = SizeofResource( hModule, hRsrc );
351 LPVOID bits = LockResource( hMem );
353 hMem = NE_LoadPEResource( pModule, type, bits, size );
356 else
358 /* 16-bit NE module */
360 /* If we got a 32-bit hRsrc, we don't need to convert it */
362 hMem = NE_LoadResource( pModule, hRsrc );
364 /* If we are to return a 32-bit resource, we should probably
365 convert it but we don't for now. FIXME !!! */
368 return hMem;
371 /**********************************************************************
372 * RES_LockResource
374 static LPVOID RES_LockResource( HGLOBAL handle, BOOL bRet16 )
376 LPVOID bits = NULL;
378 TRACE("(%08x, %s)\n", handle, bRet16? "NE" : "PE" );
380 if ( HIWORD( handle ) )
382 /* 32-bit memory handle */
384 if ( bRet16 )
385 FIXME("can't return SEGPTR to 32-bit resource %08x.\n", handle );
386 else
387 bits = (LPVOID)handle;
389 else
391 /* 16-bit memory handle */
393 /* May need to reload the resource if discarded */
394 SEGPTR segPtr = WIN16_GlobalLock16( handle );
396 if ( bRet16 )
397 bits = (LPVOID)segPtr;
398 else
399 bits = PTR_SEG_TO_LIN( segPtr );
402 return bits;
405 /**********************************************************************
406 * RES_FreeResource
408 static BOOL RES_FreeResource( HGLOBAL handle )
410 HGLOBAL retv = handle;
412 TRACE("(%08x)\n", handle );
414 if ( HIWORD( handle ) )
416 /* 32-bit memory handle: nothing to do */
418 else
420 /* 16-bit memory handle */
421 NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) );
423 /* Try NE resource first */
424 retv = NE_FreeResource( pModule, handle );
426 /* If this failed, call USER.DestroyIcon32; this will check
427 whether it is a shared cursor/icon; if not it will call
428 GlobalFree16() */
429 if ( retv ) {
430 if ( Callout.DestroyIcon32 )
431 retv = Callout.DestroyIcon32( handle, CID_RESOURCE );
432 else
433 retv = GlobalFree16( handle );
437 return (BOOL)retv;
441 /**********************************************************************
442 * FindResource16 (KERNEL.60)
444 HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
446 LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
447 LPCSTR typeStr = HIWORD(type)? PTR_SEG_TO_LIN(type) : (LPCSTR)type;
449 return RES_FindResource( hModule, typeStr, nameStr,
450 GetSystemDefaultLangID(), FALSE, TRUE );
453 /**********************************************************************
454 * FindResourceA (KERNEL32.128)
456 HANDLE WINAPI FindResourceA( HMODULE hModule, LPCSTR name, LPCSTR type )
458 return RES_FindResource( hModule, type, name,
459 GetSystemDefaultLangID(), FALSE, FALSE );
462 /**********************************************************************
463 * FindResourceExA (KERNEL32.129)
465 HANDLE WINAPI FindResourceExA( HMODULE hModule,
466 LPCSTR type, LPCSTR name, WORD lang )
468 return RES_FindResource( hModule, type, name,
469 lang, FALSE, FALSE );
472 /**********************************************************************
473 * FindResourceExW (KERNEL32.130)
475 HRSRC WINAPI FindResourceExW( HMODULE hModule,
476 LPCWSTR type, LPCWSTR name, WORD lang )
478 return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
479 lang, TRUE, FALSE );
482 /**********************************************************************
483 * FindResourceW (KERNEL32.131)
485 HRSRC WINAPI FindResourceW(HINSTANCE hModule, LPCWSTR name, LPCWSTR type)
487 return RES_FindResource( hModule, (LPCSTR)type, (LPCSTR)name,
488 GetSystemDefaultLangID(), TRUE, FALSE );
491 /**********************************************************************
492 * LoadResource16 (KERNEL.61)
494 HGLOBAL16 WINAPI LoadResource16( HMODULE16 hModule, HRSRC16 hRsrc )
496 return RES_LoadResource( hModule, hRsrc, TRUE );
499 /**********************************************************************
500 * LoadResource (KERNEL32.370)
502 HGLOBAL WINAPI LoadResource( HINSTANCE hModule, HRSRC hRsrc )
504 return RES_LoadResource( hModule, hRsrc, FALSE );
507 /**********************************************************************
508 * LockResource16 (KERNEL.62)
510 SEGPTR WINAPI WIN16_LockResource16( HGLOBAL16 handle )
512 return (SEGPTR)RES_LockResource( handle, TRUE );
514 LPVOID WINAPI LockResource16( HGLOBAL16 handle )
516 return RES_LockResource( handle, FALSE );
519 /**********************************************************************
520 * LockResource (KERNEL32.384)
522 LPVOID WINAPI LockResource( HGLOBAL handle )
524 return RES_LockResource( handle, FALSE );
527 /**********************************************************************
528 * FreeResource16 (KERNEL.63)
530 BOOL16 WINAPI FreeResource16( HGLOBAL16 handle )
532 return RES_FreeResource( handle );
535 /**********************************************************************
536 * FreeResource (KERNEL32.145)
538 BOOL WINAPI FreeResource( HGLOBAL handle )
540 return RES_FreeResource( handle );
543 /**********************************************************************
544 * AccessResource16 (KERNEL.64)
546 INT16 WINAPI AccessResource16( HINSTANCE16 hModule, HRSRC16 hRsrc )
548 return RES_AccessResource( hModule, hRsrc, TRUE );
551 /**********************************************************************
552 * AccessResource (KERNEL32.64)
554 INT WINAPI AccessResource( HMODULE hModule, HRSRC hRsrc )
556 return RES_AccessResource( hModule, hRsrc, FALSE );
559 /**********************************************************************
560 * SizeofResource16 (KERNEL.65)
562 DWORD WINAPI SizeofResource16( HMODULE16 hModule, HRSRC16 hRsrc )
564 return RES_SizeofResource( hModule, hRsrc, TRUE );
567 /**********************************************************************
568 * SizeofResource (KERNEL32.522)
570 DWORD WINAPI SizeofResource( HINSTANCE hModule, HRSRC hRsrc )
572 return RES_SizeofResource( hModule, hRsrc, FALSE );
577 /**********************************************************************
578 * LoadAccelerators16 [USER.177]
580 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
582 HRSRC16 hRsrc;
584 if (HIWORD(lpTableName))
585 TRACE_(accel)("%04x '%s'\n",
586 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
587 else
588 TRACE_(accel)("%04x %04x\n",
589 instance, LOWORD(lpTableName) );
591 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
592 WARN_(accel)("couldn't find accelerator table resource\n");
593 return 0;
596 TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
597 return LoadResource16(instance,hRsrc);
600 /**********************************************************************
601 * LoadAcceleratorsW [USER.177]
602 * The image layout seems to look like this (not 100% sure):
603 * 00: BYTE type type of accelerator
604 * 01: BYTE pad (to WORD boundary)
605 * 02: WORD event
606 * 04: WORD IDval
607 * 06: WORD pad (to DWORD boundary)
609 HACCEL WINAPI LoadAcceleratorsW(HINSTANCE instance,LPCWSTR lpTableName)
611 HRSRC hRsrc;
612 HACCEL hMem,hRetval=0;
613 DWORD size;
615 if (HIWORD(lpTableName))
616 TRACE_(accel)("%p '%s'\n",
617 (LPVOID)instance, (char *)( lpTableName ) );
618 else
619 TRACE_(accel)("%p 0x%04x\n",
620 (LPVOID)instance, LOWORD(lpTableName) );
622 if (!(hRsrc = FindResourceW( instance, lpTableName, RT_ACCELERATORW )))
624 WARN_(accel)("couldn't find accelerator table resource\n");
625 } else {
626 hMem = LoadResource( instance, hRsrc );
627 size = SizeofResource( instance, hRsrc );
628 if(size>=sizeof(PE_ACCEL))
630 LPPE_ACCEL accel_table = (LPPE_ACCEL) hMem;
631 LPACCEL16 accel16;
632 int i,nrofaccells = size/sizeof(PE_ACCEL);
634 hRetval = GlobalAlloc16(0,sizeof(ACCEL16)*nrofaccells);
635 accel16 = (LPACCEL16)GlobalLock16(hRetval);
636 for (i=0;i<nrofaccells;i++) {
637 accel16[i].fVirt = accel_table[i].fVirt;
638 accel16[i].key = accel_table[i].key;
639 accel16[i].cmd = accel_table[i].cmd;
641 accel16[i-1].fVirt |= 0x80;
644 TRACE_(accel)("returning HACCEL 0x%x\n", hRsrc);
645 return hRetval;
648 /***********************************************************************
649 * LoadAcceleratorsA
651 HACCEL WINAPI LoadAcceleratorsA(HINSTANCE instance,LPCSTR lpTableName)
653 LPWSTR uni;
654 HACCEL result;
655 if (HIWORD(lpTableName))
656 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
657 else
658 uni = (LPWSTR)lpTableName;
659 result = LoadAcceleratorsW(instance,uni);
660 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
661 return result;
664 /**********************************************************************
665 * CopyAcceleratorTableA (USER32.58)
667 INT WINAPI CopyAcceleratorTableA(HACCEL src, LPACCEL dst, INT entries)
669 return CopyAcceleratorTableW(src, dst, entries);
672 /**********************************************************************
673 * CopyAcceleratorTableW (USER32.59)
675 * By mortene@pvv.org 980321
677 INT WINAPI CopyAcceleratorTableW(HACCEL src, LPACCEL dst,
678 INT entries)
680 int i,xsize;
681 LPACCEL16 accel = (LPACCEL16)GlobalLock16(src);
682 BOOL done = FALSE;
684 /* Do parameter checking to avoid the explosions and the screaming
685 as far as possible. */
686 if((dst && (entries < 1)) || (src == (HACCEL)NULL) || !accel) {
687 WARN_(accel)("Application sent invalid parameters (%p %p %d).\n",
688 (LPVOID)src, (LPVOID)dst, entries);
689 return 0;
691 xsize = GlobalSize16(src)/sizeof(ACCEL16);
692 if (xsize>entries) entries=xsize;
694 i=0;
695 while(!done) {
696 /* Spit out some debugging information. */
697 TRACE_(accel)("accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
698 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
700 /* Copy data to the destination structure array (if dst == NULL,
701 we're just supposed to count the number of entries). */
702 if(dst) {
703 dst[i].fVirt = accel[i].fVirt;
704 dst[i].key = accel[i].key;
705 dst[i].cmd = accel[i].cmd;
707 /* Check if we've reached the end of the application supplied
708 accelerator table. */
709 if(i+1 == entries) {
710 /* Turn off the high order bit, just in case. */
711 dst[i].fVirt &= 0x7f;
712 done = TRUE;
716 /* The highest order bit seems to mark the end of the accelerator
717 resource table, but not always. Use GlobalSize() check too. */
718 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
720 i++;
723 return i;
726 /*********************************************************************
727 * CreateAcceleratorTableA (USER32.64)
729 * By mortene@pvv.org 980321
731 HACCEL WINAPI CreateAcceleratorTableA(LPACCEL lpaccel, INT cEntries)
733 HACCEL hAccel;
734 LPACCEL16 accel;
735 int i;
737 /* Do parameter checking just in case someone's trying to be
738 funny. */
739 if(cEntries < 1) {
740 WARN_(accel)("Application sent invalid parameters (%p %d).\n",
741 lpaccel, cEntries);
742 SetLastError(ERROR_INVALID_PARAMETER);
743 return (HACCEL)NULL;
745 FIXME_(accel)("should check that the accelerator descriptions are valid,"
746 " return NULL and SetLastError() if not.\n");
749 /* Allocate memory and copy the table. */
750 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
752 TRACE_(accel)("handle %x\n", hAccel);
753 if(!hAccel) {
754 ERR_(accel)("Out of memory.\n");
755 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
756 return (HACCEL)NULL;
758 accel = GlobalLock16(hAccel);
759 for (i=0;i<cEntries;i++) {
760 accel[i].fVirt = lpaccel[i].fVirt;
761 accel[i].key = lpaccel[i].key;
762 accel[i].cmd = lpaccel[i].cmd;
764 /* Set the end-of-table terminator. */
765 accel[cEntries-1].fVirt |= 0x80;
767 TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
768 return hAccel;
771 /*********************************************************************
772 * CreateAcceleratorTableW (USER32.64)
776 HACCEL WINAPI CreateAcceleratorTableW(LPACCEL lpaccel, INT cEntries)
778 HACCEL hAccel;
779 LPACCEL16 accel;
780 int i;
781 char ckey;
783 /* Do parameter checking just in case someone's trying to be
784 funny. */
785 if(cEntries < 1) {
786 WARN_(accel)("Application sent invalid parameters (%p %d).\n",
787 lpaccel, cEntries);
788 SetLastError(ERROR_INVALID_PARAMETER);
789 return (HACCEL)NULL;
791 FIXME_(accel)("should check that the accelerator descriptions are valid,"
792 " return NULL and SetLastError() if not.\n");
795 /* Allocate memory and copy the table. */
796 hAccel = GlobalAlloc16(0,cEntries*sizeof(ACCEL16));
798 TRACE_(accel)("handle %x\n", hAccel);
799 if(!hAccel) {
800 ERR_(accel)("Out of memory.\n");
801 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
802 return (HACCEL)NULL;
804 accel = GlobalLock16(hAccel);
807 for (i=0;i<cEntries;i++) {
808 accel[i].fVirt = lpaccel[i].fVirt;
809 if( !(accel[i].fVirt & FVIRTKEY) ) {
810 ckey = (char) lpaccel[i].key;
811 if(!MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &ckey, 1, &accel[i].key, 1))
812 WARN_(accel)("Error converting ASCII accelerator table to Unicode");
814 else
815 accel[i].key = lpaccel[i].key;
816 accel[i].cmd = lpaccel[i].cmd;
819 /* Set the end-of-table terminator. */
820 accel[cEntries-1].fVirt |= 0x80;
822 TRACE_(accel)("Allocated accelerator handle %x\n", hAccel);
823 return hAccel;
826 /******************************************************************************
827 * DestroyAcceleratorTable [USER32.130]
828 * Destroys an accelerator table
830 * NOTES
831 * By mortene@pvv.org 980321
833 * PARAMS
834 * handle [I] Handle to accelerator table
836 * RETURNS STD
838 BOOL WINAPI DestroyAcceleratorTable( HACCEL handle )
840 return !GlobalFree16(handle);
843 /**********************************************************************
844 * LoadString16
846 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
847 LPSTR buffer, INT16 buflen )
849 HGLOBAL16 hmem;
850 HRSRC16 hrsrc;
851 unsigned char *p;
852 int string_num;
853 int i;
855 TRACE("inst=%04x id=%04x buff=%08x len=%d\n",
856 instance, resource_id, (int) buffer, buflen);
858 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
859 if (!hrsrc) return 0;
860 hmem = LoadResource16( instance, hrsrc );
861 if (!hmem) return 0;
863 p = LockResource16(hmem);
864 string_num = resource_id & 0x000f;
865 for (i = 0; i < string_num; i++)
866 p += *p + 1;
868 TRACE("strlen = %d\n", (int)*p );
870 if (buffer == NULL) return *p;
871 i = min(buflen - 1, *p);
872 if (i > 0) {
873 memcpy(buffer, p + 1, i);
874 buffer[i] = '\0';
875 } else {
876 if (buflen > 1) {
877 buffer[0] = '\0';
878 return 0;
880 WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
882 FreeResource16( hmem );
884 TRACE("'%s' loaded !\n", buffer);
885 return i;
888 /**********************************************************************
889 * LoadStringW (USER32.376)
891 INT WINAPI LoadStringW( HINSTANCE instance, UINT resource_id,
892 LPWSTR buffer, INT buflen )
894 HGLOBAL hmem;
895 HRSRC hrsrc;
896 WCHAR *p;
897 int string_num;
898 int i;
900 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
901 resource_id = (UINT)(-((INT)resource_id));
902 TRACE("instance = %04x, id = %04x, buffer = %08x, "
903 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
905 /* Use bits 4 - 19 (incremented by 1) as resourceid, mask out
906 * 20 - 31. */
907 hrsrc = FindResourceW( instance, (LPCWSTR)(((resource_id>>4)&0xffff)+1),
908 RT_STRINGW );
909 if (!hrsrc) return 0;
910 hmem = LoadResource( instance, hrsrc );
911 if (!hmem) return 0;
913 p = LockResource(hmem);
914 string_num = resource_id & 0x000f;
915 for (i = 0; i < string_num; i++)
916 p += *p + 1;
918 TRACE("strlen = %d\n", (int)*p );
920 if (buffer == NULL) return *p;
921 i = min(buflen - 1, *p);
922 if (i > 0) {
923 memcpy(buffer, p + 1, i * sizeof (WCHAR));
924 buffer[i] = (WCHAR) 0;
925 } else {
926 if (buflen > 1) {
927 buffer[0] = (WCHAR) 0;
928 return 0;
930 #if 0
931 WARN("Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
932 #endif
935 TRACE("%s loaded !\n", debugstr_w(buffer));
936 return i;
939 /**********************************************************************
940 * LoadStringA (USER32.375)
942 INT WINAPI LoadStringA( HINSTANCE instance, UINT resource_id,
943 LPSTR buffer, INT buflen )
945 INT retval;
946 LPWSTR wbuf;
948 TRACE("instance = %04x, id = %04x, buffer = %08x, "
949 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
951 if(buffer == NULL) /* asked size of string */
952 return LoadStringW(instance, resource_id, NULL, 0);
954 wbuf = HeapAlloc(GetProcessHeap(), 0, buflen * sizeof(WCHAR));
955 if(!wbuf)
956 return 0;
958 retval = LoadStringW(instance, resource_id, wbuf, buflen);
959 if(retval != 0)
961 retval = WideCharToMultiByte(CP_ACP, 0, wbuf, retval, buffer, buflen - 1, NULL, NULL);
962 buffer[retval] = 0;
963 TRACE("%s loaded !\n", debugstr_a(buffer));
965 HeapFree( GetProcessHeap(), 0, wbuf );
967 return retval;
970 /* Messages...used by FormatMessage32* (KERNEL32.something)
972 * They can be specified either directly or using a message ID and
973 * loading them from the resource.
975 * The resourcedata has following format:
976 * start:
977 * 0: DWORD nrofentries
978 * nrofentries * subentry:
979 * 0: DWORD firstentry
980 * 4: DWORD lastentry
981 * 8: DWORD offset from start to the stringentries
983 * (lastentry-firstentry) * stringentry:
984 * 0: WORD len (0 marks end)
985 * 2: WORD flags
986 * 4: CHAR[len-4]
987 * (stringentry i of a subentry refers to the ID 'firstentry+i')
989 * Yes, ANSI strings in win32 resources. Go figure.
992 /**********************************************************************
993 * LoadMessageA (internal)
995 INT WINAPI LoadMessageA( HMODULE instance, UINT id, WORD lang,
996 LPSTR buffer, INT buflen )
998 HGLOBAL hmem;
999 HRSRC hrsrc;
1000 PMESSAGE_RESOURCE_DATA mrd;
1001 PMESSAGE_RESOURCE_BLOCK mrb;
1002 PMESSAGE_RESOURCE_ENTRY mre;
1003 int i,slen;
1005 TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
1007 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
1008 hrsrc = FindResourceExW(instance,RT_MESSAGELISTW,(LPWSTR)1,lang);
1009 if (!hrsrc) return 0;
1010 hmem = LoadResource( instance, hrsrc );
1011 if (!hmem) return 0;
1013 mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
1014 mre = NULL;
1015 mrb = &(mrd->Blocks[0]);
1016 for (i=mrd->NumberOfBlocks;i--;) {
1017 if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
1018 mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
1019 id -= mrb->LowId;
1020 break;
1022 mrb++;
1024 if (!mre)
1025 return 0;
1026 for (i=id;i--;) {
1027 if (!mre->Length)
1028 return 0;
1029 mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+(mre->Length));
1031 slen=mre->Length;
1032 TRACE(" - strlen=%d\n",slen);
1033 i = min(buflen - 1, slen);
1034 if (buffer == NULL)
1035 return slen;
1036 if (i>0) {
1037 lstrcpynA(buffer,(char*)mre->Text,i);
1038 buffer[i]=0;
1039 } else {
1040 if (buflen>1) {
1041 buffer[0]=0;
1042 return 0;
1045 if (buffer)
1046 TRACE("'%s' copied !\n", buffer);
1047 return i;
1050 /**********************************************************************
1051 * LoadMessageW (internal)
1053 INT WINAPI LoadMessageW( HMODULE instance, UINT id, WORD lang,
1054 LPWSTR buffer, INT buflen )
1056 INT retval;
1057 LPSTR buffer2 = NULL;
1058 if (buffer && buflen)
1059 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
1060 retval = LoadMessageA(instance,id,lang,buffer2,buflen);
1061 if (buffer)
1063 if (retval) {
1064 lstrcpynAtoW( buffer, buffer2, buflen );
1065 retval = lstrlenW( buffer );
1067 HeapFree( GetProcessHeap(), 0, buffer2 );
1069 return retval;
1073 /**********************************************************************
1074 * EnumResourceTypesA (KERNEL32.90)
1076 BOOL WINAPI EnumResourceTypesA( HMODULE hmodule,ENUMRESTYPEPROCA lpfun,
1077 LONG lParam)
1079 /* FIXME: move WINE_MODREF stuff here */
1080 return PE_EnumResourceTypesA(hmodule,lpfun,lParam);
1083 /**********************************************************************
1084 * EnumResourceTypesW (KERNEL32.91)
1086 BOOL WINAPI EnumResourceTypesW( HMODULE hmodule,ENUMRESTYPEPROCW lpfun,
1087 LONG lParam)
1089 /* FIXME: move WINE_MODREF stuff here */
1090 return PE_EnumResourceTypesW(hmodule,lpfun,lParam);
1093 /**********************************************************************
1094 * EnumResourceNamesA (KERNEL32.88)
1096 BOOL WINAPI EnumResourceNamesA( HMODULE hmodule, LPCSTR type,
1097 ENUMRESNAMEPROCA lpfun, LONG lParam )
1099 /* FIXME: move WINE_MODREF stuff here */
1100 return PE_EnumResourceNamesA(hmodule,type,lpfun,lParam);
1102 /**********************************************************************
1103 * EnumResourceNamesW (KERNEL32.89)
1105 BOOL WINAPI EnumResourceNamesW( HMODULE hmodule, LPCWSTR type,
1106 ENUMRESNAMEPROCW lpfun, LONG lParam )
1108 /* FIXME: move WINE_MODREF stuff here */
1109 return PE_EnumResourceNamesW(hmodule,type,lpfun,lParam);
1112 /**********************************************************************
1113 * EnumResourceLanguagesA (KERNEL32.86)
1115 BOOL WINAPI EnumResourceLanguagesA( HMODULE hmodule, LPCSTR type,
1116 LPCSTR name, ENUMRESLANGPROCA lpfun,
1117 LONG lParam)
1119 /* FIXME: move WINE_MODREF stuff here */
1120 return PE_EnumResourceLanguagesA(hmodule,type,name,lpfun,lParam);
1122 /**********************************************************************
1123 * EnumResourceLanguagesW (KERNEL32.87)
1125 BOOL WINAPI EnumResourceLanguagesW( HMODULE hmodule, LPCWSTR type,
1126 LPCWSTR name, ENUMRESLANGPROCW lpfun,
1127 LONG lParam)
1129 /* FIXME: move WINE_MODREF stuff here */
1130 return PE_EnumResourceLanguagesW(hmodule,type,name,lpfun,lParam);