Jacek Caban : gdi32: Use NtGdiCreateClientObj for metafile objects.
Alexandre Julliard
julliard at winehq.org
Fri Jul 9 16:45:34 CDT 2021
Module: wine
Branch: master
Commit: 3d8a8fc13268dd27c1a8e113c6f3dd2d3d14176a
URL: https://source.winehq.org/git/wine.git/?a=commit;h=3d8a8fc13268dd27c1a8e113c6f3dd2d3d14176a
Author: Jacek Caban <jacek at codeweavers.com>
Date: Fri Jul 9 15:28:39 2021 +0200
gdi32: Use NtGdiCreateClientObj for metafile objects.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 );
More information about the wine-cvs
mailing list