Huw Davies : winspool: Update the ppd file of an already installed printer in the first call to OpenPrinter .

Alexandre Julliard julliard at winehq.org
Tue Jun 12 13:36:33 CDT 2012


Module: wine
Branch: master
Commit: 28ef1af6d0435211e243bc4b22856fa8fc579d52
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=28ef1af6d0435211e243bc4b22856fa8fc579d52

Author: Huw Davies <huw at codeweavers.com>
Date:   Tue Jun 12 09:42:49 2012 +0100

winspool: Update the ppd file of an already installed printer in the first call to OpenPrinter.

---

 dlls/winspool.drv/info.c |  201 +++++++++++++++++++++++++++++++---------------
 1 files changed, 137 insertions(+), 64 deletions(-)

diff --git a/dlls/winspool.drv/info.c b/dlls/winspool.drv/info.c
index a5ccf49..ed470bb 100644
--- a/dlls/winspool.drv/info.c
+++ b/dlls/winspool.drv/info.c
@@ -450,6 +450,62 @@ static inline DWORD set_reg_DWORD( HKEY hkey, const WCHAR *keyname, const DWORD
     return RegSetValueExW( hkey, keyname, 0, REG_DWORD, (const BYTE*)&value, sizeof(value) );
 }
 
+/******************************************************************
+ *  get_opened_printer
+ *  Get the pointer to the opened printer referred by the handle
+ */
+static opened_printer_t *get_opened_printer(HANDLE hprn)
+{
+    UINT_PTR idx = (UINT_PTR)hprn;
+    opened_printer_t *ret = NULL;
+
+    EnterCriticalSection(&printer_handles_cs);
+
+    if ((idx > 0) && (idx <= nb_printer_handles)) {
+        ret = printer_handles[idx - 1];
+    }
+    LeaveCriticalSection(&printer_handles_cs);
+    return ret;
+}
+
+/******************************************************************
+ *  get_opened_printer_name
+ *  Get the pointer to the opened printer name referred by the handle
+ */
+static LPCWSTR get_opened_printer_name(HANDLE hprn)
+{
+    opened_printer_t *printer = get_opened_printer(hprn);
+    if(!printer) return NULL;
+    return printer->name;
+}
+
+static DWORD open_printer_reg_key( const WCHAR *name, HKEY *key )
+{
+    HKEY printers;
+    DWORD err;
+
+    *key = NULL;
+    err = RegCreateKeyW( HKEY_LOCAL_MACHINE, PrintersW, &printers );
+    if (err) return err;
+
+    err = RegOpenKeyW( printers, name, key );
+    if (err) err = ERROR_INVALID_PRINTER_NAME;
+    RegCloseKey( printers );
+    return err;
+}
+
+/******************************************************************
+ *  WINSPOOL_GetOpenedPrinterRegKey
+ *
+ */
+static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
+{
+    LPCWSTR name = get_opened_printer_name(hPrinter);
+
+    if(!name) return ERROR_INVALID_HANDLE;
+    return open_printer_reg_key( name, phkey );
+}
+
 static void
 WINSPOOL_SetDefaultPrinter(const char *devname, const char *name, BOOL force) {
     char qbuf[200];
@@ -476,13 +532,13 @@ WINSPOOL_SetDefaultPrinter(const char *devname, const char *name, BOOL force) {
     }
 }
 
-static BOOL add_printer_driver(WCHAR *name, WCHAR *ppd)
+static BOOL add_printer_driver(const WCHAR *name, WCHAR *ppd)
 {
     DRIVER_INFO_3W di3;
 
     ZeroMemory(&di3, sizeof(DRIVER_INFO_3W));
     di3.cVersion         = 3;
-    di3.pName            = name;
+    di3.pName            = (WCHAR*)name;
     di3.pEnvironment     = envname_x86W;
     di3.pDriverPath      = driver_nt;
     di3.pDataFile        = ppd;
@@ -831,7 +887,61 @@ static BOOL CUPS_LoadPrinters(void)
     RegCloseKey(hkeyPrinters);
     return TRUE;
 }
+
+static char *get_cups_name( HANDLE printer )
+{
+    WCHAR *port;
+    DWORD err, needed, type;
+    char *ret = NULL;
+    HKEY key;
+
+    err = WINSPOOL_GetOpenedPrinterRegKey( printer, &key );
+    if (err) return NULL;
+    err = RegQueryValueExW( key, PortW, 0, &type, NULL, &needed );
+    if (err || needed <= sizeof( CUPS_Port )) goto end;
+    port = HeapAlloc( GetProcessHeap(), 0, needed );
+    if (!port) goto end;
+    RegQueryValueExW( key, PortW, 0, &type, (BYTE*)port, &needed );
+    if (!memcmp( port, CUPS_Port, sizeof(CUPS_Port) - sizeof(WCHAR) ))
+    {
+        WCHAR *name = port + sizeof(CUPS_Port) / sizeof(WCHAR) - 1;
+        needed = WideCharToMultiByte( CP_UNIXCP, 0, name, -1, NULL, 0, NULL, NULL );
+        ret = HeapAlloc( GetProcessHeap(), 0, needed );
+        if(ret) WideCharToMultiByte( CP_UNIXCP, 0, name, -1, ret, needed, NULL, NULL );
+    }
+    HeapFree( GetProcessHeap(), 0, port );
+end:
+    RegCloseKey( key );
+    return ret;
+}
+#endif
+
+static BOOL update_driver( HANDLE printer )
+{
+    BOOL ret = FALSE;
+#ifdef SONAME_LIBCUPS
+    const WCHAR *name = get_opened_printer_name( printer );
+    WCHAR *ppd_dir, *ppd;
+    char *cups_name;
+
+    if (!name) return FALSE;
+    cups_name = get_cups_name( printer );
+    if (!cups_name) return FALSE;
+
+    ppd_dir = get_ppd_dir();
+    ppd = get_ppd_filename( ppd_dir, name );
+    if (get_cups_ppd( cups_name, ppd ))
+    {
+        TRACE( "updating driver %s\n", debugstr_w( name ) );
+        ret = add_printer_driver( name, ppd );
+        unlink_ppd( ppd );
+    }
+    HeapFree( GetProcessHeap(), 0, ppd_dir );
+    HeapFree( GetProcessHeap(), 0, ppd );
+    HeapFree( GetProcessHeap(), 0, cups_name );
 #endif
+    return ret;
+}
 
 static BOOL PRINTCAP_ParseEntry( const char *pent, BOOL isfirst )
 {
@@ -1243,62 +1353,6 @@ end:
     return (HANDLE)handle;
 }
 
-/******************************************************************
- *  get_opened_printer
- *  Get the pointer to the opened printer referred by the handle
- */
-static opened_printer_t *get_opened_printer(HANDLE hprn)
-{
-    UINT_PTR idx = (UINT_PTR)hprn;
-    opened_printer_t *ret = NULL;
-
-    EnterCriticalSection(&printer_handles_cs);
-
-    if ((idx > 0) && (idx <= nb_printer_handles)) {
-        ret = printer_handles[idx - 1];
-    }
-    LeaveCriticalSection(&printer_handles_cs);
-    return ret;
-}
-
-/******************************************************************
- *  get_opened_printer_name
- *  Get the pointer to the opened printer name referred by the handle
- */
-static LPCWSTR get_opened_printer_name(HANDLE hprn)
-{
-    opened_printer_t *printer = get_opened_printer(hprn);
-    if(!printer) return NULL;
-    return printer->name;
-}
-
-static DWORD open_printer_reg_key( const WCHAR *name, HKEY *key )
-{
-    HKEY printers;
-    DWORD err;
-
-    *key = NULL;
-    err = RegCreateKeyW( HKEY_LOCAL_MACHINE, PrintersW, &printers );
-    if (err) return err;
-
-    err = RegOpenKeyW( printers, name, key );
-    if (err) err = ERROR_INVALID_PRINTER_NAME;
-    RegCloseKey( printers );
-    return err;
-}
-
-/******************************************************************
- *  WINSPOOL_GetOpenedPrinterRegKey
- *
- */
-static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
-{
-    LPCWSTR name = get_opened_printer_name(hPrinter);
-
-    if(!name) return ERROR_INVALID_HANDLE;
-    return open_printer_reg_key( name, phkey );
-}
-
 static void old_printer_check( BOOL delete_phase )
 {
     PRINTER_INFO_5W* pi;
@@ -1348,6 +1402,7 @@ static void old_printer_check( BOOL delete_phase )
 
 static const WCHAR winspool_mutex_name[] = {'_','_','W','I','N','E','_','W','I','N','S','P','O','O','L','_',
                                             'M','U','T','E','X','_','_','\0'};
+static HANDLE init_mutex;
 
 void WINSPOOL_LoadSystemPrinters(void)
 {
@@ -1355,19 +1410,18 @@ void WINSPOOL_LoadSystemPrinters(void)
     DWORD               needed, num, i;
     WCHAR               PrinterName[256];
     BOOL                done = FALSE;
-    HANDLE              mutex;
 
     /* FIXME: The init code should be moved to spoolsv.exe */
-    mutex = CreateMutexW( NULL, TRUE, winspool_mutex_name );
-    if (!mutex)
+    init_mutex = CreateMutexW( NULL, TRUE, winspool_mutex_name );
+    if (!init_mutex)
     {
         ERR( "Failed to create mutex\n" );
         return;
     }
     if (GetLastError() == ERROR_ALREADY_EXISTS)
     {
-        WaitForSingleObject( mutex, INFINITE );
-        ReleaseMutex( mutex );
+        WaitForSingleObject( init_mutex, INFINITE );
+        ReleaseMutex( init_mutex );
         TRACE( "Init already done\n" );
         return;
     }
@@ -1403,7 +1457,7 @@ void WINSPOOL_LoadSystemPrinters(void)
 
     old_printer_check( TRUE );
 
-    ReleaseMutex( mutex );
+    ReleaseMutex( init_mutex );
     return;
 }
 
@@ -2277,6 +2331,25 @@ BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter, LPPRINTER_DEFAU
 
     /* Get the unique handle of the printer or Printserver */
     *phPrinter = get_opened_printer_entry(lpPrinterName, pDefault);
+
+    WaitForSingleObject( init_mutex, INFINITE );
+    if (*phPrinter)
+    {
+        HKEY key;
+        DWORD deleting = 0, size = sizeof( deleting ), type;
+        DWORD status;
+        WINSPOOL_GetOpenedPrinterRegKey( *phPrinter, &key );
+        RegQueryValueExW( key, May_Delete_Value, NULL, &type, (LPBYTE)&deleting, &size );
+        status = get_dword_from_reg( key, StatusW );
+        if (!deleting && (status & PRINTER_STATUS_DRIVER_UPDATE_NEEDED))
+        {
+            update_driver( *phPrinter );
+            set_reg_DWORD( key, StatusW, status & ~PRINTER_STATUS_DRIVER_UPDATE_NEEDED );
+        }
+        RegCloseKey( key );
+    }
+    ReleaseMutex( init_mutex );
+
     TRACE("returning %d with %u and %p\n", *phPrinter != NULL, GetLastError(), *phPrinter);
     return (*phPrinter != 0);
 }




More information about the wine-cvs mailing list