Release 960414
[wine.git] / win32 / resource.c
blobdfe55370ea7a63e648c2f5c82397539520005de6
1 /*
2 * Win32 Resources
4 * Copyright 1995 Thomas Sandford
5 * Copyright 1996 Martin von Loewis
7 * Based on the Win16 resource handling code in loader/resource.c
8 * Copyright 1993 Robert J. Amstadt
9 * Copyright 1995 Alexandre Julliard
11 * This is not even at ALPHA level yet. Don't expect it to work!
14 #include <sys/types.h>
15 #include "wintypes.h"
16 #include "windows.h"
17 #include "kernel32.h"
18 #include "pe_image.h"
19 #include "module.h"
20 #include "handle32.h"
21 #include "libres.h"
22 #include "resource32.h"
23 #include "stackframe.h"
24 #include "neexe.h"
25 #include "accel.h"
26 #include "xmalloc.h"
27 #include "string32.h"
28 #include "stddebug.h"
29 #include "debug.h"
31 int language = 0x0409;
33 #if 0
34 #define PrintId(name) \
35 if (HIWORD((DWORD)name)) \
36 dprintf_resource( stddeb, "'%s'", name); \
37 else \
38 dprintf_resource( stddeb, "#%04x", LOWORD(name));
39 #else
40 #define PrintId(name)
41 #endif
43 /**********************************************************************
44 * GetResDirEntry
46 * Helper function - goes down one level of PE resource tree
49 PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr,
50 LPCWSTR name,
51 DWORD root)
53 int entrynum;
54 PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable;
55 int namelen;
57 if (HIWORD(name)) {
58 /* FIXME: what about #xxx names? */
59 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
60 (BYTE *) resdirptr +
61 sizeof(IMAGE_RESOURCE_DIRECTORY));
62 namelen = STRING32_lstrlenW(name);
63 for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++)
65 PIMAGE_RESOURCE_DIR_STRING_U str =
66 (PIMAGE_RESOURCE_DIR_STRING_U) (root +
67 (entryTable[entrynum].Name & 0x7fffffff));
68 if(namelen != str->Length)
69 continue;
70 if(STRING32_lstrcmpniW(name,str->NameString,str->Length)==0)
71 return (PIMAGE_RESOURCE_DIRECTORY) (
72 root +
73 (entryTable[entrynum].OffsetToData & 0x7fffffff));
75 return NULL;
76 } else {
77 entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) (
78 (BYTE *) resdirptr +
79 sizeof(IMAGE_RESOURCE_DIRECTORY) +
80 resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY));
81 for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++)
82 if ((DWORD)entryTable[entrynum].Name == (DWORD)name)
83 return (PIMAGE_RESOURCE_DIRECTORY) (
84 root +
85 (entryTable[entrynum].OffsetToData & 0x7fffffff));
86 return NULL;
90 /**********************************************************************
91 * FindResource (KERNEL.60)
93 HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
95 #ifndef WINELIB
96 PE_MODULE *pe;
97 NE_MODULE *pModule;
98 PIMAGE_RESOURCE_DIRECTORY resdirptr;
99 DWORD root;
100 HANDLE32 result;
102 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
103 dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule );
104 PrintId( type );
105 dprintf_resource( stddeb, " name=" );
106 PrintId( name );
107 dprintf_resource( stddeb, "\n" );
108 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
109 if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0; /* FIXME? */
110 if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
112 resdirptr = (PIMAGE_RESOURCE_DIRECTORY) pe->pe_resource;
113 root = (DWORD) resdirptr;
114 if ((resdirptr = GetResDirEntry(resdirptr, type, root)) == NULL)
115 return 0;
116 if ((resdirptr = GetResDirEntry(resdirptr, name, root)) == NULL)
117 return 0;
118 result = GetResDirEntry(resdirptr, (LPCWSTR)language, root);
119 /* Try LANG_NEUTRAL, too */
120 if(!result)
121 return GetResDirEntry(resdirptr, (LPCWSTR)0, root);
122 return result;
124 #else
125 return LIBRES_FindResource( hModule, name, type );
126 #endif
130 /**********************************************************************
131 * LoadResource (KERNEL.61)
133 HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc )
135 #ifndef WINELIB
136 NE_MODULE *pModule;
137 PE_MODULE *pe;
139 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
140 dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
141 hModule, hRsrc );
142 if (!hRsrc) return 0;
144 if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
145 if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0; /* FIXME? */
146 if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
147 return (HANDLE32) (pe->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
148 #else
149 return LIBRES_LoadResource( hModule, hRsrc );
150 #endif
154 /**********************************************************************
155 * LockResource (KERNEL.62)
157 LPVOID LockResource32( HANDLE32 handle )
159 return (LPVOID) handle;
162 /**********************************************************************
163 * FreeResource (KERNEL.63)
165 BOOL FreeResource32( HANDLE32 handle )
167 /* no longer used in Win32 */
168 return TRUE;
171 /**********************************************************************
172 * AccessResource (KERNEL.64)
174 INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc )
176 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
177 dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
178 hModule, hRsrc );
179 if (!hRsrc) return 0;
180 fprintf(stderr,"AccessResource32: not implemented\n");
181 return 0;
185 /**********************************************************************
186 * SizeofResource (KERNEL.65)
188 DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc )
190 hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
191 dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
192 hModule, hRsrc );
193 fprintf(stderr,"SizeofResource32: not implemented\n");
194 return 0;
197 /**********************************************************************
198 * LoadAccelerators [USER.177]
200 HANDLE32 WIN32_LoadAcceleratorsW(HINSTANCE instance, LPCWSTR lpTableName)
202 #if 0
203 HANDLE32 hAccel;
204 HANDLE32 rsc_mem;
205 HANDLE32 hRsrc;
206 BYTE *lp;
207 ACCELHEADER *lpAccelTbl;
208 int i, n;
210 if (HIWORD(lpTableName))
211 dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
212 instance, (char *)( lpTableName ) );
213 else
214 dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
215 instance, LOWORD(lpTableName) );
217 if (!(hRsrc = FindResource32( instance, lpTableName,
218 (LPCWSTR)RT_ACCELERATOR )))
219 return 0;
220 if (!(rsc_mem = LoadResource32( instance, hRsrc ))) return 0;
222 lp = (BYTE *)LockResource32(rsc_mem);
223 n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY);
224 hAccel = GlobalAlloc(GMEM_MOVEABLE,
225 sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY));
226 lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
227 lpAccelTbl->wCount = 0;
228 for (i = 0; i < n; i++) {
229 lpAccelTbl->tbl[i].type = *(lp++);
230 lpAccelTbl->tbl[i].wEvent = *((WORD *)lp);
231 lp += 2;
232 lpAccelTbl->tbl[i].wIDval = *((WORD *)lp);
233 lp += 2;
234 if (lpAccelTbl->tbl[i].wEvent == 0) break;
235 dprintf_accel(stddeb,
236 "Accelerator #%u / event=%04X id=%04X type=%02X \n",
237 i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval,
238 lpAccelTbl->tbl[i].type);
239 lpAccelTbl->wCount++;
241 GlobalUnlock(hAccel);
242 FreeResource( rsc_mem );
243 return hAccel;
244 #else
245 fprintf(stderr,"LoadAcceleratorsW: not implemented\n");
246 return 0;
247 #endif
250 HANDLE32 WIN32_LoadAcceleratorsA(HINSTANCE instance, LPCSTR lpTableName)
252 LPWSTR uni=STRING32_DupAnsiToUni(lpTableName);
253 HANDLE32 result=WIN32_LoadAcceleratorsW(instance,uni);
254 free(uni);
255 return result;
258 /**********************************************************************
259 * LoadString
262 WIN32_LoadStringW(HINSTANCE instance, DWORD resource_id, LPWSTR buffer, int buflen)
264 HANDLE32 hmem, hrsrc;
265 WCHAR *p;
266 int string_num;
267 int i;
269 dprintf_resource(stddeb, "LoadString: instance = %04x, id = %04x, buffer = %08x, "
270 "length = %d\n", instance, (int)resource_id, (int) buffer, buflen);
272 hrsrc = FindResource32( instance, (LPCWSTR)((resource_id>>4)+1),
273 (LPCWSTR)RT_STRING );
274 if (!hrsrc) return 0;
275 hmem = LoadResource32( instance, hrsrc );
276 if (!hmem) return 0;
278 p = LockResource32(hmem);
279 string_num = resource_id & 0x000f;
280 for (i = 0; i < string_num; i++)
281 p += *p + 1;
283 dprintf_resource( stddeb, "strlen = %d\n", (int)*p );
285 i = MIN(buflen - 1, *p);
286 if (buffer == NULL)
287 return i;
288 if (i > 0) {
289 memcpy(buffer, p + 1, i * sizeof (WCHAR));
290 buffer[i] = (WCHAR) 0;
291 } else {
292 if (buflen > 1) {
293 buffer[0] = (WCHAR) 0;
294 return 0;
296 #if 0
297 fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
298 fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
299 #endif
301 dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
302 return i;
305 /**********************************************************************
306 * LoadStringA
309 WIN32_LoadStringA(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen)
311 WCHAR *buffer2 = xmalloc(buflen*2);
312 int retval = WIN32_LoadStringW(instance, resource_id, buffer2, buflen);
314 while (*buffer2)
315 *buffer++ = (char) *buffer2++;
316 *buffer = 0;
317 return retval;
320 HICON LoadIconW32(HINSTANCE hisnt, LPCTSTR lpszIcon)
323 return LoadIcon(0, IDI_APPLICATION);
326 HICON LoadIconA32(HINSTANCE hinst, LPCTSTR lpszIcon)
329 return LoadIconW32(hinst, lpszIcon);
331 /**********************************************************************
332 * LoadBitmapW
334 HBITMAP WIN32_LoadBitmapW( HANDLE instance, LPCWSTR name )
336 HBITMAP hbitmap = 0;
337 HDC hdc;
338 HANDLE32 hRsrc;
339 HANDLE32 handle;
340 BITMAPINFO *info;
342 if (!instance) /* OEM bitmap */
344 if (HIWORD((int)name)) return 0;
345 return OBM_LoadBitmap( LOWORD((int)name) );
348 if (!(hRsrc = FindResource32( instance, name,
349 (LPWSTR)RT_BITMAP ))) return 0;
350 if (!(handle = LoadResource32( instance, hRsrc ))) return 0;
352 info = (BITMAPINFO *)LockResource32( handle );
353 if ((hdc = GetDC(0)) != 0)
355 char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS );
356 hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT,
357 bits, info, DIB_RGB_COLORS );
358 ReleaseDC( 0, hdc );
360 return hbitmap;
362 /**********************************************************************
363 * LoadBitmapA
365 HBITMAP WIN32_LoadBitmapA( HANDLE instance, LPCSTR name )
367 HBITMAP res;
368 if(!HIWORD(name))
369 res = WIN32_LoadBitmapW(instance,(LPWSTR)name);
370 else{
371 LPWSTR uni=STRING32_DupAnsiToUni(name);
372 res=WIN32_LoadBitmapW(instance,uni);
373 free(uni);
375 return res;
378 /**********************************************************************
379 * WIN32_ParseMenu
380 * LoadMenu helper function
382 BYTE* WIN32_ParseMenu(HMENU hMenu,BYTE *it)
384 char entry[200]; /* buffer for ANSI names */
385 int bufsize=100;
386 int len;
387 WORD flags;
388 WORD wMenuID;
389 WCHAR *utext;
391 flags=*(WORD*)it;
392 it+=sizeof(WORD);
393 /* POPUP entries have no ID, but a sub menu */
394 if(flags & MF_POPUP)
396 wMenuID = CreatePopupMenu();
397 len = STRING32_lstrlenW((LPWSTR)it);
398 utext = (WCHAR*)it;
399 it += sizeof(WCHAR)*(len+1);
400 it = WIN32_ParseMenu(wMenuID,it);
401 } else {
402 wMenuID=*(WORD*)it;
403 it+=sizeof(WORD);
404 utext = (LPWSTR)it;
405 len = STRING32_lstrlenW((LPWSTR)it);
406 it += sizeof(WCHAR)*(len+1);
407 if(!wMenuID && !*utext)
408 flags |= MF_SEPARATOR;
410 if(len>=bufsize) continue; /* hack hack */
411 STRING32_UniToAnsi(entry,utext);
412 AppendMenu(hMenu,flags,wMenuID,MAKE_SEGPTR(entry));
413 }while(!(flags & MF_END));
414 return it;
417 /*****************************************************************
418 * LoadMenuIndirectW (USER32.371)
420 HMENU WIN32_LoadMenuIndirectW(void *menu)
422 BYTE *it=menu;
423 HMENU hMenu = CreateMenu();
424 /*skip menu header*/
425 if(*(DWORD*)it)
426 fprintf(stderr,"Unknown menu header\n");
427 it+=2*sizeof(WORD);
428 WIN32_ParseMenu(hMenu,it);
429 return hMenu;
432 /*****************************************************************
433 * LoadMenuW (USER32.372)
435 HMENU WIN32_LoadMenuW(HANDLE instance, LPCWSTR name)
437 HANDLE32 hrsrc;
438 hrsrc=FindResource32(instance,name,(LPWSTR)RT_MENU);
439 if(!hrsrc)return 0;
440 return WIN32_LoadMenuIndirectW(LoadResource32(instance, hrsrc));
443 /*****************************************************************
444 * LoadMenuIndirectA (USER32.370)
446 HMENU WIN32_LoadMenuIndirectA(void *menu)
448 fprintf(stderr,"WIN32_LoadMenuIndirectA not implemented\n");
449 return 0;
452 /*****************************************************************
453 * LoadMenuA (USER32.370)
455 HMENU WIN32_LoadMenuA(HANDLE instance,LPCSTR name)
457 HMENU res;
458 if(!HIWORD(name))
459 res = WIN32_LoadMenuW(instance,(LPWSTR)name);
460 else{
461 LPWSTR uni=STRING32_DupAnsiToUni(name);
462 res=WIN32_LoadMenuW(instance,uni);
463 free(uni);
465 return res;