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>

diff --git a/misc/printdrv.c b/misc/printdrv.c
index 2fbafdf..2aac7a9 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 @@
 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 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 @@
  */
 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 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 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 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 @@
  */
 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 @@
  */
 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 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 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 @@
     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;
-}
-
-