[PATCH 2/2] winspool+localspl: Move AddPrinterW implementation to localspl [v2]

Detlef Riekenberg wine.dev at web.de
Fri Feb 16 18:42:39 CST 2018


We need to move AddPrinter to allow importing CUPS printers
centralized in the spooler service. (bug 3507, bug 10358)

localspl will be used from the application (through winspool.drv)
and from the spooler service (through spoolss.dll)

The changes before and after the code move are as minimal as possible

v2:
updates related to Huw comments.

Could you explain a bit more about where this going?  How much more will
need to move to localspl to enable this to happen?  Is it possible for
the spooler service to use winspool.drv instead of spoolss.dll?

I did not made all changes yet.
My plan is to change things in small steps and only the code needed to fix
3507/10358 (and everything needed for android)
Afterwards the virtual pdf printer

>> +static const WCHAR providerW[] = {'P','r','o','v','i','d','e','r',0};

> providerW is unused.

thanks, fixed

>> +    if(buffer) {
> I know this is copied from winspool.drv, but let's try to be consistent
> with the formatting and put that brace on a new line.  Same for other K&R
> style hunks below.

fixed

> Calling back to winspool.drv seems awkward.  You could simply have winspool.drv set
> pi->pDevMode before calling localspl.  Of course, that leaves the question of what
> spoolss should do, but that depends on what your answers are to the first questions.

That is only temporary, until DrvConvertDevMode is ready
I changed the comments to make this clear.

The cleanest way would be moving the cups/lpr implementation
to localspl
and then use the code from winspool.drv and the spooler service.

--
bye bye ... Detlef

Signed-off-by: Detlef Riekenberg <wine.dev at web.de>

---
 dlls/localspl/provider.c | 353 ++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/winspool.drv/info.c | 184 ++++--------------------
 2 files changed, 378 insertions(+), 159 deletions(-)

diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c
index 3538947..fe5955d 100644
--- a/dlls/localspl/provider.c
+++ b/dlls/localspl/provider.c
@@ -94,13 +94,22 @@ static monitor_t * pm_localport;
 
 static const PRINTPROVIDOR * pprovider = NULL;
 
+static const WCHAR attributesW[] = {'A','t','t','r','i','b','u','t','e','s',0};
 static const WCHAR backslashW[] = {'\\',0};
 static const WCHAR bs_ports_bsW[] = {'\\','P','o','r','t','s','\\',0};
+static const WCHAR commaW[] = {',',0};
 static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0};
 static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0};
 static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0};
+static const WCHAR default_devmodeW[] = {'D','e','f','a','u','l','t',' ','D','e','v','M','o','d','e',0}; //
+static const WCHAR default_priorityW[] = {'D','e','f','a','u','l','t',' ','P','r','i','o','r','i','t','y',0};
 static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0};
+static const WCHAR descriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
+static const WCHAR devicesW[] = {'d','e','v','i','c','e','s',0};
+static const WCHAR dnstimeoutW[] = {'d','n','s','T','i','m','e','o','u','t',0};
+static const WCHAR driver_nt[] = {'w','i','n','e','p','s','.','d','r','v',0};
 static const WCHAR driverW[] = {'D','r','i','v','e','r',0};
+static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
 static const WCHAR emptyW[] = {0};
 static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\',
                                   'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
@@ -118,6 +127,7 @@ static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0};
 static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0};
 static const WCHAR ia64_subdirW[] = {'i','a','6','4',0};
 static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0};
+static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0};
 static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0};
 static const WCHAR monitorsW[] = {'S','y','s','t','e','m','\\',
                                 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
@@ -125,15 +135,28 @@ static const WCHAR monitorsW[] = {'S','y','s','t','e','m','\\',
                                 'P','r','i','n','t','\\',
                                 'M','o','n','i','t','o','r','s','\\',0};
 static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0};
+static const WCHAR nameW[] = {'N','a','m','e',0};
+static const WCHAR parametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
+static const WCHAR portW[] = {'P','o','r','t',0};
 static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0};
+static const WCHAR print_processorW[] = {'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r',0};
+static const WCHAR printerportsW[] = {'P','r','i','n','t','e','r','P','o','r','t','s',0};
 static const WCHAR printersW[] = {'S','y','s','t','e','m','\\',
                                   'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
                                   'C','o','n','t','r','o','l','\\',
                                   'P','r','i','n','t','\\',
                                   'P','r','i','n','t','e','r','s',0};
-static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0};
-static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0};
+static const WCHAR printer_driverW[] = {'P','r','i','n','t','e','r',' ','D','r','i','v','e','r',0};
+static const WCHAR priorityW[] = {'P','r','i','o','r','i','t','y',0};
+static const WCHAR separator_fileW[] = {'S','e','p','a','r','a','t','o','r',' ','F','i','l','e',0};
+static const WCHAR share_nameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
 static const WCHAR spoolprtprocsW[] = {'\\','s','p','o','o','l','\\','p','r','t','p','r','o','c','s','\\',0};
+static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0};
+static const WCHAR starttimeW[] = {'S','t','a','r','t','T','i','m','e',0};
+static const WCHAR statusW[] = {'S','t','a','t','u','s',0};
+static const WCHAR timeout_15_45[] = {',','1','5',',','4','5',0};
+static const WCHAR txtimeoutW[] = {'t','x','T','i','m','e','o','u','t',0};
+static const WCHAR untiltimeW[] = {'U','n','t','i','l','T','i','m','e',0};
 static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0};
 static const WCHAR version0_subdirW[] = {'\\','0',0};
 static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0};
@@ -141,12 +164,23 @@ static const WCHAR version3_subdirW[] = {'\\','3',0};
 static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0};
 static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
 static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0};
+static const WCHAR winnt_cv_devicesW[] = {'S','o','f','t','w','a','r','e','\\',
+                                          'M','i','c','r','o','s','o','f','t','\\',
+                                          'W','i','n','d','o','w','s',' ','N','T','\\',
+                                          'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+                                          'D','e','v','i','c','e','s',0};
 static const WCHAR winnt_cv_portsW[] = {'S','o','f','t','w','a','r','e','\\',
                                         'M','i','c','r','o','s','o','f','t','\\',
                                         'W','i','n','d','o','w','s',' ','N','T','\\',
                                         'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
                                         'P','o','r','t','s',0};
+static const WCHAR winnt_cv_printerportsW[] = {'S','o','f','t','w','a','r','e','\\',
+                                               'M','i','c','r','o','s','o','f','t','\\',
+                                               'W','i','n','d','o','w','s',' ','N','T','\\',
+                                               'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+                                               'P','r','i','n','t','e','r','P','o','r','t','s',0};
 static const WCHAR winprintW[] = {'w','i','n','p','r','i','n','t',0};
+static const WCHAR winspooldrvW[] = {'w','i','n','s','p','o','o','l','.','d','r','v',0};
 static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0};
 static const WCHAR x64_subdirW[] = {'x','6','4',0};
 static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
@@ -177,6 +211,50 @@ static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_
 
 
 /******************************************************************
+ * set_reg_DWORD [internal]
+ *
+ * Save a DWORD in the registry
+ *
+ */
+static inline DWORD set_reg_DWORD( HKEY hkey, const WCHAR *keyname, const DWORD value )
+{
+    return RegSetValueExW( hkey, keyname, 0, REG_DWORD, (const BYTE*)&value, sizeof(value) );
+}
+
+/******************************************************************
+ * set_reg_szW [internal]
+ *
+ * Save a WSTR to the registry
+ *
+ */
+static inline DWORD set_reg_szW(HKEY hkey, const WCHAR *keyname, const WCHAR *value)
+{
+    if (value)
+        return RegSetValueExW(hkey, keyname, 0, REG_SZ, (const BYTE*)value,
+                              (lstrlenW(value) + 1) * sizeof(WCHAR));
+    else
+        return ERROR_FILE_NOT_FOUND;
+}
+
+/******************************************************************
+ * set_reg_devmode [internal]
+ *
+ * Save a DEVNODEW in the registry
+ *
+ */
+static inline DWORD set_reg_devmode( HKEY key, const WCHAR *name, const DEVMODEW *dm )
+{
+    if (dm)
+    {
+        return RegSetValueExW( key, name, 0, REG_BINARY,
+                              (LPBYTE)dm, dm->dmSize + dm->dmDriverExtra );
+    }
+    else
+        return ERROR_FILE_NOT_FOUND;
+}
+
+
+/******************************************************************
  * strdupW [internal]
  *
  * create a copy of a unicode-string
@@ -1678,6 +1756,275 @@ static BOOL WINAPI fpAddPortEx(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR
     return res;
 }
 
+/*****************************************************************************
+ * localspl_OpenDriverReg [internal]
+ *
+ * opens the registry for the printer drivers depending on the given input
+ * variable pEnvironment
+ *
+ * RETURNS:
+ *    the opened hkey on success
+ *    NULL on error
+ */
+static HKEY localspl_OpenDriverReg(LPCWSTR pEnvironment)
+{
+    HKEY retval = NULL;
+    LPWSTR buffer;
+    const printenv_t * env;
+
+    TRACE("(%s)\n", debugstr_w(pEnvironment));
+
+    env = validate_envW(pEnvironment);
+    if (!env) return NULL;
+
+    buffer = heap_alloc((strlenW(fmt_driversW) + strlenW(env->envname) + strlenW(env->versionregpath) + 1) * sizeof(WCHAR));
+
+    if(buffer)
+    {
+        wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath);
+        RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval);
+        heap_free(buffer);
+    }
+    return retval;
+}
+
+/*****************************************************************************
+ * set_devices_and_printerports [internal]
+ *
+ * set the [Devices] and [PrinterPorts] entries for a printer.
+ *
+ */
+static void set_devices_and_printerports(PRINTER_INFO_2W *pi)
+{
+    DWORD portlen = lstrlenW(pi->pPortName) * sizeof(WCHAR);
+    WCHAR *devline;
+    HKEY  hkey;
+
+    TRACE("(%p) %s\n", pi, debugstr_w(pi->pPrinterName));
+
+    /* FIXME: the driver must change to "winspool" */
+    devline = heap_alloc(sizeof(driver_nt) + portlen + sizeof(timeout_15_45));
+    if (devline)
+    {
+        lstrcpyW(devline, driver_nt);
+        lstrcatW(devline, commaW);
+        lstrcatW(devline, pi->pPortName);
+
+        TRACE("using %s\n", debugstr_w(devline));
+        WriteProfileStringW(devicesW, pi->pPrinterName, devline);
+        if (!RegCreateKeyW(HKEY_CURRENT_USER, winnt_cv_devicesW, &hkey))
+        {
+            RegSetValueExW(hkey, pi->pPrinterName, 0, REG_SZ, (LPBYTE)devline,
+                            (lstrlenW(devline) + 1) * sizeof(WCHAR));
+            RegCloseKey(hkey);
+        }
+
+        lstrcatW(devline, timeout_15_45);
+        WriteProfileStringW(printerportsW, pi->pPrinterName, devline);
+        if (!RegCreateKeyW(HKEY_CURRENT_USER, winnt_cv_printerportsW, &hkey))
+        {
+            RegSetValueExW(hkey, pi->pPrinterName, 0, REG_SZ, (LPBYTE)devline,
+                            (lstrlenW(devline) + 1) * sizeof(WCHAR));
+            RegCloseKey(hkey);
+        }
+        heap_free(devline);
+    }
+}
+
+/******************************************************************************
+ * get_default_devmode [internal]
+ *
+ * Get the default DEVMODE from the driver interface dll
+ * using DrvConvertDevMode with CDM_DRIVER_DEFAULT
+ *
+ */
+
+static WINAPI DEVMODEW * get_default_devmode(LPWSTR printername, LPWSTR drivername)
+{
+
+    LONG size;
+    HMODULE hwinspool;
+    DEVMODEW * dm = NULL;
+    LONG (WINAPI * pDocumentPropertiesW)(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName,
+                                         LPDEVMODEW pDevModeOutput, LPDEVMODEW pDevModeInput, DWORD fMode);
+
+    TRACE("printername: %s, drivername: %s\n", debugstr_w(printername), debugstr_w(drivername));
+
+    /* Fallback, until DrvConvertDevMode is supported */
+    hwinspool = LoadLibraryW(winspooldrvW);
+    if (!hwinspool) return NULL;
+
+    pDocumentPropertiesW = (void *) GetProcAddress(hwinspool, "DocumentPropertiesW");
+    if (!pDocumentPropertiesW)
+    {
+        FreeLibrary(hwinspool);
+        return NULL;
+    }
+
+    size = pDocumentPropertiesW(0, 0, printername, NULL, NULL, 0);
+
+    if (size < 0)
+    {
+        FIXME("DocumentPropertiesW on printer %s failed\n", debugstr_w(printername));
+        size = sizeof(DEVMODEW);
+    }
+
+
+    dm = heap_alloc_zero(size );
+    dm->dmSize = size;
+    if (pDocumentPropertiesW(0, 0, printername, dm, NULL, DM_OUT_BUFFER) < 0)
+    {
+        WARN("DocumentPropertiesW on printer %s failed!\n", debugstr_w(printername));
+        heap_free( dm );
+        dm = NULL;
+    }
+    else
+    {
+        /* set devmode to printer name */
+        lstrcpynW( dm->dmDeviceName, printername, CCHDEVICENAME );
+    }
+
+    FreeLibrary(hwinspool);
+    return dm;
+}
+
+/******************************************************************************
+ * fpAddPrinter [exported through PRINTPROVIDOR]
+ *
+ * Install a Printer with various Printer Parameter
+ *
+ * PARAMS
+ *  pName       [I] Servername or NULL (local Computer)
+ *  Level       [I] Level for the supplied PRINTER_INFO_*W struct
+ *  pPrinter    [I] PTR to PRINTER_INFO_*W struct with the Printer Parameter
+ *
+ * RESULTS
+ *  A Handle for the printer
+ *
+ */
+static HANDLE WINAPI fpAddPrinter(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
+{
+    PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
+    LPDEVMODEW dm;
+    HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
+
+    TRACE("(%s,%d,%p)\n", debugstr_w(pName), Level, pPrinter);
+
+    if(pName && *pName)
+    {
+        ERR("pName = %s - unsupported\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    if(Level != 2)
+    {
+        ERR("Level = %d, unsupported!\n", Level);
+        SetLastError(ERROR_INVALID_LEVEL);
+        return 0;
+    }
+
+    if(!pPrinter)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+
+    if(RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkeyPrinters) != ERROR_SUCCESS)
+    {
+        ERR("Can't create Printers key\n");
+        return 0;
+    }
+
+    if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter))
+    {
+        if (!RegQueryValueW(hkeyPrinter, attributesW, NULL, NULL))
+        {
+            SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
+            RegCloseKey(hkeyPrinter);
+            RegCloseKey(hkeyPrinters);
+            return 0;
+        }
+        RegCloseKey(hkeyPrinter);
+    }
+
+    hkeyDrivers = localspl_OpenDriverReg(NULL);
+
+    if(!hkeyDrivers)
+    {
+        ERR("Can't create Drivers key\n");
+        RegCloseKey(hkeyPrinters);
+        return 0;
+    }
+
+    if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) != ERROR_SUCCESS)
+    {
+        WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
+        RegCloseKey(hkeyPrinters);
+        RegCloseKey(hkeyDrivers);
+        SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
+        return 0;
+    }
+
+    RegCloseKey(hkeyDriver);
+    RegCloseKey(hkeyDrivers);
+
+    /* FIXME: We should accept all installed PrintProcessor */
+    if(lstrcmpiW(pi->pPrintProcessor, winprintW))
+    {
+        FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
+        SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
+        RegCloseKey(hkeyPrinters);
+        return 0;
+    }
+
+    if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) != ERROR_SUCCESS)
+    {
+        FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
+        SetLastError(ERROR_INVALID_PRINTER_NAME);
+        RegCloseKey(hkeyPrinters);
+        return 0;
+    }
+
+    set_reg_DWORD(hkeyPrinter, attributesW, pi->Attributes);
+    set_reg_szW(hkeyPrinter,   datatypeW, pi->pDatatype);
+    set_reg_DWORD(hkeyPrinter, default_priorityW, pi->DefaultPriority);
+    set_reg_szW(hkeyPrinter,   descriptionW, pi->pComment);
+    set_reg_DWORD(hkeyPrinter, dnstimeoutW, 0);
+    set_reg_szW(hkeyPrinter,   locationW, pi->pLocation);
+    set_reg_szW(hkeyPrinter,   nameW, pi->pPrinterName);
+    set_reg_szW(hkeyPrinter,   parametersW, pi->pParameters);
+    set_reg_szW(hkeyPrinter,   portW, pi->pPortName);
+    set_reg_szW(hkeyPrinter,   print_processorW, pi->pPrintProcessor);
+    set_reg_szW(hkeyPrinter,   printer_driverW, pi->pDriverName);
+    set_reg_DWORD(hkeyPrinter, priorityW, pi->Priority);
+    set_reg_szW(hkeyPrinter,   separator_fileW, pi->pSepFile);
+    set_reg_szW(hkeyPrinter,   share_nameW, pi->pShareName);
+    set_reg_DWORD(hkeyPrinter, starttimeW, pi->StartTime);
+    set_reg_DWORD(hkeyPrinter, statusW, pi->Status);
+    set_reg_DWORD(hkeyPrinter, txtimeoutW, 0);
+    set_reg_DWORD(hkeyPrinter, untiltimeW, pi->UntilTime);
+
+    set_devices_and_printerports(pi);
+
+    if(pi->pDevMode)
+        dm = pi->pDevMode;
+    else
+    {
+        dm = get_default_devmode(pi->pPrinterName, pi->pDriverName);
+    }
+
+    set_reg_devmode( hkeyPrinter, default_devmodeW, dm );
+    if(!pi->pDevMode)
+        heap_free( dm );
+
+    RegCloseKey(hkeyPrinter);
+    RegCloseKey(hkeyPrinters);
+
+    return printer_alloc_handle(pi->pPrinterName, NULL);
+}
+
+
 /******************************************************************************
  * fpAddPrinterDriverEx [exported through PRINTPROVIDOR]
  *
@@ -2353,7 +2700,7 @@ void setup_provider(void)
         NULL,   /* fpSetJob */
         NULL,   /* fpGetJob */
         NULL,   /* fpEnumJobs */
-        NULL,   /* fpAddPrinter */
+        fpAddPrinter,
         NULL,   /* fpDeletePrinter */
         NULL,   /* fpSetPrinter */
         NULL,   /* fpGetPrinter */
diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index d28ca89..e6423fe 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -274,8 +274,6 @@ static const WCHAR windowsW[] = {'w','i','n','d','o','w','s',0};
 static       WCHAR rawW[] = {'R','A','W',0};
 static       WCHAR driver_9x[] = {'w','i','n','e','p','s','1','6','.','d','r','v',0};
 static       WCHAR driver_nt[] = {'w','i','n','e','p','s','.','d','r','v',0};
-static const WCHAR timeout_15_45[] = {',','1','5',',','4','5',0};
-static const WCHAR commaW[] = {',',0};
 static       WCHAR emptyStringW[] = {0};
 
 static const WCHAR May_Delete_Value[] = {'W','i','n','e','M','a','y','D','e','l','e','t','e','M','e',0};
@@ -3113,176 +3111,50 @@ static HKEY WINSPOOL_OpenDriverReg( LPCVOID pEnvironment)
     return retval;
 }
 
-/*****************************************************************************
- * set_devices_and_printerports [internal]
- *
- * set the [Devices] and [PrinterPorts] entries for a printer.
- *
- */
-static void set_devices_and_printerports(PRINTER_INFO_2W *pi)
-{
-    DWORD portlen = lstrlenW(pi->pPortName) * sizeof(WCHAR);
-    WCHAR *devline;
-    HKEY  hkey;
-
-    TRACE("(%p) %s\n", pi, debugstr_w(pi->pPrinterName));
-
-    /* FIXME: the driver must change to "winspool" */
-    devline = HeapAlloc(GetProcessHeap(), 0, sizeof(driver_nt) + portlen + sizeof(timeout_15_45));
-    if (devline) {
-        lstrcpyW(devline, driver_nt);
-        lstrcatW(devline, commaW);
-        lstrcatW(devline, pi->pPortName);
-
-        TRACE("using %s\n", debugstr_w(devline));
-        WriteProfileStringW(devicesW, pi->pPrinterName, devline);
-        if (!RegCreateKeyW(HKEY_CURRENT_USER, user_printers_reg_key, &hkey)) {
-            RegSetValueExW(hkey, pi->pPrinterName, 0, REG_SZ, (LPBYTE)devline,
-                            (lstrlenW(devline) + 1) * sizeof(WCHAR));
-            RegCloseKey(hkey);
-        }
-
-        lstrcatW(devline, timeout_15_45);
-        WriteProfileStringW(PrinterPortsW, pi->pPrinterName, devline);
-        if (!RegCreateKeyW(HKEY_CURRENT_USER, WinNT_CV_PrinterPortsW, &hkey)) {
-            RegSetValueExW(hkey, pi->pPrinterName, 0, REG_SZ, (LPBYTE)devline,
-                            (lstrlenW(devline) + 1) * sizeof(WCHAR));
-            RegCloseKey(hkey);
-        }
-        HeapFree(GetProcessHeap(), 0, devline);
-    }
-}
 
 /*****************************************************************************
  *          AddPrinterW  [WINSPOOL.@]
+ *
+ * Install a Printer with various Printer Parameter
+ *
+ * PARAMS
+ *  pName       [I] Servername or NULL (local Computer)
+ *  Level       [I] Level for the supplied PRINTER_INFO_*W struct
+ *  pPrinter    [I] PTR to PRINTER_INFO_*W struct with the Printer Parameter
+ *
+ * RESULTS
+ *  Success: TRUE
+ *  Failure: FALSE
+ *
  */
 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
 {
-    PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
-    LPDEVMODEW dm;
-    HANDLE retval;
-    HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
-    LONG size;
+    HANDLE backend_printer;
+    HANDLE res = NULL;
 
     TRACE("(%s,%d,%p)\n", debugstr_w(pName), Level, pPrinter);
 
-    if(pName && *pName) {
-        ERR("pName = %s - unsupported\n", debugstr_w(pName));
-	SetLastError(ERROR_INVALID_PARAMETER);
-	return 0;
-    }
-    if(Level != 2) {
-        ERR("Level = %d, unsupported!\n", Level);
-	SetLastError(ERROR_INVALID_LEVEL);
-	return 0;
-    }
-    if(!pPrinter) {
-        SetLastError(ERROR_INVALID_PARAMETER);
-	return 0;
-    }
-    if(RegCreateKeyW(HKEY_LOCAL_MACHINE, PrintersW, &hkeyPrinters) !=
-       ERROR_SUCCESS) {
-        ERR("Can't create Printers key\n");
-	return 0;
-    }
-    if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) {
-	if (!RegQueryValueW(hkeyPrinter, AttributesW, NULL, NULL)) {
-	    SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
-	    RegCloseKey(hkeyPrinter);
-	    RegCloseKey(hkeyPrinters);
-	    return 0;
-	}
-	RegCloseKey(hkeyPrinter);
-    }
-    hkeyDrivers = WINSPOOL_OpenDriverReg(NULL);
-    if(!hkeyDrivers) {
-        ERR("Can't create Drivers key\n");
-	RegCloseKey(hkeyPrinters);
-	return 0;
-    }
-    if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
-       ERROR_SUCCESS) {
-        WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
-	RegCloseKey(hkeyPrinters);
-	RegCloseKey(hkeyDrivers);
-	SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
-	return 0;
-    }
-    RegCloseKey(hkeyDriver);
-    RegCloseKey(hkeyDrivers);
+    if ((backend == NULL)  && !load_backend()) return FALSE;
 
-    if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) {  /* FIXME */
-        FIXME("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
-	SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
-	RegCloseKey(hkeyPrinters);
-	return 0;
+    if (pPrinter == NULL) {
+        SetLastError(RPC_X_NULL_REF_POINTER);
+        return FALSE;
     }
 
-    if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
-       ERROR_SUCCESS) {
-        FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
-	SetLastError(ERROR_INVALID_PRINTER_NAME);
-	RegCloseKey(hkeyPrinters);
-	return 0;
-    }
+    backend_printer = backend->fpAddPrinter(pName, Level, pPrinter);
 
-    set_devices_and_printerports(pi);
-
-    set_reg_DWORD(hkeyPrinter, AttributesW, pi->Attributes);
-    set_reg_szW(hkeyPrinter, DatatypeW, pi->pDatatype);
-    set_reg_DWORD(hkeyPrinter, Default_PriorityW, pi->DefaultPriority);
-    set_reg_szW(hkeyPrinter, DescriptionW, pi->pComment);
-    set_reg_DWORD(hkeyPrinter, dnsTimeoutW, 0);
-    set_reg_szW(hkeyPrinter, LocationW, pi->pLocation);
-    set_reg_szW(hkeyPrinter, NameW, pi->pPrinterName);
-    set_reg_szW(hkeyPrinter, ParametersW, pi->pParameters);
-    set_reg_szW(hkeyPrinter, PortW, pi->pPortName);
-    set_reg_szW(hkeyPrinter, Print_ProcessorW, pi->pPrintProcessor);
-    set_reg_szW(hkeyPrinter, Printer_DriverW, pi->pDriverName);
-    set_reg_DWORD(hkeyPrinter, PriorityW, pi->Priority);
-    set_reg_szW(hkeyPrinter, Separator_FileW, pi->pSepFile);
-    set_reg_szW(hkeyPrinter, Share_NameW, pi->pShareName);
-    set_reg_DWORD(hkeyPrinter, StartTimeW, pi->StartTime);
-    set_reg_DWORD(hkeyPrinter, StatusW, pi->Status);
-    set_reg_DWORD(hkeyPrinter, txTimeoutW, 0);
-    set_reg_DWORD(hkeyPrinter, UntilTimeW, pi->UntilTime);
-
-    size = DocumentPropertiesW(0, 0, pi->pPrinterName, NULL, NULL, 0);
-
-    if (size < 0)
-    {
-        FIXME("DocumentPropertiesW on printer %s fails\n", debugstr_w(pi->pPrinterName));
-        size = sizeof(DEVMODEW);
-    }
-    if(pi->pDevMode)
-        dm = pi->pDevMode;
-    else
-    {
-        dm = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
-        dm->dmSize = size;
-        if (DocumentPropertiesW(0, 0, pi->pPrinterName, dm, NULL, DM_OUT_BUFFER) < 0)
-        {
-            WARN("DocumentPropertiesW on printer %s failed!\n", debugstr_w(pi->pPrinterName));
-            HeapFree( GetProcessHeap(), 0, dm );
-            dm = NULL;
-        }
-        else
-        {
-            /* set devmode to printer name */
-            lstrcpynW( dm->dmDeviceName, pi->pPrinterName, CCHDEVICENAME );
+    if (backend_printer) {
+        res = get_opened_printer_entry(pName, NULL, backend_printer);
+        if (!res) {
+            /* Something went wrong. Free the Handle, that we got from the backend */
+            DWORD olderror = GetLastError();
+            backend->fpClosePrinter(backend_printer);
+            SetLastError(olderror);
         }
     }
 
-    set_reg_devmode( hkeyPrinter, Default_DevModeW, dm );
-    if (!pi->pDevMode) HeapFree( GetProcessHeap(), 0, dm );
-
-    RegCloseKey(hkeyPrinter);
-    RegCloseKey(hkeyPrinters);
-    if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
-        ERR("OpenPrinter failing\n");
-	return 0;
-    }
-    return retval;
+    TRACE("returning %p for %s (got %p from backend)\n", res, debugstr_w(pName), backend_printer);
+    return res;
 }
 
 /*****************************************************************************
-- 
2.7.4




More information about the wine-devel mailing list