blob: 09707867f4c3af0f530d4a7281d9328bd73a759c [file] [log] [blame]
/*
* Resources
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "arch.h"
#include "windows.h"
#include "gdi.h"
#include "bitmap.h"
#include "global.h"
#include "neexe.h"
#include "icon.h"
#include "accel.h"
#include "dlls.h"
#include "module.h"
#include "resource.h"
#include "stddebug.h"
#include "debug.h"
#define PrintId(name) \
if (HIWORD((DWORD)name)) \
dprintf_resource( stddeb, "'%s'", (char *)PTR_SEG_TO_LIN(name)); \
else \
dprintf_resource( stddeb, "#%04x", LOWORD(name));
/**********************************************************************
* FindResource (KERNEL.60)
*/
HRSRC FindResource( HMODULE hModule, SEGPTR name, SEGPTR type )
{
WORD *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_resource(stddeb, "FindResource: module=%04x type=", hModule );
PrintId( type );
dprintf_resource( stddeb, " name=" );
PrintId( name );
dprintf_resource( stddeb, "\n" );
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_FindResource( hModule, type, name );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* LoadResource (KERNEL.61)
*/
HGLOBAL LoadResource( HMODULE hModule, HRSRC hRsrc )
{
WORD *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
hModule, hRsrc );
if (!hRsrc) return 0;
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_LoadResource( hModule, hRsrc );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* LockResource (KERNEL.62)
*/
/* 16-bit version */
SEGPTR WIN16_LockResource( HGLOBAL handle )
{
HMODULE hModule;
WORD *pModule;
dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
if (!handle) return (SEGPTR)0;
hModule = GetExePtr( handle );
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_LockResource( hModule, handle );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/* 32-bit version */
LPSTR LockResource( HGLOBAL handle )
{
HMODULE hModule;
WORD *pModule;
dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
if (!handle) return NULL;
hModule = GetExePtr( handle );
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return (LPSTR)PTR_SEG_TO_LIN( NE_LockResource( hModule, handle ) );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* FreeResource (KERNEL.63)
*/
BOOL FreeResource( HGLOBAL handle )
{
HMODULE hModule;
WORD *pModule;
dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle );
if (!handle) return FALSE;
hModule = GetExePtr( handle );
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_FreeResource( hModule, handle );
case PE_SIGNATURE:
return FALSE;
default:
return FALSE;
}
}
/**********************************************************************
* AccessResource (KERNEL.64)
*/
int AccessResource( HMODULE hModule, HRSRC hRsrc )
{
WORD *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
hModule, hRsrc );
if (!hRsrc) return 0;
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_AccessResource( hModule, hRsrc );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* SizeofResource (KERNEL.65)
*/
DWORD SizeofResource( HMODULE hModule, HRSRC hRsrc )
{
WORD *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
hModule, hRsrc );
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_SizeofResource( hModule, hRsrc );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* AllocResource (KERNEL.66)
*/
HGLOBAL AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
{
WORD *pModule;
hModule = GetExePtr( hModule ); /* In case we were passed an hInstance */
dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
hModule, hRsrc, size );
if (!hRsrc) return 0;
if (!(pModule = (WORD *)GlobalLock( hModule ))) return 0;
switch(*pModule)
{
case NE_SIGNATURE:
return NE_AllocResource( hModule, hRsrc, size );
case PE_SIGNATURE:
return 0;
default:
return 0;
}
}
/**********************************************************************
* DirectResAlloc (KERNEL.168)
* Check Schulman, p. 232 for details
*/
HANDLE DirectResAlloc(HANDLE hInstance, WORD wType, WORD wSize)
{
HANDLE hModule;
dprintf_resource(stddeb,"DirectResAlloc(%x,%x,%x)\n",hInstance,wType,wSize);
hModule = GetExePtr(hInstance);
if(!hModule)return 0;
if(wType != 0x10) /* 0x10 is the only observed value, passed from
CreateCursorIndirect. */
fprintf(stderr, "DirectResAlloc: wType = %x\n", wType);
/* This hopefully does per-module allocation rather than per-instance */
return GLOBAL_Alloc(GMEM_FIXED, wSize, hModule, FALSE, FALSE, FALSE);
}
/**********************************************************************
* ConvertCoreBitmap
*/
HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image )
{
BITMAPINFO * bmpInfo;
HBITMAP hbitmap;
char * bits;
int i, size, n_colors;
n_colors = 1 << image->bcBitCount;
if (image->bcBitCount < 24)
{
size = sizeof(BITMAPINFOHEADER) + n_colors * sizeof(RGBQUAD);
bits = (char *) (image + 1) + (n_colors * sizeof(RGBTRIPLE));
}
else
{
size = sizeof(BITMAPINFOHEADER);
bits = (char *) (image + 1);
}
bmpInfo = (BITMAPINFO *) malloc( size );
bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo->bmiHeader.biWidth = image->bcWidth;
bmpInfo->bmiHeader.biHeight = image->bcHeight;
bmpInfo->bmiHeader.biPlanes = image->bcPlanes;
bmpInfo->bmiHeader.biBitCount = image->bcBitCount;
bmpInfo->bmiHeader.biCompression = 0;
bmpInfo->bmiHeader.biSizeImage = 0;
bmpInfo->bmiHeader.biXPelsPerMeter = 0;
bmpInfo->bmiHeader.biYPelsPerMeter = 0;
bmpInfo->bmiHeader.biClrUsed = 0;
bmpInfo->bmiHeader.biClrImportant = 0;
if (image->bcBitCount < 24)
{
RGBTRIPLE * oldMap = (RGBTRIPLE *)(image + 1);
RGBQUAD * newMap = bmpInfo->bmiColors;
for (i = 0; i < n_colors; i++, oldMap++, newMap++)
{
newMap->rgbRed = oldMap->rgbtRed;
newMap->rgbGreen = oldMap->rgbtGreen;
newMap->rgbBlue = oldMap->rgbtBlue;
newMap->rgbReserved = 0;
}
}
hbitmap = CreateDIBitmap( hdc, &bmpInfo->bmiHeader, CBM_INIT,
bits, bmpInfo, DIB_RGB_COLORS );
free( bmpInfo );
return hbitmap;
}
/**********************************************************************
* ConvertInfoBitmap
*/
HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image )
{
char * bits = ((char *)image) + DIB_BitmapInfoSize(image, DIB_RGB_COLORS);
return CreateDIBitmap( hdc, &image->bmiHeader, CBM_INIT,
bits, image, DIB_RGB_COLORS );
}
/**********************************************************************
* LoadIcon [USER.174]
*/
HICON LoadIcon( HANDLE instance, SEGPTR icon_name )
{
HICON hIcon;
HRSRC hRsrc;
HANDLE rsc_mem;
WORD *lp;
ICONDESCRIP *lpicodesc;
ICONALLOC *lpico;
int width, height;
BITMAPINFO *bmi;
BITMAPINFOHEADER *bih;
RGBQUAD *rgbq;
HDC hdc;
BITMAPINFO *pInfo;
char *bits;
int size;
if (HIWORD(icon_name))
dprintf_resource( stddeb, "LoadIcon: %04x '%s'\n",
instance, (char *)PTR_SEG_TO_LIN( icon_name ) );
else
dprintf_resource( stddeb, "LoadIcon: %04x %04x\n",
instance, LOWORD(icon_name) );
if (!instance)
{
if (HIWORD((int)icon_name)) return 0; /* FIXME: should handle '#xxx' */
return OBM_LoadIcon( LOWORD((int)icon_name) );
}
if (!(hRsrc = FindResource( instance, icon_name, RT_GROUP_ICON))) return 0;
rsc_mem = LoadResource( instance, hRsrc );
if (rsc_mem == (HANDLE)NULL) {
printf("LoadIcon / Icon %08x not Found !\n", (int) icon_name);
return 0;
}
lp = (WORD *)LockResource(rsc_mem);
lpicodesc = (ICONDESCRIP *)(lp + 3);
hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
if (hIcon == (HICON)NULL) {
FreeResource( rsc_mem );
return 0;
}
lpico = (ICONALLOC *)GlobalLock(hIcon);
lpico->descriptor = *lpicodesc;
width = lpicodesc->Width;
height = lpicodesc->Height;
FreeResource( rsc_mem );
if (!(hRsrc = FindResource( instance,
MAKEINTRESOURCE(lpico->descriptor.icoDIBOffset),
RT_ICON ))) return 0;
if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
bmi = (BITMAPINFO *)LockResource(rsc_mem);
size = DIB_BitmapInfoSize( bmi, DIB_RGB_COLORS );
pInfo = (BITMAPINFO *)malloc( size );
memcpy( pInfo, bmi, size );
bih = &pInfo->bmiHeader;
bih->biHeight /= 2;
if (!(hdc = GetDC( 0 ))) return 0;
if (bih->biSize != sizeof(BITMAPINFOHEADER)) return 0;
lpico->hBitmap = CreateDIBitmap( hdc, &pInfo->bmiHeader, CBM_INIT,
(char*)bmi + size, pInfo, DIB_RGB_COLORS );
if (bih->biSizeImage == 0)
{
if (bih->biCompression != BI_RGB)
{
fprintf(stderr,"Unknown size for compressed Icon bitmap.\n");
FreeResource( rsc_mem );
ReleaseDC( 0, hdc);
return 0;
}
bih->biSizeImage = DIB_GetImageWidthBytes(bih->biWidth,bih->biBitCount)
* bih->biHeight;
}
bits = (char *)bmi + size +
bih->biSizeImage * bih->biBitCount / (bih->biBitCount+1);
bih->biBitCount = 1;
bih->biClrUsed = bih->biClrImportant = 2;
rgbq = &bmi->bmiColors[0];
rgbq[0].rgbBlue = rgbq[0].rgbGreen = rgbq[0].rgbRed = 0x00;
rgbq[1].rgbBlue = rgbq[1].rgbGreen = rgbq[1].rgbRed = 0xff;
rgbq[0].rgbReserved = rgbq[1].rgbReserved = 0;
lpico->hBitMask = CreateDIBitmap(hdc, &pInfo->bmiHeader, CBM_INIT,
/* (LPSTR)bmi + bih->biSizeImage - sizeof(BITMAPINFOHEADER) / 2 - 4,
(LPSTR)lp + bih->biSizeImage + bih->biSize + 4*lpicodesc->ColorCount, */
bits, pInfo, DIB_RGB_COLORS );
FreeResource( rsc_mem );
ReleaseDC( 0, hdc);
free( pInfo );
GlobalUnlock(hIcon);
dprintf_resource(stddeb,"LoadIcon Alloc hIcon=%X\n", hIcon);
return hIcon;
}
/**********************************************************************
* CreateIcon [USER.407]
*/
HICON CreateIcon(HANDLE hInstance, int nWidth, int nHeight,
BYTE nPlanes, BYTE nBitsPixel, LPSTR lpANDbits,
LPSTR lpXORbits)
{
HICON hIcon;
ICONALLOC *lpico;
dprintf_resource(stddeb, "CreateIcon: hInstance = %04x, nWidth = %08x, nHeight = %08x \n",
hInstance, nWidth, nHeight);
dprintf_resource(stddeb, " nPlanes = %04x, nBitsPixel = %04x,",nPlanes, nBitsPixel);
dprintf_resource(stddeb, " lpANDbits= %04x, lpXORbits = %04x, \n", (int)lpANDbits,
(int)lpXORbits);
if (hInstance == (HANDLE)NULL) {
printf("CreateIcon / hInstance %04x not Found!\n",hInstance);
return 0;
}
hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
if (hIcon == (HICON)NULL) {
printf("Can't allocate memory for Icon in CreateIcon\n");
return 0;
}
lpico= (ICONALLOC *)GlobalLock(hIcon);
lpico->descriptor.Width=nWidth;
lpico->descriptor.Height=nHeight;
lpico->descriptor.ColorCount=16; /* Dummy Value */
lpico->descriptor.Reserved1=0;
lpico->descriptor.Reserved2=nPlanes;
lpico->descriptor.Reserved3=nWidth*nHeight;
/* either nPlanes and/or nBitCount is set to one */
lpico->descriptor.icoDIBSize=nWidth*nHeight*nPlanes*nBitsPixel;
lpico->descriptor.icoDIBOffset=0;
if( !(lpico->hBitmap=CreateBitmap(nWidth, nHeight, nPlanes, nBitsPixel,
lpXORbits)) ) {
printf("CreateIcon: couldn't create the XOR bitmap\n");
return(0);
}
/* the AND BitMask is always monochrome */
if( !(lpico->hBitMask=CreateBitmap(nWidth, nHeight, 1, 1, lpANDbits)) ) {
printf("CreateIcon: couldn't create the AND bitmap\n");
return(0);
}
GlobalUnlock(hIcon);
dprintf_resource(stddeb, "CreateIcon Alloc hIcon=%X\n", hIcon);
return hIcon;
}
/**********************************************************************
* DestroyIcon [USER.457]
*/
BOOL DestroyIcon(HICON hIcon)
{
ICONALLOC *lpico;
if (hIcon == (HICON)NULL)
return FALSE;
lpico = (ICONALLOC *)GlobalLock(hIcon);
if (lpico->hBitmap != (HBITMAP)NULL)
DeleteObject(lpico->hBitmap);
GlobalFree(hIcon);
return TRUE;
}
/**********************************************************************
* DumpIcon [USER.459]
*/
DWORD DumpIcon(void* cursorIconInfo, WORD FAR *lpLen, LPSTR FAR *lpXorBits,
LPSTR FAR *lpAndMask)
{
dprintf_resource(stdnimp,"DumpIcon: Empty Stub!!!\n");
return 0;
}
/**********************************************************************
* LoadAccelerators [USER.177]
*/
HANDLE LoadAccelerators(HANDLE instance, SEGPTR lpTableName)
{
HANDLE hAccel;
HANDLE rsc_mem;
HRSRC hRsrc;
BYTE *lp;
ACCELHEADER *lpAccelTbl;
int i, n;
if (HIWORD(lpTableName))
dprintf_accel( stddeb, "LoadAccelerators: %04x '%s'\n",
instance, (char *)PTR_SEG_TO_LIN( lpTableName ) );
else
dprintf_accel( stddeb, "LoadAccelerators: %04x %04x\n",
instance, LOWORD(lpTableName) );
if (!(hRsrc = FindResource( instance, lpTableName, RT_ACCELERATOR )))
return 0;
if (!(rsc_mem = LoadResource( instance, hRsrc ))) return 0;
lp = (BYTE *)LockResource(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;
}
/**********************************************************************
* TranslateAccelerator [USER.178]
*/
int TranslateAccelerator(HWND hWnd, HANDLE hAccel, LPMSG msg)
{
ACCELHEADER *lpAccelTbl;
int i;
if (hAccel == 0 || msg == NULL) return 0;
if (msg->message != WM_KEYDOWN &&
msg->message != WM_KEYUP &&
msg->message != WM_CHAR) return 0;
dprintf_accel(stddeb, "TranslateAccelerators hAccel=%04X !\n", hAccel);
lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
for (i = 0; i < lpAccelTbl->wCount; i++) {
if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
msg->message == WM_KEYDOWN) {
if ((lpAccelTbl->tbl[i].type & SHIFT_ACCEL) &&
!(GetKeyState(VK_SHIFT) & 0xf)) {
GlobalUnlock(hAccel);
return 0;
}
if ((lpAccelTbl->tbl[i].type & CONTROL_ACCEL) &&
!(GetKeyState(VK_CONTROL) & 0xf)) {
GlobalUnlock(hAccel);
return 0;
}
if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) &&
!(GetKeyState(VK_MENU) & 0xf)) {
GlobalUnlock(hAccel);
return 0;
}
SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
GlobalUnlock(hAccel);
return 1;
}
if (msg->message == WM_KEYUP) return 1;
}
else {
if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
msg->message == WM_CHAR) {
SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
GlobalUnlock(hAccel);
return 1;
}
}
}
GlobalUnlock(hAccel);
return 0;
}
/**********************************************************************
* LoadString
*/
int
LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
{
HANDLE hmem, hrsrc;
unsigned char *p;
int string_num;
int i;
dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
"length = %d\n", instance, resource_id, (int) buffer, buflen);
hrsrc = FindResource( instance, (SEGPTR)((resource_id>>4)+1), RT_STRING );
if (!hrsrc) return 0;
hmem = LoadResource( instance, hrsrc );
if (!hmem) return 0;
p = LockResource(hmem);
string_num = resource_id & 0x000f;
for (i = 0; i < string_num; i++)
p += *p + 1;
i = min(buflen - 1, *p);
if (i > 0) {
memcpy(buffer, p + 1, i);
buffer[i] = '\0';
}
else {
if (buflen > 1) {
buffer[0] = '\0';
return 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);
}
FreeResource( hmem );
dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
return i;
}