Allocate DC objects on the process heap, and removed WIN_DC_INFO
structure (based on a patch by Ken Coleman).
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index fc11834..58d21a1 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -17,7 +17,6 @@
#include "bitmap.h"
#include "brush.h"
-#include "dc.h"
#include "font.h"
#include "heap.h"
#include "options.h"
@@ -31,9 +30,6 @@
DEFAULT_DEBUG_CHANNEL(gdi);
-/**********************************************************************/
-
-GDI_DRIVER *GDI_Driver = NULL;
/***********************************************************************
* GDI stock objects
@@ -366,6 +362,38 @@
return TRUE;
}
+#define FIRST_LARGE_HANDLE 16
+#define MAX_LARGE_HANDLES ((GDI_HEAP_SIZE - FIRST_LARGE_HANDLE) >> 2)
+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 = (i + FIRST_LARGE_HANDLE) << 2;
+ next_large_handle = i;
+ }
+ return obj;
+}
+
/***********************************************************************
* GDI_AllocObject
@@ -376,18 +404,36 @@
GDIOBJHDR *obj;
_EnterSysLevel( &GDI_level );
- if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size )))
+ switch(magic)
{
- _LeaveSysLevel( &GDI_level );
- return NULL;
+ /* allocate DCs on the larger heap */
+ 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:
+ if (!(obj = alloc_large_heap( size, handle ))) goto error;
+ break;
+ default:
+ if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size ))) goto error;
+ assert( *handle & 2 );
+ obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
+ break;
}
- obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
+
obj->hNext = 0;
obj->wMagic = magic|OBJECT_NOSYSTEM;
obj->dwCount = ++count;
TRACE_SEC( *handle, "enter" );
return obj;
+
+error:
+ _LeaveSysLevel( &GDI_level );
+ *handle = 0;
+ return NULL;
}
@@ -401,6 +447,7 @@
{
HGDIOBJ new_handle;
+ assert( handle & 2 ); /* no realloc for large handles */
LOCAL_Unlock( GDI_HeapSel, handle );
if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
{
@@ -424,8 +471,20 @@
if (handle < FIRST_STOCK_HANDLE)
{
object->wMagic = 0; /* Mark it as invalid */
- LOCAL_Unlock( GDI_HeapSel, handle );
- LOCAL_Free( GDI_HeapSel, handle );
+ if (handle & 2) /* GDI heap handle */
+ {
+ LOCAL_Unlock( GDI_HeapSel, handle );
+ LOCAL_Free( GDI_HeapSel, handle );
+ }
+ else /* large heap handle */
+ {
+ int i = (handle >> 2) - FIRST_LARGE_HANDLE;
+ if (i >= 0 && large_handles[i])
+ {
+ HeapFree( GetProcessHeap(), 0, large_handles[i] );
+ large_handles[i] = NULL;
+ }
+ }
}
TRACE_SEC( handle, "leave" );
_LeaveSysLevel( &GDI_level );
@@ -452,7 +511,7 @@
if (ptr && (magic != MAGIC_DONTCARE)
&& (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
}
- else
+ else if (handle & 2) /* GDI heap handle */
{
ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
if (ptr &&
@@ -462,6 +521,15 @@
ptr = NULL;
}
}
+ else /* large heap handle */
+ {
+ int i = (handle >> 2) - FIRST_LARGE_HANDLE;
+ if (i >= 0)
+ {
+ ptr = large_handles[i];
+ if (ptr && (magic != MAGIC_DONTCARE) && (GDIMAGIC(ptr->wMagic) != magic)) ptr = NULL;
+ }
+ }
if (!ptr)
{
@@ -480,7 +548,7 @@
*/
void GDI_ReleaseObj( HGDIOBJ handle )
{
- if (handle < FIRST_STOCK_HANDLE) LOCAL_Unlock( GDI_HeapSel, handle );
+ if (handle < FIRST_STOCK_HANDLE && (handle & 2)) LOCAL_Unlock( GDI_HeapSel, handle );
TRACE_SEC( handle, "leave" );
_LeaveSysLevel( &GDI_level );
}
@@ -778,11 +846,11 @@
if (dc)
{
switch (type) {
- case OBJ_PEN: ret = dc->w.hPen; break;
- case OBJ_BRUSH: ret = dc->w.hBrush; break;
- case OBJ_PAL: ret = dc->w.hPalette; break;
- case OBJ_FONT: ret = dc->w.hFont; break;
- case OBJ_BITMAP: ret = dc->w.hBitmap; break;
+ 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 */
FIXME("(%08x,%d): unknown type.\n",hdc,type);