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