From e39b676ae90f00e347b8d44927d375189851057b Mon Sep 17 00:00:00 2001
From: Huw D M Davies <h.davies1@physics.ox.ac.uk>
Date: Mon, 17 May 1999 16:20:51 +0000
Subject: [PATCH] Implement DocumentProperties, DeviceCapabilities, beginnings
 of Open/Get/ClosePrinter.  Additions to PSDRV_DeviceCapabilities. Split off
 WINSPOOL into its own directory. Several functions added to DC_Funcs. Based
 largely on a patch by Pascal Lessard <pascal@macadamian.com>

---
 Makefile.in                    |    2 +
 configure                      |    2 +
 configure.in                   |    1 +
 dlls/winspool/.cvsignore       |    1 +
 dlls/winspool/Makefile.in      |   16 +
 dlls/winspool/info.c           | 1166 ++++++++++++++++++++++++
 graphics/driver.c              |   79 +-
 graphics/enhmetafiledrv/init.c |    9 +-
 graphics/env.c                 |    4 +-
 graphics/escape.c              |   12 +-
 graphics/metafiledrv/init.c    |    9 +-
 graphics/psdrv/driver.c        |  269 +++++-
 graphics/psdrv/init.c          |   51 +-
 graphics/psdrv/ppd.c           |   20 +-
 graphics/psdrv/ps.c            |    6 +-
 graphics/ttydrv/init.c         |   11 +-
 graphics/win16drv/init.c       |   13 +-
 graphics/x11drv/init.c         |   13 +-
 include/debugdefs.h            |   11 +-
 include/gdi.h                  |   14 +-
 include/psdrv.h                |   23 +-
 include/ttydrv.h               |    2 +-
 include/wine/wingdi16.h        |   44 +-
 include/wingdi.h               |   46 +-
 include/winspool.h             |   10 +-
 misc/Makefile.in               |    1 -
 misc/printdrv.c                | 1514 ++++++++++----------------------
 misc/spooler.c                 |  463 ----------
 objects/dc.c                   |   42 +-
 29 files changed, 2170 insertions(+), 1684 deletions(-)
 create mode 100644 dlls/winspool/.cvsignore
 create mode 100644 dlls/winspool/Makefile.in
 create mode 100644 dlls/winspool/info.c
 delete mode 100644 misc/spooler.c

diff --git a/Makefile.in b/Makefile.in
index 29e68f88c6..30fd46ecae 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -43,6 +43,7 @@ LIBSUBDIRS = \
 	dlls/ver \
 	dlls/version \
 	dlls/winaspi \
+	dlls/winspool \
 	dlls/wnaspi32 \
 	files \
 	graphics \
@@ -118,6 +119,7 @@ LIBOBJS = \
 	dlls/ver/ver.o \
 	dlls/version/version.o \
 	dlls/winaspi/winaspi.o \
+	dlls/winspool/winspool.o \
 	dlls/wnaspi32/wnaspi32.o \
 	files/files.o \
 	graphics/graphics.o \
diff --git a/configure b/configure
index 1e7ebcec6e..1b71c3d1c9 100755
--- a/configure
+++ b/configure
@@ -5214,6 +5214,7 @@ dlls/tapi32/Makefile
 dlls/ver/Makefile
 dlls/version/Makefile
 dlls/winaspi/Makefile
+dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
 documentation/Makefile
 files/Makefile
@@ -5381,6 +5382,7 @@ dlls/tapi32/Makefile
 dlls/ver/Makefile
 dlls/version/Makefile
 dlls/winaspi/Makefile
+dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
 documentation/Makefile
 files/Makefile
diff --git a/configure.in b/configure.in
index 75149de48f..c9f802bc4f 100644
--- a/configure.in
+++ b/configure.in
@@ -742,6 +742,7 @@ dlls/tapi32/Makefile
 dlls/ver/Makefile
 dlls/version/Makefile
 dlls/winaspi/Makefile
+dlls/winspool/Makefile
 dlls/wnaspi32/Makefile
 documentation/Makefile
 files/Makefile
diff --git a/dlls/winspool/.cvsignore b/dlls/winspool/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/dlls/winspool/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/dlls/winspool/Makefile.in b/dlls/winspool/Makefile.in
new file mode 100644
index 0000000000..ee44603864
--- /dev/null
+++ b/dlls/winspool/Makefile.in
@@ -0,0 +1,16 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = winspool
+
+C_SRCS = \
+	info.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
+
diff --git a/dlls/winspool/info.c b/dlls/winspool/info.c
new file mode 100644
index 0000000000..6ff0162427
--- /dev/null
+++ b/dlls/winspool/info.c
@@ -0,0 +1,1166 @@
+/* 
+ * WINSPOOL functions
+ * 
+ * Copyright 1996 John Harvey
+ * Copyright 1998 Andreas Mohr
+ * Copyright 1999 Klaas van Gend
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "winspool.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(winspool)
+
+CRITICAL_SECTION PRINT32_RegistryBlocker;
+
+#define NUM_PRINTER_MAX 10
+
+typedef struct _OPENEDPRINTERA
+{
+    LPSTR lpsPrinterName;
+    HANDLE hPrinter;
+    LPPRINTER_DEFAULTSA lpDefault;
+} OPENEDPRINTERA, *LPOPENEDPRINTERA;
+
+
+/* Initialize the structure OpenedPrinter Table */
+static OPENEDPRINTERA OpenedPrinterTableA[NUM_PRINTER_MAX] = 
+{ 
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL},
+    {NULL, -1, NULL}
+};
+
+static char Printers[]		= "System\\CurrentControlSet\\Control\\Print\\Printers\\";
+
+
+/******************************************************************
+ *  WINSPOOL_GetOpenedPrinterEntryA
+ *  Get the first place empty in the opened printer table
+ */
+static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterEntryA()
+{
+    int i;
+    for( i=0; i< NUM_PRINTER_MAX; i++)
+	if (OpenedPrinterTableA[i].hPrinter == -1)
+	{
+	    OpenedPrinterTableA[i].hPrinter = i + 1;
+	    return &OpenedPrinterTableA[i];
+	}
+    return NULL;
+}
+
+/******************************************************************
+ *  WINSPOOL_GetOpenedPrinterA
+ *  Get the pointer to the opened printer referred by the handle
+ */
+static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterA(int printerHandle)
+{
+    if((printerHandle <=0) || (printerHandle > (NUM_PRINTER_MAX + 1)))
+	return NULL;
+    return &OpenedPrinterTableA[printerHandle -1];
+}
+
+/******************************************************************
+ *              DeviceCapabilities32A    [WINSPOOL.151]
+ *
+ */
+INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap,
+			       LPSTR pOutput, LPDEVMODEA lpdm)
+{
+    return GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm);
+
+}
+
+
+/*****************************************************************************
+ *          DeviceCapabilities32W 
+ */
+INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
+			       WORD fwCapability, LPWSTR pOutput,
+			       const DEVMODEW *pDevMode)
+{
+    FIXME("(%p,%p,%d,%p,%p): stub\n",
+          pDevice, pPort, fwCapability, pOutput, pDevMode);
+    return -1;
+}
+
+/******************************************************************
+ *              DocumentProperties32A   [WINSPOOL.155]
+ *
+ */
+LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
+                                LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
+				LPDEVMODEA pDevModeInput,DWORD fMode )
+{
+    LPOPENEDPRINTERA lpOpenedPrinter;
+    LPSTR lpName = pDeviceName;
+
+    TRACE("(%d,%d,%s,%p,%p,%ld)\n",
+	hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
+    );
+
+    if(!pDeviceName) {
+        lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
+	if(!lpOpenedPrinter) {
+	    SetLastError(ERROR_INVALID_HANDLE);
+	    return -1;
+	}
+	lpName = lpOpenedPrinter->lpsPrinterName;
+    }
+
+    return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, NULL,
+				   pDevModeInput, NULL, fMode);
+
+}
+
+
+/*****************************************************************************
+ *          DocumentProperties32W 
+ */
+LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
+                                  LPWSTR pDeviceName,
+                                  LPDEVMODEW pDevModeOutput,
+                                  LPDEVMODEW pDevModeInput, DWORD fMode)
+{
+    FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
+          hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
+	  fMode);
+    return -1;
+}
+
+
+/******************************************************************
+ *              OpenPrinter32A        [WINSPOOL.196]
+ *
+ */
+BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
+			     LPPRINTER_DEFAULTSA pDefault)
+{
+  /* Not implemented: use the DesiredAccess of pDefault to set 
+     the access rights to the printer */
+
+    LPOPENEDPRINTERA lpOpenedPrinter;
+
+    TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
+
+    /* Get a place in the opened printer buffer*/
+    lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
+
+    if((lpOpenedPrinter != NULL) && (lpPrinterName !=NULL) && 
+       (phPrinter != NULL))
+    {
+	/* Get the name of the printer */
+	lpOpenedPrinter->lpsPrinterName = 
+	  HeapAlloc(GetProcessHeap(), 0, lstrlenA(lpPrinterName));
+	lstrcpyA(lpOpenedPrinter->lpsPrinterName, lpPrinterName);
+
+	/* Get the unique handle of the printer*/
+	*phPrinter = lpOpenedPrinter->hPrinter;
+
+	if (pDefault != NULL)
+	{
+	    /* Allocate enough memory for the lpDefault structure */
+	    lpOpenedPrinter->lpDefault = 
+	      HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
+	    lpOpenedPrinter->lpDefault->pDevMode =
+	      HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
+	    lpOpenedPrinter->lpDefault->pDatatype = 
+	      HeapAlloc(GetProcessHeap(), 0, lstrlenA(pDefault->pDatatype));
+
+	    /*Copy the information from incoming parameter*/
+	    memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
+		   sizeof(DEVMODEA));
+	    lstrcpyA(lpOpenedPrinter->lpDefault->pDatatype,
+		     pDefault->pDatatype);
+	    lpOpenedPrinter->lpDefault->DesiredAccess =
+	      pDefault->DesiredAccess;
+	}
+
+	return TRUE;
+    }
+
+    if(lpOpenedPrinter == NULL)
+	FIXME("Reach the OpenedPrinterTable maximum, augment this max.\n");
+     return FALSE;
+}
+
+/******************************************************************
+ *              OpenPrinter32W        [WINSPOOL.197]
+ *
+ */
+BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
+			     LPPRINTER_DEFAULTSW pDefault)
+{
+    FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
+          pDefault);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+
+
+/******************************************************************
+ *              ENUMPRINTERS_GetDWORDFromRegistryA    internal
+ *
+ * Reads a DWORD from registry KeyName 
+ *
+ * RETURNS
+ *    value on OK or NULL on error
+ */
+DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
+				HKEY  hPrinterSettings,  /* handle to registry key */
+				LPSTR KeyName			 /* name key to retrieve string from*/
+){                   
+ DWORD DataSize=8;
+ DWORD DataType;
+ BYTE  Data[8];
+ DWORD Result=684;
+
+ if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
+  					Data, &DataSize)!=ERROR_SUCCESS)
+	FIXME("Query of register didn't succeed?\n");                     
+ if (DataType == REG_DWORD_LITTLE_ENDIAN)
+ 	Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
+ if (DataType == REG_DWORD_BIG_ENDIAN)
+ 	Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
+ return(Result);
+}
+
+
+/******************************************************************
+ *              ENUMPRINTERS_AddStringFromRegistryA    internal
+ *
+ * Reads a string from registry KeyName and writes it at
+ * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
+ *
+ * RETURNS
+ *    FALSE if there is still space left in the buffer.
+ */
+BOOL ENUMPRINTERS_AddStringFromRegistryA(
+				HKEY  hPrinterSettings,  /* handle to registry key */
+				LPSTR KeyName,			 /* name key to retrieve string from*/
+                LPSTR* Dest,		     /* pointer to write string addres to */
+                LPBYTE lpbPrinters,      /* buffer which receives info*/
+                LPDWORD dwNextStringPos, /* pos in buffer for next string */
+			    DWORD  dwBufSize,        /* max size of buffer in bytes */
+                BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
+){                   
+ DWORD DataSize=34;
+ DWORD DataType;
+ LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
+
+ while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
+  					Data, &DataSize)==ERROR_MORE_DATA)
+    {
+     Data = (LPSTR) realloc(Data, DataSize+2);
+    }
+
+ if (DataType == REG_SZ)
+ 	{                   
+	 if (bCalcSpaceOnly==FALSE)
+	 *Dest = &lpbPrinters[*dwNextStringPos];
+	 *dwNextStringPos += DataSize+1;
+	 if (*dwNextStringPos > dwBufSize)
+	 	bCalcSpaceOnly=TRUE;
+	 if (bCalcSpaceOnly==FALSE)
+        {
+         if (DataSize==0)		/* DataSize = 0 means empty string, even though*/
+         	*Dest[0]=0;			/* the data itself needs not to be empty */
+         else
+	         strcpy(*Dest, Data);
+        }
+ 	}
+ else
+ 	WARN("Expected string setting, got something else from registry");
+    
+ if (Data)
+    free(Data);
+ return(bCalcSpaceOnly);
+}
+
+
+
+/******************************************************************
+ *              ENUMPRINTERS_AddInfo2A        internal
+ *
+ *    Creates a PRINTER_INFO_2A structure at:  lpbPrinters[dwNextStructPos]
+ *    for printer PrinterNameKey.
+ *    Note that there is no check whether the information really fits!
+ *
+ * RETURNS
+ *    FALSE if there is still space left in the buffer.
+ *
+ * BUGS:
+ *    This function should not only read the registry but also ask the driver
+ *    for information.
+ */
+BOOL ENUMPRINTERS_AddInfo2A(
+                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
+                   LPBYTE lpbPrinters,   /* buffer which receives info*/
+                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
+                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
+				   DWORD  dwBufSize,        /* max size of buffer in bytes */
+                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
+){                   
+ HKEY  hPrinterSettings;
+ DWORD DevSize=0;
+ DWORD DataType;
+ LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
+  										   	   strlen(lpszPrinterName)+2);
+ LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
+
+ /* open the registry to find the attributes, etc of the printer */
+ if (lpszPrinterSettings!=NULL)
+ 	{
+     strcpy(lpszPrinterSettings,Printers);
+     strcat(lpszPrinterSettings,lpszPrinterName);
+    }
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
+ 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
+	{
+     WARN("The registry did not contain my printer anymore?\n");
+    }
+ else
+    {
+     if (bCalcSpaceOnly==FALSE)
+     lpPInfo2->pServerName = NULL;
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Name", &(lpPInfo2->pPrinterName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Share Name", &(lpPInfo2->pShareName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Port", &(lpPInfo2->pPortName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Printer Driver", &(lpPInfo2->pDriverName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Description", &(lpPInfo2->pComment), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Location", &(lpPInfo2->pLocation), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Separator File", &(lpPInfo2->pSepFile), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Print Processor", &(lpPInfo2->pPrintProcessor), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Datatype", &(lpPInfo2->pDatatype), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Parameters", &(lpPInfo2->pParameters), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     if (bCalcSpaceOnly == FALSE)
+     	{                             
+     lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
+
+     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
+	 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
+	 lpPInfo2->Priority   = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"Priority"); 
+	 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
+     								hPrinterSettings, "Default Priority"); 
+	 lpPInfo2->StartTime  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"StartTime"); 
+	 lpPInfo2->UntilTime  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"UntilTime"); 
+	 lpPInfo2->Status     = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"Status"); 
+	 lpPInfo2->cJobs      = 0;    /* FIXME: according to MSDN, this does not 
+     							   * reflect the TotalJobs Key ??? */
+	 lpPInfo2->AveragePPM = 0;    /* FIXME: according to MSDN, this does not 
+     							   * reflect the TotalPages Key ??? */
+
+     /* and read the devModes structure... */
+      RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
+  					NULL, &DevSize); /* should return ERROR_MORE_DATA */
+	      lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
+      *dwNextStringPos += DevSize + 1;      
+        } 
+ if (*dwNextStringPos > dwBufSize)
+ 	bCalcSpaceOnly=TRUE;
+ if (bCalcSpaceOnly==FALSE)
+	      RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
+  					(LPBYTE)lpPInfo2->pDevMode, &DevSize); 
+	}                                 
+
+ if (lpszPrinterSettings)
+	 free(lpszPrinterSettings);
+
+ return(bCalcSpaceOnly);     
+}
+
+/******************************************************************
+ *              ENUMPRINTERS_AddInfo4A        internal
+ *
+ *    Creates a PRINTER_INFO_4A structure at:  lpbPrinters[dwNextStructPos]
+ *    for printer PrinterNameKey.
+ *    Note that there is no check whether the information really fits!
+ *
+ * RETURNS
+ *    FALSE if there is still space left in the buffer.
+ *
+ * BUGS:
+ *    This function should not exist in Win95 mode, but does anyway.
+ */
+BOOL ENUMPRINTERS_AddInfo4A(
+                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
+                   LPBYTE lpbPrinters,   /* buffer which receives info*/
+                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
+                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
+				   DWORD  dwBufSize,        /* max size of buffer in bytes */
+                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
+){                   
+ HKEY  hPrinterSettings;
+ LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
+  										   	   strlen(lpszPrinterName)+2);
+ LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
+ 
+ /* open the registry to find the attributes of the printer */
+ if (lpszPrinterSettings!=NULL)
+ 	{
+     strcpy(lpszPrinterSettings,Printers);
+     strcat(lpszPrinterSettings,lpszPrinterName);
+    }
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
+ 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
+	{
+     WARN("The registry did not contain my printer anymore?\n");
+    }
+ else
+    {
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Name", &(lpPInfo4->pPrinterName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
+     if (bCalcSpaceOnly==FALSE)	                     
+	 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
+    }
+ if (lpszPrinterSettings)
+	 free(lpszPrinterSettings);
+
+ return(bCalcSpaceOnly);     
+}
+
+/******************************************************************
+ *              ENUMPRINTERS_AddInfo5A        internal
+ *
+ *    Creates a PRINTER_INFO_5A structure at:  lpbPrinters[dwNextStructPos]
+ *    for printer PrinterNameKey.
+ *    Settings are read from the registry.
+ *    Note that there is no check whether the information really fits!
+ * RETURNS
+ *    FALSE if there is still space left in the buffer.
+ */
+BOOL ENUMPRINTERS_AddInfo5A(
+                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
+                   LPBYTE lpbPrinters,   /* buffer which receives info*/
+                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
+                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
+				   DWORD  dwBufSize,        /* max size of buffer in bytes */
+                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
+){                   
+ HKEY  hPrinterSettings;
+ LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
+  										   	   strlen(lpszPrinterName)+2);
+ LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
+
+ /* open the registry to find the attributes, etc of the printer */
+ if (lpszPrinterSettings!=NULL)
+ 	{
+     strcpy(lpszPrinterSettings,Printers);
+     strcat(lpszPrinterSettings,lpszPrinterName);
+    }
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
+ 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
+	{
+     WARN("The registry did not contain my printer anymore?\n");
+    }
+ else
+    {
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Name", &(lpPInfo5->pPrinterName), 
+                                  lpbPrinters, dwNextStringPos, 
+                                  dwBufSize, bCalcSpaceOnly);
+     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
+     			                  "Port", &(lpPInfo5->pPortName), lpbPrinters,
+                                  dwNextStringPos, dwBufSize, bCalcSpaceOnly);
+     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
+     if (bCalcSpaceOnly == FALSE)
+   	   {
+	 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
+	 lpPInfo5->DeviceNotSelectedTimeOut 
+     					  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"txTimeout"); 
+	 lpPInfo5->TransmissionRetryTimeout
+     					  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
+     								"dnsTimeout"); 
+    }
+    }
+    
+ if (lpszPrinterSettings)
+	 free(lpszPrinterSettings);
+
+ return(bCalcSpaceOnly);     
+}
+
+
+/******************************************************************
+ *              EnumPrintersA        [WINSPOOL.174]
+ *
+ *    Enumerates the available printers, print servers and print
+ *    providers, depending on the specified flags, name and level.
+ *
+ * RETURNS:
+ *
+ *    If level is set to 1:
+ *      Not implemented yet! 
+ *      Returns TRUE with an empty list.
+ *
+ *    If level is set to 2:
+ *		Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
+ *      Returns an array of PRINTER_INFO_2 data structures in the 
+ *      lpbPrinters buffer. Note that according to MSDN also an 
+ *      OpenPrinter should be performed on every remote printer.
+ *
+ *    If level is set to 4 (officially WinNT only):
+ *		Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
+ *      Fast: Only the registry is queried to retrieve printer names,
+ *      no connection to the driver is made.
+ *      Returns an array of PRINTER_INFO_4 data structures in the 
+ *      lpbPrinters buffer.
+ *
+ *    If level is set to 5 (officially WinNT4/Win9x only):
+ *      Fast: Only the registry is queried to retrieve printer names,
+ *      no connection to the driver is made.
+ *      Returns an array of PRINTER_INFO_5 data structures in the 
+ *      lpbPrinters buffer.
+ *
+ *    If level set to 3 or 6+:
+ *	    returns zero (faillure!)
+ *      
+ *    Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
+ *    for information.
+ *
+ * BUGS:
+ *    - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
+ *    - Only levels 2, 4 and 5 are implemented at the moment.
+ *    - 16-bit printer drivers are not enumerated.
+ *    - Returned amount of bytes used/needed does not match the real Windoze 
+ *      implementation (as in this implementation, all strings are part 
+ *      of the buffer, whereas Win32 keeps them somewhere else)
+ *    - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
+ *
+ * NOTE:
+ *    - In a regular Wine installation, no registry settings for printers
+ *      exist, which makes this function return an empty list.
+ */
+BOOL  WINAPI EnumPrintersA(
+					DWORD dwType,      /* Types of print objects to enumerate */
+                    LPSTR lpszName,    /* name of objects to enumerate */
+			        DWORD dwLevel,     /* type of printer info structure */
+                    LPBYTE lpbPrinters,/* buffer which receives info*/
+			        DWORD cbBuf,       /* max size of buffer in bytes */
+                    LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */
+			        LPDWORD lpdwReturned/* number of entries returned */
+                   )
+{
+ HKEY  hPrinterListKey;
+ DWORD dwIndex=0;
+ char  PrinterName[255];
+ DWORD PrinterNameLength=255;
+ FILETIME FileTime;
+ DWORD dwNextStringPos;	  /* position of next space for a string in the buffer*/
+ DWORD dwStructPrinterInfoSize;	/* size of a Printer_Info_X structure */
+ BOOL  bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/
+ 
+ TRACE("entered.\n");
+
+ /* test whether we're requested to really fill in. If so,
+  * zero out the data area, and initialise some returns to zero,
+  * to prevent problems 
+  */
+ if (lpbPrinters==NULL || cbBuf==0)
+ 	 bCalcSpaceOnly=TRUE;
+ else
+ {
+  int i;
+  for (i=0; i<cbBuf; i++)
+  	  lpbPrinters[i]=0;
+ }
+ *lpdwReturned=0;
+ *lpdwNeeded = 0;
+
+ /* check for valid Flags */
+ if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME)
+ 	{
+     SetLastError(ERROR_INVALID_FLAGS);
+     return(0);
+    }
+ switch(dwLevel)
+ 	{
+     case 1:
+	     return(TRUE);
+     case 2:
+     case 4:
+     case 5:
+     	 break;
+     default:
+     SetLastError(ERROR_INVALID_PARAMETER);
+	     return(FALSE);
+    } 	
+
+ /* Enter critical section to prevent AddPrinters() et al. to
+  * modify whilst we're reading in the registry
+ */
+ InitializeCriticalSection(&PRINT32_RegistryBlocker);
+ EnterCriticalSection(&PRINT32_RegistryBlocker);
+ 
+ /* get a pointer to a list of all printer names in the registry */ 
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
+ 				  &hPrinterListKey) !=ERROR_SUCCESS)
+ 	{
+     /* Oh no! An empty list of printers!
+      * (which is a valid configuration anyway)
+      */
+     TRACE("No entries in the Printers part of the registry\n");
+    }
+
+ /* count the number of entries and check if it fits in the buffer
+  */
+ while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
+                   NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
+    {
+     PrinterNameLength=255;
+     dwIndex++;
+    }
+ *lpdwReturned = dwIndex;    
+ switch(dwLevel)
+ 	{
+     case 1:
+     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
+      	break;
+     case 2:
+     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
+      	break;     
+     case 4:
+     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
+      	break;
+     case 5:
+     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
+      	break;
+     default:
+     	dwStructPrinterInfoSize = 0;
+      	break;     
+    } 
+ if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
+ 	bCalcSpaceOnly = TRUE;
+    
+ /* the strings which contain e.g. PrinterName, PortName, etc,
+  * are also stored in lpbPrinters, but after the regular structs.
+  * dwNextStringPos will always point to the next free place for a 
+  * string.
+  */  
+ dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;    
+
+ /* check each entry: if OK, add to list in corresponding INFO .
+  */    
+ for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
+    {
+     PrinterNameLength=255;
+     if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
+                   NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
+     	break;	/* exit for loop*/
+        
+     /* check whether this printer is allowed in the list
+      * by comparing name to lpszName 
+      */
+     if (dwType == PRINTER_ENUM_NAME)
+        if (strcmp(PrinterName,lpszName)!=0)
+        	continue;		
+
+     switch(dwLevel)
+     	{
+         case 1:
+         	/* FIXME: unimplemented */
+            break;
+         case 2:
+            bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
+            					dwIndex*dwStructPrinterInfoSize,
+                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
+            break;
+         case 4:
+            bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
+            					dwIndex*dwStructPrinterInfoSize,
+                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
+            break;
+         case 5:
+            bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
+            					dwIndex*dwStructPrinterInfoSize,
+                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
+            break;
+        }     	
+    }
+ RegCloseKey(hPrinterListKey);
+ *lpdwNeeded = dwNextStringPos;
+ 
+ if (bCalcSpaceOnly==TRUE)
+ 	{
+    if  (lpbPrinters!=NULL)
+ 		{
+	  int i;
+	  for (i=0; i<cbBuf; i++)
+	  	  lpbPrinters[i]=0;
+	    } 
+     *lpdwReturned=0;    
+    } 
+ LeaveCriticalSection(&PRINT32_RegistryBlocker); 
+ return(TRUE);
+}
+
+/******************************************************************
+ *              EnumPrinters32W        [WINSPOOL.175]
+ *
+ */
+BOOL  WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
+			       DWORD dwLevel, LPBYTE lpbPrinters,
+			       DWORD cbBuf, LPDWORD lpdwNeeded,
+			       LPDWORD lpdwReturned)
+{
+    FIXME("Nearly empty stub\n");
+    *lpdwReturned=0;
+    *lpdwNeeded = 0;
+    return TRUE;
+}
+
+/******************************************************************
+ *              AddMonitor32A        [WINSPOOL.107]
+ *
+ */
+BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
+{
+    FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/******************************************************************
+ *              DeletePrinterDriver32A        [WINSPOOL.146]
+ *
+ */
+BOOL WINAPI
+DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
+{
+    FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
+          debugstr_a(pDriverName));
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+/******************************************************************
+ *              DeleteMonitor32A        [WINSPOOL.135]
+ *
+ */
+BOOL WINAPI
+DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
+{
+    FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
+          debugstr_a(pMonitorName));
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
+/******************************************************************
+ *              DeletePort32A        [WINSPOOL.137]
+ *
+ */
+BOOL WINAPI
+DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
+{
+    FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
+          debugstr_a(pPortName));
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/******************************************************************************
+ *    SetPrinter32W  [WINSPOOL.214]
+ */
+BOOL WINAPI
+SetPrinterW(
+  HANDLE  hPrinter,
+  DWORD     Level,
+  LPBYTE    pPrinter,
+  DWORD     Command) {
+
+       FIXME("():stub\n");
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
+}
+
+/******************************************************************************
+ *    WritePrinter32  [WINSPOOL.223]
+ */
+BOOL WINAPI
+WritePrinter( 
+  HANDLE  hPrinter,
+  LPVOID  pBuf,
+  DWORD   cbBuf,
+  LPDWORD pcWritten) {
+
+       FIXME("():stub\n");
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       return FALSE;
+}
+
+/*****************************************************************************
+ *          AddForm32A  [WINSPOOL.103]
+ */
+BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
+{
+    FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
+    return 1;
+}
+
+/*****************************************************************************
+ *          AddForm32W  [WINSPOOL.104]
+ */
+BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
+{
+    FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
+    return 1;
+}
+
+/*****************************************************************************
+ *          AddJob32A  [WINSPOOL.105]
+ */
+BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
+                        DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
+          pcbNeeded);
+    return 1;
+}
+
+/*****************************************************************************
+ *          AddJob32W  [WINSPOOL.106]
+ */
+BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
+                        LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
+          pcbNeeded);
+    return 1;
+}
+
+/*****************************************************************************
+ *          AddPrinter32A  [WINSPOOL.117]
+ */
+HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
+{
+    FIXME("(%s,%ld,%p): stub\n", pName, Level, pPrinter);
+    return 0;
+}
+
+/*****************************************************************************
+ *          AddPrinter32W  [WINSPOOL.122]
+ */
+HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
+{
+    FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
+    return 0;
+}
+
+
+/*****************************************************************************
+ *          ClosePrinter32  [WINSPOOL.126]
+ */
+BOOL WINAPI ClosePrinter(HANDLE hPrinter)
+{
+    LPOPENEDPRINTERA lpOpenedPrinter;
+
+    if ((hPrinter != -1) && (hPrinter < NUM_PRINTER_MAX + 1))
+    {
+	lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
+	HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
+	lpOpenedPrinter->lpsPrinterName = NULL;
+	
+	/* Free the memory of lpDefault if it has been initialized*/
+	if(lpOpenedPrinter->lpDefault != NULL)
+	{
+	    HeapFree(GetProcessHeap(), 0,
+		     lpOpenedPrinter->lpDefault->pDevMode);
+	    HeapFree(GetProcessHeap(), 0,
+		     lpOpenedPrinter->lpDefault->pDatatype);
+	    HeapFree(GetProcessHeap(), 0,
+		     lpOpenedPrinter->lpDefault);
+	    lpOpenedPrinter->lpDefault = NULL;
+	}
+	
+	lpOpenedPrinter->hPrinter = -1;
+	
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          DeleteForm32A  [WINSPOOL.133]
+ */
+BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
+{
+    FIXME("(%d,%s): stub\n", hPrinter, pFormName);
+    return 1;
+}
+
+/*****************************************************************************
+ *          DeleteForm32W  [WINSPOOL.134]
+ */
+BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
+{
+    FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
+    return 1;
+}
+
+/*****************************************************************************
+ *          DeletePrinter32  [WINSPOOL.143]
+ */
+BOOL WINAPI DeletePrinter(HANDLE hPrinter)
+{
+    FIXME("(%d): stub\n", hPrinter);
+    return 1;
+}
+
+/*****************************************************************************
+ *          SetPrinter32A  [WINSPOOL.211]
+ */
+BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
+                           DWORD Command)
+{
+    FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          SetJob32A  [WINSPOOL.209]
+ */
+BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
+                       LPBYTE pJob, DWORD Command)
+{
+    FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
+         Command);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          SetJob32W  [WINSPOOL.210]
+ */
+BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
+                       LPBYTE pJob, DWORD Command)
+{
+    FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
+         Command);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          GetForm32A  [WINSPOOL.181]
+ */
+BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
+                 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
+         Level,pForm,cbBuf,pcbNeeded); 
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          GetForm32W  [WINSPOOL.182]
+ */
+BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
+                 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
+	  debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          SetForm32A  [WINSPOOL.207]
+ */
+BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
+                        LPBYTE pForm)
+{
+    FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          SetForm32W  [WINSPOOL.208]
+ */
+BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
+                        LPBYTE pForm)
+{
+    FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          ReadPrinter32  [WINSPOOL.202]
+ */
+BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
+                           LPDWORD pNoBytesRead)
+{
+    FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          ResetPrinter32A  [WINSPOOL.203]
+ */
+BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
+{
+    FIXME("(%d, %p): stub\n", hPrinter, pDefault);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          ResetPrinter32W  [WINSPOOL.204]
+ */
+BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
+{
+    FIXME("(%d, %p): stub\n", hPrinter, pDefault);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          GetPrinter32A  [WINSPOOL.187]
+ */
+BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
+			DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
+		  cbBuf, pcbNeeded);
+
+    *pcbNeeded = sizeof(PRINTER_INFO_2A);
+
+    if(cbBuf < *pcbNeeded) {
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+	return FALSE;
+    }
+    memset(pPrinter, 0, cbBuf);
+
+    return TRUE;
+}
+
+/*****************************************************************************
+ *          GetPrinter32W  [WINSPOOL.194]
+ */
+BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
+                    DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
+          cbBuf, pcbNeeded);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          GetPrinterDriver32A  [WINSPOOL.190]
+ */
+BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
+                                 DWORD Level, LPBYTE pDriverInfo,
+                                 DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
+         Level,pDriverInfo,cbBuf, pcbNeeded);
+    return FALSE;
+}
+
+/*****************************************************************************
+ *          GetPrinterDriver32W  [WINSPOOL.193]
+ */
+BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
+                                  DWORD Level, LPBYTE pDriverInfo, 
+                                  DWORD cbBuf, LPDWORD pcbNeeded)
+{
+    FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
+          Level,pDriverInfo,cbBuf, pcbNeeded);
+    return FALSE;
+}
+/*****************************************************************************
+ *          AddPrinterDriver32A  [WINSPOOL.120]
+ */
+BOOL WINAPI AddPrinterDriverA(LPSTR printerName,DWORD level, 
+				   LPBYTE pDriverInfo)
+{
+    FIXME("(%s,%ld,%p): stub\n",printerName,level,pDriverInfo);
+    return FALSE;
+}
+/*****************************************************************************
+ *          AddPrinterDriver32W  [WINSPOOL.121]
+ */
+BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level, 
+				   LPBYTE pDriverInfo)
+{
+    FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
+	  level,pDriverInfo);
+    return FALSE;
+}
+
+
+/*****************************************************************************
+ *          PrinterProperties  [WINSPOOL.201]
+ *
+ *     Displays a dialog to set the properties of the printer.
+ *
+ * RETURNS 
+ *     nonzero on succes or zero on faillure
+ *
+ * BUGS
+ *	   implemented as stub only
+ */
+BOOL WINAPI PrinterProperties(HWND hWnd,      /* handle to parent window */
+                              HANDLE hPrinter /* handle to printer object */
+){
+    FIXME("(%d,%d): stub\n", hWnd, hPrinter);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+
diff --git a/graphics/driver.c b/graphics/driver.c
index c5ab9a19e9..e0d9f78047 100644
--- a/graphics/driver.c
+++ b/graphics/driver.c
@@ -9,8 +9,7 @@
 #include "heap.h"
 #include "debugtools.h"
 
-DECLARE_DEBUG_CHANNEL(driver)
-DECLARE_DEBUG_CHANNEL(gdi)
+DEFAULT_DEBUG_CHANNEL(driver)
 
 typedef struct tagGRAPHICS_DRIVER
 {
@@ -40,7 +39,7 @@ BOOL DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs )
     /* No name -> it's the generic driver */
     if (genericDriver)
     {
-        WARN_(driver)(" already a generic driver\n" );
+        WARN(" already a generic driver\n" );
         HeapFree( SystemHeap, 0, driver );
         return FALSE;
     }
@@ -57,6 +56,7 @@ const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name )
 {
     GRAPHICS_DRIVER *driver = firstDriver;
 
+    TRACE(": %s\n", name);
     while (driver && name)
     {
         if (!strcasecmp( driver->name, name )) return driver->funcs;
@@ -97,8 +97,23 @@ BOOL DRIVER_UnregisterDriver( LPCSTR name )
     }
 }
 
+/*****************************************************************************
+ *      DRIVER_GetDriverName
+ *
+ */
+BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size )
+{
+    char *p;
+    size = GetProfileStringA("devices", device, "", driver, size);
+    if(!size) return FALSE;
 
-
+    p = strchr(driver, ',');
+    if(!p) return FALSE;
+    *p = '\0';
+    TRACE("Found '%s' for '%s'\n", driver, device);
+    return TRUE;
+}
+    
 /*****************************************************************************
  *      GDI_CallDevInstall16   [GDI32.100]
  *
@@ -107,8 +122,8 @@ BOOL DRIVER_UnregisterDriver( LPCSTR name )
 INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd, 
                                  LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort )
 {
-    FIXME_(gdi)("(%p, %04x, %s, %s, %s)\n", 
-                lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
+    FIXME("(%p, %04x, %s, %s, %s)\n", 
+	  lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
     return -1;
 }
 
@@ -132,8 +147,8 @@ INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd,
 INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice, 
                                              LPCSTR lpszPort, LPVOID lpPropSheet )
 {
-    FIXME_(gdi)("(%04x, %s, %s, %p)\n", 
-                hWnd, lpszDevice, lpszPort, lpPropSheet );
+    FIXME("(%04x, %s, %s, %p)\n", 
+      hWnd, lpszDevice, lpszPort, lpPropSheet );
     return -1;
 }
 
@@ -144,14 +159,22 @@ INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice,
  * ExtDeviceMode proc.
  */
 INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd, 
-                                    LPDEVMODE16 lpdmOutput, LPSTR lpszDevice, 
-                                    LPSTR lpszPort, LPDEVMODE16 lpdmInput, 
+                                    LPDEVMODEA lpdmOutput, LPSTR lpszDevice, 
+                                    LPSTR lpszPort, LPDEVMODEA lpdmInput, 
                                     LPSTR lpszProfile, DWORD fwMode )
 {
-    FIXME_(gdi)("(%04x, %p, %s, %s, %p, %s, %ld)\n", 
-                hwnd, lpdmOutput, lpszDevice, lpszPort, 
-                lpdmInput, lpszProfile, fwMode );
-    return -1;
+    char buf[300];
+    const DC_FUNCTIONS *funcs;
+
+    TRACE("(%04x, %p, %s, %s, %p, %s, %ld)\n", 
+	  hwnd, lpdmOutput, lpszDevice, lpszPort, 
+	  lpdmInput, lpszProfile, fwMode );
+
+    if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
+    funcs = DRIVER_FindDriver( buf );
+    if(!funcs || !funcs->pExtDeviceMode) return -1;
+    return funcs->pExtDeviceMode(hwnd, lpdmOutput, lpszDevice, lpszPort,
+				 lpdmInput, lpszProfile, fwMode);
 }
 
 /****************************************************************************
@@ -161,10 +184,10 @@ INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd,
  * AdvancedSetupDialog proc.
  */
 INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
-                                          LPDEVMODE16 devin, LPDEVMODE16 devout )
+                                          LPDEVMODEA devin, LPDEVMODEA devout )
 {
-    FIXME_(gdi)("(%04x, %s, %p, %p)\n", 
-                hwnd, lpszDevice, devin, devout );
+    TRACE("(%04x, %s, %p, %p)\n", 
+	  hwnd, lpszDevice, devin, devout );
     return -1;
 }
 
@@ -174,12 +197,22 @@ INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
  * This should load the correct driver for lpszDevice and calls this driver's
  * DeviceCapabilities proc.
  */
-DWORD WINAPI GDI_CallDeviceCapabilities16( LPSTR lpszDevice, LPSTR lpszPort,
-                                           DWORD fwCapability, LPSTR lpszOutput, 
-                                           LPDEVMODE16 lpdm )
+DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort,
+                                           WORD fwCapability, LPSTR lpszOutput,
+                                           LPDEVMODEA lpdm )
 {
-    FIXME_(gdi)("(%s, %s, %ld, %p, %p)\n", 
-                lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );
-    return -1L;
+    char buf[300];
+    const DC_FUNCTIONS *funcs;
+
+    TRACE("(%s, %s, %d, %p, %p)\n", 
+	  lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );
+
+
+    if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
+    funcs = DRIVER_FindDriver( buf );
+    if(!funcs || !funcs->pDeviceCapabilities) return -1;
+    return funcs->pDeviceCapabilities( lpszDevice, lpszPort, fwCapability,
+				       lpszOutput, lpdm);
 }
 
+
diff --git a/graphics/enhmetafiledrv/init.c b/graphics/enhmetafiledrv/init.c
index 083c2f32fc..51c7670daf 100644
--- a/graphics/enhmetafiledrv/init.c
+++ b/graphics/enhmetafiledrv/init.c
@@ -20,20 +20,25 @@ DEFAULT_DEBUG_CHANNEL(enhmetafile)
 
 static const DC_FUNCTIONS EMFDRV_Funcs =
 {
+    NULL,                            /* pAbortDoc */
     EMFDRV_Arc,                      /* pArc */
     NULL,                            /* pBitBlt */
     NULL,                            /* pBitmapBits */	
     EMFDRV_Chord,                    /* pChord */
     NULL,                            /* pCreateBitmap */
     NULL, /* no implementation */    /* pCreateDC */
-    NULL, /* no implementation */    /* pDeleteDC */
     NULL,                            /* pCreateDIBSection */
     NULL,                            /* pCreateDIBSection16 */
+    NULL, /* no implementation */    /* pDeleteDC */
     NULL,                            /* pDeleteObject */
+    NULL,                            /* pDeviceCapabilities */
     EMFDRV_Ellipse,                  /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
     NULL,                            /* pEnumDeviceFonts */
     NULL,                            /* pEscape */
     EMFDRV_ExcludeClipRect,          /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
     EMFDRV_ExtFloodFill,             /* pExtFloodFill */
     NULL,                            /* pExtTextOut */
     EMFDRV_FillRgn,                  /* pFillRgn */
@@ -87,6 +92,8 @@ static const DC_FUNCTIONS EMFDRV_Funcs =
     EMFDRV_SetViewportOrg,           /* pSetViewportOrg */
     EMFDRV_SetWindowExt,             /* pSetWindowExt */
     EMFDRV_SetWindowOrg,             /* pSetWindowOrg */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
     NULL,                            /* pStretchBlt */
     NULL                             /* pStretchDIBits */
 };
diff --git a/graphics/env.c b/graphics/env.c
index 024721a0bd..26f8e095bb 100644
--- a/graphics/env.c
+++ b/graphics/env.c
@@ -75,7 +75,7 @@ static ATOM PortNameToAtom(LPCSTR lpPortName, BOOL16 add)
 /***********************************************************************
  *           GetEnvironment   (GDI.134)
  */
-INT16 WINAPI GetEnvironment16(LPCSTR lpPortName, LPDEVMODE16 lpdev, UINT16 nMaxSize)
+INT16 WINAPI GetEnvironment16(LPCSTR lpPortName, LPDEVMODEA lpdev, UINT16 nMaxSize)
 {
     ATOM atom;
     LPCSTR p;
@@ -104,7 +104,7 @@ INT16 WINAPI GetEnvironment16(LPCSTR lpPortName, LPDEVMODE16 lpdev, UINT16 nMaxS
 /***********************************************************************
  *          SetEnvironment   (GDI.132)
  */
-INT16 WINAPI SetEnvironment16(LPCSTR lpPortName, LPDEVMODE16 lpdev, UINT16 nCount)
+INT16 WINAPI SetEnvironment16(LPCSTR lpPortName, LPDEVMODEA lpdev, UINT16 nCount)
 {
     ATOM atom; 
     BOOL16 nullport = FALSE;
diff --git a/graphics/escape.c b/graphics/escape.c
index 06e511ac5f..2281ca3dd0 100644
--- a/graphics/escape.c
+++ b/graphics/escape.c
@@ -34,13 +34,16 @@ INT WINAPI Escape( HDC hdc, INT nEscape, INT cbInput,
     segin	= (SEGPTR)lpszInData;
     segout	= (SEGPTR)lpvOutData;
     switch (nEscape) {
-    	/* Escape(hdc,QUERYESCSUPPORT,LPINT32,NULL) */
-    case QUERYESCSUPPORT: {
+    	/* Escape(hdc,QUERYESCSUPPORT,LPINT,NULL) */
+        /* Escape(hdc,EXT_DEVICE_CAPS,LPINT,NULL) */
+    case QUERYESCSUPPORT:
+    case EXT_DEVICE_CAPS:
+      {
     	LPINT16 x = (LPINT16)SEGPTR_NEW(INT16);
 	*x = *(INT*)lpszInData;
 	segin = SEGPTR_GET(x);
 	break;
-    }
+      }
 
     	/* Escape(hdc,GETSCALINGFACTOR,NULL,LPPOINT32) */
     	/* Escape(hdc,GETPHYSPAGESIZE,NULL,LPPOINT32) */
@@ -101,6 +104,9 @@ INT WINAPI Escape( HDC hdc, INT nEscape, INT cbInput,
 		TRACE("target DC implements Escape %d\n",nEscape);
     	SEGPTR_FREE(PTR_SEG_TO_LIN(segin));
 	break;
+    case EXT_DEVICE_CAPS:
+        SEGPTR_FREE(PTR_SEG_TO_LIN(segin));
+	break;
     case GETSCALINGFACTOR:
     case GETPRINTINGOFFSET:
     case GETPHYSPAGESIZE: {
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index ce880ce805..21f60a85c3 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -19,20 +19,25 @@ DEFAULT_DEBUG_CHANNEL(metafile)
 
 static const DC_FUNCTIONS MFDRV_Funcs =
 {
+    NULL,                            /* pAbortDoc */
     MFDRV_Arc,                       /* pArc */
     MFDRV_BitBlt,                    /* pBitBlt */
     NULL,                            /* pBitmapBits */	
     MFDRV_Chord,                     /* pChord */
     NULL,                            /* pCreateBitmap */
     NULL, /* no implementation */    /* pCreateDC */
-    NULL, /* no implementation */    /* pDeleteDC */
     NULL,                            /* pCreateDIBSection */
     NULL,                            /* pCreateDIBSection16 */
+    NULL, /* no implementation */    /* pDeleteDC */
     NULL,                            /* pDeleteObject */
+    NULL,                            /* pDeviceCapabilities */
     MFDRV_Ellipse,                   /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
     NULL,                            /* pEnumDeviceFonts */
     NULL,                            /* pEscape */
     MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
     MFDRV_ExtFloodFill,              /* pExtFloodFill */
     MFDRV_ExtTextOut,                /* pExtTextOut */
     MFDRV_FillRgn,                   /* pFillRgn */
@@ -86,6 +91,8 @@ static const DC_FUNCTIONS MFDRV_Funcs =
     MFDRV_SetViewportOrg,            /* pSetViewportOrg */
     MFDRV_SetWindowExt,              /* pSetWindowExt */
     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
     MFDRV_StretchBlt,                /* pStretchBlt */
     MFDRV_StretchDIBits              /* pStretchDIBits */
 };
diff --git a/graphics/psdrv/driver.c b/graphics/psdrv/driver.c
index a9315a9483..3134df28ff 100644
--- a/graphics/psdrv/driver.c
+++ b/graphics/psdrv/driver.c
@@ -11,15 +11,13 @@
 
 #include <string.h>
 #include "psdrv.h"
-#include "debug.h"
+#include "debugtools.h"
 #include "resource.h"
 #include "winuser.h"
 #include "winspool.h"
 
 DEFAULT_DEBUG_CHANNEL(psdrv)
 
-static LONG Resolutions[][2] = { {600,600} };
-
 
 /************************************************************************
  *
@@ -28,35 +26,62 @@ static LONG Resolutions[][2] = { {600,600} };
  * Updates dm1 with some fields from dm2
  *
  */
-void PSDRV_MergeDevmodes(PSDRV_DEVMODE16 *dm1, PSDRV_DEVMODE16 *dm2,
+void PSDRV_MergeDevmodes(PSDRV_DEVMODEA *dm1, PSDRV_DEVMODEA *dm2,
 			 PRINTERINFO *pi)
 {
     /* some sanity checks here on dm2 */
+
     if(dm2->dmPublic.dmFields & DM_ORIENTATION)
-        dm1->dmPublic.dmOrientation = dm2->dmPublic.dmOrientation;
-	    /* NB PaperWidth is always < PaperLength */
-        
+        dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
+
+    /* NB PaperWidth is always < PaperLength */
+
     if(dm2->dmPublic.dmFields & DM_PAPERSIZE) {
         PAGESIZE *page;
 
 	for(page = pi->ppd->PageSizes; page; page = page->next) {
-	    if(page->WinPage == dm2->dmPublic.dmPaperSize)
+	    if(page->WinPage == dm2->dmPublic.u1.s1.dmPaperSize)
 	        break;
 	}
 	if(page) {
-	    dm1->dmPublic.dmPaperSize = dm2->dmPublic.dmPaperSize;
-	    dm1->dmPublic.dmPaperWidth = page->PaperDimension->x * 
+	    dm1->dmPublic.u1.s1.dmPaperSize = dm2->dmPublic.u1.s1.dmPaperSize;
+	    dm1->dmPublic.u1.s1.dmPaperWidth = page->PaperDimension->x * 
 								254.0 / 72.0;
-	    dm1->dmPublic.dmPaperLength = page->PaperDimension->y *
+	    dm1->dmPublic.u1.s1.dmPaperLength = page->PaperDimension->y *
 								254.0 / 72.0;
-	    TRACE(psdrv, "Changing page to %s %d x %d\n", page->FullName,
-		     dm1->dmPublic.dmPaperWidth, dm1->dmPublic.dmPaperLength );
+	    TRACE("Changing page to %s %d x %d\n", page->FullName,
+		  dm1->dmPublic.u1.s1.dmPaperWidth,
+		  dm1->dmPublic.u1.s1.dmPaperLength );
 	} else {
-	    TRACE(psdrv, "Trying to change to unsupported pagesize %d\n",
-		      dm2->dmPublic.dmPaperSize);
+	    TRACE("Trying to change to unsupported pagesize %d\n",
+		      dm2->dmPublic.u1.s1.dmPaperSize);
 	}
     }
 
+    if(dm2->dmPublic.dmFields & DM_PAPERLENGTH) {
+        dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength; 
+	TRACE("Changing PaperLength to %d\n",
+	      dm2->dmPublic.u1.s1.dmPaperLength);
+	FIXME("Changing PaperLength.  Do we adjust PaperSize?\n");
+    }
+
+    if(dm2->dmPublic.dmFields & DM_PAPERWIDTH) {
+        dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth; 
+	TRACE("Changing PaperWidth to %d\n",
+	      dm2->dmPublic.u1.s1.dmPaperWidth);
+	FIXME("Changing PaperWidth.  Do we adjust PaperSize?\n");
+    }
+
+    if(dm2->dmPublic.dmFields & DM_SCALE) {
+        dm1->dmPublic.dmScale = dm2->dmPublic.dmScale;
+	TRACE("Changing Scale to %d\n", dm2->dmPublic.dmScale);
+    }
+
+    if(dm2->dmPublic.dmFields & DM_COPIES) {
+        dm1->dmPublic.dmCopies = dm2->dmPublic.dmCopies;
+	TRACE("Changing Copies to %d\n", dm2->dmPublic.dmCopies);
+    }
+
     if(dm2->dmPublic.dmFields & DM_DEFAULTSOURCE) {
         INPUTSLOT *slot;
 	
@@ -66,14 +91,55 @@ void PSDRV_MergeDevmodes(PSDRV_DEVMODE16 *dm1, PSDRV_DEVMODE16 *dm2,
 	}
 	if(slot) {
 	    dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
-	    TRACE(psdrv, "Changing bin to '%s'\n", slot->FullName);
+	    TRACE("Changing bin to '%s'\n", slot->FullName);
 	} else {
-	  TRACE(psdrv, "Trying to change to unsupported bin %d\n",
+	  TRACE("Trying to change to unsupported bin %d\n",
 		dm2->dmPublic.dmDefaultSource);
 	}
     }
 
-    /* etc */
+   if (dm2->dmPublic.dmFields & DM_DEFAULTSOURCE )
+       dm1->dmPublic.dmDefaultSource = dm2->dmPublic.dmDefaultSource;
+   if (dm2->dmPublic.dmFields & DM_PRINTQUALITY )
+       dm1->dmPublic.dmPrintQuality = dm2->dmPublic.dmPrintQuality;
+   if (dm2->dmPublic.dmFields & DM_COLOR )
+       dm1->dmPublic.dmColor = dm2->dmPublic.dmColor;
+   if (dm2->dmPublic.dmFields & DM_DUPLEX )
+       dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex;
+   if (dm2->dmPublic.dmFields & DM_YRESOLUTION )
+       dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution;
+   if (dm2->dmPublic.dmFields & DM_TTOPTION )
+       dm1->dmPublic.dmTTOption = dm2->dmPublic.dmTTOption;
+   if (dm2->dmPublic.dmFields & DM_COLLATE )
+       dm1->dmPublic.dmCollate = dm2->dmPublic.dmCollate;
+   if (dm2->dmPublic.dmFields & DM_FORMNAME )
+       strncpy(dm1->dmPublic.dmFormName, dm2->dmPublic.dmFormName, CCHFORMNAME);
+   if (dm2->dmPublic.dmFields & DM_BITSPERPEL )
+       dm1->dmPublic.dmBitsPerPel = dm2->dmPublic.dmBitsPerPel;
+   if (dm2->dmPublic.dmFields & DM_PELSWIDTH )
+       dm1->dmPublic.dmPelsWidth = dm2->dmPublic.dmPelsWidth;
+   if (dm2->dmPublic.dmFields & DM_PELSHEIGHT )
+       dm1->dmPublic.dmPelsHeight = dm2->dmPublic.dmPelsHeight;
+   if (dm2->dmPublic.dmFields & DM_DISPLAYFLAGS )
+       dm1->dmPublic.dmDisplayFlags = dm2->dmPublic.dmDisplayFlags;
+   if (dm2->dmPublic.dmFields & DM_DISPLAYFREQUENCY )
+       dm1->dmPublic.dmDisplayFrequency = dm2->dmPublic.dmDisplayFrequency;
+   if (dm2->dmPublic.dmFields & DM_POSITION )
+       dm1->dmPublic.u1.dmPosition = dm2->dmPublic.u1.dmPosition;
+   if (dm2->dmPublic.dmFields & DM_LOGPIXELS )
+       dm1->dmPublic.dmLogPixels = dm2->dmPublic.dmLogPixels;
+   if (dm2->dmPublic.dmFields & DM_ICMMETHOD )
+       dm1->dmPublic.dmICMMethod = dm2->dmPublic.dmICMMethod;
+   if (dm2->dmPublic.dmFields & DM_ICMINTENT )
+       dm1->dmPublic.dmICMIntent = dm2->dmPublic.dmICMIntent;
+   if (dm2->dmPublic.dmFields & DM_MEDIATYPE )
+       dm1->dmPublic.dmMediaType = dm2->dmPublic.dmMediaType;
+   if (dm2->dmPublic.dmFields & DM_DITHERTYPE )
+       dm1->dmPublic.dmDitherType = dm2->dmPublic.dmDitherType;
+   if (dm2->dmPublic.dmFields & DM_PANNINGWIDTH )
+       dm1->dmPublic.dmPanningWidth = dm2->dmPublic.dmPanningWidth;
+   if (dm2->dmPublic.dmFields & DM_PANNINGHEIGHT )
+       dm1->dmPublic.dmPanningHeight = dm2->dmPublic.dmPanningHeight;
 
     return;
 }
@@ -91,7 +157,7 @@ LRESULT WINAPI PSDRV_NewPrinterDlgProc(HWND hWnd, UINT wMsg,
 {
   switch (wMsg) {
   case WM_INITDIALOG:
-    TRACE(psdrv,"WM_INITDIALOG lParam=%08lX\n", lParam);
+    TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
     ShowWindow(hWnd, SW_SHOWNORMAL);
     return TRUE;
  
@@ -119,7 +185,7 @@ LRESULT WINAPI PSDRV_AdvancedSetupDlgProc(HWND hWnd, UINT wMsg,
 {
   switch (wMsg) {
   case WM_INITDIALOG:
-    TRACE(psdrv,"WM_INITDIALOG lParam=%08lX\n", lParam);
+    TRACE("WM_INITDIALOG lParam=%08lX\n", lParam);
     SendDlgItemMessageA(hWnd, 99, CB_ADDSTRING, 0, 
 			  (LPARAM)"Default Tray");
     ShowWindow(hWnd, SW_SHOWNORMAL);
@@ -157,10 +223,10 @@ LRESULT WINAPI PSDRV_AdvancedSetupDlgProc(HWND hWnd, UINT wMsg,
  *
  */
 WORD WINAPI PSDRV_AdvancedSetupDialog16(HWND16 hwnd, HANDLE16 hDriver,
-					 LPDEVMODE16 devin, LPDEVMODE16 devout)
+					 LPDEVMODEA devin, LPDEVMODEA devout)
 {
 
-  TRACE(psdrv, "hwnd = %04x, hDriver = %04x devin=%p devout=%p\n", hwnd,
+  TRACE("hwnd = %04x, hDriver = %04x devin=%p devout=%p\n", hwnd,
 	hDriver, devin, devout);
   return IDCANCEL;
 
@@ -181,46 +247,63 @@ WORD WINAPI PSDRV_AdvancedSetupDialog16(HWND16 hwnd, HANDLE16 hDriver,
  * Just returns default devmode at the moment
  */
 INT16 WINAPI PSDRV_ExtDeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
-LPDEVMODE16 lpdmOutput, LPSTR lpszDevice, LPSTR lpszPort,
-LPDEVMODE16 lpdmInput, LPSTR lpszProfile, WORD fwMode)
+				   LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
+				   LPSTR lpszPort, LPDEVMODEA lpdmInput,
+				   LPSTR lpszProfile, WORD fwMode)
 {
   PRINTERINFO *pi = PSDRV_FindPrinterInfo(lpszDevice);
 
-  TRACE(psdrv,
-"(hwnd=%04x, hDriver=%04x, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
+  TRACE("(hwnd=%04x, hDriver=%04x, devOut=%p, Device='%s', Port='%s', devIn=%p, Profile='%s', Mode=%04x)\n",
 hwnd, hDriver, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile,
 fwMode);
 
   if(!fwMode)
-    return sizeof(DEVMODE16); /* Just copy dmPublic bit of PSDRV_DEVMODE */
+    return sizeof(DEVMODEA); /* Just copy dmPublic bit of PSDRV_DEVMODE */
 
-  if((fwMode & DM_PROMPT) || (fwMode & DM_UPDATE))
-    FIXME(psdrv, "Mode %d not implemented\n", fwMode);
+  if(fwMode & DM_PROMPT)
+    FIXME("Mode DM_PROMPT not implemented\n");
+
+  if(fwMode & DM_UPDATE)
+    FIXME("Mode DM_UPDATE.  Just do the same as DM_COPY\n");
 
   if((fwMode & DM_MODIFY) && lpdmInput) {
-    TRACE(psdrv, "DM_MODIFY set. devIn->dmFields = %08lx\n", lpdmInput->dmFields);
-    PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODE16 *)lpdmInput, pi);
+    TRACE("DM_MODIFY set. devIn->dmFields = %08lx\n", lpdmInput->dmFields);
+    PSDRV_MergeDevmodes(pi->Devmode, (PSDRV_DEVMODEA *)lpdmInput, pi);
   }
 
-  if(fwMode & DM_COPY) {
-    memcpy(lpdmOutput, pi->Devmode, sizeof(DEVMODE16));
+  if((fwMode & DM_COPY) || (fwMode & DM_UPDATE)) {
+    memcpy(lpdmOutput, pi->Devmode, sizeof(DEVMODEA));
   }
   return IDOK;
 }
 
+/**************************************************************
+ *
+ *       PSDRV_ExtDeviceMode
+ */
+INT PSDRV_ExtDeviceMode(HWND hwnd, LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
+			LPSTR lpszPort, LPDEVMODEA lpdmInput,
+			LPSTR lpszProfile, DWORD dwMode)
+{
+    return PSDRV_ExtDeviceMode16(hwnd, 0, lpdmOutput, lpszDevice, lpszPort,
+				 lpdmInput, lpszProfile, dwMode);
+}
 
 /***************************************************************
  *
  *	PSDRV_DeviceCapabilities16	[WINEPS.91]
  *
  */
-DWORD WINAPI PSDRV_DeviceCapabilities16(LPSTR lpszDevice, LPSTR lpszPort,
-  WORD fwCapability, LPSTR lpszOutput, LPDEVMODE16 lpdm)
+DWORD WINAPI PSDRV_DeviceCapabilities16(LPCSTR lpszDevice, LPCSTR lpszPort,
+					WORD fwCapability, LPSTR lpszOutput,
+					LPDEVMODEA lpDevMode)
 {
   PRINTERINFO *pi;
-
+  DEVMODEA *lpdm;
   pi = PSDRV_FindPrinterInfo(lpszDevice);
-  TRACE(psdrv, "Cap=%d. Got PrinterInfo = %p\n", fwCapability, pi);
+  TRACE("Cap=%d. Got PrinterInfo = %p\n", fwCapability, pi);
+
+  lpdm = lpDevMode ? lpDevMode : (DEVMODEA *)pi->Devmode;
 
   switch(fwCapability) {
 
@@ -296,18 +379,120 @@ DWORD WINAPI PSDRV_DeviceCapabilities16(LPSTR lpszDevice, LPSTR lpszPort,
       return i;
     }
 
-  case DC_ENUMRESOLUTIONS:
-    if(lpszOutput != NULL)
-      memcpy(lpszOutput, Resolutions, sizeof(Resolutions));
-    return sizeof(Resolutions) / sizeof(Resolutions[0]);
+  case DC_BINADJUST:
+    FIXME("DC_BINADJUST: stub.\n");
+    return DCBA_FACEUPNONE;
 
+  case DC_ENUMRESOLUTIONS:
+    {
+      LONG *lp = (LONG*)lpszOutput;
+
+      if(lpszOutput != NULL) {
+	lp[0] = (LONG)pi->ppd->DefaultResolution;
+	lp[1] = (LONG)pi->ppd->DefaultResolution;
+      }
+      return 1;
+    }
+
+  case DC_COPIES:
+    FIXME("DC_COPIES: returning %d.  Is this correct?\n", lpdm->dmCopies);
+    return lpdm->dmCopies;
+
+  case DC_DRIVER:
+    return lpdm->dmDriverVersion;
+
+  case DC_DATATYPE_PRODUCED:
+    FIXME("DATA_TYPE_PRODUCED: stub.\n");
+    return -1; /* simulate that the driver supports 'RAW' */
+
+  case DC_DUPLEX:
+    FIXME("DC_DUPLEX: returning %d.  Is this correct?\n", lpdm->dmDuplex);
+    return lpdm->dmDuplex;
+
+  case DC_EMF_COMPLIANT:
+    FIXME("DC_EMF_COMPLIANT: stub.\n");
+    return -1; /* simulate that the driver do not support EMF */
+
+  case DC_EXTRA:
+    return lpdm->dmDriverExtra;
+
+  case DC_FIELDS:
+    return lpdm->dmFields;
+
+  case DC_FILEDEPENDENCIES:
+    FIXME("DC_FILEDEPENDENCIES: stub.\n");
+    return 0;
+
+  case DC_MAXEXTENT:
+    {
+      PAGESIZE *ps;
+      int i;
+      POINT ptMax;
+      ptMax.x = ptMax.y = 0;
+
+      if(lpszOutput == NULL)
+	return -1;
+ 
+      i = 0;
+      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
+	if(ps->PaperDimension->x > ptMax.x)
+	  ptMax.x = ps->PaperDimension->x;
+	if(ps->PaperDimension->y > ptMax.y)
+	  ptMax.y = ps->PaperDimension->y;
+      }
+      *((POINT*)lpszOutput) = ptMax;
+      return 1;
+    }
+
+  case DC_MINEXTENT:
+    {
+      PAGESIZE *ps;
+      int i;
+      POINT ptMax;
+      ptMax.x = ptMax.y = 0;
+
+      if(lpszOutput == NULL)
+	return -1;
+ 
+      i = 0;
+      for(ps = pi->ppd->PageSizes; ps; ps = ps->next, i++) {
+	if(ps->PaperDimension->x > ptMax.x)
+	  ptMax.x = ps->PaperDimension->x;
+	if(ps->PaperDimension->y > ptMax.y)
+	  ptMax.y = ps->PaperDimension->y;
+      }
+      *((POINT*)lpszOutput) = ptMax;
+      return 1;
+    }
+
+  case DC_SIZE:
+    return lpdm->dmSize;
+
+  case DC_TRUETYPE:
+    FIXME("DC_TRUETYPE: stub\n");
+    return DCTT_SUBDEV;
+
+  case DC_VERSION:
+    return lpdm->dmSpecVersion;
 
   default:
-    FIXME(psdrv, "Unsupported capability %d\n", fwCapability);
+    FIXME("Unsupported capability %d\n", fwCapability);
   }
   return -1;
 }
 
+/**************************************************************
+ *
+ *     PSDRV_DeviceCapabilities
+ */
+DWORD PSDRV_DeviceCapabilities(LPCSTR lpszDevice, LPCSTR lpszPort,
+			       WORD fwCapability, LPSTR lpszOutput,
+			       LPDEVMODEA lpdm)
+{
+  return PSDRV_DeviceCapabilities16(lpszDevice, lpszPort, fwCapability,
+				    lpszOutput, lpdm);
+}
+
 /***************************************************************
  *
  *	PSDRV_DeviceMode16	[WINEPS.13]
diff --git a/graphics/psdrv/init.c b/graphics/psdrv/init.c
index d72e502720..fbf111c1c7 100644
--- a/graphics/psdrv/init.c
+++ b/graphics/psdrv/init.c
@@ -17,25 +17,30 @@
 DEFAULT_DEBUG_CHANNEL(psdrv)
 
 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
-                               LPCSTR output, const DEVMODE16* initData );
+                               LPCSTR output, const DEVMODEA* initData );
 static BOOL PSDRV_DeleteDC( DC *dc );
 
 static const DC_FUNCTIONS PSDRV_Funcs =
 {
+    NULL,                            /* pAbortDoc */
     PSDRV_Arc,                       /* pArc */
     NULL,                            /* pBitBlt */
     NULL,                            /* pBitmapBits */
     PSDRV_Chord,                     /* pChord */
     NULL,                            /* pCreateBitmap */
     PSDRV_CreateDC,                  /* pCreateDC */
-    PSDRV_DeleteDC,                  /* pDeleteDC */
     NULL,                            /* pCreateDIBSection */
     NULL,                            /* pCreateDIBSection16 */
+    PSDRV_DeleteDC,                  /* pDeleteDC */
     NULL,                            /* pDeleteObject */
+    PSDRV_DeviceCapabilities,        /* pDeviceCapabilities */
     PSDRV_Ellipse,                   /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
     PSDRV_EnumDeviceFonts,           /* pEnumDeviceFonts */
     PSDRV_Escape,                    /* pEscape */
     NULL,                            /* pExcludeClipRect */
+    PSDRV_ExtDeviceMode,             /* pExtDeviceMode */
     NULL,                            /* pExtFloodFill */
     PSDRV_ExtTextOut,                /* pExtTextOut */
     NULL,                            /* pFillRgn */
@@ -89,6 +94,8 @@ static const DC_FUNCTIONS PSDRV_Funcs =
     NULL,                            /* pSetViewportOrg (optional) */
     NULL,                            /* pSetWindowExt (optional) */
     NULL,                            /* pSetWindowOrg (optional) */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
     NULL,                            /* pStretchBlt */
     PSDRV_StretchDIBits              /* pStretchDIBits */
 };
@@ -121,10 +128,9 @@ static DeviceCaps PSDRV_DevCaps = {
 			PC_INTERIORS,
 /* textCaps */		TC_CR_ANY, /* psdrv 0x59f7 */
 /* clipCaps */		CP_RECTANGLE,
-/* rasterCaps */	RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 |
-			RC_DI_BITMAP | RC_DIBTODEV | RC_BIGFONT |
-			RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS, 
-			/* psdrv 0x6e99 */
+/* rasterCaps */	RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT |
+			RC_DIBTODEV | RC_STRETCHBLT |
+			RC_STRETCHDIB, /* psdrv 0x6e99 */
 /* aspectX */		600,
 /* aspectY */		600,
 /* aspectXY */		848,
@@ -135,22 +141,26 @@ static DeviceCaps PSDRV_DevCaps = {
 /* palette size */	0,
 /* ..etc */		0, 0 };
 
-static PSDRV_DEVMODE16 DefaultDevmode = 
+static PSDRV_DEVMODEA DefaultDevmode = 
 {
   { /* dmPublic */
 /* dmDeviceName */	"Wine PostScript Driver",
 /* dmSpecVersion */	0x30a,
 /* dmDriverVersion */	0x001,
-/* dmSize */		sizeof(DEVMODE16),
+/* dmSize */		sizeof(DEVMODEA),
 /* dmDriverExtra */	0,
 /* dmFields */		DM_ORIENTATION | DM_PAPERSIZE | DM_PAPERLENGTH |
 			DM_PAPERWIDTH | DM_SCALE | DM_COPIES | 
 			DM_DEFAULTSOURCE | DM_COLOR | DM_DUPLEX | 
 			DM_YRESOLUTION | DM_TTOPTION,
+   { /* u1 */
+     { /* s1 */
 /* dmOrientation */	DMORIENT_PORTRAIT,
 /* dmPaperSize */	DMPAPER_A4,
 /* dmPaperLength */	2969,
-/* dmPaperWidth */      2101,
+/* dmPaperWidth */      2101
+     }
+   },
 /* dmScale */		100, /* ?? */
 /* dmCopies */		1,
 /* dmDefaultSource */	DMBIN_AUTO,
@@ -203,7 +213,7 @@ BOOL PSDRV_Init(void)
  *	     PSDRV_CreateDC
  */
 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
-                               LPCSTR output, const DEVMODE16* initData )
+                               LPCSTR output, const DEVMODEA* initData )
 {
     PSDRV_PDEVICE *physDev;
     PRINTERINFO *pi = PSDRV_FindPrinterInfo(device);
@@ -225,29 +235,29 @@ static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
 
     physDev->pi = pi;
 
-    physDev->Devmode = (PSDRV_DEVMODE16 *)HeapAlloc( PSDRV_Heap, 0,
-						     sizeof(PSDRV_DEVMODE16) );
+    physDev->Devmode = (PSDRV_DEVMODEA *)HeapAlloc( PSDRV_Heap, 0,
+						     sizeof(PSDRV_DEVMODEA) );
     if(!physDev->Devmode) {
         HeapFree( PSDRV_Heap, 0, physDev );
 	return FALSE;
     }
     
-    memcpy( physDev->Devmode, pi->Devmode, sizeof(PSDRV_DEVMODE16) );
+    memcpy( physDev->Devmode, pi->Devmode, sizeof(PSDRV_DEVMODEA) );
 
     if(initData) {
-        PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODE16 *)initData, pi);
+        PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)initData, pi);
     }
 
     
     devCaps = HeapAlloc( PSDRV_Heap, 0, sizeof(PSDRV_DevCaps) );
     memcpy(devCaps, &PSDRV_DevCaps, sizeof(PSDRV_DevCaps));
 
-    if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_PORTRAIT) {
-        devCaps->horzSize = physDev->Devmode->dmPublic.dmPaperWidth / 10;
-	devCaps->vertSize = physDev->Devmode->dmPublic.dmPaperLength / 10;
+    if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
+        devCaps->horzSize = physDev->Devmode->dmPublic.u1.s1.dmPaperWidth / 10;
+	devCaps->vertSize = physDev->Devmode->dmPublic.u1.s1.dmPaperLength / 10;
     } else {
-        devCaps->horzSize = physDev->Devmode->dmPublic.dmPaperLength / 10;
-	devCaps->vertSize = physDev->Devmode->dmPublic.dmPaperWidth / 10;
+        devCaps->horzSize = physDev->Devmode->dmPublic.u1.s1.dmPaperLength / 10;
+	devCaps->vertSize = physDev->Devmode->dmPublic.u1.s1.dmPaperWidth / 10;
     }
 
     devCaps->horzRes = physDev->pi->ppd->DefaultResolution * 
@@ -278,7 +288,8 @@ static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
     			    dc->w.devCaps->vertRes);
     
     dc->w.hFont = PSDRV_DefaultFont;
-    physDev->job.output = HEAP_strdupA( PSDRV_Heap, 0, output );
+    physDev->job.output = output ? HEAP_strdupA( PSDRV_Heap, 0, output ) :
+      NULL;
     physDev->job.hJob = 0;
     return TRUE;
 }
diff --git a/graphics/psdrv/ppd.c b/graphics/psdrv/ppd.c
index 213babe150..b8c1c72a0b 100644
--- a/graphics/psdrv/ppd.c
+++ b/graphics/psdrv/ppd.c
@@ -433,7 +433,8 @@ PPD *PSDRV_ParsePPD(char *fname)
 	    TRACE(psdrv, "ColorDevice = %d\n", (int)ppd->ColorDevice);
 	}
 
-	else if(!strcmp("*DefaultResolution", tuple.key)) {
+	else if((!strcmp("*DefaultResolution", tuple.key)) ||
+		(!strcmp("*DefaultJCLResolution", tuple.key))) {
 	    sscanf(tuple.value, "%d", &(ppd->DefaultResolution));
 	    TRACE(psdrv, "DefaultResolution = %d\n", ppd->DefaultResolution);
 	}
@@ -628,6 +629,8 @@ PPD *PSDRV_ParsePPD(char *fname)
 	PAGESIZE *page;
 	CONSTRAINT *con;
 	INPUTSLOT *slot;
+	OPTION *option;
+	OPTIONENTRY *optionEntry;
 
 	for(fn = ppd->InstalledFonts; fn; fn = fn->next)
 	    TRACE(psdrv, "'%s'\n", fn->Name);
@@ -645,11 +648,20 @@ PPD *PSDRV_ParsePPD(char *fname)
 	}
 
 	for(con = ppd->Constraints; con; con = con->next)
-	    TRACE(psdrv, "%s %s %s %s\n", con->Feature1, con->Value1,
-		  con->Feature2, con->Value2);
+	    TRACE(psdrv, "CONSTRAINTS@ %s %s %s %s\n", con->Feature1,
+		  con->Value1, con->Feature2, con->Value2);
+
+	for(option = ppd->InstalledOptions; option; option = option->next) {
+	    TRACE(psdrv, "OPTION: %s %s %s\n", option->OptionName,
+		  option->FullName, option->DefaultOption);
+	    for(optionEntry = option->Options; optionEntry;
+		optionEntry = optionEntry->next)
+	        TRACE(psdrv, "\tOPTIONENTRY: %s %s %s\n", optionEntry->Name,
+		      optionEntry->FullName, optionEntry->InvocationString);
+	}
 
 	for(slot = ppd->InputSlots; slot; slot = slot->next)
-	    TRACE(psdrv, "Slot '%s' Name '%s' (%d) Invocation '%s'\n",
+	    TRACE(psdrv, "INPUTSLOTS '%s' Name '%s' (%d) Invocation '%s'\n",
 		  slot->Name, slot->FullName, slot->WinBin, 
 		  slot->InvocationString);
     }
diff --git a/graphics/psdrv/ps.c b/graphics/psdrv/ps.c
index 039e3cc3fe..438e21a882 100644
--- a/graphics/psdrv/ps.c
+++ b/graphics/psdrv/ps.c
@@ -286,7 +286,7 @@ INT PSDRV_WriteHeader( DC *dc, char *title, int len )
         return 0;
     }
 
-    if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
+    if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
       /* BBox co-ords are in default user co-ord system so urx < ury even in
 	 landscape mode */
 	urx = (int) (dc->w.devCaps->vertSize * 72.0 / 25.4);
@@ -348,7 +348,7 @@ INT PSDRV_WriteHeader( DC *dc, char *title, int len )
     }
 
     for(page = physDev->pi->ppd->PageSizes; page; page = page->next) {
-        if(page->WinPage == physDev->Devmode->dmPublic.dmPaperSize) {
+        if(page->WinPage == physDev->Devmode->dmPublic.u1.s1.dmPaperSize) {
 	    if(page->InvocationString) {
 	        PSDRV_WriteFeature(physDev->job.hJob, "*PageSize", page->Name,
 			     page->InvocationString);
@@ -419,7 +419,7 @@ INT PSDRV_WriteNewPage( DC *dc )
         return 0;
     }
 
-    if(physDev->Devmode->dmPublic.dmOrientation == DMORIENT_LANDSCAPE) {
+    if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
         if(physDev->pi->ppd->LandscapeOrientation == -90) {
 	    xtrans = dc->w.devCaps->vertRes;
 	    ytrans = dc->w.devCaps->horzRes;
diff --git a/graphics/ttydrv/init.c b/graphics/ttydrv/init.c
index 295667fe18..01fd7a03b4 100644
--- a/graphics/ttydrv/init.c
+++ b/graphics/ttydrv/init.c
@@ -17,21 +17,26 @@ DEFAULT_DEBUG_CHANNEL(ttydrv)
 
 static const DC_FUNCTIONS TTYDRV_DC_Driver =
 {
+  NULL,                /* pAbortDoc */
   NULL,                /* pArc */
   NULL,                /* pBitBlt */
   NULL,                /* pBitmapBits */
   NULL,                /* pChord */
   NULL,                /* pCreateBitmap */
   TTYDRV_DC_CreateDC,  /* pCreateDC */
-  TTYDRV_DC_DeleteDC,  /* pDeleteDC */
   NULL,                /* pCreateDIBSection */
   NULL,                /* pCreateDIBSection16 */
+  TTYDRV_DC_DeleteDC,  /* pDeleteDC */
   NULL,                /* pDeleteObject */
+  NULL,                /* pDeviceCapabilities */
   NULL,                /* pEllipse */
+  NULL,                /* pEndDoc */
+  NULL,                /* pEndPage */
   NULL,                /* pEnumDeviceFonts */
   TTYDRV_DC_Escape,    /* pEscape */
   NULL,                /* pExcludeClipRect */
   NULL,                /* pExcludeVisRect */
+  NULL,                /* pExtDeviceMode */
   NULL,                /* pExtFloodFill */
   NULL,                /* pExtTextOut */
   NULL,                /* pGetCharWidth */
@@ -83,6 +88,8 @@ static const DC_FUNCTIONS TTYDRV_DC_Driver =
   NULL,                /* pSetViewportOrg (optional) */
   NULL,                /* pSetWindowExt (optional) */
   NULL,                /* pSetWindowOrg (optional) */
+  NULL,                /* pStartDoc */
+  NULL,                /* pStartPage */
   NULL,                /* pStretchBlt */
   NULL                 /* pStretchDIBits */
 };
@@ -172,7 +179,7 @@ void TTYDRV_GDI_Finalize(void)
  *	     TTYDRV_DC_CreateDC
  */
 BOOL TTYDRV_DC_CreateDC(DC *dc, LPCSTR driver, LPCSTR device,
-			    LPCSTR output, const DEVMODE16 *initData)
+			    LPCSTR output, const DEVMODEA *initData)
 {
   FIXME(ttydrv, "(%p, %s, %s, %s, %p): semistub\n",
     dc, debugstr_a(driver), debugstr_a(device), 
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index 00ba38baf1..303eb7e642 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -38,26 +38,31 @@ LPDRAWMODE 	win16drv_DrawModeP;
 
 
 static BOOL WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
-                                 LPCSTR output, const DEVMODE16* initData );
+                                 LPCSTR output, const DEVMODEA* initData );
 static INT WIN16DRV_Escape( DC *dc, INT nEscape, INT cbInput, 
                               SEGPTR lpInData, SEGPTR lpOutData );
 
 static const DC_FUNCTIONS WIN16DRV_Funcs =
 {
+    NULL,                            /* pAbortDoc */
     NULL,                            /* pArc */
     NULL,                            /* pBitBlt */
     NULL,                            /* pBitmapBits */
     NULL,                            /* pChord */
     NULL,                            /* pCreateBitmap */
     WIN16DRV_CreateDC,               /* pCreateDC */
-    NULL,                            /* pDeleteDC */
     NULL,                            /* pCreateDIBSection */
     NULL,                            /* pCreateDIBSection16 */
+    NULL,                            /* pDeleteDC */
     NULL,                            /* pDeleteObject */
+    NULL,                            /* pDeviceCapabilities */
     WIN16DRV_Ellipse,                /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
     WIN16DRV_EnumDeviceFonts,        /* pEnumDeviceFonts */
     WIN16DRV_Escape,                 /* pEscape */
     NULL,                            /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
     NULL,                            /* pExtFloodFill */
     WIN16DRV_ExtTextOut,             /* pExtTextOut */
     NULL,                            /* pFillRgn */
@@ -111,6 +116,8 @@ static const DC_FUNCTIONS WIN16DRV_Funcs =
     NULL,                            /* pSetViewportOrgEx */
     NULL,                            /* pSetWindowExtEx */
     NULL,                            /* pSetWindowOrgEx */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
     NULL,                            /* pStretchBlt */
     NULL                             /* pStretchDIBits */
 };
@@ -164,7 +171,7 @@ void InitDrawMode(LPDRAWMODE lpDrawMode)
 }
 
 BOOL WIN16DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device, LPCSTR output,
-                          const DEVMODE16* initData )
+                          const DEVMODEA* initData )
 {
     LOADED_PRINTER_DRIVER *pLPD;
     WORD wRet;
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index 52c02c4820..76c597a674 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -24,7 +24,7 @@
 DEFAULT_DEBUG_CHANNEL(x11drv)
 
 static BOOL X11DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
-                               LPCSTR output, const DEVMODE16* initData );
+                               LPCSTR output, const DEVMODEA* initData );
 static BOOL X11DRV_DeleteDC( DC *dc );
 
 static INT X11DRV_Escape( DC *dc, INT nEscape, INT cbInput,
@@ -32,20 +32,25 @@ static INT X11DRV_Escape( DC *dc, INT nEscape, INT cbInput,
 
 static const DC_FUNCTIONS X11DRV_Funcs =
 {
+    NULL,                            /* pAbortDoc */
     X11DRV_Arc,                      /* pArc */
     X11DRV_BitBlt,                   /* pBitBlt */
     X11DRV_BitmapBits,               /* pBitmapBits */
     X11DRV_Chord,                    /* pChord */
     X11DRV_CreateBitmap,             /* pCreateBitmap */
     X11DRV_CreateDC,                 /* pCreateDC */
-    X11DRV_DeleteDC,                 /* pDeleteDC */
     X11DRV_DIB_CreateDIBSection,     /* pCreateDIBSection */
     X11DRV_DIB_CreateDIBSection16,   /* pCreateDIBSection16 */
+    X11DRV_DeleteDC,                 /* pDeleteDC */
     X11DRV_DeleteObject,             /* pDeleteObject */
+    NULL,                            /* pDeviceCapabilities */
     X11DRV_Ellipse,                  /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
     X11DRV_EnumDeviceFonts,          /* pEnumDeviceFonts */
     X11DRV_Escape,                   /* pEscape */
     NULL,                            /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
     X11DRV_ExtFloodFill,             /* pExtFloodFill */
     X11DRV_ExtTextOut,               /* pExtTextOut */
     NULL,                            /* pFillRgn */
@@ -99,6 +104,8 @@ static const DC_FUNCTIONS X11DRV_Funcs =
     NULL,                            /* pSetViewportOrg (optional) */
     NULL,                            /* pSetWindowExt (optional) */
     NULL,                            /* pSetWindowOrg (optional) */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
     X11DRV_StretchBlt,               /* pStretchBlt */
     NULL                             /* pStretchDIBits */
 };
@@ -208,7 +215,7 @@ void X11DRV_GDI_Finalize(void)
  *	     X11DRV_CreateDC
  */
 static BOOL X11DRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
-                               LPCSTR output, const DEVMODE16* initData )
+                               LPCSTR output, const DEVMODEA* initData )
 {
     X11DRV_PDEVICE *physDev;
 
diff --git a/include/debugdefs.h b/include/debugdefs.h
index 652ba913f3..d6e0298fa1 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -162,11 +162,12 @@ int dbch_win16drv = 150;
 int dbch_win32 = 151;
 int dbch_wing = 152;
 int dbch_winsock = 153;
-int dbch_wnet = 154;
-int dbch_x11 = 155;
-int dbch_x11drv = 156;
+int dbch_winspool = 154;
+int dbch_wnet = 155;
+int dbch_x11 = 156;
+int dbch_x11drv = 157;
 
-#define DEBUG_CHANNEL_COUNT 157
+#define DEBUG_CHANNEL_COUNT 158
 
 char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
@@ -325,6 +326,7 @@ char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
 {1, 1, 0, 0},
 {1, 1, 0, 0},
 {1, 1, 0, 0},
+{1, 1, 0, 0},
 {1, 1, 0, 0}
 };
 
@@ -483,6 +485,7 @@ const char * const debug_ch_name[DEBUG_CHANNEL_COUNT] = {
 "win32",
 "wing",
 "winsock",
+"winspool",
 "wnet",
 "x11",
 "x11drv"
diff --git a/include/gdi.h b/include/gdi.h
index a50dd38ca2..34459f7162 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -165,22 +165,28 @@ typedef INT (*DEVICEFONTENUMPROC)(LPENUMLOGFONT16,LPNEWTEXTMETRIC16,UINT16,LPARA
 
 typedef struct tagDC_FUNCS
 {
+    INT      (*pAbortDoc)(DC*);
     BOOL     (*pArc)(DC*,INT,INT,INT,INT,INT,INT,INT,INT);
     BOOL     (*pBitBlt)(DC*,INT,INT,INT,INT,DC*,INT,INT,DWORD);
     LONG     (*pBitmapBits)(HBITMAP,void*,LONG,WORD);
     BOOL     (*pChord)(DC*,INT,INT,INT,INT,INT,INT,INT,INT);
     BOOL     (*pCreateBitmap)(HBITMAP); 
-    BOOL     (*pCreateDC)(DC*,LPCSTR,LPCSTR,LPCSTR,const DEVMODE16*);
-    BOOL     (*pDeleteDC)(DC*);
+    BOOL     (*pCreateDC)(DC*,LPCSTR,LPCSTR,LPCSTR,const DEVMODEA*);
     HBITMAP  (*pCreateDIBSection)(DC *,BITMAPINFO *,UINT,LPVOID *,HANDLE,
 				  DWORD);
     HBITMAP16 (*pCreateDIBSection16)(DC *,BITMAPINFO *,UINT16,SEGPTR *,HANDLE,
 				     DWORD);
+    BOOL     (*pDeleteDC)(DC*);
     BOOL     (*pDeleteObject)(HGDIOBJ);
+    DWORD    (*pDeviceCapabilities)(LPCSTR,LPCSTR,WORD,LPSTR,LPDEVMODEA);
     BOOL     (*pEllipse)(DC*,INT,INT,INT,INT);
+    INT      (*pEndDoc)(DC*);
+    INT      (*pEndPage)(DC*);
     BOOL     (*pEnumDeviceFonts)(DC*,LPLOGFONT16,DEVICEFONTENUMPROC,LPARAM);
     INT      (*pEscape)(DC*,INT,INT,SEGPTR,SEGPTR);
     INT      (*pExcludeClipRect)(DC*,INT,INT,INT,INT);
+    INT      (*pExtDeviceMode)(HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,
+			       DWORD); 
     BOOL     (*pExtFloodFill)(DC*,INT,INT,COLORREF,UINT);
     BOOL     (*pExtTextOut)(DC*,INT,INT,UINT,const RECT*,LPCSTR,UINT,
 			    const INT*);
@@ -236,6 +242,8 @@ typedef struct tagDC_FUNCS
     BOOL     (*pSetViewportOrg)(DC*,INT,INT);
     BOOL     (*pSetWindowExt)(DC*,INT,INT);
     BOOL     (*pSetWindowOrg)(DC*,INT,INT);
+    INT      (*pStartDoc)(DC*,const DOCINFOA*);
+    INT      (*pStartPage)(DC*);
     BOOL     (*pStretchBlt)(DC*,INT,INT,INT,INT,DC*,INT,INT,INT,INT,DWORD);
     INT      (*pStretchDIBits)(DC*,INT,INT,INT,INT,INT,INT,INT,INT,
 			       const void *,const BITMAPINFO *,UINT,DWORD);
@@ -439,5 +447,5 @@ extern GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ16, WORD );
 extern BOOL DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs );
 extern const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name );
 extern BOOL DRIVER_UnregisterDriver( LPCSTR name );
-
+extern BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size );
 #endif  /* __WINE_GDI_H */
diff --git a/include/psdrv.h b/include/psdrv.h
index b32a32b27c..9e46a8be92 100644
--- a/include/psdrv.h
+++ b/include/psdrv.h
@@ -10,6 +10,7 @@
 #include "font.h"
 #include "pen.h"
 #include "brush.h"
+#include "wine/wingdi16.h"
 
 typedef struct {
     float	llx, lly, urx, ury;
@@ -142,7 +143,7 @@ typedef struct {
 } PPD;
 
 typedef struct {
-    DEVMODE16			dmPublic;
+    DEVMODEA			dmPublic;
     struct _tagdocprivate {
       int dummy;
     }				dmDocPrivate;
@@ -157,12 +158,12 @@ numInstalledOptions of OPTIONs
 
 */
 
-} PSDRV_DEVMODE16;
+} PSDRV_DEVMODEA;
 
 typedef struct _tagPI {
     char		*FriendlyName;
     PPD			*ppd;
-    PSDRV_DEVMODE16	*Devmode;
+    PSDRV_DEVMODEA	*Devmode;
     FONTFAMILY		*Fonts;
     struct _tagPI	*next;
 } PRINTERINFO;
@@ -225,14 +226,19 @@ typedef struct {
     PSCOLOR		bkColor;
     PSCOLOR		inkColor;	/* Last colour set */
     JOB			job;
-    PSDRV_DEVMODE16	*Devmode;
+    PSDRV_DEVMODEA	*Devmode;
     PRINTERINFO		*pi;
 } PSDRV_PDEVICE;
 
+
+extern INT16 WINAPI PSDRV_ExtDeviceMode16(HWND16 hwnd, HANDLE16 hDriver,
+		    LPDEVMODEA lpdmOutput, LPSTR lpszDevice, LPSTR lpszPort,
+		    LPDEVMODEA lpdmInput, LPSTR lpszProfile, WORD fwMode);
+
 extern HANDLE PSDRV_Heap;
 extern char *PSDRV_ANSIVector[256];
 
-extern void PSDRV_MergeDevmodes(PSDRV_DEVMODE16 *dm1, PSDRV_DEVMODE16 *dm2,
+extern void PSDRV_MergeDevmodes(PSDRV_DEVMODEA *dm1, PSDRV_DEVMODEA *dm2,
 			 PRINTERINFO *pi);
 extern BOOL PSDRV_GetFontMetrics(void);
 extern PPD *PSDRV_ParsePPD(char *fname);
@@ -340,6 +346,13 @@ extern INT PSDRV_StretchDIBits( DC *dc, INT xDst, INT yDst,
 				  INT ySrc, INT widthSrc, INT heightSrc,
 				  const void *bits, const BITMAPINFO *info,
 				  UINT wUsage, DWORD dwRop );
+extern INT PSDRV_ExtDeviceMode(HWND hwnd, LPDEVMODEA lpdmOutput,
+			       LPSTR lpszDevice, LPSTR lpszPort,
+			       LPDEVMODEA lpdmInput, LPSTR lpszProfile,
+			       DWORD dwMode);
+extern DWORD PSDRV_DeviceCapabilities(LPCSTR lpszDevice, LPCSTR lpszPort,
+				      WORD fwCapability, LPSTR lpszOutput,
+				      LPDEVMODEA lpdm);
 
 #endif
 
diff --git a/include/ttydrv.h b/include/ttydrv.h
index 7f7aa8fd46..3db13c3f94 100644
--- a/include/ttydrv.h
+++ b/include/ttydrv.h
@@ -41,7 +41,7 @@ typedef struct {
   int dummy;
 } TTYDRV_PDEVICE;
 
-extern BOOL TTYDRV_DC_CreateDC(struct tagDC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODE16 *initData);
+extern BOOL TTYDRV_DC_CreateDC(struct tagDC *dc, LPCSTR driver, LPCSTR device, LPCSTR output, const DEVMODEA *initData);
 extern BOOL TTYDRV_DC_DeleteDC(struct tagDC *dc);
 extern INT TTYDRV_DC_Escape(struct tagDC *dc, INT nEscape, INT cbInput, SEGPTR lpInData, SEGPTR lpOutData);
 
diff --git a/include/wine/wingdi16.h b/include/wine/wingdi16.h
index 369a1746d6..79197b644b 100644
--- a/include/wine/wingdi16.h
+++ b/include/wine/wingdi16.h
@@ -254,37 +254,6 @@ typedef struct
 
 typedef INT16 (CALLBACK *MFENUMPROC16)(HDC16,HANDLETABLE16*,METARECORD*,
                                        INT16,LPARAM);
-
-typedef struct
-{
-    BYTE   dmDeviceName[CCHDEVICENAME];
-    WORD   dmSpecVersion;
-    WORD   dmDriverVersion;
-    WORD   dmSize;
-    WORD   dmDriverExtra;
-    DWORD  dmFields;
-    INT16  dmOrientation;
-    INT16  dmPaperSize;
-    INT16  dmPaperLength;
-    INT16  dmPaperWidth;
-    INT16  dmScale;
-    INT16  dmCopies;
-    INT16  dmDefaultSource;
-    INT16  dmPrintQuality;
-    INT16  dmColor;
-    INT16  dmDuplex;
-    INT16  dmYResolution;
-    INT16  dmTTOption;
-    INT16  dmCollate;
-    BYTE   dmFormName[CCHFORMNAME];
-    WORD   dmUnusedPadding;
-    WORD   dmBitsPerPel;
-    DWORD  dmPelsWidth;
-    DWORD  dmPelsHeight;
-    DWORD  dmDisplayFlags;
-    DWORD  dmDisplayFrequency;
-} DEVMODE16, *LPDEVMODE16;
-
 typedef struct 
 {
     INT16    cbSize;
@@ -294,6 +263,9 @@ typedef struct
 
 typedef BOOL16 (CALLBACK* ABORTPROC16)(HDC16, INT16);
 
+#define INT_PD_DEFAULT_DEVMODE  1
+#define INT_PD_DEFAULT_MODEL    2
+
 #include "poppack.h"
 
 
@@ -314,7 +286,7 @@ HBITMAP16   WINAPI CreateBitmapIndirect16(const BITMAP16*);
 HBRUSH16    WINAPI CreateBrushIndirect16(const LOGBRUSH16*);
 HBITMAP16   WINAPI CreateCompatibleBitmap16(HDC16,INT16,INT16);
 HDC16       WINAPI CreateCompatibleDC16(HDC16);
-HDC16       WINAPI CreateDC16(LPCSTR,LPCSTR,LPCSTR,const DEVMODE16*);
+HDC16       WINAPI CreateDC16(LPCSTR,LPCSTR,LPCSTR,const DEVMODEA*);
 HBITMAP16   WINAPI CreateDIBitmap16(HDC16,const BITMAPINFOHEADER*,DWORD,
                                     LPCVOID,const BITMAPINFO*,UINT16);
 HBRUSH16    WINAPI CreateDIBPatternBrush16(HGLOBAL16,UINT16);
@@ -327,7 +299,7 @@ HFONT16     WINAPI CreateFont16(INT16,INT16,INT16,INT16,INT16,BYTE,BYTE,BYTE,
                                 BYTE,BYTE,BYTE,BYTE,BYTE,LPCSTR);
 HFONT16     WINAPI CreateFontIndirect16(const LOGFONT16*);
 HBRUSH16    WINAPI CreateHatchBrush16(INT16,COLORREF);
-HDC16       WINAPI CreateIC16(LPCSTR,LPCSTR,LPCSTR,const DEVMODE16*);
+HDC16       WINAPI CreateIC16(LPCSTR,LPCSTR,LPCSTR,const DEVMODEA*);
 HDC16       WINAPI CreateMetaFile16(LPCSTR);
 HPALETTE16  WINAPI CreatePalette16(const LOGPALETTE*);
 HBRUSH16    WINAPI CreatePatternBrush16(HBITMAP16);
@@ -392,7 +364,7 @@ HDC16       WINAPI GetDCState16(HDC16);
 INT16       WINAPI GetDeviceCaps16(HDC16,INT16);
 UINT16      WINAPI GetDIBColorTable16(HDC16,UINT16,UINT16,RGBQUAD*);
 INT16       WINAPI GetDIBits16(HDC16,HBITMAP16,UINT16,UINT16,LPVOID,LPBITMAPINFO,UINT16);
-INT16       WINAPI GetEnvironment16(LPCSTR,LPDEVMODE16,UINT16);
+INT16       WINAPI GetEnvironment16(LPCSTR,LPDEVMODEA,UINT16);
 DWORD       WINAPI GetFontLanguageInfo16(HDC16);
 DWORD       WINAPI GetGlyphOutline16(HDC16,UINT16,UINT16,LPGLYPHMETRICS16,DWORD,LPVOID,const MAT2*);
 INT16       WINAPI GetKerningPairs16(HDC16,INT16,LPKERNINGPAIR16);
@@ -472,7 +444,7 @@ BOOL16      WINAPI Rectangle16(HDC16,INT16,INT16,INT16,INT16);
 BOOL16      WINAPI RectInRegion16(HRGN16,const RECT16 *);
 BOOL16      WINAPI RectVisible16(HDC16,const RECT16*);
 BOOL16      WINAPI RemoveFontResource16(SEGPTR);
-HDC16       WINAPI ResetDC16(HDC16,const DEVMODE16 *);
+HDC16       WINAPI ResetDC16(HDC16,const DEVMODEA *);
 BOOL16      WINAPI ResizePalette16(HPALETTE16,UINT16);
 BOOL16      WINAPI RestoreDC16(HDC16,INT16);
 INT16       WINAPI RestoreVisRgn16(HDC16);
@@ -506,7 +478,7 @@ UINT16      WINAPI SetDIBColorTable16(HDC16,UINT16,UINT16,RGBQUAD*);
 INT16       WINAPI SetDIBits16(HDC16,HBITMAP16,UINT16,UINT16,LPCVOID,const BITMAPINFO*,UINT16);
 INT16       WINAPI SetDIBitsToDevice16(HDC16,INT16,INT16,INT16,INT16,INT16,
                          INT16,UINT16,UINT16,LPCVOID,const BITMAPINFO*,UINT16);
-INT16       WINAPI SetEnvironment16(LPCSTR,LPDEVMODE16,UINT16);
+INT16       WINAPI SetEnvironment16(LPCSTR,LPDEVMODEA,UINT16);
 WORD        WINAPI SetHookFlags16(HDC16,WORD);
 INT16       WINAPI SetMapMode16(HDC16,INT16);
 DWORD       WINAPI SetMapperFlags16(HDC16,DWORD);
diff --git a/include/wingdi.h b/include/wingdi.h
index a74ccf5f7b..66af681fbf 100644
--- a/include/wingdi.h
+++ b/include/wingdi.h
@@ -2625,10 +2625,15 @@ typedef struct
     WORD   dmSize;
     WORD   dmDriverExtra;
     DWORD  dmFields;
-    SHORT  dmOrientation;
-    SHORT  dmPaperSize;
-    SHORT  dmPaperLength;
-    SHORT  dmPaperWidth;
+    union {
+      struct {
+	SHORT  dmOrientation;
+	SHORT  dmPaperSize;
+	SHORT  dmPaperLength;
+	SHORT  dmPaperWidth;
+      } s1;
+      POINTL dmPosition;
+    } u1;
     SHORT  dmScale;
     SHORT  dmCopies;
     SHORT  dmDefaultSource;
@@ -2663,10 +2668,15 @@ typedef struct
     WORD   dmSize;
     WORD   dmDriverExtra;
     DWORD  dmFields;
-    SHORT  dmOrientation;
-    SHORT  dmPaperSize;
-    SHORT  dmPaperLength;
-    SHORT  dmPaperWidth;
+    union {
+      struct {
+	SHORT  dmOrientation;
+	SHORT  dmPaperSize;
+	SHORT  dmPaperLength;
+	SHORT  dmPaperWidth;
+      } s1;
+      POINTL dmPosition;
+    } u1;
     SHORT  dmScale;
     SHORT  dmCopies;
     SHORT  dmDefaultSource;
@@ -2713,6 +2723,7 @@ DECL_WINELIB_TYPE_AW(LPDEVMODE)
 #define DM_PAPERLENGTH		0x00000004L
 #define DM_PAPERWIDTH		0x00000008L
 #define DM_SCALE		0x00000010L
+#define DM_POSITION             0x00000020L
 #define DM_COPIES		0x00000100L
 #define DM_DEFAULTSOURCE	0x00000200L
 #define DM_PRINTQUALITY		0x00000400L
@@ -2720,17 +2731,20 @@ DECL_WINELIB_TYPE_AW(LPDEVMODE)
 #define DM_DUPLEX		0x00001000L
 #define DM_YRESOLUTION		0x00002000L
 #define DM_TTOPTION		0x00004000L
+#define DM_COLLATE              0x00008000L
+#define DM_FORMNAME             0x00010000L
+#define DM_LOGPIXELS            0x00020000L
 #define DM_BITSPERPEL           0x00040000L
 #define DM_PELSWIDTH            0x00080000L
 #define DM_PELSHEIGHT           0x00100000L
 #define DM_DISPLAYFLAGS         0x00200000L
 #define DM_DISPLAYFREQUENCY     0x00400000L
-#define DM_PANNINGHEIGHT        0x00800000L
-#define DM_PANNINGWIDTH         0x01000000L
-#define DM_ICMMETHOD            0x02000000L
-#define DM_ICMINTENT            0x04000000L
-#define DM_MEDIATYPE            0x08000000L
-#define DM_DITHERTYPE           0x10000000L
+#define DM_ICMMETHOD            0x00800000L
+#define DM_ICMINTENT            0x01000000L
+#define DM_MEDIATYPE            0x02000000L
+#define DM_DITHERTYPE           0x04000000L
+#define DM_PANNINGWIDTH         0x08000000L
+#define DM_PANNINGHEIGHT        0x10000000L
 
 #define DMORIENT_PORTRAIT	1
 #define DMORIENT_LANDSCAPE	2
@@ -3029,6 +3043,10 @@ BOOL      WINAPI FixBrushOrgEx(HDC,INT,INT,LPPOINT);
 BOOL      WINAPI FlattenPath(HDC);
 BOOL      WINAPI FloodFill(HDC,INT,INT,COLORREF);
 BOOL      WINAPI FrameRgn(HDC,HRGN,HBRUSH,INT,INT);
+DWORD     WINAPI GDI_CallDeviceCapabilities16(LPCSTR,LPCSTR,WORD,LPSTR,
+					      LPDEVMODEA);
+INT       WINAPI GDI_CallExtDeviceMode16(HWND,LPDEVMODEA,LPSTR,LPSTR,
+					 LPDEVMODEA,LPSTR,DWORD);
 BOOL      WINAPI GdiComment(HDC,UINT,const BYTE *);
 INT       WINAPI GetArcDirection(HDC);
 BOOL      WINAPI GetAspectRatioFilterEx(HDC,LPSIZE);
diff --git a/include/winspool.h b/include/winspool.h
index cc414bf5c4..80548b32d8 100644
--- a/include/winspool.h
+++ b/include/winspool.h
@@ -17,8 +17,6 @@ extern "C" {
 #endif
 
 /* DEFINES */
-#define INT_PD_DEFAULT_DEVMODE  1
-#define INT_PD_DEFAULT_MODEL    2
 
 #define PRINTER_ATTRIBUTE_QUEUED         0x00000001
 #define PRINTER_ATTRIBUTE_DIRECT         0x00000002
@@ -234,11 +232,11 @@ int WINAPI EndSpoolPage16(HANDLE16 hJob);
 DWORD WINAPI GetSpoolJob16(int nOption, LONG param);
 int WINAPI WriteDialog16(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg);
 
-INT WINAPI DeviceCapabilitiesA(LPCSTR printer,LPCSTR target,WORD z,
-                                   LPSTR a,LPDEVMODEA b);
+INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort,WORD fwCapability,
+			       LPSTR pOutput, LPDEVMODEA pDevMode);
 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
-                                   WORD fwCapability, LPWSTR pOutput,
-                                   const DEVMODEW *pDevMode);
+			       WORD fwCapability, LPWSTR pOutput,
+			       const DEVMODEW *pDevMode);
 
 #define DeviceCapabilities WINELIB_NAME_AW(DeviceCapabilities)
 
diff --git a/misc/Makefile.in b/misc/Makefile.in
index da0c50c738..188bc8aea2 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -24,7 +24,6 @@ C_SRCS = \
 	registry.c \
 	shell.c \
 	sound.c \
-	spooler.c \
 	spy.c \
 	stress.c \
 	string.c \
diff --git a/misc/printdrv.c b/misc/printdrv.c
index 2fbafdfe41..2aac7a94cb 100644
--- a/misc/printdrv.c
+++ b/misc/printdrv.c
@@ -2,6 +2,7 @@
  * Implementation of some printer driver bits
  * 
  * Copyright 1996 John Harvey
+ * Copyright 1998 Huw Davies
  * Copyright 1998 Andreas Mohr
  * Copyright 1999 Klaas van Gend
  */
@@ -9,18 +10,23 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include "winspool.h"
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "ldt.h"
 #include "winbase.h"
 #include "wine/wingdi16.h"
-#include "ldt.h"
+#include "winspool.h"
 #include "winerror.h"
 #include "winreg.h"
 #include "debugtools.h"
+#include "gdi.h"
+#include "dc.h"
+#include "callback.h"
+#include "xmalloc.h"
+#include "options.h"
 
-DECLARE_DEBUG_CHANNEL(gdi)
-DECLARE_DEBUG_CHANNEL(print)
-
-CRITICAL_SECTION PRINT32_RegistryBlocker;
+DEFAULT_DEBUG_CHANNEL(print)
 
 static char PrinterModel[]	= "Printer Model";
 static char DefaultDevMode[]	= "Default DevMode";
@@ -34,16 +40,16 @@ static char Printers[]		= "System\\CurrentControlSet\\Control\\Print\\Printers\\
 INT16 WINAPI StartDoc16( HDC16 hdc, const DOCINFO16 *lpdoc )
 {
   INT16 retVal;
-  TRACE_(print)("(%p)\n", lpdoc );
-  TRACE_(print)("%d 0x%lx:0x%p 0x%lx:0x%p\n",lpdoc->cbSize,
+  TRACE("(%p)\n", lpdoc );
+  TRACE("%d 0x%lx:0x%p 0x%lx:0x%p\n",lpdoc->cbSize,
 	lpdoc->lpszDocName,PTR_SEG_TO_LIN(lpdoc->lpszDocName),
 	lpdoc->lpszOutput,PTR_SEG_TO_LIN(lpdoc->lpszOutput));
-  TRACE_(print)("%d %s %s\n",lpdoc->cbSize,
+  TRACE("%d %s %s\n",lpdoc->cbSize,
 	(LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName),
 	(LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszOutput));
   retVal =  Escape16(hdc, STARTDOC,
     strlen((LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName)), lpdoc->lpszDocName, 0);
-  TRACE_(print)("Escape16 returned %d\n",retVal);
+  TRACE("Escape16 returned %d\n",retVal);
   return retVal;
 }
 
@@ -55,7 +61,7 @@ INT16 WINAPI EndPage16( HDC16 hdc )
 {
   INT16 retVal;
   retVal =  Escape16(hdc, NEWFRAME, 0, 0, 0);
-  TRACE_(print)("Escape16 returned %d\n",retVal);
+  TRACE("Escape16 returned %d\n",retVal);
   return retVal;
 }
 
@@ -65,9 +71,11 @@ INT16 WINAPI EndPage16( HDC16 hdc )
  */
 INT WINAPI StartDocA(HDC hdc ,const DOCINFOA* doc)
 {
-  FIXME_(gdi)("stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 
-  return 0; /* failure*/
+    return  Escape(hdc,
+		   STARTDOC,
+		   strlen(doc->lpszDocName),
+		   doc->lpszDocName,
+		   0);
 }
 
 /*************************************************************************
@@ -75,7 +83,7 @@ INT WINAPI StartDocA(HDC hdc ,const DOCINFOA* doc)
  * 
  */
 INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) {
-  FIXME_(gdi)("stub\n");
+  FIXME("stub\n");
   SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 
   return 0; /* failure*/
 }
@@ -86,9 +94,8 @@ INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) {
  */
 INT WINAPI StartPage(HDC hdc)
 {
-  FIXME_(gdi)("stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 
-  return 0; /* failure*/
+  FIXME("stub\n");
+  return 1;
 }
 
 /******************************************************************
@@ -97,9 +104,7 @@ INT WINAPI StartPage(HDC hdc)
  */
 INT WINAPI EndPage(HDC hdc)
 {
-  FIXME_(gdi)("stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 
-  return 0; /* failure*/
+  return Escape(hdc, NEWFRAME, 0, 0, 0);
 }
 
 /******************************************************************
@@ -117,9 +122,7 @@ INT16 WINAPI EndDoc16(HDC16 hdc)
  */
 INT WINAPI EndDoc(HDC hdc)
 {
-  FIXME_(gdi)("stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 
-  return 0; /* failure*/
+  return Escape(hdc, ENDDOC, 0, 0, 0);
 }
 
 /******************************************************************************
@@ -135,10 +138,448 @@ INT16 WINAPI AbortDoc16(HDC16 hdc)
  */
 INT WINAPI AbortDoc(HDC hdc)
 {
-    FIXME_(gdi)("(%d): stub\n", hdc);
+    FIXME("(%d): stub\n", hdc);
     return 1;
 }
 
+/**********************************************************************
+ *           QueryAbort   (GDI.155)
+ *
+ *  Calls the app's AbortProc function if avail.
+ *
+ * RETURNS
+ * TRUE if no AbortProc avail or AbortProc wants to continue printing.
+ * FALSE if AbortProc wants to abort printing.
+ */
+BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
+{
+    DC *dc = DC_GetDCPtr( hdc );
+
+    if ((!dc) || (!dc->w.lpfnPrint))
+	return TRUE;
+    return Callbacks->CallDrvAbortProc(dc->w.lpfnPrint, hdc, 0);
+}
+
+/**********************************************************************
+ *           SetAbortProc16   (GDI.381)
+ *
+ */
+INT16 WINAPI SetAbortProc16(HDC16 hdc, SEGPTR abrtprc)
+{
+    return Escape16(hdc, SETABORTPROC, 0, abrtprc, (SEGPTR)0);
+} 
+
+/**********************************************************************
+ *           SetAbortProc32   (GDI32.301)
+ *
+ */
+INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc)
+{
+    FIXME("stub\n");
+    return 1;
+}
+
+
+/****************** misc. printer related functions */
+
+/*
+ * The following function should implement a queing system
+ */
+#ifndef HPQ 
+#define HPQ WORD
+#endif
+struct hpq 
+{
+    struct hpq 	*next;
+    int		 tag;
+    int		 key;
+};
+
+static struct hpq *hpqueue;
+
+/**********************************************************************
+ *           CreatePQ   (GDI.230)
+ *
+ */
+HPQ WINAPI CreatePQ16(int size) 
+{
+#if 0
+    HGLOBAL16 hpq = 0;
+    WORD tmp_size;
+    LPWORD pPQ;
+
+    tmp_size = size << 2;
+    if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
+       return 0xffff;
+    pPQ = GlobalLock16(hpq);
+    *pPQ++ = 0;
+    *pPQ++ = tmp_size;
+    *pPQ++ = 0;
+    *pPQ++ = 0;
+    GlobalUnlock16(hpq);
+
+    return (HPQ)hpq;
+#else
+    FIXME("(%d): stub\n",size);
+    return 1;
+#endif
+}
+
+/**********************************************************************
+ *           DeletePQ   (GDI.235)
+ *
+ */
+int WINAPI DeletePQ16(HPQ hPQ) 
+{
+    return GlobalFree16((HGLOBAL16)hPQ);
+}
+
+/**********************************************************************
+ *           ExtractPQ   (GDI.232)
+ *
+ */
+int WINAPI ExtractPQ16(HPQ hPQ) 
+{ 
+    struct hpq *queue, *prev, *current, *currentPrev;
+    int key = 0, tag = -1;
+    currentPrev = prev = NULL;
+    queue = current = hpqueue;
+    if (current)
+        key = current->key;
+    
+    while (current)
+    {
+        currentPrev = current;
+        current = current->next;
+        if (current)
+        {
+            if (current->key < key)
+            {
+                queue = current;
+                prev = currentPrev;
+            }
+        }
+    }
+    if (queue)
+    {
+        tag = queue->tag;
+        
+        if (prev)
+            prev->next = queue->next;
+        else
+            hpqueue = queue->next;
+        free(queue);
+    }
+    
+    TRACE("%x got tag %d key %d\n", hPQ, tag, key); 
+
+    return tag;
+}
+
+/**********************************************************************
+ *           InsertPQ   (GDI.233)
+ *
+ */
+int WINAPI InsertPQ16(HPQ hPQ, int tag, int key) 
+{
+    struct hpq *queueItem = xmalloc(sizeof(struct hpq));
+    queueItem->next = hpqueue;
+    hpqueue = queueItem;
+    queueItem->key = key;
+    queueItem->tag = tag;
+    
+    FIXME("(%x %d %d): stub???\n", hPQ, tag, key);
+    return TRUE;
+}
+
+/**********************************************************************
+ *           MinPQ   (GDI.231)
+ *
+ */
+int WINAPI MinPQ16(HPQ hPQ) 
+{
+    FIXME("(%x): stub\n", hPQ); 
+    return 0;
+}
+
+/**********************************************************************
+ *           SizePQ   (GDI.234)
+ *
+ */
+int WINAPI SizePQ16(HPQ hPQ, int sizechange) 
+{  
+    FIXME("(%x %d): stub\n", hPQ, sizechange); 
+    return -1; 
+}
+
+
+
+/* 
+ * The following functions implement part of the spooling process to 
+ * print manager.  I would like to see wine have a version of print managers
+ * that used LPR/LPD.  For simplicity print jobs will be sent to a file for
+ * now.
+ */
+typedef struct PRINTJOB
+{
+    char	*pszOutput;
+    char 	*pszTitle;
+    HDC16  	hDC;
+    HANDLE16 	hHandle;
+    int		nIndex;
+    int		fd;
+} PRINTJOB, *PPRINTJOB;
+
+#define MAX_PRINT_JOBS 1
+#define SP_OK 1
+
+PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
+
+
+static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
+{
+    return gPrintJobsTable[0];
+}
+
+/* TTD Need to do some DOS->UNIX file conversion here */
+static int CreateSpoolFile(LPSTR pszOutput)
+{
+    int fd=-1;
+    char psCmd[1024];
+    char *psCmdP = psCmd;
+
+    /* TTD convert the 'output device' into a spool file name */
+
+    if (pszOutput == NULL || *pszOutput == '\0')
+      return -1;
+
+    PROFILE_GetWineIniString( "spooler", pszOutput, "", psCmd, sizeof(psCmd) );
+    TRACE("Got printerSpoolCommand '%s' for output device '%s'\n",
+	  psCmd, pszOutput);
+    if (!*psCmd)
+        psCmdP = pszOutput;
+    else
+    {
+        while (*psCmdP && isspace(*psCmdP))
+        {
+            psCmdP++;
+        };
+        if (!*psCmdP)
+            return -1;
+    }
+    if (*psCmdP == '|')
+    {
+        int fds[2];
+        if (pipe(fds))
+            return -1;
+        if (fork() == 0)
+        {
+            psCmdP++;
+
+            TRACE("In child need to exec %s\n",psCmdP);
+            close(0);
+            dup2(fds[0],0);
+            close (fds[1]);
+            system(psCmdP);
+            exit(0);
+            
+        }
+        close (fds[0]);
+        fd = fds[1];
+        TRACE("Need to execute a cmnd and pipe the output to it\n");
+    }
+    else
+    {
+        TRACE("Just assume its a file\n");
+
+        if ((fd = open(psCmdP, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
+        {
+            ERR("Failed to create spool file %s, errno = %d\n", 
+		psCmdP, errno);
+        }
+    }
+    return fd;
+}
+
+static int FreePrintJob(HANDLE16 hJob)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob;
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL)
+    {
+	gPrintJobsTable[pPrintJob->nIndex] = NULL;
+	free(pPrintJob->pszOutput);
+	free(pPrintJob->pszTitle);
+	if (pPrintJob->fd >= 0) close(pPrintJob->fd);
+	free(pPrintJob);
+	nRet = SP_OK;
+    }
+    return nRet;
+}
+
+/**********************************************************************
+ *           OpenJob   (GDI.240)
+ *
+ */
+HANDLE16 WINAPI OpenJob16(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
+{
+    HANDLE16 hHandle = (HANDLE16)SP_ERROR;
+    PPRINTJOB pPrintJob;
+
+    TRACE("'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
+
+    pPrintJob = gPrintJobsTable[0];
+    if (pPrintJob == NULL)
+    {
+	int fd;
+
+	/* Try an create a spool file */
+	fd = CreateSpoolFile(lpOutput);
+	if (fd >= 0)
+	{
+	    hHandle = 1;
+
+	    pPrintJob = xmalloc(sizeof(PRINTJOB));
+	    memset(pPrintJob, 0, sizeof(PRINTJOB));
+
+	    pPrintJob->pszOutput = strdup(lpOutput);
+	    if(lpTitle)
+	        pPrintJob->pszTitle = strdup(lpTitle);
+	    pPrintJob->hDC = hDC;
+	    pPrintJob->fd = fd;
+	    pPrintJob->nIndex = 0;
+	    pPrintJob->hHandle = hHandle; 
+	    gPrintJobsTable[pPrintJob->nIndex] = pPrintJob; 
+	}
+    }
+    TRACE("return %04x\n", hHandle);
+    return hHandle;
+}
+
+/**********************************************************************
+ *           CloseJob   (GDI.243)
+ *
+ */
+int WINAPI CloseJob16(HANDLE16 hJob)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob = NULL;
+
+    TRACE("%04x\n", hJob);
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL)
+    {
+	/* Close the spool file */
+	close(pPrintJob->fd);
+	FreePrintJob(hJob);
+	nRet  = 1;
+    }
+    return nRet;
+}
+
+/**********************************************************************
+ *           WriteSpool   (GDI.241)
+ *
+ */
+int WINAPI WriteSpool16(HANDLE16 hJob, LPSTR lpData, WORD cch)
+{
+    int nRet = SP_ERROR;
+    PPRINTJOB pPrintJob = NULL;
+
+    TRACE("%04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
+
+    pPrintJob = FindPrintJobFromHandle(hJob);
+    if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
+    {
+	if (write(pPrintJob->fd, lpData, cch) != cch)
+	  nRet = SP_OUTOFDISK;
+	else
+	  nRet = cch;
+	if (pPrintJob->hDC == 0) {
+	    TRACE("hDC == 0 so no QueryAbort\n");
+	}
+        else if (!(QueryAbort16(pPrintJob->hDC, (nRet == SP_OUTOFDISK) ? nRet : 0 )))
+	{
+	    CloseJob16(hJob); /* printing aborted */
+	    nRet = SP_APPABORT;
+	}
+    }
+    return nRet;
+}
+
+/**********************************************************************
+ *           WriteDialog   (GDI.242)
+ *
+ */
+int WINAPI WriteDialog16(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
+{
+    int nRet = 0;
+
+    TRACE("%04x %04x '%s'\n", hJob,  cchMsg, lpMsg);
+
+    nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
+    return nRet;
+}
+
+
+/**********************************************************************
+ *           DeleteJob  (GDI.244)
+ *
+ */
+int WINAPI DeleteJob16(HANDLE16 hJob, WORD wNotUsed)
+{
+    int nRet;
+
+    TRACE("%04x\n", hJob);
+
+    nRet = FreePrintJob(hJob);
+    return nRet;
+}
+
+/* 
+ * The following two function would allow a page to be sent to the printer
+ * when it has been processed.  For simplicity they havn't been implemented.
+ * This means a whole job has to be processed before it is sent to the printer.
+ */
+
+/**********************************************************************
+ *           StartSpoolPage   (GDI.246)
+ *
+ */
+int WINAPI StartSpoolPage16(HANDLE16 hJob)
+{
+    FIXME("StartSpoolPage GDI.246 unimplemented\n");
+    return 1;
+
+}
+
+
+/**********************************************************************
+ *           EndSpoolPage   (GDI.247)
+ *
+ */
+int WINAPI EndSpoolPage16(HANDLE16 hJob)
+{
+    FIXME("EndSpoolPage GDI.247 unimplemented\n");
+    return 1;
+}
+
+
+/**********************************************************************
+ *           GetSpoolJob   (GDI.245)
+ *
+ */
+DWORD WINAPI GetSpoolJob16(int nOption, LONG param)
+{
+    DWORD retval = 0;
+    TRACE("In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
+    return retval;
+}
+
+
 /******************************************************************
  *                  DrvGetPrinterDataInternal
  *
@@ -188,14 +629,14 @@ DWORD WINAPI DrvGetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
     DWORD dwType, PrinterAttr, cbPrinterAttr, SetData, size;
 
     if (HIWORD(lpPrinter))
-            TRACE_(print)("printer %s\n",lpPrinter);
+            TRACE("printer %s\n",lpPrinter);
     else
-            TRACE_(print)("printer %p\n",lpPrinter);
+            TRACE("printer %p\n",lpPrinter);
     if (HIWORD(lpProfile))
-            TRACE_(print)("profile %s\n",lpProfile);
+            TRACE("profile %s\n",lpProfile);
     else
-            TRACE_(print)("profile %p\n",lpProfile);
-    TRACE_(print)("lpType %p\n",lpType);
+            TRACE("profile %p\n",lpProfile);
+    TRACE("lpType %p\n",lpType);
 
     if ((!lpPrinter) || (!lpProfile) || (!lpNeeded))
 	return ERROR_INVALID_PARAMETER;
@@ -281,14 +722,14 @@ DWORD WINAPI DrvSetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
     DWORD res = 0;
 
     if (HIWORD(lpPrinter))
-            TRACE_(print)("printer %s\n",lpPrinter);
+            TRACE("printer %s\n",lpPrinter);
     else
-            TRACE_(print)("printer %p\n",lpPrinter);
+            TRACE("printer %p\n",lpPrinter);
     if (HIWORD(lpProfile))
-            TRACE_(print)("profile %s\n",lpProfile);
+            TRACE("profile %s\n",lpProfile);
     else
-            TRACE_(print)("profile %p\n",lpProfile);
-    TRACE_(print)("lpType %08lx\n",lpType);
+            TRACE("profile %p\n",lpProfile);
+    TRACE("lpType %08lx\n",lpType);
 
     if ((!lpPrinter) || (!lpProfile) ||
     ((DWORD)lpProfile == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
@@ -327,1006 +768,3 @@ DWORD WINAPI DrvSetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
     HeapFree(GetProcessHeap(), 0, RegStr_Printer);
     return res;
 }
-
-
-/******************************************************************
- *              DeviceCapabilities32A    [WINSPOOL.151]
- *
- */
-INT WINAPI DeviceCapabilitiesA(LPCSTR printer,LPCSTR target,WORD z,
-                                   LPSTR a,LPDEVMODEA b)
-{
-    FIXME_(print)("(%s,%s,%d,%p,%p):stub.\n",printer,target,z,a,b);
-    return 1;   	
-}
-
-
-/*****************************************************************************
- *          DeviceCapabilities32W 
- */
-INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
-                                   WORD fwCapability, LPWSTR pOutput,
-                                   const DEVMODEW *pDevMode)
-{
-    FIXME_(print)("(%p,%p,%d,%p,%p): stub\n",
-          pDevice, pPort, fwCapability, pOutput, pDevMode);
-    return -1;
-}
-
-/******************************************************************
- *              DocumentProperties32A   [WINSPOOL.155]
- *
- */
-LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
-                                LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
-                                  LPDEVMODEA pDevModeInput,DWORD fMode )
-{
-    FIXME_(print)("(%d,%d,%s,%p,%p,%ld):stub.\n",
-	hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
-    );
-    return 1;
-}
-
-
-/*****************************************************************************
- *          DocumentProperties32W 
- */
-LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
-                                  LPWSTR pDeviceName,
-                                  LPDEVMODEW pDevModeOutput,
-                                  LPDEVMODEW pDevModeInput, DWORD fMode)
-{
-    FIXME_(print)("(%d,%d,%s,%p,%p,%ld): stub\n",
-          hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
-	  fMode);
-    return -1;
-}
-
-
-/******************************************************************
- *              OpenPrinter32A        [WINSPOOL.196]
- *
- */
-BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
-			     LPPRINTER_DEFAULTSA pDefault)
-{
-    FIXME_(print)("(%s,%p,%p):stub\n",debugstr_a(lpPrinterName), phPrinter,
-          pDefault);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-/******************************************************************
- *              OpenPrinter32W        [WINSPOOL.197]
- *
- */
-BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
-			     LPPRINTER_DEFAULTSW pDefault)
-{
-    FIXME_(print)("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
-          pDefault);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-
-
-
-/******************************************************************
- *              ENUMPRINTERS_GetDWORDFromRegistryA    internal
- *
- * Reads a DWORD from registry KeyName 
- *
- * RETURNS
- *    value on OK or NULL on error
- */
-DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
-				HKEY  hPrinterSettings,  /* handle to registry key */
-				LPSTR KeyName			 /* name key to retrieve string from*/
-){                   
- DWORD DataSize=8;
- DWORD DataType;
- BYTE  Data[8];
- DWORD Result=684;
-
- if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
-  					Data, &DataSize)!=ERROR_SUCCESS)
-	FIXME_(print)("Query of register didn't succeed?");                     
- if (DataType == REG_DWORD_LITTLE_ENDIAN)
- 	Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
- if (DataType == REG_DWORD_BIG_ENDIAN)
- 	Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
- return(Result);
-}
-
-
-/******************************************************************
- *              ENUMPRINTERS_AddStringFromRegistryA    internal
- *
- * Reads a string from registry KeyName and writes it at
- * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
- *
- * RETURNS
- *    FALSE if there is still space left in the buffer.
- */
-BOOL ENUMPRINTERS_AddStringFromRegistryA(
-				HKEY  hPrinterSettings,  /* handle to registry key */
-				LPSTR KeyName,			 /* name key to retrieve string from*/
-                LPSTR* Dest,		     /* pointer to write string addres to */
-                LPBYTE lpbPrinters,      /* buffer which receives info*/
-                LPDWORD dwNextStringPos, /* pos in buffer for next string */
-			    DWORD  dwBufSize,        /* max size of buffer in bytes */
-                BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
-){                   
- DWORD DataSize=34;
- DWORD DataType;
- LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
-
- while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
-  					Data, &DataSize)==ERROR_MORE_DATA)
-    {
-     Data = (LPSTR) realloc(Data, DataSize+2);
-    }
-
- if (DataType == REG_SZ)
- 	{                   
-	 if (bCalcSpaceOnly==FALSE)
-	 *Dest = &lpbPrinters[*dwNextStringPos];
-	 *dwNextStringPos += DataSize+1;
-	 if (*dwNextStringPos > dwBufSize)
-	 	bCalcSpaceOnly=TRUE;
-	 if (bCalcSpaceOnly==FALSE)
-        {
-         if (DataSize==0)		/* DataSize = 0 means empty string, even though*/
-         	*Dest[0]=0;			/* the data itself needs not to be empty */
-         else
-	         strcpy(*Dest, Data);
-        }
- 	}
- else
- 	WARN_(print)("Expected string setting, got something else from registry");
-    
- if (Data)
-    free(Data);
- return(bCalcSpaceOnly);
-}
-
-
-
-/******************************************************************
- *              ENUMPRINTERS_AddInfo2A        internal
- *
- *    Creates a PRINTER_INFO_2A structure at:  lpbPrinters[dwNextStructPos]
- *    for printer PrinterNameKey.
- *    Note that there is no check whether the information really fits!
- *
- * RETURNS
- *    FALSE if there is still space left in the buffer.
- *
- * BUGS:
- *    This function should not only read the registry but also ask the driver
- *    for information.
- */
-BOOL ENUMPRINTERS_AddInfo2A(
-                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
-                   LPBYTE lpbPrinters,   /* buffer which receives info*/
-                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
-                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
-				   DWORD  dwBufSize,        /* max size of buffer in bytes */
-                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
-){                   
- HKEY  hPrinterSettings;
- DWORD DevSize=0;
- DWORD DataType;
- LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
-  										   	   strlen(lpszPrinterName)+2);
- LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
-
- /* open the registry to find the attributes, etc of the printer */
- if (lpszPrinterSettings!=NULL)
- 	{
-     strcpy(lpszPrinterSettings,Printers);
-     strcat(lpszPrinterSettings,lpszPrinterName);
-    }
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
- 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
-	{
-     WARN_(print)("The registry did not contain my printer anymore?\n");
-    }
- else
-    {
-     if (bCalcSpaceOnly==FALSE)
-     lpPInfo2->pServerName = NULL;
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Name", &(lpPInfo2->pPrinterName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Share Name", &(lpPInfo2->pShareName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Port", &(lpPInfo2->pPortName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Printer Driver", &(lpPInfo2->pDriverName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Description", &(lpPInfo2->pComment), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Location", &(lpPInfo2->pLocation), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Separator File", &(lpPInfo2->pSepFile), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Print Processor", &(lpPInfo2->pPrintProcessor), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Datatype", &(lpPInfo2->pDatatype), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Parameters", &(lpPInfo2->pParameters), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     if (bCalcSpaceOnly == FALSE)
-     	{                             
-     lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
-
-     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
-	 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
-	 lpPInfo2->Priority   = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"Priority"); 
-	 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
-     								hPrinterSettings, "Default Priority"); 
-	 lpPInfo2->StartTime  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"StartTime"); 
-	 lpPInfo2->UntilTime  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"UntilTime"); 
-	 lpPInfo2->Status     = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"Status"); 
-	 lpPInfo2->cJobs      = 0;    /* FIXME: according to MSDN, this does not 
-     							   * reflect the TotalJobs Key ??? */
-	 lpPInfo2->AveragePPM = 0;    /* FIXME: according to MSDN, this does not 
-     							   * reflect the TotalPages Key ??? */
-
-     /* and read the devModes structure... */
-      RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
-  					NULL, &DevSize); /* should return ERROR_MORE_DATA */
-	      lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
-      *dwNextStringPos += DevSize + 1;      
-        } 
- if (*dwNextStringPos > dwBufSize)
- 	bCalcSpaceOnly=TRUE;
- if (bCalcSpaceOnly==FALSE)
-	      RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
-  					(LPBYTE)lpPInfo2->pDevMode, &DevSize); 
-	}                                 
-
- if (lpszPrinterSettings)
-	 free(lpszPrinterSettings);
-
- return(bCalcSpaceOnly);     
-}
-
-/******************************************************************
- *              ENUMPRINTERS_AddInfo4A        internal
- *
- *    Creates a PRINTER_INFO_4A structure at:  lpbPrinters[dwNextStructPos]
- *    for printer PrinterNameKey.
- *    Note that there is no check whether the information really fits!
- *
- * RETURNS
- *    FALSE if there is still space left in the buffer.
- *
- * BUGS:
- *    This function should not exist in Win95 mode, but does anyway.
- */
-BOOL ENUMPRINTERS_AddInfo4A(
-                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
-                   LPBYTE lpbPrinters,   /* buffer which receives info*/
-                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
-                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
-				   DWORD  dwBufSize,        /* max size of buffer in bytes */
-                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
-){                   
- HKEY  hPrinterSettings;
- LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
-  										   	   strlen(lpszPrinterName)+2);
- LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
- 
- /* open the registry to find the attributes of the printer */
- if (lpszPrinterSettings!=NULL)
- 	{
-     strcpy(lpszPrinterSettings,Printers);
-     strcat(lpszPrinterSettings,lpszPrinterName);
-    }
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
- 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
-	{
-     WARN_(print)("The registry did not contain my printer anymore?\n");
-    }
- else
-    {
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Name", &(lpPInfo4->pPrinterName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
-     if (bCalcSpaceOnly==FALSE)	                     
-	 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
-    }
- if (lpszPrinterSettings)
-	 free(lpszPrinterSettings);
-
- return(bCalcSpaceOnly);     
-}
-
-/******************************************************************
- *              ENUMPRINTERS_AddInfo5A        internal
- *
- *    Creates a PRINTER_INFO_5A structure at:  lpbPrinters[dwNextStructPos]
- *    for printer PrinterNameKey.
- *    Settings are read from the registry.
- *    Note that there is no check whether the information really fits!
- * RETURNS
- *    FALSE if there is still space left in the buffer.
- */
-BOOL ENUMPRINTERS_AddInfo5A(
-                   LPSTR lpszPrinterName,/* name of printer to fill struct for*/
-                   LPBYTE lpbPrinters,   /* buffer which receives info*/
-                   DWORD  dwNextStructPos,  /* pos in buffer for struct */
-                   LPDWORD dwNextStringPos, /* pos in buffer for next string */
-				   DWORD  dwBufSize,        /* max size of buffer in bytes */
-                   BOOL   bCalcSpaceOnly    /* TRUE if out-of-space in buffer */
-){                   
- HKEY  hPrinterSettings;
- LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
-  										   	   strlen(lpszPrinterName)+2);
- LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
-
- /* open the registry to find the attributes, etc of the printer */
- if (lpszPrinterSettings!=NULL)
- 	{
-     strcpy(lpszPrinterSettings,Printers);
-     strcat(lpszPrinterSettings,lpszPrinterName);
-    }
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, 
- 						KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
-	{
-     WARN_(print)("The registry did not contain my printer anymore?\n");
-    }
- else
-    {
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Name", &(lpPInfo5->pPrinterName), 
-                                  lpbPrinters, dwNextStringPos, 
-                                  dwBufSize, bCalcSpaceOnly);
-     bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, 
-     			                  "Port", &(lpPInfo5->pPortName), lpbPrinters,
-                                  dwNextStringPos, dwBufSize, bCalcSpaceOnly);
-     					  /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
-     if (bCalcSpaceOnly == FALSE)
-   	   {
-	 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"Attributes") +PRINTER_ATTRIBUTE_LOCAL; 
-	 lpPInfo5->DeviceNotSelectedTimeOut 
-     					  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"txTimeout"); 
-	 lpPInfo5->TransmissionRetryTimeout
-     					  = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
-     								"dnsTimeout"); 
-    }
-    }
-    
- if (lpszPrinterSettings)
-	 free(lpszPrinterSettings);
-
- return(bCalcSpaceOnly);     
-}
-
-
-/******************************************************************
- *              EnumPrintersA        [WINSPOOL.174]
- *
- *    Enumerates the available printers, print servers and print
- *    providers, depending on the specified flags, name and level.
- *
- * RETURNS:
- *
- *    If level is set to 1:
- *      Not implemented yet! 
- *      Returns TRUE with an empty list.
- *
- *    If level is set to 2:
- *		Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
- *      Returns an array of PRINTER_INFO_2 data structures in the 
- *      lpbPrinters buffer. Note that according to MSDN also an 
- *      OpenPrinter should be performed on every remote printer.
- *
- *    If level is set to 4 (officially WinNT only):
- *		Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
- *      Fast: Only the registry is queried to retrieve printer names,
- *      no connection to the driver is made.
- *      Returns an array of PRINTER_INFO_4 data structures in the 
- *      lpbPrinters buffer.
- *
- *    If level is set to 5 (officially WinNT4/Win9x only):
- *      Fast: Only the registry is queried to retrieve printer names,
- *      no connection to the driver is made.
- *      Returns an array of PRINTER_INFO_5 data structures in the 
- *      lpbPrinters buffer.
- *
- *    If level set to 3 or 6+:
- *	    returns zero (faillure!)
- *      
- *    Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
- *    for information.
- *
- * BUGS:
- *    - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
- *    - Only levels 2, 4 and 5 are implemented at the moment.
- *    - 16-bit printer drivers are not enumerated.
- *    - Returned amount of bytes used/needed does not match the real Windoze 
- *      implementation (as in this implementation, all strings are part 
- *      of the buffer, whereas Win32 keeps them somewhere else)
- *    - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
- *
- * NOTE:
- *    - In a regular Wine installation, no registry settings for printers
- *      exist, which makes this function return an empty list.
- */
-BOOL  WINAPI EnumPrintersA(
-					DWORD dwType,      /* Types of print objects to enumerate */
-                    LPSTR lpszName,    /* name of objects to enumerate */
-			        DWORD dwLevel,     /* type of printer info structure */
-                    LPBYTE lpbPrinters,/* buffer which receives info*/
-			        DWORD cbBuf,       /* max size of buffer in bytes */
-                    LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */
-			        LPDWORD lpdwReturned/* number of entries returned */
-                   )
-{
- HKEY  hPrinterListKey;
- DWORD dwIndex=0;
- char  PrinterName[255];
- DWORD PrinterNameLength=255;
- FILETIME FileTime;
- DWORD dwNextStringPos;	  /* position of next space for a string in the buffer*/
- DWORD dwStructPrinterInfoSize;	/* size of a Printer_Info_X structure */
- BOOL  bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/
- 
- TRACE_(print)("entered.\n");
-
- /* test whether we're requested to really fill in. If so,
-  * zero out the data area, and initialise some returns to zero,
-  * to prevent problems 
-  */
- if (lpbPrinters==NULL || cbBuf==0)
- 	 bCalcSpaceOnly=TRUE;
- else
- {
-  int i;
-  for (i=0; i<cbBuf; i++)
-  	  lpbPrinters[i]=0;
- }
- *lpdwReturned=0;
- *lpdwNeeded = 0;
-
- /* check for valid Flags */
- if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME)
- 	{
-     SetLastError(ERROR_INVALID_FLAGS);
-     return(0);
-    }
- switch(dwLevel)
- 	{
-     case 1:
-	     return(TRUE);
-     case 2:
-     case 4:
-     case 5:
-     	 break;
-     default:
-     SetLastError(ERROR_INVALID_PARAMETER);
-	     return(FALSE);
-    } 	
-
- /* Enter critical section to prevent AddPrinters() et al. to
-  * modify whilst we're reading in the registry
- */
- InitializeCriticalSection(&PRINT32_RegistryBlocker);
- EnterCriticalSection(&PRINT32_RegistryBlocker);
- 
- /* get a pointer to a list of all printer names in the registry */ 
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
- 				  &hPrinterListKey) !=ERROR_SUCCESS)
- 	{
-     /* Oh no! An empty list of printers!
-      * (which is a valid configuration anyway)
-      */
-     TRACE_(print)("No entries in the Printers part of the registry\n");
-    }
-
- /* count the number of entries and check if it fits in the buffer
-  */
- while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
-                   NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
-    {
-     PrinterNameLength=255;
-     dwIndex++;
-    }
- *lpdwReturned = dwIndex;    
- switch(dwLevel)
- 	{
-     case 1:
-     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
-      	break;
-     case 2:
-     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
-      	break;     
-     case 4:
-     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
-      	break;
-     case 5:
-     	dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
-      	break;
-     default:
-     	dwStructPrinterInfoSize = 0;
-      	break;     
-    } 
- if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
- 	bCalcSpaceOnly = TRUE;
-    
- /* the strings which contain e.g. PrinterName, PortName, etc,
-  * are also stored in lpbPrinters, but after the regular structs.
-  * dwNextStringPos will always point to the next free place for a 
-  * string.
-  */  
- dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;    
-
- /* check each entry: if OK, add to list in corresponding INFO .
-  */    
- for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
-    {
-     PrinterNameLength=255;
-     if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
-                   NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
-     	break;	/* exit for loop*/
-        
-     /* check whether this printer is allowed in the list
-      * by comparing name to lpszName 
-      */
-     if (dwType == PRINTER_ENUM_NAME)
-        if (strcmp(PrinterName,lpszName)!=0)
-        	continue;		
-
-     switch(dwLevel)
-     	{
-         case 1:
-         	/* FIXME: unimplemented */
-            break;
-         case 2:
-            bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
-            					dwIndex*dwStructPrinterInfoSize,
-                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
-            break;
-         case 4:
-            bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
-            					dwIndex*dwStructPrinterInfoSize,
-                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
-            break;
-         case 5:
-            bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
-            					dwIndex*dwStructPrinterInfoSize,
-                                &dwNextStringPos, cbBuf, bCalcSpaceOnly);
-            break;
-        }     	
-    }
- RegCloseKey(hPrinterListKey);
- *lpdwNeeded = dwNextStringPos;
- 
- if (bCalcSpaceOnly==TRUE)
- 	{
-    if  (lpbPrinters!=NULL)
- 		{
-	  int i;
-	  for (i=0; i<cbBuf; i++)
-	  	  lpbPrinters[i]=0;
-	    } 
-     *lpdwReturned=0;    
-    } 
- LeaveCriticalSection(&PRINT32_RegistryBlocker); 
- return(TRUE);
-}
-
-/******************************************************************
- *              EnumPrinters32W        [WINSPOOL.175]
- *
- */
-BOOL  WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
-			       DWORD dwLevel, LPBYTE lpbPrinters,
-			       DWORD cbBuf, LPDWORD lpdwNeeded,
-			       LPDWORD lpdwReturned)
-{
-    FIXME_(print)("Nearly empty stub\n");
-    *lpdwReturned=0;
-    *lpdwNeeded = 0;
-    return TRUE;
-}
-
-/******************************************************************
- *              AddMonitor32A        [WINSPOOL.107]
- *
- */
-BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
-{
-    FIXME_(print)("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-/******************************************************************
- *              DeletePrinterDriver32A        [WINSPOOL.146]
- *
- */
-BOOL WINAPI
-DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
-{
-    FIXME_(print)("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
-          debugstr_a(pDriverName));
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-
-/******************************************************************
- *              DeleteMonitor32A        [WINSPOOL.135]
- *
- */
-BOOL WINAPI
-DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
-{
-    FIXME_(print)("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
-          debugstr_a(pMonitorName));
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-
-/******************************************************************
- *              DeletePort32A        [WINSPOOL.137]
- *
- */
-BOOL WINAPI
-DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
-{
-    FIXME_(print)("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
-          debugstr_a(pPortName));
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-/******************************************************************************
- *    SetPrinter32W  [WINSPOOL.214]
- */
-BOOL WINAPI
-SetPrinterW(
-  HANDLE  hPrinter,
-  DWORD     Level,
-  LPBYTE    pPrinter,
-  DWORD     Command) {
-
-       FIXME_(print)("():stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return FALSE;
-}
-
-/******************************************************************************
- *    WritePrinter32  [WINSPOOL.223]
- */
-BOOL WINAPI
-WritePrinter( 
-  HANDLE  hPrinter,
-  LPVOID  pBuf,
-  DWORD   cbBuf,
-  LPDWORD pcWritten) {
-
-       FIXME_(print)("():stub\n");
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return FALSE;
-}
-
-/*****************************************************************************
- *          AddForm32A  [WINSPOOL.103]
- */
-BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
-{
-    FIXME_(print)("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
-    return 1;
-}
-
-/*****************************************************************************
- *          AddForm32W  [WINSPOOL.104]
- */
-BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
-{
-    FIXME_(print)("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
-    return 1;
-}
-
-/*****************************************************************************
- *          AddJob32A  [WINSPOOL.105]
- */
-BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
-                        DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
-          pcbNeeded);
-    return 1;
-}
-
-/*****************************************************************************
- *          AddJob32W  [WINSPOOL.106]
- */
-BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
-                        LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
-          pcbNeeded);
-    return 1;
-}
-
-/*****************************************************************************
- *          AddPrinter32A  [WINSPOOL.117]
- */
-HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
-{
-    FIXME_(print)("(%s,%ld,%p): stub\n", pName, Level, pPrinter);
-    return 0;
-}
-
-/*****************************************************************************
- *          AddPrinter32W  [WINSPOOL.122]
- */
-HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
-{
-    FIXME_(print)("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
-    return 0;
-}
-
-
-/*****************************************************************************
- *          ClosePrinter32  [WINSPOOL.126]
- */
-BOOL WINAPI ClosePrinter(HANDLE hPrinter)
-{
-    FIXME_(print)("(%d): stub\n", hPrinter);
-    return 1;
-}
-
-/*****************************************************************************
- *          DeleteForm32A  [WINSPOOL.133]
- */
-BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
-{
-    FIXME_(print)("(%d,%s): stub\n", hPrinter, pFormName);
-    return 1;
-}
-
-/*****************************************************************************
- *          DeleteForm32W  [WINSPOOL.134]
- */
-BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
-{
-    FIXME_(print)("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
-    return 1;
-}
-
-/*****************************************************************************
- *          DeletePrinter32  [WINSPOOL.143]
- */
-BOOL WINAPI DeletePrinter(HANDLE hPrinter)
-{
-    FIXME_(print)("(%d): stub\n", hPrinter);
-    return 1;
-}
-
-/*****************************************************************************
- *          SetPrinter32A  [WINSPOOL.211]
- */
-BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
-                           DWORD Command)
-{
-    FIXME_(print)("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          SetJob32A  [WINSPOOL.209]
- */
-BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
-                       LPBYTE pJob, DWORD Command)
-{
-    FIXME_(print)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
-         Command);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          SetJob32W  [WINSPOOL.210]
- */
-BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
-                       LPBYTE pJob, DWORD Command)
-{
-    FIXME_(print)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
-         Command);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetForm32A  [WINSPOOL.181]
- */
-BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
-                 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
-         Level,pForm,cbBuf,pcbNeeded); 
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetForm32W  [WINSPOOL.182]
- */
-BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
-                 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
-	  debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          SetForm32A  [WINSPOOL.207]
- */
-BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
-                        LPBYTE pForm)
-{
-    FIXME_(print)("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          SetForm32W  [WINSPOOL.208]
- */
-BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
-                        LPBYTE pForm)
-{
-    FIXME_(print)("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          ReadPrinter32  [WINSPOOL.202]
- */
-BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
-                           LPDWORD pNoBytesRead)
-{
-    FIXME_(print)("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          ResetPrinter32A  [WINSPOOL.203]
- */
-BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
-{
-    FIXME_(print)("(%d, %p): stub\n", hPrinter, pDefault);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          ResetPrinter32W  [WINSPOOL.204]
- */
-BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
-{
-    FIXME_(print)("(%d, %p): stub\n", hPrinter, pDefault);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetPrinter32A  [WINSPOOL.187]
- */
-BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
-                    DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter, 
-         cbBuf, pcbNeeded);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetPrinter32W  [WINSPOOL.194]
- */
-BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
-                    DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
-          cbBuf, pcbNeeded);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetPrinterDriver32A  [WINSPOOL.190]
- */
-BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
-                                 DWORD Level, LPBYTE pDriverInfo,
-                                 DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
-         Level,pDriverInfo,cbBuf, pcbNeeded);
-    return FALSE;
-}
-
-/*****************************************************************************
- *          GetPrinterDriver32W  [WINSPOOL.193]
- */
-BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
-                                  DWORD Level, LPBYTE pDriverInfo, 
-                                  DWORD cbBuf, LPDWORD pcbNeeded)
-{
-    FIXME_(print)("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
-          Level,pDriverInfo,cbBuf, pcbNeeded);
-    return FALSE;
-}
-/*****************************************************************************
- *          AddPrinterDriver32A  [WINSPOOL.120]
- */
-BOOL WINAPI AddPrinterDriverA(LPSTR printerName,DWORD level, 
-				   LPBYTE pDriverInfo)
-{
-    FIXME_(print)("(%s,%ld,%p): stub\n",printerName,level,pDriverInfo);
-    return FALSE;
-}
-/*****************************************************************************
- *          AddPrinterDriver32W  [WINSPOOL.121]
- */
-BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level, 
-				   LPBYTE pDriverInfo)
-{
-    FIXME_(print)("(%s,%ld,%p): stub\n",debugstr_w(printerName),
-	  level,pDriverInfo);
-    return FALSE;
-}
-
-
-/*****************************************************************************
- *          PrinterProperties  [WINSPOOL.201]
- *
- *     Displays a dialog to set the properties of the printer.
- *
- * RETURNS 
- *     nonzero on succes or zero on faillure
- *
- * BUGS
- *	   implemented as stub only
- */
-BOOL WINAPI PrinterProperties(HWND hWnd,      /* handle to parent window */
-                              HANDLE hPrinter /* handle to printer object */
-){
-    FIXME_(print)("(%d,%d): stub\n", hWnd, hPrinter);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
-}
-
-
diff --git a/misc/spooler.c b/misc/spooler.c
deleted file mode 100644
index dbddc2940e..0000000000
--- a/misc/spooler.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Print spooler and PQ functions
- *
- * Copyright 1996 John Harvey
- *           1998 Huw Davies
- *
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "winbase.h"
-#include "wine/winuser16.h"
-#include "callback.h"
-#include "dc.h"
-#include "debug.h"
-#include "gdi.h"
-#include "options.h"
-#include "winerror.h"
-#include "xmalloc.h"
-
-DEFAULT_DEBUG_CHANNEL(print)
-
-/**********************************************************************
- *           QueryAbort   (GDI.155)
- *
- *  Calls the app's AbortProc function if avail.
- *
- * RETURNS
- * TRUE if no AbortProc avail or AbortProc wants to continue printing.
- * FALSE if AbortProc wants to abort printing.
- */
-BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
-{
-    DC *dc = DC_GetDCPtr( hdc );
-
-    if ((!dc) || (!dc->w.lpfnPrint))
-	return TRUE;
-    return Callbacks->CallDrvAbortProc(dc->w.lpfnPrint, hdc, 0);
-}
-
-/**********************************************************************
- *           SetAbortProc16   (GDI.381)
- *
- */
-INT16 WINAPI SetAbortProc16(HDC16 hdc, SEGPTR abrtprc)
-{
-    return Escape16(hdc, SETABORTPROC, 0, abrtprc, (SEGPTR)0);
-} 
-
-/**********************************************************************
- *           SetAbortProc32   (GDI32.301)
- *
- */
-INT WINAPI SetAbortProc(HDC hdc, ABORTPROC abrtprc)
-{
-    FIXME(print, "stub\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return SP_ERROR;
-}
-
-
-/****************** misc. printer related functions */
-
-/*
- * The following function should implement a queing system
- */
-#ifndef HPQ 
-#define HPQ WORD
-#endif
-struct hpq 
-{
-    struct hpq 	*next;
-    int		 tag;
-    int		 key;
-};
-
-static struct hpq *hpqueue;
-
-/**********************************************************************
- *           CreatePQ   (GDI.230)
- *
- */
-HPQ WINAPI CreatePQ16(int size) 
-{
-#if 0
-    HGLOBAL16 hpq = 0;
-    WORD tmp_size;
-    LPWORD pPQ;
-
-    tmp_size = size << 2;
-    if (!(hpq = GlobalAlloc16(GMEM_SHARE|GMEM_MOVEABLE, tmp_size + 8)))
-       return 0xffff;
-    pPQ = GlobalLock16(hpq);
-    *pPQ++ = 0;
-    *pPQ++ = tmp_size;
-    *pPQ++ = 0;
-    *pPQ++ = 0;
-    GlobalUnlock16(hpq);
-
-    return (HPQ)hpq;
-#else
-    FIXME(print, "(%d): stub\n",size);
-    return 1;
-#endif
-}
-
-/**********************************************************************
- *           DeletePQ   (GDI.235)
- *
- */
-int WINAPI DeletePQ16(HPQ hPQ) 
-{
-    return GlobalFree16((HGLOBAL16)hPQ);
-}
-
-/**********************************************************************
- *           ExtractPQ   (GDI.232)
- *
- */
-int WINAPI ExtractPQ16(HPQ hPQ) 
-{ 
-    struct hpq *queue, *prev, *current, *currentPrev;
-    int key = 0, tag = -1;
-    currentPrev = prev = NULL;
-    queue = current = hpqueue;
-    if (current)
-        key = current->key;
-    
-    while (current)
-    {
-        currentPrev = current;
-        current = current->next;
-        if (current)
-        {
-            if (current->key < key)
-            {
-                queue = current;
-                prev = currentPrev;
-            }
-        }
-    }
-    if (queue)
-    {
-        tag = queue->tag;
-        
-        if (prev)
-            prev->next = queue->next;
-        else
-            hpqueue = queue->next;
-        free(queue);
-    }
-    
-    TRACE(print, "%x got tag %d key %d\n", hPQ, tag, key); 
-
-    return tag;
-}
-
-/**********************************************************************
- *           InsertPQ   (GDI.233)
- *
- */
-int WINAPI InsertPQ16(HPQ hPQ, int tag, int key) 
-{
-    struct hpq *queueItem = xmalloc(sizeof(struct hpq));
-    queueItem->next = hpqueue;
-    hpqueue = queueItem;
-    queueItem->key = key;
-    queueItem->tag = tag;
-    
-    FIXME(print, "(%x %d %d): stub???\n", hPQ, tag, key);
-    return TRUE;
-}
-
-/**********************************************************************
- *           MinPQ   (GDI.231)
- *
- */
-int WINAPI MinPQ16(HPQ hPQ) 
-{
-    FIXME(print, "(%x): stub\n", hPQ); 
-    return 0;
-}
-
-/**********************************************************************
- *           SizePQ   (GDI.234)
- *
- */
-int WINAPI SizePQ16(HPQ hPQ, int sizechange) 
-{  
-    FIXME(print, "(%x %d): stub\n", hPQ, sizechange); 
-    return -1; 
-}
-
-
-
-/* 
- * The following functions implement part of the spooling process to 
- * print manager.  I would like to see wine have a version of print managers
- * that used LPR/LPD.  For simplicity print jobs will be sent to a file for
- * now.
- */
-typedef struct PRINTJOB
-{
-    char	*pszOutput;
-    char 	*pszTitle;
-    HDC16  	hDC;
-    HANDLE16 	hHandle;
-    int		nIndex;
-    int		fd;
-} PRINTJOB, *PPRINTJOB;
-
-#define MAX_PRINT_JOBS 1
-#define SP_OK 1
-
-PPRINTJOB gPrintJobsTable[MAX_PRINT_JOBS];
-
-
-static PPRINTJOB FindPrintJobFromHandle(HANDLE16 hHandle)
-{
-    return gPrintJobsTable[0];
-}
-
-/* TTD Need to do some DOS->UNIX file conversion here */
-static int CreateSpoolFile(LPSTR pszOutput)
-{
-    int fd=-1;
-    char psCmd[1024];
-    char *psCmdP = psCmd;
-
-    /* TTD convert the 'output device' into a spool file name */
-
-    if (pszOutput == NULL || *pszOutput == '\0')
-      return -1;
-
-    PROFILE_GetWineIniString( "spooler", pszOutput, "", psCmd, sizeof(psCmd) );
-    TRACE(print, "Got printerSpoolCommand '%s' for output device '%s'\n",
-	  psCmd, pszOutput);
-    if (!*psCmd)
-        psCmdP = pszOutput;
-    else
-    {
-        while (*psCmdP && isspace(*psCmdP))
-        {
-            psCmdP++;
-        };
-        if (!*psCmdP)
-            return -1;
-    }
-    if (*psCmdP == '|')
-    {
-        int fds[2];
-        if (pipe(fds))
-            return -1;
-        if (fork() == 0)
-        {
-            psCmdP++;
-
-            TRACE(print, "In child need to exec %s\n",psCmdP);
-            close(0);
-            dup2(fds[0],0);
-            close (fds[1]);
-            system(psCmdP);
-            exit(0);
-            
-        }
-        close (fds[0]);
-        fd = fds[1];
-        TRACE(print,"Need to execute a cmnd and pipe the output to it\n");
-    }
-    else
-    {
-        TRACE(print, "Just assume its a file\n");
-
-        if ((fd = open(psCmdP, O_CREAT | O_TRUNC | O_WRONLY , 0600)) < 0)
-        {
-            ERR(print, "Failed to create spool file %s, errno = %d\n", 
-		psCmdP, errno);
-        }
-    }
-    return fd;
-}
-
-static int FreePrintJob(HANDLE16 hJob)
-{
-    int nRet = SP_ERROR;
-    PPRINTJOB pPrintJob;
-
-    pPrintJob = FindPrintJobFromHandle(hJob);
-    if (pPrintJob != NULL)
-    {
-	gPrintJobsTable[pPrintJob->nIndex] = NULL;
-	free(pPrintJob->pszOutput);
-	free(pPrintJob->pszTitle);
-	if (pPrintJob->fd >= 0) close(pPrintJob->fd);
-	free(pPrintJob);
-	nRet = SP_OK;
-    }
-    return nRet;
-}
-
-/**********************************************************************
- *           OpenJob   (GDI.240)
- *
- */
-HANDLE16 WINAPI OpenJob16(LPSTR lpOutput, LPSTR lpTitle, HDC16 hDC)
-{
-    HANDLE16 hHandle = (HANDLE16)SP_ERROR;
-    PPRINTJOB pPrintJob;
-
-    TRACE(print, "'%s' '%s' %04x\n", lpOutput, lpTitle, hDC);
-
-    pPrintJob = gPrintJobsTable[0];
-    if (pPrintJob == NULL)
-    {
-	int fd;
-
-	/* Try an create a spool file */
-	fd = CreateSpoolFile(lpOutput);
-	if (fd >= 0)
-	{
-	    hHandle = 1;
-
-	    pPrintJob = xmalloc(sizeof(PRINTJOB));
-	    memset(pPrintJob, 0, sizeof(PRINTJOB));
-
-	    pPrintJob->pszOutput = strdup(lpOutput);
-	    if(lpTitle)
-	        pPrintJob->pszTitle = strdup(lpTitle);
-	    pPrintJob->hDC = hDC;
-	    pPrintJob->fd = fd;
-	    pPrintJob->nIndex = 0;
-	    pPrintJob->hHandle = hHandle; 
-	    gPrintJobsTable[pPrintJob->nIndex] = pPrintJob; 
-	}
-    }
-    TRACE(print, "return %04x\n", hHandle);
-    return hHandle;
-}
-
-/**********************************************************************
- *           CloseJob   (GDI.243)
- *
- */
-int WINAPI CloseJob16(HANDLE16 hJob)
-{
-    int nRet = SP_ERROR;
-    PPRINTJOB pPrintJob = NULL;
-
-    TRACE(print, "%04x\n", hJob);
-
-    pPrintJob = FindPrintJobFromHandle(hJob);
-    if (pPrintJob != NULL)
-    {
-	/* Close the spool file */
-	close(pPrintJob->fd);
-	FreePrintJob(hJob);
-	nRet  = 1;
-    }
-    return nRet;
-}
-
-/**********************************************************************
- *           WriteSpool   (GDI.241)
- *
- */
-int WINAPI WriteSpool16(HANDLE16 hJob, LPSTR lpData, WORD cch)
-{
-    int nRet = SP_ERROR;
-    PPRINTJOB pPrintJob = NULL;
-
-    TRACE(print, "%04x %08lx %04x\n", hJob, (DWORD)lpData, cch);
-
-    pPrintJob = FindPrintJobFromHandle(hJob);
-    if (pPrintJob != NULL && pPrintJob->fd >= 0 && cch)
-    {
-	if (write(pPrintJob->fd, lpData, cch) != cch)
-	  nRet = SP_OUTOFDISK;
-	else
-	  nRet = cch;
-	if (pPrintJob->hDC == 0) {
-	    TRACE(print, "hDC == 0 so no QueryAbort\n");
-	}
-        else if (!(QueryAbort16(pPrintJob->hDC, (nRet == SP_OUTOFDISK) ? nRet : 0 )))
-	{
-	    CloseJob16(hJob); /* printing aborted */
-	    nRet = SP_APPABORT;
-	}
-    }
-    return nRet;
-}
-
-/**********************************************************************
- *           WriteDialog   (GDI.242)
- *
- */
-int WINAPI WriteDialog16(HANDLE16 hJob, LPSTR lpMsg, WORD cchMsg)
-{
-    int nRet = 0;
-
-    TRACE(print, "%04x %04x '%s'\n", hJob,  cchMsg, lpMsg);
-
-    nRet = MessageBox16(0, lpMsg, "Printing Error", MB_OKCANCEL);
-    return nRet;
-}
-
-
-/**********************************************************************
- *           DeleteJob  (GDI.244)
- *
- */
-int WINAPI DeleteJob16(HANDLE16 hJob, WORD wNotUsed)
-{
-    int nRet;
-
-    TRACE(print, "%04x\n", hJob);
-
-    nRet = FreePrintJob(hJob);
-    return nRet;
-}
-
-/* 
- * The following two function would allow a page to be sent to the printer
- * when it has been processed.  For simplicity they havn't been implemented.
- * This means a whole job has to be processed before it is sent to the printer.
- */
-
-/**********************************************************************
- *           StartSpoolPage   (GDI.246)
- *
- */
-int WINAPI StartSpoolPage16(HANDLE16 hJob)
-{
-    FIXME(print, "StartSpoolPage GDI.246 unimplemented\n");
-    return 1;
-
-}
-
-
-/**********************************************************************
- *           EndSpoolPage   (GDI.247)
- *
- */
-int WINAPI EndSpoolPage16(HANDLE16 hJob)
-{
-    FIXME(print, "EndSpoolPage GDI.247 unimplemented\n");
-    return 1;
-}
-
-
-/**********************************************************************
- *           GetSpoolJob   (GDI.245)
- *
- */
-DWORD WINAPI GetSpoolJob16(int nOption, LONG param)
-{
-    DWORD retval = 0;
-    TRACE(print, "In GetSpoolJob param 0x%lx noption %d\n",param, nOption);
-    return retval;
-}
diff --git a/objects/dc.c b/objects/dc.c
index 48997179ef..b8a8ed544b 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -503,12 +503,18 @@ BOOL WINAPI RestoreDC( HDC hdc, INT level )
  *           CreateDC16    (GDI.53)
  */
 HDC16 WINAPI CreateDC16( LPCSTR driver, LPCSTR device, LPCSTR output,
-                         const DEVMODE16 *initData )
+                         const DEVMODEA *initData )
 {
     DC * dc;
     const DC_FUNCTIONS *funcs;
+    char buf[300];
 
-    if (!(funcs = DRIVER_FindDriver( driver ))) return 0;
+    if (device) {
+	if(!DRIVER_GetDriverName( device, buf, sizeof(buf) )) return 0;
+    } else
+        strcpy(buf, driver);
+
+    if (!(funcs = DRIVER_FindDriver( buf ))) return 0;
     if (!(dc = DC_AllocDC( funcs ))) return 0;
     dc->w.flags = 0;
 
@@ -535,7 +541,7 @@ HDC16 WINAPI CreateDC16( LPCSTR driver, LPCSTR device, LPCSTR output,
 HDC WINAPI CreateDCA( LPCSTR driver, LPCSTR device, LPCSTR output,
                           const DEVMODEA *initData )
 {
-    return CreateDC16( driver, device, output, (const DEVMODE16 *)initData );
+    return CreateDC16( driver, device, output, (const DEVMODEA *)initData );
 }
 
 
@@ -549,7 +555,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
     LPSTR deviceA = HEAP_strdupWtoA( GetProcessHeap(), 0, device );
     LPSTR outputA = HEAP_strdupWtoA( GetProcessHeap(), 0, output );
     HDC res = CreateDC16( driverA, deviceA, outputA,
-                            (const DEVMODE16 *)initData /*FIXME*/ );
+                            (const DEVMODEA *)initData /*FIXME*/ );
     HeapFree( GetProcessHeap(), 0, driverA );
     HeapFree( GetProcessHeap(), 0, deviceA );
     HeapFree( GetProcessHeap(), 0, outputA );
@@ -561,7 +567,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output,
  *           CreateIC16    (GDI.153)
  */
 HDC16 WINAPI CreateIC16( LPCSTR driver, LPCSTR device, LPCSTR output,
-                         const DEVMODE16* initData )
+                         const DEVMODEA* initData )
 {
       /* Nothing special yet for ICs */
     return CreateDC16( driver, device, output, initData );
@@ -702,7 +708,7 @@ BOOL WINAPI DeleteDC( HDC hdc )
 /***********************************************************************
  *           ResetDC16    (GDI.376)
  */
-HDC16 WINAPI ResetDC16( HDC16 hdc, const DEVMODE16 *devmode )
+HDC16 WINAPI ResetDC16( HDC16 hdc, const DEVMODEA *devmode )
 {
     FIXME(dc, "stub\n" );
     return hdc;
@@ -745,9 +751,33 @@ INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     INT ret;
+    POINT pt;
 
     if (!dc) return 0;
 
+    /* Device capabilities for the printer */
+    switch (cap)
+    {
+    case PHYSICALWIDTH:
+        if(Escape(hdc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.x;
+    case PHYSICALHEIGHT:
+	if(Escape(hdc, GETPHYSPAGESIZE, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.y;
+    case PHYSICALOFFSETX:
+	if(Escape(hdc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.x;
+    case PHYSICALOFFSETY:
+	if(Escape(hdc, GETPRINTINGOFFSET, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.y;
+    case SCALINGFACTORX:
+	if(Escape(hdc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.x;
+    case SCALINGFACTORY:
+	if(Escape(hdc, GETSCALINGFACTOR, 0, NULL, (LPVOID)&pt) > 0)
+	    return pt.y;
+    }
+
     if ((cap < 0) || (cap > sizeof(DeviceCaps)-sizeof(WORD)))
     {
       GDI_HEAP_UNLOCK( hdc );