Define all macros described on MSDN.
[wine] / objects / gdiobj.c
index b586ba8..285d912 100644 (file)
  * GDI functions
  *
  * Copyright 1993 Alexandre Julliard
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
 #include "config.h"
 
+#include <assert.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <stdio.h>
 
-#include "bitmap.h"
-#include "brush.h"
-#include "dc.h"
-#include "font.h"
-#include "heap.h"
-#include "options.h"
-#include "palette.h"
-#include "pen.h"
-#include "region.h"
-#include "debugtools.h"
-#include "gdi.h"
-#include "tweak.h"
 #include "windef.h"
+#include "winbase.h"
 #include "wingdi.h"
-#include "winuser.h"
+#include "winreg.h"
+#include "winerror.h"
+
+#include "local.h"
+#include "gdi.h"
+#include "gdi_private.h"
+#include "wine/debug.h"
 
-DEFAULT_DEBUG_CHANNEL(gdi)
+WINE_DEFAULT_DEBUG_CHANNEL(gdi);
 
-/**********************************************************************/
+#define HGDIOBJ_32(h16)   ((HGDIOBJ)(ULONG_PTR)(h16))
 
-GDI_DRIVER *GDI_Driver = NULL;
+#define GDI_HEAP_SIZE 0xffe0
 
 /***********************************************************************
- *          GDI stock objects 
+ *          GDI stock objects
  */
 
-static BRUSHOBJ WhiteBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },             /* header */
-    { BS_SOLID, RGB(255,255,255), 0 }  /* logbrush */
-};
-
-static BRUSHOBJ LtGrayBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },             /* header */
-/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
-    { BS_SOLID, RGB(192,192,192), 0 }  /* logbrush */
-};
+static const LOGBRUSH WhiteBrush = { BS_SOLID, RGB(255,255,255), 0 };
+static const LOGBRUSH BlackBrush = { BS_SOLID, RGB(0,0,0), 0 };
+static const LOGBRUSH NullBrush  = { BS_NULL, 0, 0 };
 
-static BRUSHOBJ GrayBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },             /* header */
-/* FIXME : this should perhaps be BS_HATCHED, at least for 1 bitperpixel */
-    { BS_SOLID, RGB(128,128,128), 0 }  /* logbrush */
-};
+/* FIXME: these should perhaps be BS_HATCHED, at least for 1 bitperpixel */
+static const LOGBRUSH LtGrayBrush = { BS_SOLID, RGB(192,192,192), 0 };
+static const LOGBRUSH GrayBrush   = { BS_SOLID, RGB(128,128,128), 0 };
 
-static BRUSHOBJ DkGrayBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },          /* header */
 /* This is BS_HATCHED, for 1 bitperpixel. This makes the spray work in pbrush */
-/* NB_HATCH_STYLES is an index into HatchBrushes */
-    { BS_HATCHED, RGB(0,0,0), NB_HATCH_STYLES }  /* logbrush */
-};
+/* See HatchBrushes in x11drv for the HS_DIAGCROSS+1 hack */
+static const LOGBRUSH DkGrayBrush = { BS_HATCHED, RGB(0,0,0), (HS_DIAGCROSS+1) };
 
-static BRUSHOBJ BlackBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },       /* header */
-    { BS_SOLID, RGB(0,0,0), 0 }  /* logbrush */
-};
+static const LOGPEN WhitePen = { PS_SOLID, { 0, 0 }, RGB(255,255,255) };
+static const LOGPEN BlackPen = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
+static const LOGPEN NullPen  = { PS_NULL,  { 0, 0 }, 0 };
 
-static BRUSHOBJ NullBrush =
-{
-    { 0, BRUSH_MAGIC, 1 },  /* header */
-    { BS_NULL, 0, 0 }       /* logbrush */
-};
+static const LOGBRUSH DCBrush = { BS_SOLID, RGB(255,255,255), 0 };
+static const LOGPEN DCPen     = { PS_SOLID, { 0, 0 }, RGB(0,0,0) };
 
-static PENOBJ WhitePen =
-{
-    { 0, PEN_MAGIC, 1 },                     /* header */
-    { PS_SOLID, { 1, 0 }, RGB(255,255,255) } /* logpen */
-};
+/* reserve one extra entry for the stock default bitmap */
+/* this is what Windows does too */
+#define NB_STOCK_OBJECTS (STOCK_LAST+2)
 
-static PENOBJ BlackPen =
-{
-    { 0, PEN_MAGIC, 1 },               /* header */
-    { PS_SOLID, { 1, 0 }, RGB(0,0,0) } /* logpen */
-};
+static HGDIOBJ stock_objects[NB_STOCK_OBJECTS];
 
-static PENOBJ NullPen =
+static SYSLEVEL GDI_level;
+static CRITICAL_SECTION_DEBUG critsect_debug =
 {
-    { 0, PEN_MAGIC, 1 },      /* header */
-    { PS_NULL, { 1, 0 }, 0 }  /* logpen */
+    0, 0, &GDI_level.crst,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { 0, (DWORD)(__FILE__ ": GDI_level") }
 };
+static SYSLEVEL GDI_level = { { &critsect_debug, -1, 0, 0, 0, 0 }, 3 };
 
-static FONTOBJ OEMFixedFont =
-{
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
-      0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
-};
-/* Filler to make the location counter dword aligned again.  This is necessary
-   since (a) FONTOBJ is packed, (b) gcc places initialised variables in the code
-   segment, and (c) Solaris assembler is stupid.  */
-static UINT16 align_OEMFixedFont = 1;
+static WORD GDI_HeapSel;
 
-static FONTOBJ AnsiFixedFont =
+inline static BOOL get_bool(char *buffer)
 {
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
-};
-static UINT16 align_AnsiFixedFont = 1;
+    return (buffer[0] == 'y' || buffer[0] == 'Y' ||
+            buffer[0] == 't' || buffer[0] == 'T' ||
+            buffer[0] == '1');
+}
 
-static FONTOBJ AnsiVarFont =
-{
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
-};
-static UINT16 align_AnsiVarFont = 1;
 
-static FONTOBJ SystemFont =
-{
-    { 0, FONT_MAGIC, 1 },
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "System" }
-};
-static UINT16 align_SystemFont = 1;
+/****************************************************************************
+ *
+ *     language-independent stock fonts
+ *
+ */
 
-static FONTOBJ DeviceDefaultFont =
-{
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "" }
-};
-static UINT16 align_DeviceDefaultFont = 1;
+static const LOGFONTW OEMFixedFont =
+{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
+  0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
 
-static FONTOBJ SystemFixedFont =
+static const LOGFONTW AnsiFixedFont =
+{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+  0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, {'\0'} };
+
+static const LOGFONTW AnsiVarFont =
+{ 12, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+  0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+  {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'} };
+
+/******************************************************************************
+ *
+ *      language-dependent stock fonts
+ *
+ *      'ANSI' charset and 'DEFAULT' charset is not same.
+ *      The chars in CP_ACP should be drawn with 'DEFAULT' charset.
+ *      'ANSI' charset seems to be identical with ISO-8859-1.
+ *      'DEFAULT' charset is a language-dependent charset.
+ *
+ *      'System' font seems to be an alias for language-dependent font.
+ */
+
+/*
+ * language-dependenet stock fonts for all known charsets
+ * please see TranslateCharsetInfo (objects/font.c) and
+ * CharsetBindingInfo (graphics/x11drv/xfont.c),
+ * and modify entries for your language if needed.
+ */
+struct DefaultFontInfo
 {
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, "" }
+        UINT            charset;
+        LOGFONTW        SystemFont;
+        LOGFONTW        DeviceDefaultFont;
+        LOGFONTW        SystemFixedFont;
+        LOGFONTW        DefaultGuiFont;
 };
-static UINT16 align_SystemFixedFont = 1;
 
-/* FIXME: Is this correct? */
-static FONTOBJ DefaultGuiFont =
+static const struct DefaultFontInfo default_fonts[] =
 {
-    { 0, FONT_MAGIC, 1 },   /* header */
-    { 0, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-      0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "MS Sans Serif" }
+    {   ANSI_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   EASTEUROPE_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, EASTEUROPE_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   RUSSIAN_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, RUSSIAN_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   GREEK_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GREEK_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   TURKISH_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, TURKISH_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   HEBREW_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HEBREW_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   ARABIC_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ARABIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   BALTIC_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, BALTIC_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   THAI_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, THAI_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','a','n','s',' ','S','e','r','i','f','\0'}
+        },
+    },
+    {   SHIFTJIS_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','U','I',' ','G','o','t','h','i','c','\0'}
+        },
+    },
+    {   GB2312_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, GB2312_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','S','o','n','g','\0'}   /* FIXME: Is this correct? */
+        },
+    },
+    {   HANGEUL_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, HANGEUL_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'G','u','l','i','m'},
+        },
+    },
+    {   CHINESEBIG5_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, CHINESEBIG5_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}       /* FIXME - what is the native font??? */
+        },
+    },
+    {   JOHAB_CHARSET,
+        { /* System */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'S','y','s','t','e','m','\0'}
+        },
+        { /* Device Default */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'\0'}
+        },
+        { /* System Fixed */
+          16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
+           0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN,
+           {'\0'}
+        },
+        { /* DefaultGuiFont */
+         -11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, JOHAB_CHARSET,
+           0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS,
+           {'M','S',' ','M','i','n','g','l','i','u','\0'} /* FIXME: Is this correct? */
+        },
+    },
 };
-static UINT16 align_DefaultGuiFont = 1;
 
 
-static GDIOBJHDR * StockObjects[NB_STOCK_OBJECTS] =
+/******************************************************************************
+ *      get_default_fonts
+ */
+static const struct DefaultFontInfo* get_default_fonts(UINT charset)
 {
-    (GDIOBJHDR *) &WhiteBrush,
-    (GDIOBJHDR *) &LtGrayBrush,
-    (GDIOBJHDR *) &GrayBrush,
-    (GDIOBJHDR *) &DkGrayBrush,
-    (GDIOBJHDR *) &BlackBrush,
-    (GDIOBJHDR *) &NullBrush,
-    (GDIOBJHDR *) &WhitePen,
-    (GDIOBJHDR *) &BlackPen,
-    (GDIOBJHDR *) &NullPen,
-    NULL,
-    (GDIOBJHDR *) &OEMFixedFont,
-    (GDIOBJHDR *) &AnsiFixedFont,
-    (GDIOBJHDR *) &AnsiVarFont,
-    (GDIOBJHDR *) &SystemFont,
-    (GDIOBJHDR *) &DeviceDefaultFont,
-    NULL,            /* DEFAULT_PALETTE created by PALETTE_Init */
-    (GDIOBJHDR *) &SystemFixedFont,
-    (GDIOBJHDR *) &DefaultGuiFont
-};
+        int     n;
+
+        for(n=0;n<(sizeof(default_fonts)/sizeof(default_fonts[0]));n++)
+        {
+                if ( default_fonts[n].charset == charset )
+                        return &default_fonts[n];
+        }
+
+        FIXME( "unhandled charset 0x%08x - use ANSI_CHARSET for default stock objects\n", charset );
+        return &default_fonts[0];
+}
 
-HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
 
 /******************************************************************************
+ *      get_default_charset    (internal)
  *
- *   void  ReadFontInformation(
- *      char const  *fontName,
- *      FONTOBJ  *font,
- *      int  defHeight,
- *      int  defBold,
- *      int  defItalic,
- *      int  defUnderline,
- *      int  defStrikeOut )
- *
- *   ReadFontInformation() checks the Wine configuration file's Tweak.Fonts
- *   section for entries containing fontName.Height, fontName.Bold, etc.,
- *   where fontName is the name specified in the call (e.g., "System").  It
- *   attempts to be user friendly by accepting 'n', 'N', 'f', 'F', or '0' as
- *   the first character in the boolean attributes (bold, italic, and
- *   underline).
- *****************************************************************************/
-
-static void  ReadFontInformation(
-    char const *fontName,
-    FONTOBJ *font,
-    int  defHeight,
-    int  defBold,
-    int  defItalic,
-    int  defUnderline,
-    int  defStrikeOut )
+ * get the language-dependent charset that can handle CP_ACP correctly.
+ */
+static UINT get_default_charset( void )
 {
+    CHARSETINFO     csi;
+    UINT    uACP;
+
+    uACP = GetACP();
+    csi.ciCharset = ANSI_CHARSET;
+    if ( ! TranslateCharsetInfo( (LPDWORD)uACP, &csi, TCI_SRCCODEPAGE ) )
+    {
+        FIXME( "unhandled codepage %u - use ANSI_CHARSET for default stock objects\n", uACP );
+        return ANSI_CHARSET;
+    }
+
+    return csi.ciCharset;
+}
+
+
+/******************************************************************************
+ *           create_stock_font
+ */
+static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY hkey )
+{
+    LOGFONTW lf;
     char  key[256];
+    char buffer[MAX_PATH];
+    DWORD type, count;
+
+    if (!hkey) return CreateFontIndirectW( font );
 
-    /* In order for the stock fonts to be independent of 
-     * mapping mode, the height (& width) must be 0
-     */
+    lf = *font;
     sprintf(key, "%s.Height", fontName);
-    font->logfont.lfHeight =
-       PROFILE_GetWineIniInt("Tweak.Fonts", key, defHeight);
+    count = sizeof(buffer);
+    if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
+        lf.lfHeight = atoi(buffer);
 
     sprintf(key, "%s.Bold", fontName);
-    font->logfont.lfWeight =
-       (PROFILE_GetWineIniBool("Tweak.Fonts", key, defBold)) ?
-       FW_BOLD : FW_NORMAL;
+    count = sizeof(buffer);
+    if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
+        lf.lfWeight = get_bool(buffer) ? FW_BOLD : FW_NORMAL;
 
     sprintf(key, "%s.Italic", fontName);
-    font->logfont.lfItalic =
-       PROFILE_GetWineIniBool("Tweak.Fonts", key, defItalic);
+    count = sizeof(buffer);
+    if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
+        lf.lfItalic = get_bool(buffer);
 
     sprintf(key, "%s.Underline", fontName);
-    font->logfont.lfUnderline =
-       PROFILE_GetWineIniBool("Tweak.Fonts", key, defUnderline);
+    count = sizeof(buffer);
+    if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
+        lf.lfUnderline = get_bool(buffer);
 
     sprintf(key, "%s.StrikeOut", fontName);
-    font->logfont.lfStrikeOut =
-       PROFILE_GetWineIniBool("Tweak.Fonts", key, defStrikeOut);
-
-    return;
+    count = sizeof(buffer);
+    if(!RegQueryValueExA(hkey, key, 0, &type, buffer, &count))
+        lf.lfStrikeOut = get_bool(buffer);
+    return CreateFontIndirectW( &lf );
 }
 
-/***********************************************************************
- * Because the stock fonts have their structure initialized with
- * a height of 0 to keep them independent of mapping mode, simply
- * returning the LOGFONT as is will not work correctly.
- * These "FixStockFontSizeXXX()" methods will get the correct
- * size for the fonts.
- */
-static void GetFontMetrics(HFONT handle, LPTEXTMETRICA lptm)
-{
-  HDC         hdc;
-  HFONT       hOldFont;
-
-  hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
-
-  hOldFont = (HFONT)SelectObject(hdc, handle);
 
-  GetTextMetricsA(hdc, lptm);
+#define TRACE_SEC(handle,text) \
+   TRACE("(%p): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
 
-  SelectObject(hdc, hOldFont);
 
-  DeleteDC(hdc);
-}
-
-static inline void FixStockFontSize16(
-  HFONT  handle, 
-  INT16  count, 
-  LPVOID buffer)
+/***********************************************************************
+ *           inc_ref_count
+ *
+ * Increment the reference count of a GDI object.
+ */
+inline static void inc_ref_count( HGDIOBJ handle )
 {
-  TEXTMETRICA tm;
-  LOGFONT16*  pLogFont = (LOGFONT16*)buffer;
-
-  /*
-   * Was the lfHeight field copied (it's the first field)?
-   * If it was and it was null, replace the height.
-   */
-  if ( (count >= 2*sizeof(INT16)) &&
-       (pLogFont->lfHeight == 0) )
-  {
-    GetFontMetrics(handle, &tm);
-    
-    pLogFont->lfHeight = tm.tmHeight;
-    pLogFont->lfWidth  = tm.tmAveCharWidth;
-  }
-}
+    GDIOBJHDR *header;
 
-static inline void FixStockFontSizeA(
-  HFONT  handle, 
-  INT    count, 
-  LPVOID buffer)
-{
-  TEXTMETRICA tm;
-  LOGFONTA*  pLogFont = (LOGFONTA*)buffer;
-
-  /*
-   * Was the lfHeight field copied (it's the first field)?
-   * If it was and it was null, replace the height.
-   */
-  if ( (count >= 2*sizeof(INT)) &&
-       (pLogFont->lfHeight == 0) )
-  {
-    GetFontMetrics(handle, &tm);
-
-    pLogFont->lfHeight = tm.tmHeight;
-    pLogFont->lfWidth  = tm.tmAveCharWidth;
-  }
+    if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
+    {
+        header->dwCount++;
+        GDI_ReleaseObj( handle );
+    }
 }
 
-/**
- * Since the LOGFONTA and LOGFONTW structures are identical up to the 
- * lfHeight member (the one of interest in this case) we simply define
- * the W version as the A version. 
+
+/***********************************************************************
+ *           dec_ref_count
+ *
+ * Decrement the reference count of a GDI object.
  */
-#define FixStockFontSizeW FixStockFontSizeA
+inline static void dec_ref_count( HGDIOBJ handle )
+{
+    GDIOBJHDR *header;
 
+    if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
+    {
+        if (header->dwCount) header->dwCount--;
+        if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
+        else
+        {
+            /* handle delayed DeleteObject*/
+            header->dwCount = 0;
+            GDI_ReleaseObj( handle );
+            TRACE( "executing delayed DeleteObject for %p\n", handle );
+            DeleteObject( handle );
+        }
+    }
+}
 
 
 /***********************************************************************
@@ -318,123 +583,297 @@ static inline void FixStockFontSizeA(
  */
 BOOL GDI_Init(void)
 {
-    BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
-
-    /* Kill some warnings.  */
-    (void)align_OEMFixedFont;
-    (void)align_AnsiFixedFont;
-    (void)align_AnsiVarFont;
-    (void)align_SystemFont;
-    (void)align_DeviceDefaultFont;
-    (void)align_SystemFixedFont;
-    (void)align_DefaultGuiFont;
-
-    /* TWEAK: Initialize font hints */
-    ReadFontInformation("OEMFixed", &OEMFixedFont, 0, 0, 0, 0, 0);
-    ReadFontInformation("AnsiFixed", &AnsiFixedFont, 0, 0, 0, 0, 0);
-    ReadFontInformation("AnsiVar", &AnsiVarFont, 0, 0, 0, 0, 0);
-    ReadFontInformation("System", &SystemFont, 0, systemIsBold, 0, 0, 0);
-    ReadFontInformation("DeviceDefault", &DeviceDefaultFont, 0, 0, 0, 0, 0);
-    ReadFontInformation("SystemFixed", &SystemFixedFont, 0, systemIsBold, 0, 0, 0);
-    ReadFontInformation("DefaultGui", &DefaultGuiFont, 0, 0, 0, 0, 0);
-
-    /* Create default palette */
-
-    /* DR well *this* palette can't be moveable (?) */
+    HINSTANCE16 instance;
+    HKEY hkey;
+    GDIOBJHDR *ptr;
+    const struct DefaultFontInfo* deffonts;
+    int i;
+
+    if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine\\Wine\\Config\\Tweak.Fonts", &hkey))
+        hkey = 0;
+
+    /* create GDI heap */
+    if ((instance = LoadLibrary16( "GDI.EXE" )) >= 32) GDI_HeapSel = instance | 7;
+
+    /* create stock objects */
+    stock_objects[WHITE_BRUSH]  = CreateBrushIndirect( &WhiteBrush );
+    stock_objects[LTGRAY_BRUSH] = CreateBrushIndirect( &LtGrayBrush );
+    stock_objects[GRAY_BRUSH]   = CreateBrushIndirect( &GrayBrush );
+    stock_objects[DKGRAY_BRUSH] = CreateBrushIndirect( &DkGrayBrush );
+    stock_objects[BLACK_BRUSH]  = CreateBrushIndirect( &BlackBrush );
+    stock_objects[NULL_BRUSH]   = CreateBrushIndirect( &NullBrush );
+
+    stock_objects[WHITE_PEN]    = CreatePenIndirect( &WhitePen );
+    stock_objects[BLACK_PEN]    = CreatePenIndirect( &BlackPen );
+    stock_objects[NULL_PEN]     = CreatePenIndirect( &NullPen );
+
+    stock_objects[DEFAULT_PALETTE] = PALETTE_Init();
+    stock_objects[DEFAULT_BITMAP]  = CreateBitmap( 1, 1, 1, 1, NULL );
+
+    /* language-independent stock fonts */
+    stock_objects[OEM_FIXED_FONT]      = create_stock_font( "OEMFixed", &OEMFixedFont, hkey );
+    stock_objects[ANSI_FIXED_FONT]     = create_stock_font( "AnsiFixed", &AnsiFixedFont, hkey );
+    stock_objects[ANSI_VAR_FONT]       = create_stock_font( "AnsiVar", &AnsiVarFont, hkey );
+
+    /* language-dependent stock fonts */
+    deffonts = get_default_fonts(get_default_charset());
+    stock_objects[SYSTEM_FONT]         = create_stock_font( "System", &deffonts->SystemFont, hkey );
+    stock_objects[DEVICE_DEFAULT_FONT] = create_stock_font( "DeviceDefault", &deffonts->DeviceDefaultFont, hkey );
+    stock_objects[SYSTEM_FIXED_FONT]   = create_stock_font( "SystemFixed", &deffonts->SystemFixedFont, hkey );
+    stock_objects[DEFAULT_GUI_FONT]    = create_stock_font( "DefaultGui", &deffonts->DefaultGuiFont, hkey );
+
+    stock_objects[DC_BRUSH]     = CreateBrushIndirect( &DCBrush );
+    stock_objects[DC_PEN]       = CreatePenIndirect( &DCPen );
+
+    /* clear the NOSYSTEM bit on all stock objects*/
+    for (i = 0; i < NB_STOCK_OBJECTS; i++)
     {
-    HPALETTE16 hpalette = PALETTE_Init();
-    if( !hpalette )
-        return FALSE;
-    StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
+        if (!stock_objects[i])
+        {
+            if (i == 9) continue;  /* there's no stock object 9 */
+            ERR( "could not create stock object %d\n", i );
+            return FALSE;
+        }
+        ptr = GDI_GetObjPtr( stock_objects[i], MAGIC_DONTCARE );
+        ptr->wMagic &= ~OBJECT_NOSYSTEM;
+        GDI_ReleaseObj( stock_objects[i] );
     }
 
-    hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL ); 
+    if (hkey) RegCloseKey( hkey );
+
+    WineEngInit();
+
     return TRUE;
 }
 
+#define FIRST_LARGE_HANDLE 16
+#define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE >> 2) - FIRST_LARGE_HANDLE)
+static GDIOBJHDR *large_handles[MAX_LARGE_HANDLES];
+static int next_large_handle;
+
+/***********************************************************************
+ *           alloc_large_heap
+ *
+ * Allocate a GDI handle from the large heap. Helper for GDI_AllocObject
+ */
+inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle )
+{
+    int i;
+    GDIOBJHDR *obj;
+
+    for (i = next_large_handle + 1; i < MAX_LARGE_HANDLES; i++)
+        if (!large_handles[i]) goto found;
+    for (i = 0; i <= next_large_handle; i++)
+        if (!large_handles[i]) goto found;
+    *handle = 0;
+    return NULL;
+
+ found:
+    if ((obj = HeapAlloc( GetProcessHeap(), 0, size )))
+    {
+        large_handles[i] = obj;
+        *handle = (HGDIOBJ)(ULONG_PTR)((i + FIRST_LARGE_HANDLE) << 2);
+        next_large_handle = i;
+    }
+    return obj;
+}
+
 
 /***********************************************************************
  *           GDI_AllocObject
  */
-HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
+void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle, const struct gdi_obj_funcs *funcs )
 {
-    static DWORD count = 0;
-    GDIOBJHDR * obj;
-    HGDIOBJ16 handle;
-    if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
-      handle = GDI_HEAP_ALLOC( size );
-    else 
-      handle = GDI_HEAP_ALLOC_MOVEABLE( size );
-    if (!handle) return 0;
-    obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
+    GDIOBJHDR *obj;
+    HLOCAL16 hlocal;
+
+    _EnterSysLevel( &GDI_level );
+    switch(magic)
+    {
+    default:
+        if (GDI_HeapSel)
+        {
+            if (!(hlocal = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
+            assert( hlocal & 2 );
+            obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hlocal );
+            *handle = (HGDIOBJ)(ULONG_PTR)hlocal;
+            break;
+        }
+        /* fall through */
+    case DC_MAGIC:
+    case DISABLED_DC_MAGIC:
+    case META_DC_MAGIC:
+    case METAFILE_MAGIC:
+    case METAFILE_DC_MAGIC:
+    case ENHMETAFILE_MAGIC:
+    case ENHMETAFILE_DC_MAGIC:
+    case MEMORY_DC_MAGIC:
+    case BITMAP_MAGIC:
+    case PALETTE_MAGIC:
+        if (!(obj = alloc_large_heap( size, handle ))) goto error;
+        break;
+    }
+
     obj->hNext   = 0;
-    obj->wMagic  = magic;
-    obj->dwCount = ++count;
-    GDI_HEAP_UNLOCK( handle );
-    return handle;
+    obj->wMagic  = magic|OBJECT_NOSYSTEM;
+    obj->dwCount = 0;
+    obj->funcs   = funcs;
+    obj->hdcs    = NULL;
+
+    TRACE_SEC( *handle, "enter" );
+    return obj;
+
+error:
+    _LeaveSysLevel( &GDI_level );
+    *handle = 0;
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           GDI_ReallocObject
+ *
+ * The object ptr must have been obtained with GDI_GetObjPtr.
+ * The new pointer must be released with GDI_ReleaseObj.
+ */
+void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
+{
+    HGDIOBJ new_handle;
+
+    if ((UINT_PTR)handle & 2)  /* GDI heap handle */
+    {
+        HLOCAL16 h = LOWORD(handle);
+        LOCAL_Unlock( GDI_HeapSel, h );
+        if ((new_handle = (HGDIOBJ)(ULONG_PTR)LOCAL_ReAlloc( GDI_HeapSel, h, size, LMEM_MOVEABLE )))
+        {
+            assert( new_handle == handle );  /* moveable handle cannot change */
+            return LOCAL_Lock( GDI_HeapSel, h );
+        }
+    }
+    else
+    {
+        int i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
+        if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
+        {
+            void *new_ptr = HeapReAlloc( GetProcessHeap(), 0, large_handles[i], size );
+            if (new_ptr)
+            {
+                large_handles[i] = new_ptr;
+                return new_ptr;
+            }
+        }
+        else ERR( "Invalid handle %p\n", handle );
+    }
+    TRACE_SEC( handle, "leave" );
+    _LeaveSysLevel( &GDI_level );
+    return NULL;
 }
 
 
 /***********************************************************************
  *           GDI_FreeObject
  */
-BOOL GDI_FreeObject( HGDIOBJ handle )
+BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
 {
-    GDIOBJHDR * object;
+    GDIOBJHDR *object = ptr;
 
-      /* Can't free stock objects */
-    if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
-        return TRUE;
-    
-    object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-    if (!object) return FALSE;
     object->wMagic = 0;  /* Mark it as invalid */
-      /* Free object */
-    
-    GDI_HEAP_FREE( handle );
+    object->funcs  = NULL;
+    if ((UINT_PTR)handle & 2)  /* GDI heap handle */
+    {
+        HLOCAL16 h = LOWORD(handle);
+        LOCAL_Unlock( GDI_HeapSel, h );
+        LOCAL_Free( GDI_HeapSel, h );
+    }
+    else  /* large heap handle */
+    {
+        int i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
+        if (i >= 0 && i < MAX_LARGE_HANDLES && large_handles[i])
+        {
+            HeapFree( GetProcessHeap(), 0, large_handles[i] );
+            large_handles[i] = NULL;
+        }
+        else ERR( "Invalid handle %p\n", handle );
+    }
+    TRACE_SEC( handle, "leave" );
+    _LeaveSysLevel( &GDI_level );
     return TRUE;
 }
 
+
 /***********************************************************************
  *           GDI_GetObjPtr
  *
  * Return a pointer to the GDI object associated to the handle.
  * Return NULL if the object has the wrong magic number.
- * Movable GDI objects are locked in memory: it is up to the caller to unlock
- * it after the caller is done with the pointer.
+ * The object must be released with GDI_ReleaseObj.
  */
-GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
+void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
 {
-    GDIOBJHDR * ptr = NULL;
+    GDIOBJHDR *ptr = NULL;
+
+    _EnterSysLevel( &GDI_level );
 
-    if (handle >= FIRST_STOCK_HANDLE)
+    if ((UINT_PTR)handle & 2)  /* GDI heap handle */
     {
-        if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
+        HLOCAL16 h = LOWORD(handle);
+        ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, h );
+        if (ptr)
+        {
+            if (((magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ||
+                (GDIMAGIC(ptr->wMagic) < FIRST_MAGIC) ||
+                (GDIMAGIC(ptr->wMagic) > LAST_MAGIC))
+            {
+                LOCAL_Unlock( GDI_HeapSel, h );
+                ptr = NULL;
+            }
+        }
+    }
+    else  /* large heap handle */
+    {
+        int i = ((UINT_PTR)handle >> 2) - FIRST_LARGE_HANDLE;
+        if (i >= 0 && i < MAX_LARGE_HANDLES)
+        {
+            ptr = large_handles[i];
+            if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
+        }
     }
-    else 
-      ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-    if (!ptr) return NULL;
-    if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) 
+
+    if (!ptr)
     {
-      GDI_HEAP_UNLOCK( handle );
-      return NULL;
+        _LeaveSysLevel( &GDI_level );
+        SetLastError( ERROR_INVALID_HANDLE );
+        WARN( "Invalid handle %p\n", handle );
     }
+    else TRACE_SEC( handle, "enter" );
+
     return ptr;
 }
 
 
 /***********************************************************************
- *           DeleteObject16    (GDI.69)
+ *           GDI_ReleaseObj
+ *
  */
-BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
+void GDI_ReleaseObj( HGDIOBJ handle )
 {
-    return DeleteObject( obj );
+    if ((UINT_PTR)handle & 2) LOCAL_Unlock( GDI_HeapSel, LOWORD(handle) );
+    TRACE_SEC( handle, "leave" );
+    _LeaveSysLevel( &GDI_level );
 }
 
 
 /***********************************************************************
- *           DeleteObject32    (GDI32.70)
+ *           GDI_CheckNotLock
+ */
+void GDI_CheckNotLock(void)
+{
+    _CheckNotSysLevel( &GDI_level );
+}
+
+
+/***********************************************************************
+ *           DeleteObject    (GDI32.@)
  */
 BOOL WINAPI DeleteObject( HGDIOBJ obj )
 {
@@ -442,219 +881,223 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
 
     GDIOBJHDR * header;
     if (HIWORD(obj)) return FALSE;
-    if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
-        return TRUE;
-    if (obj == hPseudoStockBitmap) return TRUE;
-    if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
 
-    TRACE("%04x\n", obj );
+    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
 
-      /* Delete object */
+    if (!(header->wMagic & OBJECT_NOSYSTEM)
+    &&   (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
+    {
+       TRACE("Preserving system object %p\n", obj);
+        GDI_ReleaseObj( obj );
+       return TRUE;
+    }
 
-    switch(header->wMagic)
+    while (header->hdcs)
     {
-      case PEN_MAGIC:     return GDI_FreeObject( obj );
-      case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
-      case FONT_MAGIC:    return GDI_FreeObject( obj );
-      case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
-      case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
-      case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
-      case DC_MAGIC:      return DeleteDC(obj);
-      case 0 :
-        WARN("Already deleted\n");
-        break;
-      default:
-        WARN("Unknown magic number (%d)\n",header->wMagic);
+        DC *dc = DC_GetDCPtr(header->hdcs->hdc);
+        struct hdc_list *tmp;
+
+        TRACE("hdc %p has interest in %p\n", header->hdcs->hdc, obj);
+        if(dc)
+        {
+            if(dc->funcs->pDeleteObject)
+                dc->funcs->pDeleteObject( dc->physDev, obj );
+            GDI_ReleaseObj( header->hdcs->hdc );
+        }
+        tmp = header->hdcs;
+        header->hdcs = header->hdcs->next;
+        HeapFree(GetProcessHeap(), 0, tmp);
+    }
+
+    if (header->dwCount)
+    {
+        TRACE("delayed for %p because object in use, count %ld\n", obj, header->dwCount );
+        header->dwCount |= 0x80000000; /* mark for delete */
+        GDI_ReleaseObj( obj );
+        return TRUE;
     }
+
+    TRACE("%p\n", obj );
+
+      /* Delete object */
+
+    if (header->funcs && header->funcs->pDeleteObject)
+        return header->funcs->pDeleteObject( obj, header );
+
+    GDI_ReleaseObj( obj );
     return FALSE;
 }
 
 /***********************************************************************
- *           GetStockObject16    (GDI.87)
+ *           GDI_hdc_using_object
+ *
+ * Call this if the dc requires DeleteObject notification
  */
-HGDIOBJ16 WINAPI GetStockObject16( INT16 obj )
+BOOL GDI_hdc_using_object(HGDIOBJ obj, HDC hdc)
 {
-    return (HGDIOBJ16)GetStockObject( obj );
+    GDIOBJHDR * header;
+    struct hdc_list **pphdc;
+
+    TRACE("obj %p hdc %p\n", obj, hdc);
+
+    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
+
+    if (!(header->wMagic & OBJECT_NOSYSTEM) &&
+         (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
+    {
+        GDI_ReleaseObj(obj);
+        return FALSE;
+    }
+
+    for(pphdc = &header->hdcs; *pphdc; pphdc = &(*pphdc)->next)
+        if((*pphdc)->hdc == hdc)
+            break;
+
+    if(!*pphdc) {
+        *pphdc = HeapAlloc(GetProcessHeap(), 0, sizeof(**pphdc));
+        (*pphdc)->hdc = hdc;
+        (*pphdc)->next = NULL;
+    }
+
+    GDI_ReleaseObj(obj);
+    return TRUE;
 }
 
+/***********************************************************************
+ *           GDI_hdc_not_using_object
+ *
+ */
+BOOL GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc)
+{
+    GDIOBJHDR * header;
+    struct hdc_list *phdc, **prev;
+
+    TRACE("obj %p hdc %p\n", obj, hdc);
+
+    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
+
+    if (!(header->wMagic & OBJECT_NOSYSTEM) &&
+         (header->wMagic >= FIRST_MAGIC) && (header->wMagic <= LAST_MAGIC))
+    {
+        GDI_ReleaseObj(obj);
+        return FALSE;
+    }
+
+    phdc = header->hdcs;
+    prev = &header->hdcs;
+
+    while(phdc) {
+        if(phdc->hdc == hdc) {
+            *prev = phdc->next;
+            HeapFree(GetProcessHeap(), 0, phdc);
+            phdc = *prev;
+        } else {
+            prev = &phdc->next;
+            phdc = phdc->next;
+        }
+    }
+
+    GDI_ReleaseObj(obj);
+    return TRUE;
+}
 
 /***********************************************************************
- *           GetStockObject32    (GDI32.220)
+ *           GetStockObject    (GDI32.@)
  */
 HGDIOBJ WINAPI GetStockObject( INT obj )
 {
+    HGDIOBJ ret;
     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
-    if (!StockObjects[obj]) return 0;
-    TRACE("returning %d\n",
-                FIRST_STOCK_HANDLE + obj );
-    return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
+    ret = stock_objects[obj];
+    TRACE("returning %p\n", ret );
+    return ret;
 }
 
 
 /***********************************************************************
- *           GetObject16    (GDI.82)
+ *           GetObject    (GDI.82)
  */
-INT16 WINAPI GetObject16( HANDLE16 handle, INT16 count, LPVOID buffer )
+INT16 WINAPI GetObject16( HANDLE16 handle16, INT16 count, LPVOID buffer )
 {
     GDIOBJHDR * ptr;
+    HGDIOBJ handle = HGDIOBJ_32( handle16 );
     INT16 result = 0;
-    TRACE("%04x %d %p\n", handle, count, buffer );
+
+    TRACE("%p %d %p\n", handle, count, buffer );
     if (!count) return 0;
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
-    
-    switch(ptr->wMagic)
-      {
-      case PEN_MAGIC:
-       result = PEN_GetObject16( (PENOBJ *)ptr, count, buffer );
-       break;
-      case BRUSH_MAGIC: 
-       result = BRUSH_GetObject16( (BRUSHOBJ *)ptr, count, buffer );
-       break;
-      case BITMAP_MAGIC: 
-       result = BITMAP_GetObject16( (BITMAPOBJ *)ptr, count, buffer );
-       break;
-      case FONT_MAGIC:
-       result = FONT_GetObject16( (FONTOBJ *)ptr, count, buffer );
-       
-       /*
-        * Fix the LOGFONT structure for the stock fonts
-        */
-       if ( (handle >= FIRST_STOCK_HANDLE) && 
-            (handle <= LAST_STOCK_HANDLE) )
-         FixStockFontSize16(handle, count, buffer);    
-       break;
-      case PALETTE_MAGIC:
-       result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
-       break;
-      }
-    GDI_HEAP_UNLOCK( handle );
+
+    if (ptr->funcs && ptr->funcs->pGetObject16)
+        result = ptr->funcs->pGetObject16( handle, ptr, count, buffer );
+    else
+        SetLastError( ERROR_INVALID_HANDLE );
+
+    GDI_ReleaseObj( handle );
     return result;
 }
 
 
 /***********************************************************************
- *           GetObject32A    (GDI32.204)
+ *           GetObjectA    (GDI32.@)
  */
 INT WINAPI GetObjectA( HANDLE handle, INT count, LPVOID buffer )
 {
     GDIOBJHDR * ptr;
     INT result = 0;
-    TRACE("%08x %d %p\n", handle, count, buffer );
-    if (!count) return 0;
+    TRACE("%p %d %p\n", handle, count, buffer );
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
 
-    switch(ptr->wMagic)
-    {
-      case PEN_MAGIC:
-         result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
-         break;
-      case BRUSH_MAGIC: 
-         result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
-         break;
-      case BITMAP_MAGIC: 
-         result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
-         break;
-      case FONT_MAGIC:
-         result = FONT_GetObjectA( (FONTOBJ *)ptr, count, buffer );
-         
-         /*
-          * Fix the LOGFONT structure for the stock fonts
-          */
-         if ( (handle >= FIRST_STOCK_HANDLE) && 
-              (handle <= LAST_STOCK_HANDLE) )
-           FixStockFontSizeA(handle, count, buffer);
-         break;
-      case PALETTE_MAGIC:
-         result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
-         break;
-
-      case REGION_MAGIC:
-      case DC_MAGIC:
-      case DISABLED_DC_MAGIC:
-      case META_DC_MAGIC:
-      case METAFILE_MAGIC:
-      case METAFILE_DC_MAGIC:
-      case ENHMETAFILE_MAGIC:
-      case ENHMETAFILE_DC_MAGIC:
-          FIXME("Magic %04x not implemented\n",
-                   ptr->wMagic );
-          break;
+    if (ptr->funcs && ptr->funcs->pGetObjectA)
+        result = ptr->funcs->pGetObjectA( handle, ptr, count, buffer );
+    else
+        SetLastError( ERROR_INVALID_HANDLE );
 
-      default:
-          ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
-         return 0;
-    }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
 /***********************************************************************
- *           GetObject32W    (GDI32.206)
+ *           GetObjectW    (GDI32.@)
  */
 INT WINAPI GetObjectW( HANDLE handle, INT count, LPVOID buffer )
 {
     GDIOBJHDR * ptr;
     INT result = 0;
-    TRACE("%08x %d %p\n", handle, count, buffer );
-    if (!count) return 0;
+    TRACE("%p %d %p\n", handle, count, buffer );
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
 
-    switch(ptr->wMagic)
-    {
-      case PEN_MAGIC:
-         result = PEN_GetObject( (PENOBJ *)ptr, count, buffer );
-         break;
-      case BRUSH_MAGIC: 
-         result = BRUSH_GetObject( (BRUSHOBJ *)ptr, count, buffer );
-         break;
-      case BITMAP_MAGIC: 
-         result = BITMAP_GetObject( (BITMAPOBJ *)ptr, count, buffer );
-         break;
-      case FONT_MAGIC:
-         result = FONT_GetObjectW( (FONTOBJ *)ptr, count, buffer );
-
-         /*
-          * Fix the LOGFONT structure for the stock fonts
-          */
-         if ( (handle >= FIRST_STOCK_HANDLE) && 
-              (handle <= LAST_STOCK_HANDLE) )
-           FixStockFontSizeW(handle, count, buffer);
-         break;
-      case PALETTE_MAGIC:
-         result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
-         break;
-      default:
-          FIXME("Magic %04x not implemented\n",
-                   ptr->wMagic );
-          break;
-    }
-    GDI_HEAP_UNLOCK( handle );
+    if (ptr->funcs && ptr->funcs->pGetObjectW)
+        result = ptr->funcs->pGetObjectW( handle, ptr, count, buffer );
+    else
+        SetLastError( ERROR_INVALID_HANDLE );
+
+    GDI_ReleaseObj( handle );
     return result;
 }
 
 /***********************************************************************
- *           GetObjectType    (GDI32.205)
+ *           GetObjectType    (GDI32.@)
  */
 DWORD WINAPI GetObjectType( HANDLE handle )
 {
     GDIOBJHDR * ptr;
     INT result = 0;
-    TRACE("%08x\n", handle );
+    TRACE("%p\n", handle );
 
     if (!(ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE ))) return 0;
-    
-    switch(ptr->wMagic)
+
+    switch(GDIMAGIC(ptr->wMagic))
     {
       case PEN_MAGIC:
          result = OBJ_PEN;
          break;
-      case BRUSH_MAGIC: 
+      case BRUSH_MAGIC:
          result = OBJ_BRUSH;
          break;
-      case BITMAP_MAGIC: 
+      case BITMAP_MAGIC:
          result = OBJ_BITMAP;
          break;
       case FONT_MAGIC:
@@ -684,201 +1127,116 @@ DWORD WINAPI GetObjectType( HANDLE handle )
       case ENHMETAFILE_DC_MAGIC:
          result = OBJ_ENHMETADC;
          break;
+      case MEMORY_DC_MAGIC:
+         result = OBJ_MEMDC;
+         break;
       default:
-         FIXME("Magic %04x not implemented\n",
-                          ptr->wMagic );
+         FIXME("Magic %04x not implemented\n", GDIMAGIC(ptr->wMagic) );
          break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
 /***********************************************************************
- *           GetCurrentObject          (GDI32.166)
+ *           GetCurrentObject          (GDI32.@)
  */
 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
 {
+    HANDLE ret = 0;
     DC * dc = DC_GetDCPtr( hdc );
 
-    if (!dc) 
-       return 0;
+    if (dc)
+    {
     switch (type) {
-    case OBJ_PEN:      return dc->w.hPen;
-    case OBJ_BRUSH:    return dc->w.hBrush;
-    case OBJ_PAL:      return dc->w.hPalette;
-    case OBJ_FONT:     return dc->w.hFont;
-    case OBJ_BITMAP:   return dc->w.hBitmap;
+       case OBJ_PEN:    ret = dc->hPen; break;
+       case OBJ_BRUSH:  ret = dc->hBrush; break;
+       case OBJ_PAL:    ret = dc->hPalette; break;
+       case OBJ_FONT:   ret = dc->hFont; break;
+       case OBJ_BITMAP: ret = dc->hBitmap; break;
     default:
        /* the SDK only mentions those above */
-       WARN("(%08x,%d): unknown type.\n",hdc,type);
-       return 0;
+       FIXME("(%p,%d): unknown type.\n",hdc,type);
+           break;
+        }
+        GDI_ReleaseObj( hdc );
     }
+    return ret;
 }
 
 
 /***********************************************************************
- *           SelectObject16    (GDI.45)
- */
-HGDIOBJ16 WINAPI SelectObject16( HDC16 hdc, HGDIOBJ16 handle )
-{
-    return (HGDIOBJ16)SelectObject( hdc, handle );
-}
-
-
-/***********************************************************************
- *           SelectObject32    (GDI32.299)
+ *           SelectObject    (GDI32.@)
  */
 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pSelectObject) return 0;
-    TRACE("hdc=%04x %04x\n", hdc, handle );
-    return dc->funcs->pSelectObject( dc, handle );
-}
+    HGDIOBJ ret = 0;
+    GDIOBJHDR *header = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+    if (!header) return 0;
 
+    TRACE("hdc=%p %p\n", hdc, handle );
 
-/***********************************************************************
- *           UnrealizeObject16    (GDI.150)
- */
-BOOL16 WINAPI UnrealizeObject16( HGDIOBJ16 obj )
-{
-    return UnrealizeObject( obj );
+    if (header->funcs && header->funcs->pSelectObject)
+    {
+        ret = header->funcs->pSelectObject( handle, header, hdc );
+        if (ret && ret != handle && (INT)ret > COMPLEXREGION)
+        {
+            inc_ref_count( handle );
+            dec_ref_count( ret );
+        }
+    }
+    GDI_ReleaseObj( handle );
+    return ret;
 }
 
 
 /***********************************************************************
- *           UnrealizeObject    (GDI32.358)
+ *           UnrealizeObject    (GDI32.@)
  */
 BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
 {
     BOOL result = TRUE;
   /* Check if object is valid */
 
-    GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
+    GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
     if (!header) return FALSE;
 
-    TRACE("%04x\n", obj );
+    TRACE("%p\n", obj );
 
       /* Unrealize object */
 
-    switch(header->wMagic)
-    {
-    case PALETTE_MAGIC: 
-        result = PALETTE_UnrealizeObject( obj, (PALETTEOBJ *)header );
-       break;
+    if (header->funcs && header->funcs->pUnrealizeObject)
+        result = header->funcs->pUnrealizeObject( obj, header );
 
-    case BRUSH_MAGIC:
-        /* Windows resets the brush origin. We don't need to. */
-        break;
-    }
-    GDI_HEAP_UNLOCK( obj );
+    GDI_ReleaseObj( obj );
     return result;
 }
 
 
-/***********************************************************************
- *           EnumObjects16    (GDI.71)
- */
-INT16 WINAPI EnumObjects16( HDC16 hdc, INT16 nObjType,
-                            GOBJENUMPROC16 lpEnumFunc, LPARAM lParam )
-{
-    /* Solid colors to enumerate */
-    static const COLORREF solid_colors[] =
-    { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
-      RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
-      RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
-      RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
-      RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
-      RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
-      RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
-      RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
-    };
-    
-    INT16 i, retval = 0;
-    LOGPEN16 *pen;
-    LOGBRUSH16 *brush = NULL;
-
-    TRACE("%04x %d %08lx %08lx\n",
-                 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
-    switch(nObjType)
-    {
-    case OBJ_PEN:
-        /* Enumerate solid pens */
-        if (!(pen = SEGPTR_NEW(LOGPEN16))) break;
-        for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
-        {
-            pen->lopnStyle   = PS_SOLID;
-            pen->lopnWidth.x = 1;
-            pen->lopnWidth.y = 0;
-            pen->lopnColor   = solid_colors[i];
-            retval = lpEnumFunc( SEGPTR_GET(pen), lParam );
-            TRACE("solid pen %08lx, ret=%d\n",
-                         solid_colors[i], retval);
-            if (!retval) break;
-        }
-        SEGPTR_FREE(pen);
-        break;
-
-    case OBJ_BRUSH:
-        /* Enumerate solid brushes */
-        if (!(brush = SEGPTR_NEW(LOGBRUSH16))) break;
-        for (i = 0; i < sizeof(solid_colors)/sizeof(solid_colors[0]); i++)
-        {
-            brush->lbStyle = BS_SOLID;
-            brush->lbColor = solid_colors[i];
-            brush->lbHatch = 0;
-            retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
-            TRACE("solid brush %08lx, ret=%d\n",
-                         solid_colors[i], retval);
-            if (!retval) break;
-        }
-
-        /* Now enumerate hatched brushes */
-        if (retval) for (i = HS_HORIZONTAL; i <= HS_DIAGCROSS; i++)
-        {
-            brush->lbStyle = BS_HATCHED;
-            brush->lbColor = RGB(0,0,0);
-            brush->lbHatch = i;
-            retval = lpEnumFunc( SEGPTR_GET(brush), lParam );
-            TRACE("hatched brush %d, ret=%d\n",
-                         i, retval);
-            if (!retval) break;
-        }
-        SEGPTR_FREE(brush);
-        break;
-
-    default:
-        WARN("(%d): Invalid type\n", nObjType );
-        break;
-    }
-    return retval;
-}
+/* Solid colors to enumerate */
+static const COLORREF solid_colors[] =
+{ RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
+RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
+RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
+RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
+RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
+RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
+RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
+RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
+};
 
 
 /***********************************************************************
- *           EnumObjects32    (GDI32.89)
+ *           EnumObjects    (GDI32.@)
  */
 INT WINAPI EnumObjects( HDC hdc, INT nObjType,
                             GOBJENUMPROC lpEnumFunc, LPARAM lParam )
 {
-    /* Solid colors to enumerate */
-    static const COLORREF solid_colors[] =
-    { RGB(0x00,0x00,0x00), RGB(0xff,0xff,0xff),
-      RGB(0xff,0x00,0x00), RGB(0x00,0xff,0x00),
-      RGB(0x00,0x00,0xff), RGB(0xff,0xff,0x00),
-      RGB(0xff,0x00,0xff), RGB(0x00,0xff,0xff),
-      RGB(0x80,0x00,0x00), RGB(0x00,0x80,0x00),
-      RGB(0x80,0x80,0x00), RGB(0x00,0x00,0x80),
-      RGB(0x80,0x00,0x80), RGB(0x00,0x80,0x80),
-      RGB(0x80,0x80,0x80), RGB(0xc0,0xc0,0xc0)
-    };
-    
     INT i, retval = 0;
     LOGPEN pen;
     LOGBRUSH brush;
 
-    TRACE("%04x %d %08lx %08lx\n",
-                 hdc, nObjType, (DWORD)lpEnumFunc, lParam );
+    TRACE("%p %d %p %08lx\n", hdc, nObjType, lpEnumFunc, lParam );
     switch(nObjType)
     {
     case OBJ_PEN:
@@ -933,92 +1291,59 @@ INT WINAPI EnumObjects( HDC hdc, INT nObjType,
 
 /***********************************************************************
  *           IsGDIObject    (GDI.462)
- * 
+ *
  * returns type of object if valid (W95 system programming secrets p. 264-5)
  */
-BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle )
+BOOL16 WINAPI IsGDIObject16( HGDIOBJ16 handle16 )
 {
     UINT16 magic = 0;
+    HGDIOBJ handle = HGDIOBJ_32( handle16 );
 
-    if (handle >= FIRST_STOCK_HANDLE ) 
+    GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+    if (object)
     {
-        switch (handle)
-        {
-        case STOCK_WHITE_BRUSH:
-        case STOCK_LTGRAY_BRUSH:
-        case STOCK_GRAY_BRUSH:
-        case STOCK_DKGRAY_BRUSH:
-        case STOCK_BLACK_BRUSH:
-        case STOCK_HOLLOW_BRUSH:
-            magic = BRUSH_MAGIC;
-            break;
-
-        case STOCK_WHITE_PEN:
-        case STOCK_BLACK_PEN:
-        case STOCK_NULL_PEN :
-            magic = PEN_MAGIC;
-            break;
-
-        case STOCK_OEM_FIXED_FONT:
-        case STOCK_ANSI_FIXED_FONT:
-        case STOCK_ANSI_VAR_FONT:
-        case STOCK_SYSTEM_FONT:
-        case STOCK_DEVICE_DEFAULT_FONT:
-        case STOCK_SYSTEM_FIXED_FONT:
-        case STOCK_DEFAULT_GUI_FONT:
-            magic = FONT_MAGIC;
-            break;
-
-        case STOCK_DEFAULT_PALETTE:
-            magic = PALETTE_MAGIC;
-            break;
-        }
+        magic = GDIMAGIC(object->wMagic) - PEN_MAGIC + 1;
+        GDI_ReleaseObj( handle );
     }
-    else
-    {
-       GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-       if (object)
-       {
-           magic = object->wMagic;
-           GDI_HEAP_UNLOCK( handle );
-       }
-    }
-
-    if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
-        return magic - PEN_MAGIC + 1;
-    else
-        return FALSE;
-}
-
-
-/***********************************************************************
- *           SetObjectOwner16    (GDI.461)
- */
-void WINAPI SetObjectOwner16( HGDIOBJ16 handle, HANDLE16 owner )
-{
-    /* Nothing to do */
+    return magic;
 }
 
 
 /***********************************************************************
- *           SetObjectOwner32    (GDI32.386)
+ *           SetObjectOwner    (GDI32.@)
  */
 void WINAPI SetObjectOwner( HGDIOBJ handle, HANDLE owner )
 {
     /* Nothing to do */
 }
 
+
 /***********************************************************************
  *           MakeObjectPrivate    (GDI.463)
+ *
+ * What does that mean ?
+ * Some little docu can be found in "Undocumented Windows",
+ * but this is basically useless.
+ * At least we know that this flags the GDI object's wMagic
+ * with 0x2000 (OBJECT_PRIVATE), so we just do it.
+ * But Wine doesn't react on that yet.
  */
-void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle, BOOL16 private )
+void WINAPI MakeObjectPrivate16( HGDIOBJ16 handle16, BOOL16 private )
 {
-    /* FIXME */
+    HGDIOBJ handle = HGDIOBJ_32( handle16 );
+    GDIOBJHDR *ptr = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+    if (!ptr)
+    {
+       ERR("invalid GDI object %p !\n", handle);
+       return;
+    }
+    ptr->wMagic |= OBJECT_PRIVATE;
+    GDI_ReleaseObj( handle );
 }
 
 
 /***********************************************************************
- *           GdiFlush    (GDI32.128)
+ *           GdiFlush    (GDI32.@)
  */
 BOOL WINAPI GdiFlush(void)
 {
@@ -1027,7 +1352,7 @@ BOOL WINAPI GdiFlush(void)
 
 
 /***********************************************************************
- *           GdiGetBatchLimit    (GDI32.129)
+ *           GdiGetBatchLimit    (GDI32.@)
  */
 DWORD WINAPI GdiGetBatchLimit(void)
 {
@@ -1036,7 +1361,7 @@ DWORD WINAPI GdiGetBatchLimit(void)
 
 
 /***********************************************************************
- *           GdiSetBatchLimit    (GDI32.139)
+ *           GdiSetBatchLimit    (GDI32.@)
  */
 DWORD WINAPI GdiSetBatchLimit( DWORD limit )
 {
@@ -1062,12 +1387,12 @@ DWORD WINAPI GdiSeeGdiDo16( WORD wReqType, WORD wParam1, WORD wParam2,
         return GDI_HeapSel;
     default:
         WARN("(wReqType=%04x): Unknown\n", wReqType);
-        return (DWORD)-1;
+        return ~0UL;
     }
 }
 
 /***********************************************************************
- *           GdiSignalProc     (GDI.610)
+ *           GdiSignalProc32     (GDI.610)
  */
 WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
                            DWORD dwFlags, HMODULE16 hModule )
@@ -1076,102 +1401,40 @@ WORD WINAPI GdiSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
 }
 
 /***********************************************************************
- *           FinalGdiInit16     (GDI.405)
+ *           GdiInit2     (GDI.403)
+ *
+ * See "Undocumented Windows"
  */
-void WINAPI FinalGdiInit16( HANDLE16 unknown )
+HANDLE16 WINAPI GdiInit216(
+    HANDLE16 h1, /* [in] GDI object */
+    HANDLE16 h2  /* [in] global data */
+)
 {
+    FIXME("(%04x, %04x), stub.\n", h1, h2);
+    if (h2 == 0xffff)
+       return 0xffff; /* undefined return value */
+    return h1; /* FIXME: should be the memory handle of h1 */
 }
 
 /***********************************************************************
- *           GdiFreeResources   (GDI.609)
+ *           FinalGdiInit     (GDI.405)
  */
-WORD WINAPI GdiFreeResources16( DWORD reserve )
+void WINAPI FinalGdiInit16( HBRUSH16 hPattern /* [in] fill pattern of desktop */ )
 {
-   return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
-                  (int)LOCAL_HeapSize( GDI_HeapSel ) );
 }
 
 /***********************************************************************
- *           MulDiv16   (GDI.128)
+ *           GdiFreeResources   (GDI.609)
  */
-INT16 WINAPI MulDiv16(
-            INT16 nMultiplicand, 
-            INT16 nMultiplier,
-            INT16 nDivisor)
+WORD WINAPI GdiFreeResources16( DWORD reserve )
 {
-    INT ret;
-    if (!nDivisor) return -32768;
-    /* We want to deal with a positive divisor to simplify the logic. */
-    if (nDivisor < 0)
-    {
-      nMultiplicand = - nMultiplicand;
-      nDivisor = -nDivisor;
-    }
-    /* If the result is positive, we "add" to round. else, 
-     * we subtract to round. */
-    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
-        ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
-        ret = (((int)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
-    else
-        ret = (((int)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
-    if ((ret > 32767) || (ret < -32767)) return -32768;
-    return (INT16) ret;
+   return (WORD)( (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
+                  (int)LOCAL_HeapSize( GDI_HeapSel ) );
 }
 
 
-/***********************************************************************
- *           MulDiv32   (KERNEL32.391)
- * RETURNS
- *     Result of multiplication and division
- *     -1: Overflow occurred or Divisor was 0
- */
-INT WINAPI MulDiv(
-            INT nMultiplicand, 
-            INT nMultiplier,
-            INT nDivisor)
-{
-#if SIZEOF_LONG_LONG >= 8
-    long long ret;
-
-    if (!nDivisor) return -1;
-
-    /* We want to deal with a positive divisor to simplify the logic. */
-    if (nDivisor < 0)
-    {
-      nMultiplicand = - nMultiplicand;
-      nDivisor = -nDivisor;
-    }
-
-    /* If the result is positive, we "add" to round. else, we subtract to round. */
-    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
-        ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
-      ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
-    else
-      ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
-
-    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
-    return ret;
-#else
-    if (!nDivisor) return -1;
-
-    /* We want to deal with a positive divisor to simplify the logic. */
-    if (nDivisor < 0)
-    {
-      nMultiplicand = - nMultiplicand;
-      nDivisor = -nDivisor;
-    }
-
-    /* If the result is positive, we "add" to round. else, we subtract to round. */
-    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
-        ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
-      return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
-    return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
-    
-#endif
-}
 /*******************************************************************
- *      GetColorAdjustment [GDI32.164]
+ *      GetColorAdjustment [GDI32.@]
  *
  *
  */
@@ -1182,7 +1445,7 @@ BOOL WINAPI GetColorAdjustment(HDC hdc, LPCOLORADJUSTMENT lpca)
 }
 
 /*******************************************************************
- *      GetMiterLimit [GDI32.201]
+ *      GetMiterLimit [GDI32.@]
  *
  *
  */
@@ -1193,7 +1456,7 @@ BOOL WINAPI GetMiterLimit(HDC hdc, PFLOAT peLimit)
 }
 
 /*******************************************************************
- *      SetMiterLimit [GDI32.325]
+ *      SetMiterLimit [GDI32.@]
  *
  *
  */
@@ -1204,17 +1467,25 @@ BOOL WINAPI SetMiterLimit(HDC hdc, FLOAT eNewLimit, PFLOAT peOldLimit)
 }
 
 /*******************************************************************
- *      GdiComment [GDI32.109]
+ *      GdiComment [GDI32.@]
  *
  *
  */
 BOOL WINAPI GdiComment(HDC hdc, UINT cbSize, const BYTE *lpData)
 {
-        FIXME("GdiComment, stub\n");
-        return 0;
+    DC *dc = DC_GetDCPtr(hdc);
+    BOOL ret = FALSE;
+    if(dc)
+    {
+        if (dc->funcs->pGdiComment)
+            ret = dc->funcs->pGdiComment( dc->physDev, cbSize, lpData );
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
+
 /*******************************************************************
- *      SetColorAdjustment [GDI32.309]
+ *      SetColorAdjustment [GDI32.@]
  *
  *
  */
@@ -1223,4 +1494,3 @@ BOOL WINAPI SetColorAdjustment(HDC hdc, const COLORADJUSTMENT* lpca)
         FIXME("SetColorAdjustment, stub\n");
         return 0;
 }