From 3d8a8fc13268dd27c1a8e113c6f3dd2d3d14176a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 9 Jul 2021 15:28:39 +0200 Subject: [PATCH] gdi32: Use NtGdiCreateClientObj for metafile objects. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- dlls/gdi32/gdi_private.h | 28 +++++++++++++++ dlls/gdi32/gdiobj.c | 24 +++++++++++++ dlls/gdi32/metafile.c | 83 ++++++++++++++++++++++++++++----------------- dlls/gdi32/objects.c | 14 ++++++++ dlls/gdi32/tests/metafile.c | 10 ++++++ include/ntgdi.h | 1 + 6 files changed, 128 insertions(+), 32 deletions(-) create mode 100644 dlls/gdi32/gdi_private.h diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h new file mode 100644 index 00000000000..db33f33110f --- /dev/null +++ b/dlls/gdi32/gdi_private.h @@ -0,0 +1,28 @@ +/* + * GDI definitions + * + * Copyright 1993 Alexandre Julliard + * Copyright 2021 Jacek Caban for CodeWeavers + * + * 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 + */ + +#ifndef __WINE_GDI_PRIVATE_H +#define __WINE_GDI_PRIVATE_H + +void set_gdi_client_ptr( HGDIOBJ handle, void *ptr ) DECLSPEC_HIDDEN; +void *get_gdi_client_ptr( HGDIOBJ handle, WORD type ) DECLSPEC_HIDDEN; + +#endif /* __WINE_GDI_PRIVATE_H */ diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index 40d67fb1b1f..9059f817636 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -953,6 +953,30 @@ BOOL WINAPI NtGdiDeleteObjectApp( HGDIOBJ obj ) } /*********************************************************************** + * NtGdiCreateClientObj (win32u.@) + */ +HANDLE WINAPI NtGdiCreateClientObj( ULONG type ) +{ + struct gdi_obj_header *obj; + HGDIOBJ handle; + + if (!(obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) ))) + return 0; + + handle = alloc_gdi_handle( obj, type, NULL ); + if (!handle) HeapFree( GetProcessHeap(), 0, obj ); + return handle; +} + +/*********************************************************************** + * NtGdiDeleteClientObj (win32u.@) + */ +BOOL WINAPI NtGdiDeleteClientObj( HGDIOBJ obj ) +{ + return NtGdiDeleteObjectApp( obj ); +} + +/*********************************************************************** * GDI_hdc_using_object * * Call this if the dc requires DeleteObject notification diff --git a/dlls/gdi32/metafile.c b/dlls/gdi32/metafile.c index a4aa3d61508..1b31e40bc14 100644 --- a/dlls/gdi32/metafile.c +++ b/dlls/gdi32/metafile.c @@ -55,16 +55,21 @@ #include "winreg.h" #include "winnls.h" #include "winternl.h" +#include "gdi_private.h" #include "ntgdi_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(metafile); -struct metafile + +static CRITICAL_SECTION metafile_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = { - struct gdi_obj_header obj; - METAHEADER *data; + 0, 0, &metafile_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": metafile_cs") } }; +static CRITICAL_SECTION metafile_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; /****************************************************************** * MF_AddHandle @@ -96,13 +101,13 @@ static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj) */ HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) { - struct metafile *metafile; + HANDLE handle; - if (!(metafile = HeapAlloc(GetProcessHeap(), 0, sizeof(*metafile)))) - return NULL; - metafile->data = mh; + if (!(handle = NtGdiCreateClientObj( NTGDI_OBJ_METAFILE ))) + return 0; - return alloc_gdi_handle( &metafile->obj, NTGDI_OBJ_METAFILE, NULL ); + set_gdi_client_ptr( handle, mh ); + return handle; } /****************************************************************** @@ -134,12 +139,19 @@ static POINT *convert_points( UINT count, const POINTS *pts ) BOOL WINAPI DeleteMetaFile( HMETAFILE hmf ) { - struct metafile *metafile = free_gdi_handle( hmf ); + METAHEADER *data; + BOOL ret = FALSE; - if (!metafile) return FALSE; - HeapFree( GetProcessHeap(), 0, metafile->data ); - HeapFree( GetProcessHeap(), 0, metafile ); - return TRUE; + EnterCriticalSection( &metafile_cs ); + if ((data = get_gdi_client_ptr( hmf, NTGDI_OBJ_METAFILE ))) + { + ret = NtGdiDeleteClientObj( hmf ); + if (ret) HeapFree( GetProcessHeap(), 0, data ); + } + LeaveCriticalSection( &metafile_cs ); + + if (!ret) SetLastError( ERROR_INVALID_HANDLE ); + return ret; } /****************************************************************** @@ -237,14 +249,17 @@ HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename ) /* return a copy of the metafile bits, to be freed with HeapFree */ static METAHEADER *get_metafile_bits( HMETAFILE hmf ) { - struct metafile *metafile = GDI_GetObjPtr( hmf, NTGDI_OBJ_METAFILE ); - METAHEADER *ret; + METAHEADER *ret = NULL, *metafile; - if (!metafile) return NULL; + EnterCriticalSection( &metafile_cs ); + if ((metafile = get_gdi_client_ptr( hmf, NTGDI_OBJ_METAFILE ))) + { + ret = HeapAlloc( GetProcessHeap(), 0, metafile->mtSize * 2 ); + if (ret) memcpy( ret, metafile, metafile->mtSize * 2 ); + } + else SetLastError( ERROR_INVALID_HANDLE ); + LeaveCriticalSection( &metafile_cs ); - ret = HeapAlloc( GetProcessHeap(), 0, metafile->data->mtSize * 2 ); - if (ret) memcpy( ret, metafile->data, metafile->data->mtSize * 2 ); - GDI_ReleaseObj( hmf ); return ret; } @@ -1033,24 +1048,28 @@ HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData ) * If _buf_ is zero, returns size of buffer required. Otherwise, * returns number of bytes copied. */ -UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf ) +UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT buf_size, void *buf ) { - struct metafile *metafile = GDI_GetObjPtr( hmf, NTGDI_OBJ_METAFILE ); - UINT mfSize; + METAHEADER *metafile; + UINT size = 0; - TRACE("(%p,%d,%p)\n", hmf, nSize, buf); + TRACE( "(%p,%d,%p)\n", hmf, buf_size, buf ); - if (!metafile) return 0; /* FIXME: error code */ - - mfSize = metafile->data->mtSize * 2; - if (buf) + EnterCriticalSection( &metafile_cs ); + if ((metafile = get_gdi_client_ptr( hmf, NTGDI_OBJ_METAFILE ))) { - if(mfSize > nSize) mfSize = nSize; - memmove(buf, metafile->data, mfSize); + size = metafile->mtSize * 2; + if (buf) + { + if(size > buf_size) size = buf_size; + memmove( buf, metafile, size ); + } } - GDI_ReleaseObj( hmf ); - TRACE("returning size %d\n", mfSize); - return mfSize; + else SetLastError( ERROR_INVALID_HANDLE ); + LeaveCriticalSection( &metafile_cs ); + + TRACE( "returning size %d\n", size ); + return size; } /****************************************************************** diff --git a/dlls/gdi32/objects.c b/dlls/gdi32/objects.c index bc2ecb917fb..63a79255224 100644 --- a/dlls/gdi32/objects.c +++ b/dlls/gdi32/objects.c @@ -65,6 +65,20 @@ static WORD get_object_type( HGDIOBJ obj ) return entry ? entry->ExtType : 0; } +void set_gdi_client_ptr( HGDIOBJ obj, void *ptr ) +{ + GDI_HANDLE_ENTRY *entry = handle_entry( obj ); + if (entry) entry->UserPointer = (UINT_PTR)ptr; +} + +void *get_gdi_client_ptr( HGDIOBJ obj, WORD type ) +{ + GDI_HANDLE_ENTRY *entry = handle_entry( obj ); + if (!entry || entry->ExtType != type || !entry->UserPointer) + return NULL; + return (void *)(UINT_PTR)entry->UserPointer; +} + /*********************************************************************** * GetObjectType (GDI32.@) */ diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c index 61e20072591..10c99304c74 100644 --- a/dlls/gdi32/tests/metafile.c +++ b/dlls/gdi32/tests/metafile.c @@ -3042,6 +3042,16 @@ static void test_metafile_file(void) ret = DeleteFileA(mf_name); ok(ret, "Could not delete file: %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = DeleteMetaFile(ULongToHandle(0xdeadbeef)); + ok(!ret, "DeleteMetaFile succeeded\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError()); + + SetLastError(0xdeadbeef); + size = GetMetaFileBitsEx(ULongToHandle(0xdeadbeef), 0, NULL); + ok(!size, "GetMetaFileBitsEx returned %u\n", size); + ok(GetLastError() == ERROR_INVALID_HANDLE, "GetLastError() = %u\n", GetLastError()); } static void test_enhmetafile_file(void) diff --git a/include/ntgdi.h b/include/ntgdi.h index 7e8954468fb..d8adc327548 100644 --- a/include/ntgdi.h +++ b/include/ntgdi.h @@ -99,6 +99,7 @@ HRGN WINAPI NtGdiCreateRectRgn( INT left, INT top, INT right, INT bottom ); HRGN WINAPI NtGdiCreateRoundRectRgn( INT left, INT top, INT right, INT bottom, INT ellipse_width, INT ellipse_height ); HBRUSH WINAPI NtGdiCreateSolidBrush( COLORREF color ); +BOOL WINAPI NtGdiDeleteClientObj( HGDIOBJ obj ); BOOL WINAPI NtGdiDeleteObjectApp( HGDIOBJ obj ); LONG WINAPI NtGdiDoPalette( HGDIOBJ handle, WORD start, WORD count, void *entries, DWORD func, BOOL inbound ); -- 2.11.4.GIT