wine/loader/ne/convert.c
2000-09-25 23:30:56 +00:00

443 lines
12 KiB
C

/*
* PE->NE resource conversion functions
*
* Copyright 1998 Ulrich Weigand
*/
#include <string.h>
#include "windef.h"
#include "wingdi.h"
#include "wine/winuser16.h"
#include "wine/unicode.h"
#include "wine/winestring.h"
#include "module.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(resource);
/**********************************************************************
* ConvertDialog32To16 (KERNEL.615)
*/
VOID WINAPI ConvertDialog32To16( LPVOID dialog32, DWORD size, LPVOID dialog16 )
{
LPVOID p = dialog32;
WORD nbItems, data, dialogEx;
DWORD style;
style = *((DWORD *)dialog16)++ = *((DWORD *)p)++;
dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
if (dialogEx)
{
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
style = *((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
}
else
((DWORD *)p)++; /* exStyle ignored in 16-bit standard dialog */
nbItems = *((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++;
*((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
/* Transfer menu name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
*((WORD *)dialog16)++ = *((WORD *)p)++; break;
default: lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
break;
}
/* Transfer class name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
*((WORD *)dialog16)++ = *((WORD *)p)++; break;
default: lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
break;
}
/* Transfer window caption */
lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
/* Transfer font info */
if (style & DS_SETFONT)
{
*((WORD *)dialog16)++ = *((WORD *)p)++; /* pointSize */
if (dialogEx)
{
*((WORD *)dialog16)++ = *((WORD *)p)++; /* weight */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* italic */
}
lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p ); /* faceName */
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
}
/* Transfer dialog items */
while (nbItems)
{
/* align on DWORD boundary (32-bit only) */
p = (LPVOID)((((int)p) + 3) & ~3);
if (dialogEx)
{
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* helpID */
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* exStyle */
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* style */
}
else
{
style = *((DWORD *)p)++; /* save style */
((DWORD *)p)++; /* ignore exStyle */
}
*((WORD *)dialog16)++ = *((WORD *)p)++; /* x */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* y */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* cx */
*((WORD *)dialog16)++ = *((WORD *)p)++; /* cy */
if (dialogEx)
*((DWORD *)dialog16)++ = *((DWORD *)p)++; /* ID */
else
{
*((WORD *)dialog16)++ = *((WORD *)p)++; /* ID */
*((DWORD *)dialog16)++ = style; /* style from above */
}
/* Transfer class name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
case 0xffff: ((WORD *)p)++;
*((BYTE *)dialog16)++ = (BYTE)*((WORD *)p)++; break;
default: lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
break;
}
/* Transfer window name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0; break;
case 0xffff: ((WORD *)p)++; *((BYTE *)dialog16)++ = 0xff;
*((WORD *)dialog16)++ = *((WORD *)p)++; break;
default: lstrcpyWtoA( (LPSTR)dialog16, (LPWSTR)p );
((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
break;
}
/* Transfer data */
data = *((WORD *)p)++;
if (dialogEx)
*((WORD *)dialog16)++ = data;
else
*((BYTE *)dialog16)++ = (BYTE)data;
if (data)
{
memcpy( dialog16, p, data );
(LPSTR)dialog16 += data;
(LPSTR)p += data;
}
/* Next item */
nbItems--;
}
}
/**********************************************************************
* GetDialog32Size (KERNEL.618)
*/
WORD WINAPI GetDialog32Size16( LPVOID dialog32 )
{
LPVOID p = dialog32;
WORD nbItems, data, dialogEx;
DWORD style;
style = *((DWORD *)p)++;
dialogEx = (style == 0xffff0001); /* DIALOGEX resource */
if (dialogEx)
{
((DWORD *)p)++; /* helpID */
((DWORD *)p)++; /* exStyle */
style = *((DWORD *)p)++; /* style */
}
else
((DWORD *)p)++; /* exStyle */
nbItems = *((WORD *)p)++;
((WORD *)p)++; /* x */
((WORD *)p)++; /* y */
((WORD *)p)++; /* cx */
((WORD *)p)++; /* cy */
/* Skip menu name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; break;
case 0xffff: ((WORD *)p) += 2; break;
default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
}
/* Skip class name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; break;
case 0xffff: ((WORD *)p) += 2; break;
default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
}
/* Skip window caption */
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
/* Skip font info */
if (style & DS_SETFONT)
{
((WORD *)p)++; /* pointSize */
if (dialogEx)
{
((WORD *)p)++; /* weight */
((WORD *)p)++; /* italic */
}
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; /* faceName */
}
/* Skip dialog items */
while (nbItems)
{
/* align on DWORD boundary */
p = (LPVOID)((((int)p) + 3) & ~3);
if (dialogEx)
{
((DWORD *)p)++; /* helpID */
((DWORD *)p)++; /* exStyle */
((DWORD *)p)++; /* style */
}
else
{
((DWORD *)p)++; /* style */
((DWORD *)p)++; /* exStyle */
}
((WORD *)p)++; /* x */
((WORD *)p)++; /* y */
((WORD *)p)++; /* cx */
((WORD *)p)++; /* cy */
if (dialogEx)
((DWORD *)p)++; /* ID */
else
((WORD *)p)++; /* ID */
/* Skip class name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; break;
case 0xffff: ((WORD *)p) += 2; break;
default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
}
/* Skip window name */
switch (*((WORD *)p))
{
case 0x0000: ((WORD *)p)++; break;
case 0xffff: ((WORD *)p) += 2; break;
default: ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; break;
}
/* Skip data */
data = *((WORD *)p)++;
(LPSTR)p += data;
/* Next item */
nbItems--;
}
return (WORD)((LPSTR)p - (LPSTR)dialog32);
}
/**********************************************************************
* ConvertMenu32To16 (KERNEL.616)
*/
VOID WINAPI ConvertMenu32To16( LPVOID menu32, DWORD size, LPVOID menu16 )
{
LPVOID p = menu32;
WORD version, headersize, flags, level = 1;
version = *((WORD *)menu16)++ = *((WORD *)p)++;
headersize = *((WORD *)menu16)++ = *((WORD *)p)++;
if ( headersize )
{
memcpy( menu16, p, headersize );
((LPSTR)menu16) += headersize;
((LPSTR)p) += headersize;
}
while ( level )
if ( version == 0 ) /* standard */
{
flags = *((WORD *)menu16)++ = *((WORD *)p)++;
if ( !(flags & MF_POPUP) )
*((WORD *)menu16)++ = *((WORD *)p)++; /* ID */
else
level++;
lstrcpyWtoA( (LPSTR)menu16, (LPWSTR)p );
((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
if ( flags & MF_END )
level--;
}
else /* extended */
{
*((DWORD *)menu16)++ = *((DWORD *)p)++; /* fType */
*((DWORD *)menu16)++ = *((DWORD *)p)++; /* fState */
*((WORD *)menu16)++ = (WORD)*((DWORD *)p)++; /* ID */
flags = *((BYTE *)menu16)++ = (BYTE)*((WORD *)p)++;
lstrcpyWtoA( (LPSTR)menu16, (LPWSTR)p );
((LPSTR)menu16) += strlen( (LPSTR)menu16 ) + 1;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
/* align on DWORD boundary (32-bit only) */
p = (LPVOID)((((int)p) + 3) & ~3);
/* If popup, transfer helpid */
if ( flags & 1)
{
*((DWORD *)menu16)++ = *((DWORD *)p)++;
level++;
}
if ( flags & MF_END )
level--;
}
}
/**********************************************************************
* GetMenu32Size (KERNEL.617)
*/
WORD WINAPI GetMenu32Size16( LPVOID menu32 )
{
LPVOID p = menu32;
WORD version, headersize, flags, level = 1;
version = *((WORD *)p)++;
headersize = *((WORD *)p)++;
((LPSTR)p) += headersize;
while ( level )
if ( version == 0 ) /* standard */
{
flags = *((WORD *)p)++;
if ( !(flags & MF_POPUP) )
((WORD *)p)++; /* ID */
else
level++;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
if ( flags & MF_END )
level--;
}
else /* extended */
{
((DWORD *)p)++; /* fType */
((DWORD *)p)++; /* fState */
((DWORD *)p)++; /* ID */
flags = *((WORD *)p)++;
((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1;
/* align on DWORD boundary (32-bit only) */
p = (LPVOID)((((int)p) + 3) & ~3);
/* If popup, skip helpid */
if ( flags & 1)
{
((DWORD *)p)++;
level++;
}
if ( flags & MF_END )
level--;
}
return (WORD)((LPSTR)p - (LPSTR)menu32);
}
/**********************************************************************
* ConvertAccelerator32To16
*/
VOID ConvertAccelerator32To16( LPVOID acc32, DWORD size, LPVOID acc16 )
{
int type;
do
{
/* Copy type */
type = *((BYTE *)acc16)++ = *((BYTE *)acc32)++;
/* Skip padding */
((BYTE *)acc32)++;
/* Copy event and IDval */
*((WORD *)acc16)++ = *((WORD *)acc32)++;
*((WORD *)acc16)++ = *((WORD *)acc32)++;
/* Skip padding */
((WORD *)acc32)++;
} while ( !( type & 0x80 ) );
}
/**********************************************************************
* NE_LoadPEResource
*/
HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size )
{
HGLOBAL16 handle;
TRACE("module=%04x type=%04x\n", pModule->self, type );
if (!pModule || !bits || !size) return 0;
handle = GlobalAlloc16( 0, size );
switch (type)
{
case RT_MENU16:
ConvertMenu32To16( bits, size, GlobalLock16( handle ) );
break;
case RT_DIALOG16:
ConvertDialog32To16( bits, size, GlobalLock16( handle ) );
break;
case RT_ACCELERATOR16:
ConvertAccelerator32To16( bits, size, GlobalLock16( handle ) );
break;
case RT_STRING16:
FIXME("not yet implemented!\n" );
/* fall through */
default:
memcpy( GlobalLock16( handle ), bits, size );
break;
}
return handle;
}