(CoGetClassObject) one missing CALLBACK, extremely simplified clsid
[wine/dcerpc.git] / loader / resource.c
blobd482549b2f1ef0fb927774053b528157061bed87
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 )
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 (!wm) return (HRSRC32)0;
80 switch (wm->type)
82 case MODULE32_PE:
83 hrsrc = PE_FindResourceEx32W(wm,name,type,lang);
84 break;
86 case MODULE32_ELF:
87 hrsrc = LIBRES_FindResource( hModule, name, type );
88 break;
90 default:
91 ERR(module,"unknown module type %d\n",wm->type);
92 return (HRSRC32)0;
95 if ( !hrsrc )
96 ERR(resource,"0x%08x(%s) %s(%s) not found!\n", hModule,wm->modname, debugres_w (name), debugres_w (type));
98 return hrsrc;
102 /**********************************************************************
103 * FindResource32W (KERNEL32.131)
105 HRSRC32 WINAPI FindResource32W(HINSTANCE32 hModule, LPCWSTR name, LPCWSTR type)
107 return FindResourceEx32W(hModule,type,name,WINE_LanguageId);
111 /**********************************************************************
112 * LoadResource32 (KERNEL32.370)
113 * 'loads' a resource. The current implementation just returns a pointer
114 * into the already mapped image.
115 * RETURNS
116 * pointer into the mapped resource of the passed module
118 HGLOBAL32 WINAPI LoadResource32(
119 HINSTANCE32 hModule, /* [in] module handle */
120 HRSRC32 hRsrc ) /* [in] resource handle */
122 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
124 TRACE(resource, "module=%04x res=%04x\n",
125 hModule, hRsrc );
126 if (!hRsrc) {
127 ERR(resource,"hRsrc is 0, return 0.\n");
128 return 0;
130 if (!wm) return 0;
132 switch (wm->type)
134 case MODULE32_PE:
135 return PE_LoadResource32(wm,hRsrc);
137 case MODULE32_ELF:
138 return LIBRES_LoadResource( hModule, hRsrc );
140 default:
141 ERR(resource,"unknown module type %d\n",wm->type);
142 break;
144 return 0;
148 /**********************************************************************
149 * LockResource32 (KERNEL32.384)
151 LPVOID WINAPI LockResource32( HGLOBAL32 handle )
153 return (LPVOID)handle;
157 /**********************************************************************
158 * FreeResource32 (KERNEL32.145)
160 BOOL32 WINAPI FreeResource32( HGLOBAL32 handle )
162 /* no longer used in Win32 */
163 return TRUE;
167 /**********************************************************************
168 * AccessResource32 (KERNEL32.64)
170 INT32 WINAPI AccessResource32( HMODULE32 hModule, HRSRC32 hRsrc )
172 FIXME(resource,"(module=%08x res=%08x),not implemented\n", hModule, hRsrc);
173 return 0;
177 /**********************************************************************
178 * SizeofResource32 (KERNEL32.522)
180 DWORD WINAPI SizeofResource32( HINSTANCE32 hModule, HRSRC32 hRsrc )
182 WINE_MODREF *wm = MODULE32_LookupHMODULE(PROCESS_Current(),hModule);
184 TRACE(resource, "module=%08x res=%08x\n", hModule, hRsrc );
185 if (!wm) return 0;
187 switch (wm->type)
189 case MODULE32_PE:
190 return PE_SizeofResource32(hModule,hRsrc);
192 case MODULE32_ELF:
193 FIXME(module,"Not implemented for ELF modules\n");
194 break;
196 default:
197 ERR(module,"unknown module type %d\n",wm->type);
198 break;
200 return 0;
204 /**********************************************************************
205 * LoadAccelerators16 [USER.177]
207 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, SEGPTR lpTableName)
209 HRSRC16 hRsrc;
211 if (HIWORD(lpTableName))
212 TRACE(accel, "%04x '%s'\n",
213 instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
214 else
215 TRACE(accel, "%04x %04x\n",
216 instance, LOWORD(lpTableName) );
218 if (!(hRsrc = FindResource16( instance, lpTableName, RT_ACCELERATOR16 ))) {
219 WARN(accel, "couldn't find accelerator table resource\n");
220 return 0;
223 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
224 return LoadResource16(instance,hRsrc);
227 /**********************************************************************
228 * LoadAccelerators32W [USER.177]
229 * The image layout seems to look like this (not 100% sure):
230 * 00: BYTE type type of accelerator
231 * 01: BYTE pad (to WORD boundary)
232 * 02: WORD event
233 * 04: WORD IDval
234 * 06: WORD pad (to DWORD boundary)
236 HACCEL32 WINAPI LoadAccelerators32W(HINSTANCE32 instance,LPCWSTR lpTableName)
238 HRSRC32 hRsrc;
239 HACCEL32 hRetval;
240 DWORD size;
242 if (HIWORD(lpTableName))
243 TRACE(accel, "%p '%s'\n",
244 (LPVOID)instance, (char *)( lpTableName ) );
245 else
246 TRACE(accel, "%p 0x%04x\n",
247 (LPVOID)instance, LOWORD(lpTableName) );
249 if (!(hRsrc = FindResource32W( instance, lpTableName, RT_ACCELERATOR32W )))
251 WARN(accel, "couldn't find accelerator table resource\n");
252 hRetval = 0;
254 else {
255 hRetval = LoadResource32( instance, hRsrc );
256 size = SizeofResource32( instance, hRsrc );
257 if(size>=sizeof(ACCEL32))
259 LPACCEL32 accel_table = (LPACCEL32) hRetval;
260 /* mark last element as such - sometimes it is not marked in image */
261 accel_table[size/sizeof(ACCEL32)-1].fVirt |= 0x80;
265 TRACE(accel, "returning HACCEL 0x%x\n", hRsrc);
266 return hRetval;
269 HACCEL32 WINAPI LoadAccelerators32A(HINSTANCE32 instance,LPCSTR lpTableName)
271 LPWSTR uni;
272 HACCEL32 result;
273 if (HIWORD(lpTableName))
274 uni = HEAP_strdupAtoW( GetProcessHeap(), 0, lpTableName );
275 else
276 uni = (LPWSTR)lpTableName;
277 result = LoadAccelerators32W(instance,uni);
278 if (HIWORD(uni)) HeapFree( GetProcessHeap(), 0, uni);
279 return result;
282 /**********************************************************************
283 * CopyAcceleratorTable32A (USER32.58)
285 INT32 WINAPI CopyAcceleratorTable32A(HACCEL32 src, LPACCEL32 dst, INT32 entries)
287 return CopyAcceleratorTable32W(src, dst, entries);
290 /**********************************************************************
291 * CopyAcceleratorTable32W (USER32.59)
293 * By mortene@pvv.org 980321
295 INT32 WINAPI CopyAcceleratorTable32W(HACCEL32 src, LPACCEL32 dst,
296 INT32 entries)
298 int i;
299 LPACCEL32 accel = (LPACCEL32)src;
300 BOOL32 done = FALSE;
302 /* Do parameter checking to avoid the explosions and the screaming
303 as far as possible. */
304 if((dst && (entries < 1)) || (src == (HACCEL32)NULL)) {
305 WARN(accel, "Application sent invalid parameters (%p %p %d).\n",
306 (LPVOID)src, (LPVOID)dst, entries);
307 return 0;
311 i=0;
312 while(!done) {
313 /* Spit out some debugging information. */
314 TRACE(accel, "accel %d: type 0x%02x, event '%c', IDval 0x%04x.\n",
315 i, accel[i].fVirt, accel[i].key, accel[i].cmd);
317 /* Copy data to the destination structure array (if dst == NULL,
318 we're just supposed to count the number of entries). */
319 if(dst) {
320 memcpy(&dst[i], &accel[i], sizeof(ACCEL32));
322 /* Check if we've reached the end of the application supplied
323 accelerator table. */
324 if(i+1 == entries) {
325 /* Turn off the high order bit, just in case. */
326 dst[i].fVirt &= 0x7f;
327 done = TRUE;
331 /* The highest order bit seems to mark the end of the accelerator
332 resource table. (?) */
333 if((accel[i].fVirt & 0x80) != 0) done = TRUE;
335 i++;
338 return i;
341 /*********************************************************************
342 * CreateAcceleratorTable (USER32.64)
344 * By mortene@pvv.org 980321
346 HACCEL32 WINAPI CreateAcceleratorTable32A(LPACCEL32 lpaccel, INT32 cEntries)
348 HACCEL32 hAccel;
350 /* Do parameter checking just in case someone's trying to be
351 funny. */
352 if(cEntries < 1) {
353 WARN(accel, "Application sent invalid parameters (%p %d).\n",
354 lpaccel, cEntries);
355 SetLastError(ERROR_INVALID_PARAMETER);
356 return (HACCEL32)NULL;
358 FIXME(accel, "should check that the accelerator descriptions are valid,"
359 " return NULL and SetLastError() if not.\n");
362 /* Allocate memory and copy the table. */
363 hAccel = (HACCEL32)HeapAlloc(GetProcessHeap(), 0,
364 cEntries * sizeof(ACCEL32));
365 TRACE(accel, "handle %p\n", (LPVOID)hAccel);
366 if(!hAccel) {
367 ERR(accel, "Out of memory.\n");
368 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
369 return (HACCEL32)NULL;
371 memcpy((LPACCEL32)hAccel, lpaccel, cEntries * sizeof(ACCEL32));
373 /* Set the end-of-table terminator. */
374 ((LPACCEL32)hAccel)[cEntries-1].fVirt |= 0x80;
376 TRACE(accel, "Allocated accelerator handle %x\n", hAccel);
377 return hAccel;
381 /******************************************************************************
382 * DestroyAcceleratorTable [USER32.130]
383 * Destroys an accelerator table
385 * NOTES
386 * By mortene@pvv.org 980321
388 * PARAMS
389 * handle [I] Handle to accelerator table
391 * RETURNS STD
393 BOOL32 WINAPI DestroyAcceleratorTable( HACCEL32 handle )
395 FIXME(accel, "(0x%x): stub\n", handle);
398 /* Weird.. I thought this should work. According to the API
399 specification, DestroyAcceleratorTable() should only be called on
400 HACCEL32's made by CreateAcceleratorTable(), but Microsoft Visual
401 Studio 97 calls this function with a series of different handle
402 values without ever calling CreateAcceleratorTable(). Something
403 is very fishy in Denmark... */
404 /* Update: looks like the calls to this function matches the calls
405 to LoadAccelerators() in M$ Visual Studio, except that the handle
406 values are off by some variable size from the HACCEL's returned
407 from LoadAccelerators(). WTH? */
409 /* Parameter checking to avoid any embarassing situations. */
410 #if 0
411 if(!handle) {
412 WARN(accel, "Application sent NULL ptr.\n");
413 SetLastError(ERROR_INVALID_PARAMETER);
414 return FALSE;
417 HeapFree(GetProcessHeap(), 0, (LPACCEL32)handle);
418 #endif
420 return TRUE;
423 /**********************************************************************
424 * LoadString16
426 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id,
427 LPSTR buffer, INT16 buflen )
429 HGLOBAL16 hmem;
430 HRSRC16 hrsrc;
431 unsigned char *p;
432 int string_num;
433 int i;
435 TRACE(resource,"inst=%04x id=%04x buff=%08x len=%d\n",
436 instance, resource_id, (int) buffer, buflen);
438 hrsrc = FindResource16( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING16 );
439 if (!hrsrc) return 0;
440 hmem = LoadResource16( instance, hrsrc );
441 if (!hmem) return 0;
443 p = LockResource16(hmem);
444 string_num = resource_id & 0x000f;
445 for (i = 0; i < string_num; i++)
446 p += *p + 1;
448 TRACE(resource, "strlen = %d\n", (int)*p );
450 i = MIN(buflen - 1, *p);
451 if (buffer == NULL)
452 return i;
453 if (i > 0) {
454 memcpy(buffer, p + 1, i);
455 buffer[i] = '\0';
456 } else {
457 if (buflen > 1) {
458 buffer[0] = '\0';
459 return 0;
461 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
463 FreeResource16( hmem );
465 TRACE(resource,"'%s' loaded !\n", buffer);
466 return i;
469 /**********************************************************************
470 * LoadString32W (USER32.376)
472 INT32 WINAPI LoadString32W( HINSTANCE32 instance, UINT32 resource_id,
473 LPWSTR buffer, INT32 buflen )
475 HGLOBAL32 hmem;
476 HRSRC32 hrsrc;
477 WCHAR *p;
478 int string_num;
479 int i;
481 if (HIWORD(resource_id)==0xFFFF) /* netscape 3 passes this */
482 resource_id = (UINT32)(-((INT32)resource_id));
483 TRACE(resource, "instance = %04x, id = %04x, buffer = %08x, "
484 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
486 hrsrc = FindResource32W( instance, (LPCWSTR)((resource_id>>4)+1),
487 RT_STRING32W );
488 if (!hrsrc) return 0;
489 hmem = LoadResource32( instance, hrsrc );
490 if (!hmem) return 0;
492 p = LockResource32(hmem);
493 string_num = resource_id & 0x000f;
494 for (i = 0; i < string_num; i++)
495 p += *p + 1;
497 TRACE(resource, "strlen = %d\n", (int)*p );
499 i = MIN(buflen - 1, *p);
500 if (buffer == NULL)
501 return i;
502 if (i > 0) {
503 memcpy(buffer, p + 1, i * sizeof (WCHAR));
504 buffer[i] = (WCHAR) 0;
505 } else {
506 if (buflen > 1) {
507 buffer[0] = (WCHAR) 0;
508 return 0;
510 #if 0
511 WARN(resource,"Dont know why caller give buflen=%d *p=%d trying to obtain string '%s'\n", buflen, *p, p + 1);
512 #endif
515 TRACE(resource,"%s loaded !\n", debugstr_w(buffer));
516 return i;
519 /**********************************************************************
520 * LoadString32A (USER32.375)
522 INT32 WINAPI LoadString32A( HINSTANCE32 instance, UINT32 resource_id,
523 LPSTR buffer, INT32 buflen )
525 INT32 retval;
526 LPWSTR buffer2 = NULL;
527 if (buffer && buflen)
528 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen * 2 );
529 retval = LoadString32W(instance,resource_id,buffer2,buflen);
531 if (buffer2)
533 if (retval) {
534 lstrcpynWtoA( buffer, buffer2, buflen );
535 retval = lstrlen32A( buffer );
537 else
538 *buffer = 0;
539 HeapFree( GetProcessHeap(), 0, buffer2 );
541 return retval;
544 /* Messages...used by FormatMessage32* (KERNEL32.something)
546 * They can be specified either directly or using a message ID and
547 * loading them from the resource.
549 * The resourcedata has following format:
550 * start:
551 * 0: DWORD nrofentries
552 * nrofentries * subentry:
553 * 0: DWORD firstentry
554 * 4: DWORD lastentry
555 * 8: DWORD offset from start to the stringentries
557 * (lastentry-firstentry) * stringentry:
558 * 0: WORD len (0 marks end)
559 * 2: WORD unknown (flags?)
560 * 4: CHAR[len-4]
561 * (stringentry i of a subentry refers to the ID 'firstentry+i')
563 * Yes, ANSI strings in win32 resources. Go figure.
566 /**********************************************************************
567 * LoadMessage32A (internal)
569 INT32 WINAPI LoadMessage32A( HMODULE32 instance, UINT32 id, WORD lang,
570 LPSTR buffer, INT32 buflen )
572 HGLOBAL32 hmem;
573 HRSRC32 hrsrc;
574 BYTE *p;
575 int nrofentries,i,slen;
576 struct _subentry {
577 DWORD firstentry;
578 DWORD lastentry;
579 DWORD offset;
580 } *se;
581 struct _stringentry {
582 WORD len;
583 WORD unknown;
584 CHAR str[1];
585 } *stre;
587 TRACE(resource, "instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
589 /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
590 hrsrc = FindResourceEx32W(instance,RT_MESSAGELIST32W,(LPWSTR)1,lang);
591 if (!hrsrc) return 0;
592 hmem = LoadResource32( instance, hrsrc );
593 if (!hmem) return 0;
595 p = LockResource32(hmem);
596 nrofentries = *(DWORD*)p;
597 stre = NULL;
598 se = (struct _subentry*)(p+4);
599 for (i=nrofentries;i--;) {
600 if ((id>=se->firstentry) && (id<=se->lastentry)) {
601 stre = (struct _stringentry*)(p+se->offset);
602 id -= se->firstentry;
603 break;
605 se++;
607 if (!stre)
608 return 0;
609 for (i=id;i--;) {
610 if (!(slen=stre->len))
611 return 0;
612 stre = (struct _stringentry*)(((char*)stre)+slen);
614 slen=stre->len;
615 TRACE(resource," - strlen=%d\n",slen);
616 i = MIN(buflen - 1, slen);
617 if (buffer == NULL)
618 return slen; /* different to LoadString */
619 if (i>0) {
620 lstrcpyn32A(buffer,stre->str,i);
621 buffer[i]=0;
622 } else {
623 if (buflen>1) {
624 buffer[0]=0;
625 return 0;
628 if (buffer)
629 TRACE(resource,"'%s' copied !\n", buffer);
630 return i;
633 /**********************************************************************
634 * LoadMessage32W (internal)
636 INT32 WINAPI LoadMessage32W( HMODULE32 instance, UINT32 id, WORD lang,
637 LPWSTR buffer, INT32 buflen )
639 INT32 retval;
640 LPSTR buffer2 = NULL;
641 if (buffer && buflen)
642 buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
643 retval = LoadMessage32A(instance,id,lang,buffer2,buflen);
644 if (buffer)
646 if (retval) {
647 lstrcpynAtoW( buffer, buffer2, buflen );
648 retval = lstrlen32W( buffer );
650 HeapFree( GetProcessHeap(), 0, buffer2 );
652 return retval;
656 /**********************************************************************
657 * EnumResourceTypesA (KERNEL32.90)
659 BOOL32 WINAPI EnumResourceTypes32A( HMODULE32 hmodule,ENUMRESTYPEPROC32A lpfun,
660 LONG lParam)
662 /* FIXME: move WINE_MODREF stuff here */
663 return PE_EnumResourceTypes32A(hmodule,lpfun,lParam);
666 /**********************************************************************
667 * EnumResourceTypesW (KERNEL32.91)
669 BOOL32 WINAPI EnumResourceTypes32W( HMODULE32 hmodule,ENUMRESTYPEPROC32W lpfun,
670 LONG lParam)
672 /* FIXME: move WINE_MODREF stuff here */
673 return PE_EnumResourceTypes32W(hmodule,lpfun,lParam);
676 /**********************************************************************
677 * EnumResourceNamesA (KERNEL32.88)
679 BOOL32 WINAPI EnumResourceNames32A( HMODULE32 hmodule, LPCSTR type,
680 ENUMRESNAMEPROC32A lpfun, LONG lParam )
682 /* FIXME: move WINE_MODREF stuff here */
683 return PE_EnumResourceNames32A(hmodule,type,lpfun,lParam);
685 /**********************************************************************
686 * EnumResourceNamesW (KERNEL32.89)
688 BOOL32 WINAPI EnumResourceNames32W( HMODULE32 hmodule, LPCWSTR type,
689 ENUMRESNAMEPROC32W lpfun, LONG lParam )
691 /* FIXME: move WINE_MODREF stuff here */
692 return PE_EnumResourceNames32W(hmodule,type,lpfun,lParam);
695 /**********************************************************************
696 * EnumResourceLanguagesA (KERNEL32.86)
698 BOOL32 WINAPI EnumResourceLanguages32A( HMODULE32 hmodule, LPCSTR type,
699 LPCSTR name, ENUMRESLANGPROC32A lpfun,
700 LONG lParam)
702 /* FIXME: move WINE_MODREF stuff here */
703 return PE_EnumResourceLanguages32A(hmodule,type,name,lpfun,lParam);
705 /**********************************************************************
706 * EnumResourceLanguagesW (KERNEL32.87)
708 BOOL32 WINAPI EnumResourceLanguages32W( HMODULE32 hmodule, LPCWSTR type,
709 LPCWSTR name, ENUMRESLANGPROC32W lpfun,
710 LONG lParam)
712 /* FIXME: move WINE_MODREF stuff here */
713 return PE_EnumResourceLanguages32W(hmodule,type,name,lpfun,lParam);