Module: wine Branch: master Commit: 3d8a8fc13268dd27c1a8e113c6f3dd2d3d14176a URL: https://source.winehq.org/git/wine.git/?a=commit;h=3d8a8fc13268dd27c1a8e113c...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Jul 9 15:28:39 2021 +0200
gdi32: Use NtGdiCreateClientObj for metafile objects.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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(-)
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 @@ -952,6 +952,30 @@ BOOL WINAPI NtGdiDeleteObjectApp( HGDIOBJ obj ) return TRUE; }
+/*********************************************************************** + * 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 * 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 );