Release 980503
[wine/hacks.git] / loader / resource.c
blob32f2a6dba336ee24ff215091be0a8cf3b208444a
1 /*
2 * Resources
4 * Copyright 1993 Robert J. Amstadt
5 * Copyright 1995 Alexandre Julliard
6 */
8 #include <assert.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include "windows.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 "resource.h"
25 #include "debug.h"
26 #include "libres.h"
27 #include "winerror.h"
29 extern WORD WINE_LanguageId;
32 /**********************************************************************
33 * FindResource32A (KERNEL32.128)
35 HANDLE32 WINAPI FindResource32A( HMODULE32 hModule, LPCSTR name, LPCSTR type)
37 return FindResourceEx32A(hModule,name,type,WINE_LanguageId);
40 /**********************************************************************
41 * FindResourceEx32A (KERNEL32.129)
43 HANDLE32 WINAPI FindResourceEx32A( HMODULE32 hModule, LPCSTR name, LPCSTR type,
44 WORD lang
45 ) {
46 LPWSTR xname,xtype;
47 HANDLE32 ret;
49 if (HIWORD((DWORD)name))
50 xname = HEAP_strdupAtoW( GetProcessHeap(), 0, name );
51 else
52 xname = (LPWSTR)name;
53 if (HIWORD((DWORD)type))
54 xtype = HEAP_strdupAtoW( GetProcessHeap(), 0, type);
55 else
56 xtype = (LPWSTR)type;
57 ret = FindResourceEx32W( hModule, xname, xtype, lang );
58 if (HIWORD((DWORD)name)) HeapFree( GetProcessHeap(), 0, xname );
59 if (HIWORD((DWORD)type)) HeapFree( GetProcessHeap(), 0, xtype );
60 return ret;
64 /**********************************************************************
65 * FindResourceEx32W (KERNEL32.130)
67 HRSRC32 WINAPI FindResourceEx32W( HMODULE32 hModule, LPCWSTR name,
68 LPCWSTR type, WORD lang )
70 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
71 HRSRC32 hrsrc;
73 TRACE(resource, "module=%08x "
74 "type=%s%p name=%s%p\n", wm->module,
75 (HIWORD(type))? "" : "#", type,
76 (HIWORD(name))? "" : "#", name);
77 if (__winelib) {
78 hrsrc = LIBRES_FindResource( hModule, name, type );
79 if (hrsrc)
80 return hrsrc;
82 if (wm) {
83 switch (wm->type) {
84 case MODULE32_PE:
85 return PE_FindResourceEx32W(wm,name,type,lang);
86 default:
87 ERR(module,"unknown module type %d\n",wm->type);
88 break;
91 return (HRSRC32)0;
95 /**********************************************************************
96 * FindResource32W (KERNEL32.131)
98 HRSRC32 WINAPI FindResource32W(HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type)
100 return FindResourceEx32W(hModule,name,type,WINE_LanguageId);
104 /**********************************************************************
105 * LoadResource32 (KERNEL32.370)
106 * 'loads' a resource. The current implementation just returns a pointer
107 * into the already mapped image.
108 * RETURNS
109 * pointer into the mapped resource of the passed module
111 HGLOBAL32 WINAPI LoadResource32(
112 HINSTANCE32 hModule, /* [in] module handle */
113 HRSRC32 hRsrc ) /* [in] resource handle */
115 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
117 TRACE(resource, "module=%04x res=%04x\n",
118 hModule, hRsrc );
119 if (!hRsrc) {
120 ERR(resource,"hRsrc is 0, return 0.\n");
121 return 0;
123 if (wm)
124 switch (wm->type) {
125 case MODULE32_PE:
126 return PE_LoadResource32(wm,hRsrc);
127 default:
128 ERR(resource,"unknown module type %d\n",wm->type);
129 break;
131 if (__winelib)
132 return LIBRES_LoadResource( hModule, hRsrc );
133 return 0;
137 /**********************************************************************
138 * LockResource32 (KERNEL32.384)
140 LPVOID WINAPI LockResource32( HGLOBAL32 handle )
142 return (LPVOID)handle;
146 /**********************************************************************
147 * FreeResource32 (KERNEL32.145)
149 BOOL32 WINAPI FreeResource32( HGLOBAL32 handle )
151 /* no longer used in Win32 */
152 return TRUE;
156 /**********************************************************************
157 * AccessResource32 (KERNEL32.64)
159 INT32 WINAPI AccessResource32( HMODULE32 hModule, HRSRC32 hRsrc )
161 FIXME(resource,"(module=%08x res=%08x),not implemented\n", hModule, hRsrc);
162 return 0;
166 /**********************************************************************
167 * SizeofResource32 (KERNEL32.522)
169 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
171 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
173 TRACE(resource, "module=%08x res=%08x\n", hModule, hRsrc );
174 if (wm)
175 switch (wm->type)
177 case MODULE32_PE:
179 DWORD ret;
180 ret = PE_SizeofResource32(hModule,hRsrc);
181 if (ret)
182 return ret;
183 break;
185 default:
186 ERR(module,"unknown module type %d\n",wm->type);
187 break;
189 if (__winelib)
190 fprintf(stderr,"SizeofResource32: not implemented for WINELIB\n");
191 return 0;
195 /**********************************************************************
196 * LoadAccelerators16 [USER.177]
198 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
200 HRSRC16 hRsrc;
202 if (HIWORD(lpTableName))
203 TRACE(accel, "%04x '%s'\n",
204 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
205 else
206 TRACE(accel, "%04x %04x\n",
207 instance, LOWORD(lpTableName) );
209 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
210 WARN(accel, "couldn't find accelerator table resource\n");
211 return 0;
214 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
215 return LoadResource16(instance,hRsrc);
218 /**********************************************************************
219 * LoadAccelerators32W [USER.177]
220 * The image layout seems to look like this (not 100% sure):
221 * 00: BYTE type type of accelerator
222 * 01: BYTE pad (to WORD boundary)
223 * 02: WORD event
224 * 04: WORD IDval
225 * 06: WORD pad (to DWORD boundary)
227 HACCEL32 WINAPI LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
229 HRSRC32 hRsrc;
230 HACCEL32 hRetval;
232 if (HIWORD(lpTableName))
233 TRACE(accel, "%p '%s'\n",
234 (LPVOID)instance, (char *)( lpTableName ) );
235 else
236 TRACE(accel, "%p 0x%04x\n",
237 (LPVOID)instance, LOWORD(lpTableName) );
239 if (!(hRsrc = FindResource32W( instance, lpTableName, RT_ACCELERATOR32W )))
241 WARN(accel, "couldn't find accelerator table resource\n");
242 hRetval = 0;
244 else {
245 hRetval = LoadResource32( instance, hRsrc );
248 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
249 return hRetval;
252 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
254 LPWSTR uni;
255 HACCEL32 result;
256 if (HIWORD(lpTableName))
257 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
258 else
259 uni = (LPWSTR)lpTableName;
260 result = LoadAccelerators32W(instance,uni);
261 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
262 return result;
265 /**********************************************************************
266 * CopyAcceleratorTable32A (USER32.58)
268 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
270 return CopyAcceleratorTable32W(src, dst, entries);
273 /**********************************************************************
274 * CopyAcceleratorTable32W (USER32.59)
276 * By mortene@pvv.org 980321
278 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
279 INT32 entries)
281 int i;
282 LPACCEL32 accel = (LPACCEL32)src;
283 BOOL32 done = FALSE;
285 /* Do parameter checking to avoid the explosions and the screaming
286 as far as possible. */
287 if((dst && (entries < 1)) || (src == (HACCEL32)NULL)) {
288 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
289 (LPVOID)src, (LPVOID)dst, entries);
290 return 0;
294 i=0;
295 while(!done) {
296 /* Spit out some debugging information. */
297 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
298 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
300 /* Copy data to the destination structure array (if dst == NULL,
301 we're just supposed to count the number of entries). */
302 if(dst) {
303 memcpy(&dst[i], &accel[i], sizeof(ACCEL32));
305 /* Check if we've reached the end of the application supplied
306 accelerator table. */
307 if(i+1 == entries) {
308 /* Turn off the high order bit, just in case. */
309 dst[i].fVirt &= 0x7f;
310 done = TRUE;
314 /* The highest order bit seems to mark the end of the accelerator
315 resource table. (?) */
316 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
318 i++;
321 return i;
324 /*********************************************************************
325 * CreateAcceleratorTable (USER32.64)
327 * By mortene@pvv.org 980321
329 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
331 HACCEL32 hAccel;
333 /* Do parameter checking just in case someone's trying to be
334 funny. */
335 if(cEntries < 1) {
336 WARN(accel, "Application sent invalid parameters (%p %d).\n",
337 lpaccel, cEntries);
338 SetLastError(ERROR_INVALID_PARAMETER);
339 return (HACCEL32)NULL;
341 FIXME(accel, "should check that the accelerator descriptions are valid,"
342 " return NULL and SetLastError() if not.\n");
345 /* Allocate memory and copy the table. */
346 hAccel = (HACCEL32)HeapAlloc(GetProcessHeap(), 0,
347 cEntries * sizeof(ACCEL32));
348 TRACE(accel, "handle %p\n", (LPVOID)hAccel);
349 if(!hAccel) {
350 WARN(accel, "Out of memory.\n");
351 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
352 return (HACCEL32)NULL;
354 memcpy((LPACCEL32)hAccel, lpaccel, cEntries * sizeof(ACCEL32));
356 /* Set the end-of-table terminator. */
357 ((LPACCEL32)hAccel)[cEntries-1].fVirt |= 0x80;
359 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
360 return hAccel;
364 /******************************************************************************
365 * DestroyAcceleratorTable [USER32.130]
366 * Destroys an accelerator table
368 * NOTES
369 * By mortene@pvv.org 980321
371 * PARAMS
372 * handle [I] Handle to accelerator table
374 * RETURNS STD
376 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
378 FIXME(accel, "(0x%x): stub\n", handle);
381 /* Weird.. I thought this should work. According to the API
382 specification, DestroyAcceleratorTable() should only be called on
383 HACCEL32's made by CreateAcceleratorTable(), but Microsoft Visual
384 Studio 97 calls this function with a series of different handle
385 values without ever calling CreateAcceleratorTable(). Something
386 is very fishy in Denmark... */
387 /* Update: looks like the calls to this function matches the calls
388 to LoadAccelerators() in M$ Visual Studio, except that the handle
389 values are off by some variable size from the HACCEL's returned
390 from LoadAccelerators(). WTH? */
392 /* Parameter checking to avoid any embarassing situations. */
393 /* if(!handle) { */
394 /* WARN(accel, "Application sent NULL ptr.\n"); */
395 /* SetLastError(ERROR_INVALID_PARAMETER); */
396 /* return FALSE; */
397 /* } */
399 /* HeapFree(GetProcessHeap(), 0, (LPACCEL32)handle); */
401 return TRUE;
404 /**********************************************************************
405 * LoadString16
407 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
408 LPSTR buffer, INT16 buflen )
410 HGLOBAL16 hmem;
411 HRSRC16 hrsrc;
412 unsigned char *p;
413 int string_num;
414 int i;
416 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
417 instance, resource_id, (int) buffer, buflen);
419 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
420 if (!hrsrc) return 0;
421 hmem = LoadResource16( instance, hrsrc );
422 if (!hmem) return 0;
424 p = LockResource16(hmem);
425 string_num = resource_id & 0x000f;
426 for (i = 0; i < string_num; i++)
427 p += *p + 1;
429 TRACE(resource, "strlen = %d\n", (int)*p );
431 i = MIN(buflen - 1, *p);
432 if (buffer == NULL)
433 return i;
434 if (i > 0) {
435 memcpy(buffer, p + 1, i);
436 buffer[i] = '\0';
437 } else {
438 if (buflen > 1) {
439 buffer[0] = '\0';
440 return 0;
442 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
444 FreeResource16( hmem );
446 TRACE(resource,"'%s' copied !\n", buffer);
447 return i;
450 /**********************************************************************
451 * LoadString32W (USER32.376)
453 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
454 LPWSTR buffer, INT32 buflen )
456 HGLOBAL32 hmem;
457 HRSRC32 hrsrc;
458 WCHAR *p;
459 int string_num;
460 int i;
462 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
463 resource_id = (UINT32)(-((INT32)resource_id));
464 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
465 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
467 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
468 RT_STRING32W );
469 if (!hrsrc) return 0;
470 hmem = LoadResource32( instance, hrsrc );
471 if (!hmem) return 0;
473 p = LockResource32(hmem);
474 string_num = resource_id & 0x000f;
475 for (i = 0; i < string_num; i++)
476 p += *p + 1;
478 TRACE(resource, "strlen = %d\n", (int)*p );
480 i = MIN(buflen - 1, *p);
481 if (buffer == NULL)
482 return i;
483 if (i > 0) {
484 memcpy(buffer, p + 1, i * sizeof (WCHAR));
485 buffer[i] = (WCHAR) 0;
486 } else {
487 if (buflen > 1) {
488 buffer[0] = (WCHAR) 0;
489 return 0;
491 #if 0
492 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
493 #endif
496 TRACE(resource,"'%s' copied !\n", (char *)buffer);
497 return i;
500 /**********************************************************************
501 * LoadString32A (USER32.375)
503 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
504 LPSTR buffer, INT32 buflen )
506 INT32 retval;
507 LPWSTR buffer2 = NULL;
508 if (buffer && buflen)
509 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
510 retval = LoadString32W(instance,resource_id,buffer2,buflen);
512 if (buffer2)
514 if (retval) {
515 lstrcpynWtoA( buffer, buffer2, buflen );
516 retval = lstrlen32A( buffer );
518 else
519 *buffer = 0;
520 HeapFree( GetProcessHeap(), 0, buffer2 );
522 return retval;
525 /* Messages...used by FormatMessage32* (KERNEL32.something)
527 * They can be specified either directly or using a message ID and
528 * loading them from the resource.
530 * The resourcedata has following format:
531 * start:
532 * 0: DWORD nrofentries
533 * nrofentries * subentry:
534 * 0: DWORD firstentry
535 * 4: DWORD lastentry
536 * 8: DWORD offset from start to the stringentries
538 * (lastentry-firstentry) * stringentry:
539 * 0: WORD len (0 marks end)
540 * 2: WORD unknown (flags?)
541 * 4: CHAR[len-4]
542 * (stringentry i of a subentry refers to the ID 'firstentry+i')
544 * Yes, ANSI strings in win32 resources. Go figure.
547 /**********************************************************************
548 * LoadMessage32A (internal)
550 INT32 LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
551 LPSTR buffer, INT32 buflen )
553 HGLOBAL32 hmem;
554 HRSRC32 hrsrc;
555 BYTE *p;
556 int nrofentries,i,slen;
557 struct _subentry {
558 DWORD firstentry;
559 DWORD lastentry;
560 DWORD offset;
561 } *se;
562 struct _stringentry {
563 WORD len;
564 WORD unknown;
565 CHAR str[1];
566 } *stre;
568 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
570 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
571 hrsrc = FindResourceEx32W(instance,(LPWSTR)1,RT_MESSAGELIST32W,lang);
572 if (!hrsrc) return 0;
573 hmem = LoadResource32( instance, hrsrc );
574 if (!hmem) return 0;
576 p = LockResource32(hmem);
577 nrofentries = *(DWORD*)p;
578 stre = NULL;
579 se = (struct _subentry*)(p+4);
580 for (i=nrofentries;i--;) {
581 if ((id>=se->firstentry) && (id<=se->lastentry)) {
582 stre = (struct _stringentry*)(p+se->offset);
583 id -= se->firstentry;
584 break;
586 se++;
588 if (!stre)
589 return 0;
590 for (i=id;i--;) {
591 if (!(slen=stre->len))
592 return 0;
593 stre = (struct _stringentry*)(((char*)stre)+slen);
595 slen=stre->len;
596 TRACE(resource," - strlen=%d\n",slen);
597 i = MIN(buflen - 1, slen);
598 if (buffer == NULL)
599 return slen; /* different to LoadString */
600 if (i>0) {
601 lstrcpyn32A(buffer,stre->str,i);
602 buffer[i]=0;
603 } else {
604 if (buflen>1) {
605 buffer[0]=0;
606 return 0;
609 if (buffer)
610 TRACE(resource,"'%s' copied !\n", buffer);
611 return i;
614 /**********************************************************************
615 * LoadMessage32W (internal)
617 INT32 LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
618 LPWSTR buffer, INT32 buflen )
620 INT32 retval;
621 LPSTR buffer2 = NULL;
622 if (buffer && buflen)
623 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
624 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
625 if (buffer)
627 if (retval) {
628 lstrcpynAtoW( buffer, buffer2, buflen );
629 retval = lstrlen32W( buffer );
631 HeapFree( GetProcessHeap(), 0, buffer2 );
633 return retval;
637 /**********************************************************************
638 * EnumResourceTypesA (KERNEL32.90)
640 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
641 LONG lParam)
643 /* FIXME: move WINE_MODREF stuff here */
644 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
647 /**********************************************************************
648 * EnumResourceTypesW (KERNEL32.91)
650 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
651 LONG lParam)
653 /* FIXME: move WINE_MODREF stuff here */
654 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
657 /**********************************************************************
658 * EnumResourceNamesA (KERNEL32.88)
660 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
661 ENUMRESNAMEPROC32A lpfun, LONG lParam )
663 /* FIXME: move WINE_MODREF stuff here */
664 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
666 /**********************************************************************
667 * EnumResourceNamesW (KERNEL32.89)
669 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
670 ENUMRESNAMEPROC32W lpfun, LONG lParam )
672 /* FIXME: move WINE_MODREF stuff here */
673 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
676 /**********************************************************************
677 * EnumResourceLanguagesA (KERNEL32.86)
679 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
680 LPCSTR name, ENUMRESLANGPROC32A lpfun,
681 LONG lParam)
683 /* FIXME: move WINE_MODREF stuff here */
684 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
686 /**********************************************************************
687 * EnumResourceLanguagesW (KERNEL32.87)
689 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
690 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
691 LONG lParam)
693 /* FIXME: move WINE_MODREF stuff here */
694 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);