| /* |
| * Win32 Resources |
| * |
| * Copyright 1995 Thomas Sandford |
| * Copyright 1996 Martin von Loewis |
| * |
| * Based on the Win16 resource handling code in loader/resource.c |
| * Copyright 1993 Robert J. Amstadt |
| * Copyright 1995 Alexandre Julliard |
| * |
| * This is not even at ALPHA level yet. Don't expect it to work! |
| */ |
| |
| #include <sys/types.h> |
| #include "wintypes.h" |
| #include "windows.h" |
| #include "kernel32.h" |
| #include "pe_image.h" |
| #include "handle32.h" |
| #include "libres.h" |
| #include "resource32.h" |
| #include "stackframe.h" |
| #include "neexe.h" |
| #include "accel.h" |
| #include "xmalloc.h" |
| #include "string32.h" |
| #include "stddebug.h" |
| #include "debug.h" |
| |
| int language = 0x0409; |
| |
| #if 0 |
| #define PrintId(name) \ |
| if (HIWORD((DWORD)name)) \ |
| dprintf_resource( stddeb, "'%s'", name); \ |
| else \ |
| dprintf_resource( stddeb, "#%04x", LOWORD(name)); |
| #else |
| #define PrintId(name) |
| #endif |
| |
| /********************************************************************** |
| * GetResDirEntry |
| * |
| * Helper function - goes down one level of PE resource tree |
| * |
| */ |
| PIMAGE_RESOURCE_DIRECTORY GetResDirEntry(PIMAGE_RESOURCE_DIRECTORY resdirptr, |
| LPCWSTR name, |
| DWORD root) |
| { |
| int entrynum; |
| PIMAGE_RESOURCE_DIRECTORY_ENTRY entryTable; |
| int namelen; |
| |
| if (HIWORD(name)) { |
| /* FIXME: what about #xxx names? */ |
| entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ( |
| (BYTE *) resdirptr + |
| sizeof(IMAGE_RESOURCE_DIRECTORY)); |
| namelen = STRING32_lstrlenW(name); |
| for (entrynum = 0; entrynum < resdirptr->NumberOfNamedEntries; entrynum++) |
| { |
| PIMAGE_RESOURCE_DIR_STRING_U str = |
| (PIMAGE_RESOURCE_DIR_STRING_U) (root + |
| (entryTable[entrynum].Name & 0x7fffffff)); |
| if(namelen != str->Length) |
| continue; |
| if(STRING32_lstrcmpniW(name,str->NameString,str->Length)==0) |
| return (PIMAGE_RESOURCE_DIRECTORY) ( |
| root + |
| (entryTable[entrynum].OffsetToData & 0x7fffffff)); |
| } |
| return NULL; |
| } else { |
| entryTable = (PIMAGE_RESOURCE_DIRECTORY_ENTRY) ( |
| (BYTE *) resdirptr + |
| sizeof(IMAGE_RESOURCE_DIRECTORY) + |
| resdirptr->NumberOfNamedEntries * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); |
| for (entrynum = 0; entrynum < resdirptr->NumberOfIdEntries; entrynum++) |
| if ((DWORD)entryTable[entrynum].Name == (DWORD)name) |
| return (PIMAGE_RESOURCE_DIRECTORY) ( |
| root + |
| (entryTable[entrynum].OffsetToData & 0x7fffffff)); |
| return NULL; |
| } |
| } |
| |
| /********************************************************************** |
| * FindResource (KERNEL.60) |
| */ |
| HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type ) |
| { |
| #ifndef WINELIB |
| struct w_files *wptr = wine_files; |
| PIMAGE_RESOURCE_DIRECTORY resdirptr; |
| DWORD root; |
| HANDLE32 result; |
| |
| hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ |
| dprintf_resource(stddeb, "FindResource: module=%08x type=", hModule ); |
| PrintId( type ); |
| dprintf_resource( stddeb, " name=" ); |
| PrintId( name ); |
| dprintf_resource( stddeb, "\n" ); |
| while (wptr != NULL && (wptr->hModule != hModule)) |
| wptr = wptr->next; |
| if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL)) |
| return 0; |
| resdirptr = (PIMAGE_RESOURCE_DIRECTORY) wptr->pe->pe_resource; |
| root = (DWORD) resdirptr; |
| if ((resdirptr = GetResDirEntry(resdirptr, type, root)) == NULL) |
| return 0; |
| if ((resdirptr = GetResDirEntry(resdirptr, name, root)) == NULL) |
| return 0; |
| result = GetResDirEntry(resdirptr, (LPCWSTR)language, root); |
| /* Try LANG_NEUTRAL, too */ |
| if(!result) |
| return GetResDirEntry(resdirptr, (LPCWSTR)0, root); |
| #else |
| return LIBRES_FindResource( hModule, name, type ); |
| #endif |
| } |
| |
| |
| /********************************************************************** |
| * LoadResource (KERNEL.61) |
| */ |
| HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc ) |
| { |
| #ifndef WINELIB |
| struct w_files *wptr = wine_files; |
| |
| hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ |
| dprintf_resource(stddeb, "LoadResource: module="NPFMT" res="NPFMT"\n", |
| hModule, hRsrc ); |
| if (!hRsrc) return 0; |
| while (wptr != NULL && (wptr->hModule != hModule)) |
| wptr = wptr->next; |
| if ((wptr == NULL) || (wptr->pe == NULL) || (wptr->pe->pe_resource == NULL)) |
| return 0; |
| return (HANDLE32) (wptr->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData); |
| #else |
| return LIBRES_LoadResource( hModule, hRsrc ); |
| #endif |
| } |
| |
| |
| /********************************************************************** |
| * LockResource (KERNEL.62) |
| */ |
| LPVOID LockResource32( HANDLE32 handle ) |
| { |
| return (LPVOID) handle; |
| } |
| |
| /********************************************************************** |
| * FreeResource (KERNEL.63) |
| */ |
| BOOL FreeResource32( HANDLE32 handle ) |
| { |
| /* no longer used in Win32 */ |
| return TRUE; |
| } |
| |
| /********************************************************************** |
| * AccessResource (KERNEL.64) |
| */ |
| INT AccessResource32( HINSTANCE hModule, HRSRC hRsrc ) |
| { |
| hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ |
| dprintf_resource(stddeb, "AccessResource: module="NPFMT" res="NPFMT"\n", |
| hModule, hRsrc ); |
| if (!hRsrc) return 0; |
| fprintf(stderr,"AccessResource32: not implemented\n"); |
| return 0; |
| } |
| |
| |
| /********************************************************************** |
| * SizeofResource (KERNEL.65) |
| */ |
| DWORD SizeofResource32( HINSTANCE hModule, HRSRC hRsrc ) |
| { |
| hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */ |
| dprintf_resource(stddeb, "SizeofResource: module="NPFMT" res="NPFMT"\n", |
| hModule, hRsrc ); |
| fprintf(stderr,"SizeofResource32: not implemented\n"); |
| return 0; |
| } |
| |
| /********************************************************************** |
| * LoadAccelerators [USER.177] |
| */ |
| HANDLE32 WIN32_LoadAcceleratorsW(HINSTANCE instance, LPCWSTR lpTableName) |
| { |
| #if 0 |
| HANDLE32 hAccel; |
| HANDLE32 rsc_mem; |
| HANDLE32 hRsrc; |
| BYTE *lp; |
| ACCELHEADER *lpAccelTbl; |
| int i, n; |
| |
| if (HIWORD(lpTableName)) |
| dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" '%s'\n", |
| instance, (char *)( lpTableName ) ); |
| else |
| dprintf_accel( stddeb, "LoadAccelerators: "NPFMT" %04x\n", |
| instance, LOWORD(lpTableName) ); |
| |
| if (!(hRsrc = FindResource32( instance, lpTableName, |
| (LPCWSTR)RT_ACCELERATOR ))) |
| return 0; |
| if (!(rsc_mem = LoadResource32( instance, hRsrc ))) return 0; |
| |
| lp = (BYTE *)LockResource32(rsc_mem); |
| n = SizeofResource( instance, hRsrc ) / sizeof(ACCELENTRY); |
| hAccel = GlobalAlloc(GMEM_MOVEABLE, |
| sizeof(ACCELHEADER) + (n + 1)*sizeof(ACCELENTRY)); |
| lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel); |
| lpAccelTbl->wCount = 0; |
| for (i = 0; i < n; i++) { |
| lpAccelTbl->tbl[i].type = *(lp++); |
| lpAccelTbl->tbl[i].wEvent = *((WORD *)lp); |
| lp += 2; |
| lpAccelTbl->tbl[i].wIDval = *((WORD *)lp); |
| lp += 2; |
| if (lpAccelTbl->tbl[i].wEvent == 0) break; |
| dprintf_accel(stddeb, |
| "Accelerator #%u / event=%04X id=%04X type=%02X \n", |
| i, lpAccelTbl->tbl[i].wEvent, lpAccelTbl->tbl[i].wIDval, |
| lpAccelTbl->tbl[i].type); |
| lpAccelTbl->wCount++; |
| } |
| GlobalUnlock(hAccel); |
| FreeResource( rsc_mem ); |
| return hAccel; |
| #else |
| fprintf(stderr,"LoadAcceleratorsW: not implemented\n"); |
| return 0; |
| #endif |
| } |
| |
| HANDLE32 WIN32_LoadAcceleratorsA(HINSTANCE instance, LPCSTR lpTableName) |
| { |
| LPWSTR uni=STRING32_DupAnsiToUni(lpTableName); |
| HANDLE32 result=WIN32_LoadAcceleratorsW(instance,uni); |
| free(uni); |
| return result; |
| } |
| |
| /********************************************************************** |
| * LoadString |
| */ |
| int |
| WIN32_LoadStringW(HINSTANCE instance, DWORD resource_id, LPWSTR buffer, int buflen) |
| { |
| HANDLE32 hmem, hrsrc; |
| WCHAR *p; |
| int string_num; |
| int i; |
| |
| dprintf_resource(stddeb, "LoadString: instance = "NPFMT", id = %04x, buffer = %08x, " |
| "length = %d\n", instance, (int)resource_id, (int) buffer, buflen); |
| |
| hrsrc = FindResource32( instance, (LPCWSTR)((resource_id>>4)+1), |
| (LPCWSTR)RT_STRING ); |
| if (!hrsrc) return 0; |
| hmem = LoadResource32( instance, hrsrc ); |
| if (!hmem) return 0; |
| |
| p = LockResource32(hmem); |
| string_num = resource_id & 0x000f; |
| for (i = 0; i < string_num; i++) |
| p += *p + 1; |
| |
| dprintf_resource( stddeb, "strlen = %d\n", (int)*p ); |
| |
| i = MIN(buflen - 1, *p); |
| if (buffer == NULL) |
| return i; |
| if (i > 0) { |
| memcpy(buffer, p + 1, i * sizeof (WCHAR)); |
| buffer[i] = (WCHAR) 0; |
| } else { |
| if (buflen > 1) { |
| buffer[0] = (WCHAR) 0; |
| return 0; |
| } |
| #if 0 |
| fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p); |
| fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1); |
| #endif |
| } |
| dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer); |
| return i; |
| } |
| |
| /********************************************************************** |
| * LoadStringA |
| */ |
| int |
| WIN32_LoadStringA(HINSTANCE instance, DWORD resource_id, LPSTR buffer, int buflen) |
| { |
| WCHAR *buffer2 = xmalloc(buflen*2); |
| int retval = WIN32_LoadStringW(instance, resource_id, buffer2, buflen); |
| |
| while (*buffer2) |
| *buffer++ = (char) *buffer2++; |
| *buffer = 0; |
| return retval; |
| } |
| |
| HICON LoadIconW32(HINSTANCE hisnt, LPCTSTR lpszIcon) |
| |
| { |
| return LoadIcon(0, IDI_APPLICATION); |
| } |
| |
| HICON LoadIconA32(HINSTANCE hinst, LPCTSTR lpszIcon) |
| |
| { |
| return LoadIconW32(hinst, lpszIcon); |
| } |
| /********************************************************************** |
| * LoadBitmapW |
| */ |
| HBITMAP WIN32_LoadBitmapW( HANDLE instance, LPCWSTR name ) |
| { |
| HBITMAP hbitmap = 0; |
| HDC hdc; |
| HANDLE32 hRsrc; |
| HANDLE32 handle; |
| BITMAPINFO *info; |
| |
| if (!instance) /* OEM bitmap */ |
| { |
| if (HIWORD((int)name)) return 0; |
| return OBM_LoadBitmap( LOWORD((int)name) ); |
| } |
| |
| if (!(hRsrc = FindResource32( instance, name, |
| (LPWSTR)RT_BITMAP ))) return 0; |
| if (!(handle = LoadResource32( instance, hRsrc ))) return 0; |
| |
| info = (BITMAPINFO *)LockResource32( handle ); |
| if ((hdc = GetDC(0)) != 0) |
| { |
| char *bits = (char *)info + DIB_BitmapInfoSize( info, DIB_RGB_COLORS ); |
| hbitmap = CreateDIBitmap( hdc, &info->bmiHeader, CBM_INIT, |
| bits, info, DIB_RGB_COLORS ); |
| ReleaseDC( 0, hdc ); |
| } |
| return hbitmap; |
| } |
| /********************************************************************** |
| * LoadBitmapA |
| */ |
| HBITMAP WIN32_LoadBitmapA( HANDLE instance, LPCSTR name ) |
| { |
| HBITMAP res; |
| if(!HIWORD(name)) |
| res = WIN32_LoadBitmapW(instance,(LPWSTR)name); |
| else{ |
| LPWSTR uni=STRING32_DupAnsiToUni(name); |
| res=WIN32_LoadBitmapW(instance,uni); |
| free(uni); |
| } |
| return res; |
| } |
| |
| /********************************************************************** |
| * WIN32_ParseMenu |
| * LoadMenu helper function |
| */ |
| BYTE* WIN32_ParseMenu(HMENU hMenu,BYTE *it) |
| { |
| char entry[200]; /* buffer for ANSI names */ |
| int bufsize=100; |
| int len; |
| WORD flags; |
| WORD wMenuID; |
| WCHAR *utext; |
| do{ |
| flags=*(WORD*)it; |
| it+=sizeof(WORD); |
| /* POPUP entries have no ID, but a sub menu */ |
| if(flags & MF_POPUP) |
| { |
| wMenuID = CreatePopupMenu(); |
| len = STRING32_lstrlenW((LPWSTR)it); |
| utext = (WCHAR*)it; |
| it += sizeof(WCHAR)*(len+1); |
| it = WIN32_ParseMenu(wMenuID,it); |
| } else { |
| wMenuID=*(WORD*)it; |
| it+=sizeof(WORD); |
| utext = (LPWSTR)it; |
| len = STRING32_lstrlenW((LPWSTR)it); |
| it += sizeof(WCHAR)*(len+1); |
| if(!wMenuID && !*utext) |
| flags |= MF_SEPARATOR; |
| } |
| if(len>=bufsize) continue; /* hack hack */ |
| STRING32_UniToAnsi(entry,utext); |
| AppendMenu(hMenu,flags,wMenuID,MAKE_SEGPTR(entry)); |
| }while(!(flags & MF_END)); |
| return it; |
| } |
| |
| /***************************************************************** |
| * LoadMenuIndirectW (USER32.371) |
| */ |
| HMENU WIN32_LoadMenuIndirectW(void *menu) |
| { |
| BYTE *it=menu; |
| HMENU hMenu = CreateMenu(); |
| /*skip menu header*/ |
| if(*(DWORD*)it) |
| fprintf(stderr,"Unknown menu header\n"); |
| it+=2*sizeof(WORD); |
| WIN32_ParseMenu(hMenu,it); |
| return hMenu; |
| } |
| |
| /***************************************************************** |
| * LoadMenuW (USER32.372) |
| */ |
| HMENU WIN32_LoadMenuW(HANDLE instance, LPCWSTR name) |
| { |
| HANDLE32 hrsrc; |
| hrsrc=FindResource32(instance,name,(LPWSTR)RT_MENU); |
| if(!hrsrc)return 0; |
| return WIN32_LoadMenuIndirectW(LoadResource32(instance, hrsrc)); |
| } |
| |
| /***************************************************************** |
| * LoadMenuIndirectA (USER32.370) |
| */ |
| HMENU WIN32_LoadMenuIndirectA(void *menu) |
| { |
| fprintf(stderr,"WIN32_LoadMenuIndirectA not implemented\n"); |
| return 0; |
| } |
| |
| /***************************************************************** |
| * LoadMenuA (USER32.370) |
| */ |
| HMENU WIN32_LoadMenuA(HANDLE instance,LPCSTR name) |
| { |
| HMENU res; |
| if(!HIWORD(name)) |
| res = WIN32_LoadMenuW(instance,(LPWSTR)name); |
| else{ |
| LPWSTR uni=STRING32_DupAnsiToUni(name); |
| res=WIN32_LoadMenuW(instance,uni); |
| free(uni); |
| } |
| return res; |
| } |