| /* |
| * PE->NE resource conversion functions |
| * |
| * Copyright 1998 Ulrich Weigand |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <string.h> |
| #include "windef.h" |
| #include "wingdi.h" |
| #include "wine/winuser16.h" |
| #include "wine/unicode.h" |
| #include "module.h" |
| #include "wine/debug.h" |
| |
| WINE_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: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); |
| ((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: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); |
| ((LPSTR)dialog16) += strlen( (LPSTR)dialog16 ) + 1; |
| ((LPWSTR)p) += strlenW( (LPWSTR)p ) + 1; |
| break; |
| } |
| |
| /* Transfer window caption */ |
| WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); |
| ((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 */ |
| } |
| WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); /* 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: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); |
| ((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: WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)dialog16, 0x7fffffff, NULL,NULL ); |
| ((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++; |
| |
| WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL ); |
| ((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)++; |
| |
| WideCharToMultiByte( CP_ACP, 0, (LPWSTR)p, -1, (LPSTR)menu16, 0x7fffffff, NULL,NULL ); |
| ((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; |
| } |