/* * Metafile functions * * Copyright David W. Metcalfe, 1994 * Copyright Niels de Carpentier, 1996 * Copyright Albrecht Kleine, 1996 * Copyright Huw Davies, 1996 * * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include <string.h> #include <fcntl.h> #include "wine/winbase16.h" #include "wine/wingdi16.h" #include "wownt32.h" #include "winreg.h" #include "winternl.h" #include "gdi_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(metafile); /****************************************************************** * MF_GetMetaHeader16 * * Returns ptr to METAHEADER associated with HMETAFILE16 * Should be followed by call to MF_ReleaseMetaHeader16 */ static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf ) { return GlobalLock16(hmf); } /****************************************************************** * MF_ReleaseMetaHeader16 * * Releases METAHEADER associated with HMETAFILE16 */ static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf ) { return GlobalUnlock16( hmf ); } /****************************************************************** * MF_Create_HMETATFILE16 * * Creates a HMETAFILE16 object from a METAHEADER * * HMETAFILE16s are Global memory handles. */ static HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh) { HMETAFILE16 hmf; DWORD size = mh->mtSize * sizeof(WORD); hmf = GlobalAlloc16(GMEM_MOVEABLE, size); if(hmf) { METAHEADER *mh_dest = GlobalLock16(hmf); memcpy(mh_dest, mh, size); GlobalUnlock16(hmf); } HeapFree(GetProcessHeap(), 0, mh); return hmf; } /********************************************************************** * CreateMetaFile (GDI.125) */ HDC16 WINAPI CreateMetaFile16( LPCSTR filename ) { return HDC_16( CreateMetaFileA( filename ) ); } /****************************************************************** * CloseMetaFile (GDI.126) */ HMETAFILE16 WINAPI CloseMetaFile16(HDC16 hdc) { HMETAFILE16 hmf16 = 0; HMETAFILE hmf = CloseMetaFile( HDC_32(hdc) ); if (hmf) { UINT size = GetMetaFileBitsEx( hmf, 0, NULL ); hmf16 = GlobalAlloc16( GMEM_MOVEABLE, size ); if (hmf16) { void *buffer = GlobalLock16( hmf16 ); GetMetaFileBitsEx( hmf, size, buffer ); GlobalUnlock16( hmf16 ); } DeleteMetaFile( hmf ); } return hmf16; } /****************************************************************** * DeleteMetaFile (GDI.127) */ BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf ) { return !GlobalFree16( hmf ); } /****************************************************************** * GetMetaFile (GDI.124) */ HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename ) { METAHEADER *mh; HANDLE hFile; TRACE("%s\n", lpFilename); if(!lpFilename) return 0; if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) return 0; mh = MF_ReadMetaFile(hFile); CloseHandle(hFile); if(!mh) return 0; return MF_Create_HMETAFILE16( mh ); } /****************************************************************** * CopyMetaFile (GDI.151) */ HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename) { METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile ); METAHEADER *mh2 = NULL; HANDLE hFile; TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename); if(!mh) return 0; if(mh->mtType == METAFILE_DISK) mh2 = MF_LoadDiskBasedMetaFile(mh); else { mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 ); memcpy( mh2, mh, mh->mtSize * 2 ); } MF_ReleaseMetaHeader16( hSrcMetaFile ); if(lpFilename) { /* disk based metafile */ DWORD w; if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { HeapFree( GetProcessHeap(), 0, mh2 ); return 0; } WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL); CloseHandle(hFile); mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE); } return MF_Create_HMETAFILE16( mh2 ); } /****************************************************************** * IsValidMetaFile (GDI.410) * * Attempts to check if a given metafile is correctly formatted. * Currently, the only things verified are several properties of the * header. * * RETURNS * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise. * * BUGS * This is not exactly what windows does, see _Undocumented_Windows_ * for details. */ BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf) { BOOL16 res=FALSE; METAHEADER *mh = MF_GetMetaHeader16(hmf); if (mh) { if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK) if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16)) if (mh->mtVersion == MFVERSION) res=TRUE; MF_ReleaseMetaHeader16(hmf); } TRACE("IsValidMetaFile %x => %d\n",hmf,res); return res; } /****************************************************************** * PlayMetaFile (GDI.123) * */ BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf ) { BOOL16 ret; METAHEADER *mh = MF_GetMetaHeader16( hmf ); ret = MF_PlayMetaFile( HDC_32(hdc), mh ); MF_ReleaseMetaHeader16( hmf ); return ret; } /****************************************************************** * EnumMetaFile (GDI.175) * */ BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf, MFENUMPROC16 lpEnumFunc, LPARAM lpData ) { METAHEADER *mh = MF_GetMetaHeader16(hmf); METARECORD *mr; HANDLETABLE16 *ht; HDC hdc = HDC_32(hdc16); HGLOBAL16 hHT; SEGPTR spht; unsigned int offset = 0; WORD i, seg; HPEN hPen; HBRUSH hBrush; HFONT hFont; WORD args[8]; BOOL16 result = TRUE, loaded = FALSE; TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData); if(!mh) return FALSE; if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */ mh = MF_LoadDiskBasedMetaFile(mh); if(!mh) return FALSE; loaded = TRUE; } /* save the current pen, brush and font */ hPen = GetCurrentObject(hdc, OBJ_PEN); hBrush = GetCurrentObject(hdc, OBJ_BRUSH); hFont = GetCurrentObject(hdc, OBJ_FONT); /* create the handle table */ hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(HANDLETABLE16) * mh->mtNoObjects); spht = WOWGlobalLock16(hHT); seg = hmf | 7; offset = mh->mtHeaderSize * 2; /* loop through metafile records */ args[7] = hdc16; args[6] = SELECTOROF(spht); args[5] = OFFSETOF(spht); args[4] = seg + (HIWORD(offset) << __AHSHIFT); args[3] = LOWORD(offset); args[2] = mh->mtNoObjects; args[1] = HIWORD(lpData); args[0] = LOWORD(lpData); while (offset < (mh->mtSize * 2)) { DWORD ret; mr = (METARECORD *)((char *)mh + offset); WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret ); if (!LOWORD(ret)) { result = FALSE; break; } offset += (mr->rdSize * 2); args[4] = seg + (HIWORD(offset) << __AHSHIFT); args[3] = LOWORD(offset); } SelectObject(hdc, hBrush); SelectObject(hdc, hPen); SelectObject(hdc, hFont); ht = GlobalLock16(hHT); /* free objects in handle table */ for(i = 0; i < mh->mtNoObjects; i++) if(*(ht->objectHandle + i) != 0) DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) )); /* free handle table */ GlobalFree16(hHT); if(loaded) HeapFree( GetProcessHeap(), 0, mh ); MF_ReleaseMetaHeader16(hmf); return result; } /****************************************************************** * GetMetaFileBits (GDI.159) * * Trade in a metafile object handle for a handle to the metafile memory. * * PARAMS * hmf [I] metafile handle */ HGLOBAL16 WINAPI GetMetaFileBits16( HMETAFILE16 hmf ) { TRACE("hMem out: %04x\n", hmf); return hmf; } /****************************************************************** * SetMetaFileBits (GDI.160) * * Trade in a metafile memory handle for a handle to a metafile object. * The memory region should hold a proper metafile, otherwise * problems will occur when it is used. Validity of the memory is not * checked. The function is essentially just the identity function. * * PARAMS * hMem [I] handle to a memory region holding a metafile * * RETURNS * Handle to a metafile on success, NULL on failure.. */ HMETAFILE16 WINAPI SetMetaFileBits16( HGLOBAL16 hMem ) { TRACE("hmf out: %04x\n", hMem); return hMem; } /****************************************************************** * SetMetaFileBitsBetter (GDI.196) * * Trade in a metafile memory handle for a handle to a metafile object, * making a cursory check (using IsValidMetaFile()) that the memory * handle points to a valid metafile. * * RETURNS * Handle to a metafile on success, NULL on failure.. */ HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta ) { if( IsValidMetaFile16( hMeta ) ) return GlobalReAlloc16( hMeta, 0, GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY); return 0; }