merge from 2.2 (deleteprinterdriver RPC)
authorGerald Carter <jerry@samba.org>
Fri, 18 May 2001 04:11:17 +0000 (04:11 +0000)
committerGerald Carter <jerry@samba.org>
Fri, 18 May 2001 04:11:17 +0000 (04:11 +0000)
source/include/smb.h
source/printing/nt_printing.c
source/rpc_server/srv_spoolss.c
source/rpc_server/srv_spoolss_nt.c
source/rpcclient/cmd_spoolss.c

index 8b18ee50104f154bf418fac03c4340f9deb16d30..7881334df8ff0fe9de565f8560b4cde0558789dd 100644 (file)
@@ -205,6 +205,7 @@ implemented */
 #define ERROR_INVALID_PRINTER_NAME     (1801)
 #define ERROR_INVALID_DATATYPE        (1804)
 #define ERROR_INVALID_ENVIRONMENT      (1805)
+#define ERROR_PRINTER_DRIVER_IN_USE    (3001)
 
 /* here's a special one from observing NT */
 #define ERRnoipc 66 /* don't support ipc */
index 164ad587423fb553eac77249b285e7f19c6834a9..a0031ae35ad7346db82f19cb4aa22541d1fb5694 100644 (file)
@@ -2844,6 +2844,107 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
        return result;
 }
 
+
+/****************************************************************************
+  Determine whether or not a particular driver is currently assigned
+  to a printer
+****************************************************************************/
+BOOL printer_driver_in_use (char *arch, char *driver)
+{
+       TDB_DATA kbuf, newkey, dbuf;
+       NT_PRINTER_INFO_LEVEL_2 info;
+       int ret;
+
+       if (!tdb)
+               nt_printing_init();     
+
+       DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
+       
+       /* loop through the printers.tdb and check for the drivername */
+       for (kbuf = tdb_firstkey(tdb); kbuf.dptr;
+            newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) 
+       {
+
+               dbuf = tdb_fetch(tdb, kbuf);
+               if (!dbuf.dptr) 
+                       continue;
+
+               if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0) 
+                       continue;
+
+               ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
+                       &info.attributes,
+                       &info.priority,
+                       &info.default_priority,
+                       &info.starttime,
+                       &info.untiltime,
+                       &info.status,
+                       &info.cjobs,
+                       &info.averageppm,
+                       &info.changeid,
+                       &info.c_setprinter,
+                       &info.setuptime,
+                       info.servername,
+                       info.printername,
+                       info.sharename,
+                       info.portname,
+                       info.drivername,
+                       info.comment,
+                       info.location,
+                       info.sepfile,
+                       info.printprocessor,
+                       info.datatype,
+                       info.parameters);
+
+               safe_free(dbuf.dptr);
+               
+               DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
+                       info.printername, info.drivername));
+                       
+               if (strcmp(info.drivername, driver) == 0) 
+               {
+                       DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
+                               info.printername, driver));
+                       return True;
+               }       
+       }
+       DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
+       
+       
+       
+       /* report that the driver is in use by default */
+       return False;
+}
+
+/****************************************************************************
+ Remove a printer driver from the TDB.  This assumes that the the driver was
+ previously looked up.
+ ***************************************************************************/
+uint32 delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
+{
+       pstring         key;
+       fstring         arch;
+       TDB_DATA        kbuf;
+
+
+       get_short_archi(arch, i->environment);
+       slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
+               arch, i->cversion, i->name); 
+       DEBUG(5,("delete_printer_driver: key = [%s]\n", key));
+
+       kbuf.dptr=key;
+       kbuf.dsize=strlen(key)+1;
+
+       if (tdb_delete(tdb, kbuf) == -1) {
+               DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
+               return NT_STATUS_ACCESS_VIOLATION;
+       }
+       
+       DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
+               i->name));
+       
+       return NT_STATUS_NO_PROBLEMO;
+}
 /****************************************************************************
 ****************************************************************************/
 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
index ddd8255139af2312235ff954c843a92ab3150c4a..1adc783e24a3afcb1f8dc4340397aed6e5a5f375 100755 (executable)
@@ -213,6 +213,38 @@ static BOOL api_spoolss_deleteprinter(pipes_struct *p)
 }
 
 
+/********************************************************************
+ * api_spoolss_deleteprinterdriver
+ *
+ * called from the spoolss dispatcher
+ ********************************************************************/
+
+static BOOL api_spoolss_deleteprinterdriver(pipes_struct *p)
+{
+       SPOOL_Q_DELETEPRINTERDRIVER q_u;
+       SPOOL_R_DELETEPRINTERDRIVER r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if (!spoolss_io_q_deleteprinterdriver("", &q_u, data, 0)) {
+               DEBUG(0,("spoolss_io_q_deleteprinterdriver: unable to unmarshall SPOOL_Q_DELETEPRINTERDRIVER.\n"));
+               return False;
+       }
+
+       r_u.status = _spoolss_deleteprinterdriver(p, &q_u, &r_u);
+
+       if (!spoolss_io_r_deleteprinterdriver("",&r_u,rdata,0)) {
+               DEBUG(0,("spoolss_io_r_deleteprinter: unable to marshall SPOOL_R_DELETEPRINTER.\n"));
+               return False;
+       }
+
+       return True;
+}
+
+
 /********************************************************************
  * api_spoolss_rffpcnex
  * ReplyFindFirstPrinterChangeNotifyEx
@@ -1169,6 +1201,7 @@ struct api_struct api_spoolss_cmds[] =
  {"SPOOLSS_ENUMPRINTERDRIVERS",        SPOOLSS_ENUMPRINTERDRIVERS,        api_spoolss_enumprinterdrivers        },
  {"SPOOLSS_ADDPRINTEREX",              SPOOLSS_ADDPRINTEREX,              api_spoolss_addprinterex              },
  {"SPOOLSS_ADDPRINTERDRIVER",          SPOOLSS_ADDPRINTERDRIVER,          api_spoolss_addprinterdriver          },
+ {"SPOOLSS_DELETEPRINTERDRIVER",       SPOOLSS_DELETEPRINTERDRIVER,       api_spoolss_deleteprinterdriver       },
  {"SPOOLSS_GETPRINTERDRIVERDIRECTORY", SPOOLSS_GETPRINTERDRIVERDIRECTORY, api_spoolss_getprinterdriverdirectory },
  {"SPOOLSS_ENUMPRINTERDATA",           SPOOLSS_ENUMPRINTERDATA,           api_spoolss_enumprinterdata           },
  {"SPOOLSS_SETPRINTERDATA",            SPOOLSS_SETPRINTERDATA,            api_spoolss_setprinterdata            },
index d714972179eebaa5d96cc4ed20a2526d7e40ba79..1d1eced2ea5c53ccdd3da00b574a939291a828c5 100644 (file)
@@ -34,6 +34,13 @@ extern pstring global_myname;
 #define PRINTER_HANDLE_IS_PRINTER      0
 #define PRINTER_HANDLE_IS_PRINTSERVER  1
 
+struct table_node {
+       char    *long_archi;
+       char    *short_archi;
+       int     version;
+};
+
+
 /* structure to store the printer handles */
 /* and a reference to what it's pointing to */
 /* and the notify info asked about */
@@ -1058,6 +1065,81 @@ uint32 _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL
        return result;
 }
 
+/*******************************************************************
+ * static function to lookup the version id corresponding to an
+ * long architecture string
+ ******************************************************************/
+static int get_version_id (char * arch)
+{
+       int i;
+       struct table_node archi_table[]= {
+               {"Windows 4.0",          "WIN40",       0 },
+               {"Windows NT x86",       "W32X86",      2 },
+               {"Windows NT R4000",     "W32MIPS",     2 },    
+               {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
+               {"Windows NT PowerPC",   "W32PPC",      2 },
+               {NULL,                   "",            -1 }
+       };
+       for (i=0; archi_table[i].long_archi != NULL; i++)
+       {
+               if (strcmp(arch, archi_table[i].long_archi) == 0)
+                       return (archi_table[i].version);
+        }
+       
+       return -1;
+}
+
+/********************************************************************
+ * _spoolss_deleteprinterdriver
+ *
+ * We currently delete the driver for the architecture only.
+ * This can leave the driver for other archtectures.  However,
+ * since every printer associates a "Windows NT x86" driver name
+ * and we cannot delete that one while it is in use, **and** since
+ * it is impossible to assign a driver to a Samba printer without
+ * having the "Windows NT x86" driver installed,...
+ * 
+ * ....we should not get into trouble here.  
+ *
+ *                                                      --jerry
+ ********************************************************************/
+
+uint32 _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, 
+                                   SPOOL_R_DELETEPRINTERDRIVER *r_u)
+{
+       fstring                         driver;
+       fstring                         arch;
+       NT_PRINTER_DRIVER_INFO_LEVEL    info;
+       int                             version;
+        
+       unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
+       unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
+       
+       /* check that we have a valid driver name first */
+       if ((version=get_version_id(arch)) == -1) {
+               /* this is what NT returns */
+               return ERROR_INVALID_ENVIRONMENT;
+       }
+               
+       ZERO_STRUCT(info);
+       if (get_a_printer_driver (&info, 3, driver, arch, version) != 0) {
+               /* this is what NT returns */
+               return ERROR_UNKNOWN_PRINTER_DRIVER;
+       }
+       
+
+       if (printer_driver_in_use(arch, driver))
+       {
+               /* this is what NT returns */
+               return ERROR_PRINTER_DRIVER_IN_USE;
+       }
+
+       return delete_printer_driver(info.info_3);       
+}
+
+
 /********************************************************************
  GetPrinterData on a printer server Handle.
 ********************************************************************/
index fc1ac49430774a27433493091606e500e46453a2..32131ad780f2d2459909a023326d88a1c64783b6 100644 (file)
@@ -1315,11 +1315,12 @@ static uint32 cmd_spoolss_deletedriver (struct cli_state *cli, int argc, char **
        uint32                  result = NT_STATUS_UNSUCCESSFUL;
        fstring                 servername;
        TALLOC_CTX              *mem_ctx = NULL;
+       int                     i;
        
        /* parse the command arguements */
-       if (argc != 3)
+       if (argc != 2)
        {
-               printf ("Usage: %s <arch> <driver>\n", argv[0]);
+               printf ("Usage: %s <driver>\n", argv[0]);
                return NT_STATUS_NOPROBLEMO;
         }
 
@@ -1339,13 +1340,19 @@ static uint32 cmd_spoolss_deletedriver (struct cli_state *cli, int argc, char **
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       /* make the call to remove the driver */
-       if ((result = cli_spoolss_deleteprinterdriver(cli, mem_ctx, argv[1], argv[2])) != NT_STATUS_NO_PROBLEMO)
+       /* delete the driver for all architectures */
+       for (i=0; archi_table[i].long_archi; i++)
        {
-               printf ("Failed to remove %s driver %s!\n", argv[1], argv[2]);
-               goto done;;
+               /* make the call to remove the driver */
+               if ((result = cli_spoolss_deleteprinterdriver(cli, mem_ctx, 
+                       archi_table[i].long_archi, argv[1])) != NT_STATUS_NO_PROBLEMO)
+               {
+                       printf ("Failed to remove driver %s for arch [%s] - error %s!\n", 
+                               argv[1], archi_table[i].long_archi, get_nt_error_msg(result));
+               }
+               else
+                       printf ("Driver %s removed for arch [%s].\n", argv[1], archi_table[i].long_archi);
        }
-       printf ("%s driver %s removed.\n", argv[1], argv[2]);
                
 
 done:
@@ -1353,7 +1360,7 @@ done:
        cli_nt_session_close (cli);
        talloc_destroy(mem_ctx);
        
-       return result;          
+       return NT_STATUS_NO_PROBLEMO;           
 }