Update the modemn status bit that indicates whether the RLSD line is
[wine.git] / loader / resource.c
bloba87307651cdc5da2b892663f98b3fdec3b88040f
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 "resource.h"
24 #include "debug.h"
25 #include "libres.h"
26 #include "winerror.h"
27 #include "debugstr.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,type,name,WINE_LanguageId);
40 /**********************************************************************
41 * FindResourceEx32A (KERNEL32.129)
43 HANDLE32 WINAPI FindResourceEx32A( HMODULE32 hModule, LPCSTR type, LPCSTR name,
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, xtype, xname, 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 type,
68 LPCWSTR name, WORD lang )
69 { HRSRC32 ret;
70 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
71 HRSRC32 hrsrc;
73 TRACE(resource, "module=%08x(%s) type=%s name=%s\n",
74 hModule, wm->modname,
75 debugres_w (type),
76 debugres_w (name));
78 if (__winelib) {
79 hrsrc = LIBRES_FindResource( hModule, name, type );
80 if (hrsrc)
81 return hrsrc;
83 if (wm) {
84 switch (wm->type) {
85 case MODULE32_PE:
86 ret = PE_FindResourceEx32W(wm,name,type,lang);
87 if ( ret==0 )
88 ERR(resource,"(0x%08x(%s),%s not found!\n",hModule,wm->modname,debugres_w (name));
89 return ret;
90 default:
91 ERR(module,"unknown module type %d\n",wm->type);
92 break;
95 return (HRSRC32)0;
99 /**********************************************************************
100 * FindResource32W (KERNEL32.131)
102 HRSRC32 WINAPI FindResource32W(HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type)
104 return FindResourceEx32W(hModule,type,name,WINE_LanguageId);
108 /**********************************************************************
109 * LoadResource32 (KERNEL32.370)
110 * 'loads' a resource. The current implementation just returns a pointer
111 * into the already mapped image.
112 * RETURNS
113 * pointer into the mapped resource of the passed module
115 HGLOBAL32 WINAPI LoadResource32(
116 HINSTANCE32 hModule, /* [in] module handle */
117 HRSRC32 hRsrc ) /* [in] resource handle */
119 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
121 TRACE(resource, "module=%04x res=%04x\n",
122 hModule, hRsrc );
123 if (!hRsrc) {
124 ERR(resource,"hRsrc is 0, return 0.\n");
125 return 0;
127 if (wm)
128 switch (wm->type) {
129 case MODULE32_PE:
130 return PE_LoadResource32(wm,hRsrc);
131 default:
132 ERR(resource,"unknown module type %d\n",wm->type);
133 break;
135 if (__winelib)
136 return LIBRES_LoadResource( hModule, hRsrc );
137 return 0;
141 /**********************************************************************
142 * LockResource32 (KERNEL32.384)
144 LPVOID WINAPI LockResource32( HGLOBAL32 handle )
146 return (LPVOID)handle;
150 /**********************************************************************
151 * FreeResource32 (KERNEL32.145)
153 BOOL32 WINAPI FreeResource32( HGLOBAL32 handle )
155 /* no longer used in Win32 */
156 return TRUE;
160 /**********************************************************************
161 * AccessResource32 (KERNEL32.64)
163 INT32 WINAPI AccessResource32( HMODULE32 hModule, HRSRC32 hRsrc )
165 FIXME(resource,"(module=%08x res=%08x),not implemented\n", hModule, hRsrc);
166 return 0;
170 /**********************************************************************
171 * SizeofResource32 (KERNEL32.522)
173 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
175 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
177 TRACE(resource, "module=%08x res=%08x\n", hModule, hRsrc );
178 if (wm)
179 switch (wm->type)
181 case MODULE32_PE:
183 DWORD ret;
184 ret = PE_SizeofResource32(hModule,hRsrc);
185 if (ret)
186 return ret;
187 break;
189 default:
190 ERR(module,"unknown module type %d\n",wm->type);
191 break;
193 if (__winelib)
194 FIXME(module,"Not implemented for WINELIB\n");
195 return 0;
199 /**********************************************************************
200 * LoadAccelerators16 [USER.177]
202 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
204 HRSRC16 hRsrc;
206 if (HIWORD(lpTableName))
207 TRACE(accel, "%04x '%s'\n",
208 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
209 else
210 TRACE(accel, "%04x %04x\n",
211 instance, LOWORD(lpTableName) );
213 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
214 WARN(accel, "couldn't find accelerator table resource\n");
215 return 0;
218 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
219 return LoadResource16(instance,hRsrc);
222 /**********************************************************************
223 * LoadAccelerators32W [USER.177]
224 * The image layout seems to look like this (not 100% sure):
225 * 00: BYTE type type of accelerator
226 * 01: BYTE pad (to WORD boundary)
227 * 02: WORD event
228 * 04: WORD IDval
229 * 06: WORD pad (to DWORD boundary)
231 HACCEL32 WINAPI LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
233 HRSRC32 hRsrc;
234 HACCEL32 hRetval;
235 DWORD size;
237 if (HIWORD(lpTableName))
238 TRACE(accel, "%p '%s'\n",
239 (LPVOID)instance, (char *)( lpTableName ) );
240 else
241 TRACE(accel, "%p 0x%04x\n",
242 (LPVOID)instance, LOWORD(lpTableName) );
244 if (!(hRsrc = FindResource32W( instance, lpTableName, RT_ACCELERATOR32W )))
246 WARN(accel, "couldn't find accelerator table resource\n");
247 hRetval = 0;
249 else {
250 hRetval = LoadResource32( instance, hRsrc );
251 size = SizeofResource32( instance, hRsrc );
252 if(size>=sizeof(ACCEL32))
254 LPACCEL32 accel_table = (LPACCEL32) hRetval;
255 /* mark last element as such - sometimes it is not marked in image */
256 accel_table[size/sizeof(ACCEL32)-1].fVirt |= 0x80;
260 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
261 return hRetval;
264 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
266 LPWSTR uni;
267 HACCEL32 result;
268 if (HIWORD(lpTableName))
269 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
270 else
271 uni = (LPWSTR)lpTableName;
272 result = LoadAccelerators32W(instance,uni);
273 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
274 return result;
277 /**********************************************************************
278 * CopyAcceleratorTable32A (USER32.58)
280 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
282 return CopyAcceleratorTable32W(src, dst, entries);
285 /**********************************************************************
286 * CopyAcceleratorTable32W (USER32.59)
288 * By mortene@pvv.org 980321
290 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
291 INT32 entries)
293 int i;
294 LPACCEL32 accel = (LPACCEL32)src;
295 BOOL32 done = FALSE;
297 /* Do parameter checking to avoid the explosions and the screaming
298 as far as possible. */
299 if((dst && (entries < 1)) || (src == (HACCEL32)NULL)) {
300 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
301 (LPVOID)src, (LPVOID)dst, entries);
302 return 0;
306 i=0;
307 while(!done) {
308 /* Spit out some debugging information. */
309 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
310 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
312 /* Copy data to the destination structure array (if dst == NULL,
313 we're just supposed to count the number of entries). */
314 if(dst) {
315 memcpy(&dst[i], &accel[i], sizeof(ACCEL32));
317 /* Check if we've reached the end of the application supplied
318 accelerator table. */
319 if(i+1 == entries) {
320 /* Turn off the high order bit, just in case. */
321 dst[i].fVirt &= 0x7f;
322 done = TRUE;
326 /* The highest order bit seems to mark the end of the accelerator
327 resource table. (?) */
328 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
330 i++;
333 return i;
336 /*********************************************************************
337 * CreateAcceleratorTable (USER32.64)
339 * By mortene@pvv.org 980321
341 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
343 HACCEL32 hAccel;
345 /* Do parameter checking just in case someone's trying to be
346 funny. */
347 if(cEntries < 1) {
348 WARN(accel, "Application sent invalid parameters (%p %d).\n",
349 lpaccel, cEntries);
350 SetLastError(ERROR_INVALID_PARAMETER);
351 return (HACCEL32)NULL;
353 FIXME(accel, "should check that the accelerator descriptions are valid,"
354 " return NULL and SetLastError() if not.\n");
357 /* Allocate memory and copy the table. */
358 hAccel = (HACCEL32)HeapAlloc(GetProcessHeap(), 0,
359 cEntries * sizeof(ACCEL32));
360 TRACE(accel, "handle %p\n", (LPVOID)hAccel);
361 if(!hAccel) {
362 ERR(accel, "Out of memory.\n");
363 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
364 return (HACCEL32)NULL;
366 memcpy((LPACCEL32)hAccel, lpaccel, cEntries * sizeof(ACCEL32));
368 /* Set the end-of-table terminator. */
369 ((LPACCEL32)hAccel)[cEntries-1].fVirt |= 0x80;
371 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
372 return hAccel;
376 /******************************************************************************
377 * DestroyAcceleratorTable [USER32.130]
378 * Destroys an accelerator table
380 * NOTES
381 * By mortene@pvv.org 980321
383 * PARAMS
384 * handle [I] Handle to accelerator table
386 * RETURNS STD
388 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
390 FIXME(accel, "(0x%x): stub\n", handle);
393 /* Weird.. I thought this should work. According to the API
394 specification, DestroyAcceleratorTable() should only be called on
395 HACCEL32's made by CreateAcceleratorTable(), but Microsoft Visual
396 Studio 97 calls this function with a series of different handle
397 values without ever calling CreateAcceleratorTable(). Something
398 is very fishy in Denmark... */
399 /* Update: looks like the calls to this function matches the calls
400 to LoadAccelerators() in M$ Visual Studio, except that the handle
401 values are off by some variable size from the HACCEL's returned
402 from LoadAccelerators(). WTH? */
404 /* Parameter checking to avoid any embarassing situations. */
405 #if 0
406 if(!handle) {
407 WARN(accel, "Application sent NULL ptr.\n");
408 SetLastError(ERROR_INVALID_PARAMETER);
409 return FALSE;
412 HeapFree(GetProcessHeap(), 0, (LPACCEL32)handle);
413 #endif
415 return TRUE;
418 /**********************************************************************
419 * LoadString16
421 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
422 LPSTR buffer, INT16 buflen )
424 HGLOBAL16 hmem;
425 HRSRC16 hrsrc;
426 unsigned char *p;
427 int string_num;
428 int i;
430 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
431 instance, resource_id, (int) buffer, buflen);
433 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
434 if (!hrsrc) return 0;
435 hmem = LoadResource16( instance, hrsrc );
436 if (!hmem) return 0;
438 p = LockResource16(hmem);
439 string_num = resource_id & 0x000f;
440 for (i = 0; i < string_num; i++)
441 p += *p + 1;
443 TRACE(resource, "strlen = %d\n", (int)*p );
445 i = MIN(buflen - 1, *p);
446 if (buffer == NULL)
447 return i;
448 if (i > 0) {
449 memcpy(buffer, p + 1, i);
450 buffer[i] = '\0';
451 } else {
452 if (buflen > 1) {
453 buffer[0] = '\0';
454 return 0;
456 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
458 FreeResource16( hmem );
460 TRACE(resource,"'%s' loaded !\n", buffer);
461 return i;
464 /**********************************************************************
465 * LoadString32W (USER32.376)
467 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
468 LPWSTR buffer, INT32 buflen )
470 HGLOBAL32 hmem;
471 HRSRC32 hrsrc;
472 WCHAR *p;
473 int string_num;
474 int i;
476 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
477 resource_id = (UINT32)(-((INT32)resource_id));
478 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
479 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
481 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
482 RT_STRING32W );
483 if (!hrsrc) return 0;
484 hmem = LoadResource32( instance, hrsrc );
485 if (!hmem) return 0;
487 p = LockResource32(hmem);
488 string_num = resource_id & 0x000f;
489 for (i = 0; i < string_num; i++)
490 p += *p + 1;
492 TRACE(resource, "strlen = %d\n", (int)*p );
494 i = MIN(buflen - 1, *p);
495 if (buffer == NULL)
496 return i;
497 if (i > 0) {
498 memcpy(buffer, p + 1, i * sizeof (WCHAR));
499 buffer[i] = (WCHAR) 0;
500 } else {
501 if (buflen > 1) {
502 buffer[0] = (WCHAR) 0;
503 return 0;
505 #if 0
506 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
507 #endif
510 TRACE(resource,"%s loaded !\n", debugstr_w(buffer));
511 return i;
514 /**********************************************************************
515 * LoadString32A (USER32.375)
517 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
518 LPSTR buffer, INT32 buflen )
520 INT32 retval;
521 LPWSTR buffer2 = NULL;
522 if (buffer && buflen)
523 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
524 retval = LoadString32W(instance,resource_id,buffer2,buflen);
526 if (buffer2)
528 if (retval) {
529 lstrcpynWtoA( buffer, buffer2, buflen );
530 retval = lstrlen32A( buffer );
532 else
533 *buffer = 0;
534 HeapFree( GetProcessHeap(), 0, buffer2 );
536 return retval;
539 /* Messages...used by FormatMessage32* (KERNEL32.something)
541 * They can be specified either directly or using a message ID and
542 * loading them from the resource.
544 * The resourcedata has following format:
545 * start:
546 * 0: DWORD nrofentries
547 * nrofentries * subentry:
548 * 0: DWORD firstentry
549 * 4: DWORD lastentry
550 * 8: DWORD offset from start to the stringentries
552 * (lastentry-firstentry) * stringentry:
553 * 0: WORD len (0 marks end)
554 * 2: WORD unknown (flags?)
555 * 4: CHAR[len-4]
556 * (stringentry i of a subentry refers to the ID 'firstentry+i')
558 * Yes, ANSI strings in win32 resources. Go figure.
561 /**********************************************************************
562 * LoadMessage32A (internal)
564 INT32 WINAPI LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
565 LPSTR buffer, INT32 buflen )
567 HGLOBAL32 hmem;
568 HRSRC32 hrsrc;
569 BYTE *p;
570 int nrofentries,i,slen;
571 struct _subentry {
572 DWORD firstentry;
573 DWORD lastentry;
574 DWORD offset;
575 } *se;
576 struct _stringentry {
577 WORD len;
578 WORD unknown;
579 CHAR str[1];
580 } *stre;
582 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
584 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
585 hrsrc = FindResourceEx32W(instance,RT_MESSAGELIST32W,(LPWSTR)1,lang);
586 if (!hrsrc) return 0;
587 hmem = LoadResource32( instance, hrsrc );
588 if (!hmem) return 0;
590 p = LockResource32(hmem);
591 nrofentries = *(DWORD*)p;
592 stre = NULL;
593 se = (struct _subentry*)(p+4);
594 for (i=nrofentries;i--;) {
595 if ((id>=se->firstentry) && (id<=se->lastentry)) {
596 stre = (struct _stringentry*)(p+se->offset);
597 id -= se->firstentry;
598 break;
600 se++;
602 if (!stre)
603 return 0;
604 for (i=id;i--;) {
605 if (!(slen=stre->len))
606 return 0;
607 stre = (struct _stringentry*)(((char*)stre)+slen);
609 slen=stre->len;
610 TRACE(resource," - strlen=%d\n",slen);
611 i = MIN(buflen - 1, slen);
612 if (buffer == NULL)
613 return slen; /* different to LoadString */
614 if (i>0) {
615 lstrcpyn32A(buffer,stre->str,i);
616 buffer[i]=0;
617 } else {
618 if (buflen>1) {
619 buffer[0]=0;
620 return 0;
623 if (buffer)
624 TRACE(resource,"'%s' copied !\n", buffer);
625 return i;
628 /**********************************************************************
629 * LoadMessage32W (internal)
631 INT32 WINAPI LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
632 LPWSTR buffer, INT32 buflen )
634 INT32 retval;
635 LPSTR buffer2 = NULL;
636 if (buffer && buflen)
637 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
638 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
639 if (buffer)
641 if (retval) {
642 lstrcpynAtoW( buffer, buffer2, buflen );
643 retval = lstrlen32W( buffer );
645 HeapFree( GetProcessHeap(), 0, buffer2 );
647 return retval;
651 /**********************************************************************
652 * EnumResourceTypesA (KERNEL32.90)
654 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
655 LONG lParam)
657 /* FIXME: move WINE_MODREF stuff here */
658 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
661 /**********************************************************************
662 * EnumResourceTypesW (KERNEL32.91)
664 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
665 LONG lParam)
667 /* FIXME: move WINE_MODREF stuff here */
668 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
671 /**********************************************************************
672 * EnumResourceNamesA (KERNEL32.88)
674 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
675 ENUMRESNAMEPROC32A lpfun, LONG lParam )
677 /* FIXME: move WINE_MODREF stuff here */
678 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
680 /**********************************************************************
681 * EnumResourceNamesW (KERNEL32.89)
683 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
684 ENUMRESNAMEPROC32W lpfun, LONG lParam )
686 /* FIXME: move WINE_MODREF stuff here */
687 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
690 /**********************************************************************
691 * EnumResourceLanguagesA (KERNEL32.86)
693 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
694 LPCSTR name, ENUMRESLANGPROC32A lpfun,
695 LONG lParam)
697 /* FIXME: move WINE_MODREF stuff here */
698 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
700 /**********************************************************************
701 * EnumResourceLanguagesW (KERNEL32.87)
703 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
704 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
705 LONG lParam)
707 /* FIXME: move WINE_MODREF stuff here */
708 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);