s3-printing: Handled case when smbd spools a file on behalf of spoolss.
[kai/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
index 0063502cfc3f5e85dd961d430be330fefc5b58a2..1f0b36450f91707aaf568afa4a6325c621f43270 100644 (file)
    up, all the errors returned are DOS errors, not NT status codes. */
 
 #include "includes.h"
+#include "nt_printing.h"
 #include "srv_spoolss_util.h"
 #include "../librpc/gen_ndr/srv_spoolss.h"
 #include "../librpc/gen_ndr/cli_spoolss.h"
 #include "rpc_client/init_spoolss.h"
 #include "librpc/gen_ndr/messaging.h"
+#include "librpc/gen_ndr/ndr_security.h"
 #include "registry.h"
 #include "registry/reg_objects.h"
 
@@ -223,7 +225,6 @@ static int printer_entry_destructor(Printer_entry *Printer)
        Printer->notify.client_connected = false;
 
        TALLOC_FREE(Printer->devmode);
-       free_a_printer( &Printer->printer_info, 2 );
 
        /* Remove from the internal list. */
        DLIST_REMOVE(printers_list, Printer);
@@ -335,6 +336,7 @@ static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const c
 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
+       WERROR result;
 
        if (!Printer) {
                DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
@@ -357,7 +359,9 @@ static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
        /* this does not need a become root since the access check has been
           done on the handle already */
 
-       if (del_a_printer( Printer->sharename ) != 0) {
+       result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
+                                          Printer->sharename, "");
+       if (!W_ERROR_IS_OK(result)) {
                DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
                return WERR_BADFID;
        }
@@ -666,12 +670,13 @@ static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
        _data->data.devmode.devmode = _devmode;
 
-#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
+#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
        _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
        if (!_data->data.sd.sd) { \
                _data->data.sd.sd_size = 0; \
        } \
-       _data->data.sd.sd_size = _size;
+       _data->data.sd.sd_size = \
+               ndr_size_security_descriptor(_data->data.sd.sd, 0);
 
 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
                                   struct tm *t,
@@ -937,10 +942,9 @@ static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MS
        return ctr->num_groups;
 }
 
-void construct_info_data(struct spoolss_Notify *info_data,
-                        enum spoolss_NotifyType type,
-                        uint16_t field,
-                        int id);
+static void construct_info_data(struct spoolss_Notify *info_data,
+                               enum spoolss_NotifyType type,
+                               uint16_t field, int id);
 
 /***********************************************************************
  Send a change notication message on all handles which have a call
@@ -1283,47 +1287,72 @@ void do_drv_upgrade_printer(struct messaging_context *msg,
                            struct server_id server_id,
                            DATA_BLOB *data)
 {
-       fstring drivername;
+       TALLOC_CTX *tmp_ctx;
+       struct auth_serversupplied_info *server_info = NULL;
+       struct spoolss_PrinterInfo2 *pinfo2;
+       NTSTATUS status;
+       WERROR result;
+       const char *drivername;
        int snum;
        int n_services = lp_numservices();
        size_t len;
 
+       tmp_ctx = talloc_new(NULL);
+       if (!tmp_ctx) return;
+
+       status = make_server_info_system(tmp_ctx, &server_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("do_drv_upgrade_printer: "
+                         "Could not create system server_info\n"));
+               goto done;
+       }
+
        len = MIN(data->length,sizeof(drivername)-1);
-       strncpy(drivername, (const char *)data->data, len);
+       drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
+       if (!drivername) {
+               DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
+               goto done;
+       }
 
-       DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
+       DEBUG(10, ("do_drv_upgrade_printer: "
+                  "Got message for new driver [%s]\n", drivername));
 
        /* Iterate the printer list */
 
-       for (snum=0; snum<n_services; snum++)
-       {
-               if (lp_snum_ok(snum) && lp_print_ok(snum) )
-               {
-                       WERROR result;
-                       NT_PRINTER_INFO_LEVEL *printer = NULL;
+       for (snum = 0; snum < n_services; snum++) {
+               if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
+                       continue;
+               }
 
-                       result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
-                       if (!W_ERROR_IS_OK(result))
-                               continue;
+               result = winreg_get_printer(tmp_ctx, server_info, NULL,
+                                           lp_const_servicename(snum),
+                                           &pinfo2);
+
+               if (!W_ERROR_IS_OK(result)) {
+                       continue;
+               }
 
-                       if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
-                       {
-                               DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
+               if (strcmp(drivername, pinfo2->drivername) != 0) {
+                       continue;
+               }
 
-                               /* all we care about currently is the change_id */
+               DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
 
-                               result = mod_a_printer(printer, 2);
-                               if (!W_ERROR_IS_OK(result)) {
-                                       DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
-                                               win_errstr(result)));
-                               }
-                       }
+               /* all we care about currently is the change_id */
+               result = winreg_printer_update_changeid(tmp_ctx,
+                                                       server_info,
+                                                       pinfo2->printername);
 
-                       free_a_printer(&printer, 2);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(3, ("do_drv_upgrade_printer: "
+                                 "Failed to update changeid [%s]\n",
+                                 win_errstr(result)));
                }
        }
 
        /* all done */
+done:
+       talloc_free(tmp_ctx);
 }
 
 /********************************************************************
@@ -1694,6 +1723,7 @@ WERROR _spoolss_DeletePrinter(pipes_struct *p,
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
        WERROR result;
+       int snum;
 
        if (Printer && Printer->document_started) {
                struct spoolss_EndDocPrinter e;
@@ -1703,9 +1733,14 @@ WERROR _spoolss_DeletePrinter(pipes_struct *p,
                _spoolss_EndDocPrinter(p, &e);
        }
 
-       result = delete_printer_handle(p, r->in.handle);
+       if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
+               winreg_delete_printer_key(p->mem_ctx,
+                                         p->server_info,
+                                         lp_const_servicename(snum),
+                                         "");
+       }
 
-       update_c_setprinter(false);
+       result = delete_printer_handle(p, r->in.handle);
 
        return result;
 }
@@ -1752,7 +1787,6 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
        struct spoolss_DriverInfo8 *info_win2k = NULL;
        int                             version;
        WERROR                          status;
-       WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
@@ -1775,19 +1809,20 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
        if ((version = get_version_id(r->in.architecture)) == -1)
                return WERR_INVALID_ENVIRONMENT;
 
-       if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
-                                               r->in.architecture,
-                                               version)))
-       {
+       status = winreg_get_driver(p->mem_ctx, p->server_info,
+                                  r->in.architecture, r->in.driver,
+                                  version, &info);
+       if (!W_ERROR_IS_OK(status)) {
                /* try for Win2k driver if "Windows NT x86" */
 
                if ( version == 2 ) {
                        version = 3;
-                       if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
-                                                               &info,
-                                                               r->in.driver,
-                                                               r->in.architecture,
-                                                               version))) {
+
+                       status = winreg_get_driver(p->mem_ctx, p->server_info,
+                                                  r->in.architecture,
+                                                  r->in.driver,
+                                                  version, &info);
+                       if (!W_ERROR_IS_OK(status)) {
                                status = WERR_UNKNOWN_PRINTER_DRIVER;
                                goto done;
                        }
@@ -1800,43 +1835,35 @@ WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
 
        }
 
-       if (printer_driver_in_use(info)) {
+       if (printer_driver_in_use(p->mem_ctx, p->server_info, info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
 
-       if ( version == 2 )
-       {
-               if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
-                                                      &info_win2k,
-                                                      r->in.driver,
-                                                      r->in.architecture, 3)))
-               {
+       if (version == 2) {
+               status = winreg_get_driver(p->mem_ctx, p->server_info,
+                                          r->in.architecture,
+                                          r->in.driver, 3, &info_win2k);
+               if (W_ERROR_IS_OK(status)) {
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
 
-                       status_win2k = delete_printer_driver(
-                               p, info_win2k, 3, false);
-                       free_a_printer_driver(info_win2k);
+                       status = winreg_del_driver(p->mem_ctx,
+                                                  p->server_info,
+                                                  info_win2k, 3);
+                       talloc_free(info_win2k);
 
                        /* this should not have failed---if it did, report to client */
-                       if ( !W_ERROR_IS_OK(status_win2k) )
-                       {
-                               status = status_win2k;
+                       if (!W_ERROR_IS_OK(status)) {
                                goto done;
                        }
                }
        }
 
-       status = delete_printer_driver(p, info, version, false);
-
-       /* if at least one of the deletes succeeded return OK */
-
-       if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
-               status = WERR_OK;
+       status = winreg_del_driver(p->mem_ctx, p->server_info, info, version);
 
 done:
-       free_a_printer_driver(info);
+       talloc_free(info);
 
        return status;
 }
@@ -1853,7 +1880,6 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
        int                             version;
        bool                            delete_files;
        WERROR                          status;
-       WERROR                          status_win2k = WERR_ACCESS_DENIED;
        SE_PRIV                         se_printop = SE_PRINT_OPERATOR;
 
        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
@@ -1879,11 +1905,12 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
        if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
                version = r->in.version;
 
-       status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
-                                     r->in.architecture, version);
+       status = winreg_get_driver(p->mem_ctx, p->server_info,
+                                  r->in.architecture, r->in.driver,
+                                  version, &info);
+       if (!W_ERROR_IS_OK(status)) {
+               status = WERR_UNKNOWN_PRINTER_DRIVER;
 
-       if ( !W_ERROR_IS_OK(status) )
-       {
                /*
                 * if the client asked for a specific version,
                 * or this is something other than Windows NT x86,
@@ -1896,15 +1923,17 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                /* try for Win2k driver if "Windows NT x86" */
 
                version = 3;
-               if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
-                                                       r->in.architecture,
-                                                       version))) {
+               status = winreg_get_driver(info, p->server_info,
+                                          r->in.architecture,
+                                          r->in.driver,
+                                          version, &info);
+               if (!W_ERROR_IS_OK(status)) {
                        status = WERR_UNKNOWN_PRINTER_DRIVER;
                        goto done;
                }
        }
 
-       if (printer_driver_in_use(info)) {
+       if (printer_driver_in_use(info, p->server_info, info)) {
                status = WERR_PRINTER_DRIVER_IN_USE;
                goto done;
        }
@@ -1925,7 +1954,9 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
 
        /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
 
-       if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
+       if (delete_files &&
+           (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
+           printer_driver_files_in_use(info, p->server_info, info)) {
                /* no idea of the correct error here */
                status = WERR_ACCESS_DENIED;
                goto done;
@@ -1935,14 +1966,17 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
        /* also check for W32X86/3 if necessary; maybe we already have? */
 
        if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
-               if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
-                                                      r->in.driver,
-                                                      r->in.architecture, 3)))
-               {
-
-                       if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
+               status = winreg_get_driver(info, p->server_info,
+                                          r->in.architecture,
+                                          r->in.driver, 3, &info_win2k);
+               if (W_ERROR_IS_OK(status)) {
+
+                       if (delete_files &&
+                           (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
+                           printer_driver_files_in_use(info, p->server_info,
+                                                       info_win2k)) {
                                /* no idea of the correct error here */
-                               free_a_printer_driver(info_win2k);
+                               talloc_free(info_win2k);
                                status = WERR_ACCESS_DENIED;
                                goto done;
                        }
@@ -1950,41 +1984,47 @@ WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
                        /* if we get to here, we now have 2 driver info structures to remove */
                        /* remove the Win2k driver first*/
 
-                       status_win2k = delete_printer_driver(
-                               p, info_win2k, 3, delete_files);
-                       free_a_printer_driver(info_win2k);
+                       status = winreg_del_driver(info, p->server_info,
+                                                  info_win2k, 3);
 
                        /* this should not have failed---if it did, report to client */
 
-                       if ( !W_ERROR_IS_OK(status_win2k) )
+                       if (!W_ERROR_IS_OK(status)) {
                                goto done;
+                       }
+
+                       /*
+                        * now delete any associated files if delete_files is
+                        * true. Even if this part failes, we return succes
+                        * because the driver doesn not exist any more
+                        */
+                       if (delete_files) {
+                               delete_driver_files(p->server_info,
+                                                   info_win2k);
+                       }
                }
        }
 
-       status = delete_printer_driver(p, info, version, delete_files);
+       status = winreg_del_driver(info, p->server_info, info, version);
+       if (!W_ERROR_IS_OK(status)) {
+               goto done;
+       }
 
-       if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
-               status = WERR_OK;
-done:
-       free_a_printer_driver(info);
+       /*
+        * now delete any associated files if delete_files is
+        * true. Even if this part failes, we return succes
+        * because the driver doesn not exist any more
+        */
+       if (delete_files) {
+               delete_driver_files(p->server_info, info);
+       }
 
+done:
+       talloc_free(info);
        return status;
 }
 
 
-/****************************************************************************
- Internal routine for storing printerdata
- ***************************************************************************/
-
-WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
-                         const char *key, const char *value,
-                         uint32_t type, uint8_t *data, int real_len)
-{
-       /* the registry objects enforce uniqueness based on value name */
-
-       return add_printer_data( printer->info_2, key, value, type, data, real_len );
-}
-
 /********************************************************************
  GetPrinterData on a printer server Handle.
 ********************************************************************/
@@ -2394,10 +2434,10 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
 static void spoolss_notify_server_name(int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
-                                      NT_PRINTER_INFO_LEVEL *printer,
+                                      struct spoolss_PrinterInfo2 *pinfo2,
                                       TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
 }
 
 /*******************************************************************
@@ -2407,14 +2447,14 @@ static void spoolss_notify_server_name(int snum,
 static void spoolss_notify_printer_name(int snum,
                                        struct spoolss_Notify *data,
                                        print_queue_struct *queue,
-                                       NT_PRINTER_INFO_LEVEL *printer,
+                                       struct spoolss_PrinterInfo2 *pinfo2,
                                        TALLOC_CTX *mem_ctx)
 {
        /* the notify name should not contain the \\server\ part */
-       char *p = strrchr(printer->info_2->printername, '\\');
+       const char *p = strrchr(pinfo2->printername, '\\');
 
        if (!p) {
-               p = printer->info_2->printername;
+               p = pinfo2->printername;
        } else {
                p++;
        }
@@ -2429,7 +2469,7 @@ static void spoolss_notify_printer_name(int snum,
 static void spoolss_notify_share_name(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
@@ -2442,10 +2482,10 @@ static void spoolss_notify_share_name(int snum,
 static void spoolss_notify_port_name(int snum,
                                     struct spoolss_Notify *data,
                                     print_queue_struct *queue,
-                                    NT_PRINTER_INFO_LEVEL *printer,
+                                    struct spoolss_PrinterInfo2 *pinfo2,
                                     TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
 }
 
 /*******************************************************************
@@ -2456,10 +2496,10 @@ static void spoolss_notify_port_name(int snum,
 static void spoolss_notify_driver_name(int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
-                                      NT_PRINTER_INFO_LEVEL *printer,
+                                      struct spoolss_PrinterInfo2 *pinfo2,
                                       TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
 }
 
 /*******************************************************************
@@ -2469,18 +2509,18 @@ static void spoolss_notify_driver_name(int snum,
 static void spoolss_notify_comment(int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
-                                  NT_PRINTER_INFO_LEVEL *printer,
+                                  struct spoolss_PrinterInfo2 *pinfo2,
                                   TALLOC_CTX *mem_ctx)
 {
-       char *p;
+       const char *p;
 
-       if (*printer->info_2->comment == '\0') {
+       if (*pinfo2->comment == '\0') {
                p = lp_comment(snum);
        } else {
-               p = printer->info_2->comment;
+               p = pinfo2->comment;
        }
 
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
 }
 
 /*******************************************************************
@@ -2491,10 +2531,10 @@ static void spoolss_notify_comment(int snum,
 static void spoolss_notify_location(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
 }
 
 /*******************************************************************
@@ -2505,7 +2545,7 @@ static void spoolss_notify_location(int snum,
 static void spoolss_notify_devmode(int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
-                                  NT_PRINTER_INFO_LEVEL *printer,
+                                  struct spoolss_PrinterInfo2 *pinfo2,
                                   TALLOC_CTX *mem_ctx)
 {
        /* for a dummy implementation we have to zero the fields */
@@ -2519,10 +2559,10 @@ static void spoolss_notify_devmode(int snum,
 static void spoolss_notify_sepfile(int snum,
                                   struct spoolss_Notify *data,
                                   print_queue_struct *queue,
-                                  NT_PRINTER_INFO_LEVEL *printer,
+                                  struct spoolss_PrinterInfo2 *pinfo2,
                                   TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
 }
 
 /*******************************************************************
@@ -2533,10 +2573,10 @@ static void spoolss_notify_sepfile(int snum,
 static void spoolss_notify_print_processor(int snum,
                                           struct spoolss_Notify *data,
                                           print_queue_struct *queue,
-                                          NT_PRINTER_INFO_LEVEL *printer,
+                                          struct spoolss_PrinterInfo2 *pinfo2,
                                           TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
 }
 
 /*******************************************************************
@@ -2547,10 +2587,10 @@ static void spoolss_notify_print_processor(int snum,
 static void spoolss_notify_parameters(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
 }
 
 /*******************************************************************
@@ -2561,10 +2601,10 @@ static void spoolss_notify_parameters(int snum,
 static void spoolss_notify_datatype(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
 }
 
 /*******************************************************************
@@ -2576,12 +2616,10 @@ static void spoolss_notify_datatype(int snum,
 static void spoolss_notify_security_desc(int snum,
                                         struct spoolss_Notify *data,
                                         print_queue_struct *queue,
-                                        NT_PRINTER_INFO_LEVEL *printer,
+                                        struct spoolss_PrinterInfo2 *pinfo2,
                                         TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
-                                         printer->info_2->secdesc_buf->sd_size,
-                                         printer->info_2->secdesc_buf->sd);
+       SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
 }
 
 /*******************************************************************
@@ -2592,10 +2630,10 @@ static void spoolss_notify_security_desc(int snum,
 static void spoolss_notify_attributes(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
 }
 
 /*******************************************************************
@@ -2605,10 +2643,10 @@ static void spoolss_notify_attributes(int snum,
 static void spoolss_notify_priority(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
 }
 
 /*******************************************************************
@@ -2618,10 +2656,10 @@ static void spoolss_notify_priority(int snum,
 static void spoolss_notify_default_priority(int snum,
                                            struct spoolss_Notify *data,
                                            print_queue_struct *queue,
-                                           NT_PRINTER_INFO_LEVEL *printer,
+                                           struct spoolss_PrinterInfo2 *pinfo2,
                                            TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
 }
 
 /*******************************************************************
@@ -2631,10 +2669,10 @@ static void spoolss_notify_default_priority(int snum,
 static void spoolss_notify_start_time(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
 }
 
 /*******************************************************************
@@ -2644,10 +2682,10 @@ static void spoolss_notify_start_time(int snum,
 static void spoolss_notify_until_time(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
 }
 
 /*******************************************************************
@@ -2657,7 +2695,7 @@ static void spoolss_notify_until_time(int snum,
 static void spoolss_notify_status(int snum,
                                  struct spoolss_Notify *data,
                                  print_queue_struct *queue,
-                                 NT_PRINTER_INFO_LEVEL *printer,
+                                 struct spoolss_PrinterInfo2 *pinfo2,
                                  TALLOC_CTX *mem_ctx)
 {
        print_status_struct status;
@@ -2673,7 +2711,7 @@ static void spoolss_notify_status(int snum,
 static void spoolss_notify_cjobs(int snum,
                                 struct spoolss_Notify *data,
                                 print_queue_struct *queue,
-                                NT_PRINTER_INFO_LEVEL *printer,
+                                struct spoolss_PrinterInfo2 *pinfo2,
                                 TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
@@ -2686,12 +2724,12 @@ static void spoolss_notify_cjobs(int snum,
 static void spoolss_notify_average_ppm(int snum,
                                       struct spoolss_Notify *data,
                                       print_queue_struct *queue,
-                                      NT_PRINTER_INFO_LEVEL *printer,
+                                      struct spoolss_PrinterInfo2 *pinfo2,
                                       TALLOC_CTX *mem_ctx)
 {
        /* always respond 8 pages per minutes */
        /* a little hard ! */
-       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
 }
 
 /*******************************************************************
@@ -2701,7 +2739,7 @@ static void spoolss_notify_average_ppm(int snum,
 static void spoolss_notify_username(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
@@ -2714,7 +2752,7 @@ static void spoolss_notify_username(int snum,
 static void spoolss_notify_job_status(int snum,
                                      struct spoolss_Notify *data,
                                      print_queue_struct *queue,
-                                     NT_PRINTER_INFO_LEVEL *printer,
+                                     struct spoolss_PrinterInfo2 *pinfo2,
                                      TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
@@ -2727,7 +2765,7 @@ static void spoolss_notify_job_status(int snum,
 static void spoolss_notify_job_name(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
@@ -2740,7 +2778,7 @@ static void spoolss_notify_job_name(int snum,
 static void spoolss_notify_job_status_string(int snum,
                                             struct spoolss_Notify *data,
                                             print_queue_struct *queue,
-                                            NT_PRINTER_INFO_LEVEL *printer,
+                                            struct spoolss_PrinterInfo2 *pinfo2,
                                             TALLOC_CTX *mem_ctx)
 {
        /*
@@ -2778,7 +2816,7 @@ static void spoolss_notify_job_status_string(int snum,
 static void spoolss_notify_job_time(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
@@ -2791,7 +2829,7 @@ static void spoolss_notify_job_time(int snum,
 static void spoolss_notify_job_size(int snum,
                                    struct spoolss_Notify *data,
                                    print_queue_struct *queue,
-                                   NT_PRINTER_INFO_LEVEL *printer,
+                                   struct spoolss_PrinterInfo2 *pinfo2,
                                    TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
@@ -2803,7 +2841,7 @@ static void spoolss_notify_job_size(int snum,
 static void spoolss_notify_total_pages(int snum,
                                struct spoolss_Notify *data,
                                print_queue_struct *queue,
-                               NT_PRINTER_INFO_LEVEL *printer,
+                               struct spoolss_PrinterInfo2 *pinfo2,
                                TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
@@ -2815,7 +2853,7 @@ static void spoolss_notify_total_pages(int snum,
 static void spoolss_notify_pages_printed(int snum,
                                struct spoolss_Notify *data,
                                print_queue_struct *queue,
-                               NT_PRINTER_INFO_LEVEL *printer,
+                               struct spoolss_PrinterInfo2 *pinfo2,
                                TALLOC_CTX *mem_ctx)
 {
        /* Add code when back-end tracks this */
@@ -2829,7 +2867,7 @@ static void spoolss_notify_pages_printed(int snum,
 static void spoolss_notify_job_position(int snum,
                                        struct spoolss_Notify *data,
                                        print_queue_struct *queue,
-                                       NT_PRINTER_INFO_LEVEL *printer,
+                                       struct spoolss_PrinterInfo2 *pinfo2,
                                        TALLOC_CTX *mem_ctx)
 {
        SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
@@ -2842,7 +2880,7 @@ static void spoolss_notify_job_position(int snum,
 static void spoolss_notify_submitted_time(int snum,
                                          struct spoolss_Notify *data,
                                          print_queue_struct *queue,
-                                         NT_PRINTER_INFO_LEVEL *printer,
+                                         struct spoolss_PrinterInfo2 *pinfo2,
                                          TALLOC_CTX *mem_ctx)
 {
        data->data.string.string = NULL;
@@ -2862,7 +2900,8 @@ struct s_notify_info_data_table
        enum spoolss_NotifyTable variable_type;
        void (*fn) (int snum, struct spoolss_Notify *data,
                    print_queue_struct *queue,
-                   NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
+                   struct spoolss_PrinterInfo2 *pinfo2,
+                   TALLOC_CTX *mem_ctx);
 };
 
 /* A table describing the various print notification constants and
@@ -2967,10 +3006,9 @@ static bool search_notify(enum spoolss_NotifyType type,
 /****************************************************************************
 ****************************************************************************/
 
-void construct_info_data(struct spoolss_Notify *info_data,
-                        enum spoolss_NotifyType type,
-                        uint16_t field,
-                        int id)
+static void construct_info_data(struct spoolss_Notify *info_data,
+                               enum spoolss_NotifyType type,
+                               uint16_t field, int id)
 {
        info_data->type                 = type;
        info_data->field.field          = field;
@@ -2986,6 +3024,7 @@ void construct_info_data(struct spoolss_Notify *info_data,
 
 static bool construct_notify_printer_info(Printer_entry *print_hnd,
                                          struct spoolss_NotifyInfo *info,
+                                         struct spoolss_PrinterInfo2 *pinfo2,
                                          int snum,
                                          const struct spoolss_NotifyOptionType *option_type,
                                          uint32_t id,
@@ -2996,7 +3035,6 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
        uint16_t field;
 
        struct spoolss_Notify *current_data;
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
        print_queue_struct *queue=NULL;
 
        type = option_type->type;
@@ -3005,9 +3043,6 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
                (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
                option_type->count, lp_servicename(snum)));
 
-       if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
-               return false;
-
        for(field_num=0; field_num < option_type->count; field_num++) {
                field = option_type->fields[field_num].field;
 
@@ -3021,7 +3056,6 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
                                                      info->count + 1);
                if (info->notifies == NULL) {
                        DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
-                       free_a_printer(&printer, 2);
                        return false;
                }
 
@@ -3029,16 +3063,17 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
 
                construct_info_data(current_data, type, field, id);
 
-               DEBUG(10,("construct_notify_printer_info: calling [%s]  snum=%d  printername=[%s])\n",
-                               notify_info_data_table[j].name, snum, printer->info_2->printername ));
+               DEBUG(10, ("construct_notify_printer_info: "
+                          "calling [%s]  snum=%d  printername=[%s])\n",
+                          notify_info_data_table[j].name, snum,
+                          pinfo2->printername));
 
                notify_info_data_table[j].fn(snum, current_data, queue,
-                                            printer, mem_ctx);
+                                            pinfo2, mem_ctx);
 
                info->count++;
        }
 
-       free_a_printer(&printer, 2);
        return true;
 }
 
@@ -3050,7 +3085,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd,
 
 static bool construct_notify_jobs_info(print_queue_struct *queue,
                                       struct spoolss_NotifyInfo *info,
-                                      NT_PRINTER_INFO_LEVEL *printer,
+                                      struct spoolss_PrinterInfo2 *pinfo2,
                                       int snum,
                                       const struct spoolss_NotifyOptionType *option_type,
                                       uint32_t id,
@@ -3087,7 +3122,7 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
 
                construct_info_data(current_data, type, field, id);
                notify_info_data_table[j].fn(snum, current_data, queue,
-                                            printer, mem_ctx);
+                                            pinfo2, mem_ctx);
                info->count++;
        }
 
@@ -3135,6 +3170,8 @@ static WERROR printserver_notify_info(pipes_struct *p,
        int i;
        struct spoolss_NotifyOption *option;
        struct spoolss_NotifyOptionType option_type;
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+       WERROR result;
 
        DEBUG(4,("printserver_notify_info\n"));
 
@@ -3159,10 +3196,32 @@ static WERROR printserver_notify_info(pipes_struct *p,
                if (option_type.type != PRINTER_NOTIFY_TYPE)
                        continue;
 
-               for (snum=0; snum<n_services; snum++)
-               {
-                       if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
-                               construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
+               for (snum = 0; snum < n_services; snum++) {
+                       if (!lp_browseable(snum) ||
+                           !lp_snum_ok(snum) ||
+                           !lp_print_ok(snum)) {
+                               continue; /* skip */
+                       }
+
+                       /* FIXME: should we use a SYSTEM server_info here? */
+                       result = winreg_get_printer(mem_ctx, p->server_info,
+                                                   Printer->servername,
+                                                   lp_servicename(snum),
+                                                   &pinfo2);
+                       if (!W_ERROR_IS_OK(result)) {
+                               DEBUG(4, ("printserver_notify_info: "
+                                         "Failed to get printer [%s]\n",
+                                         lp_servicename(snum)));
+                               continue;
+                       }
+
+
+                       construct_notify_printer_info(Printer, info,
+                                                     pinfo2, snum,
+                                                     &option_type, snum,
+                                                     mem_ctx);
+
+                       TALLOC_FREE(pinfo2);
                }
        }
 
@@ -3204,6 +3263,8 @@ static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
        int count,j;
        print_queue_struct *queue=NULL;
        print_status_struct status;
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+       WERROR result;
 
        DEBUG(4,("printer_notify_info\n"));
 
@@ -3225,40 +3286,42 @@ static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
 
        get_printer_snum(p, hnd, &snum, NULL);
 
+       /* FIXME: should we use a SYSTEM server_info here ? */
+       result = winreg_get_printer(mem_ctx, p->server_info,
+                                   Printer->servername,
+                                   lp_servicename(snum), &pinfo2);
+       if (!W_ERROR_IS_OK(result)) {
+               return WERR_BADFID;
+       }
+
        for (i=0; i<option->count; i++) {
                option_type = option->types[i];
 
                switch (option_type.type) {
                case PRINTER_NOTIFY_TYPE:
-                       if(construct_notify_printer_info(Printer, info, snum,
-                                                        &option_type, id,
-                                                        mem_ctx))
+                       if (construct_notify_printer_info(Printer, info,
+                                                         pinfo2, snum,
+                                                         &option_type, id,
+                                                         mem_ctx)) {
                                id--;
+                       }
                        break;
 
-               case JOB_NOTIFY_TYPE: {
-                       NT_PRINTER_INFO_LEVEL *printer = NULL;
+               case JOB_NOTIFY_TYPE:
 
                        count = print_queue_status(snum, &queue, &status);
 
-                       if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
-                               goto done;
-
                        for (j=0; j<count; j++) {
                                construct_notify_jobs_info(&queue[j], info,
-                                                          printer, snum,
+                                                          pinfo2, snum,
                                                           &option_type,
                                                           queue[j].job,
                                                           mem_ctx);
                        }
 
-                       free_a_printer(&printer, 2);
-
-               done:
                        SAFE_FREE(queue);
                        break;
                }
-               }
        }
 
        /*
@@ -3275,6 +3338,8 @@ static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
                info->data[i].id, info->data[i].size, info->data[i].enc_type));
        }
        */
+
+       talloc_free(pinfo2);
        return WERR_OK;
 }
 
@@ -3420,7 +3485,7 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
        r->last_error                   = WERR_OK;
        r->status                       = nt_printq_status(status.status);
        r->enumerate_network_printers   = 0x0;
-       r->c_setprinter                 = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
+       r->c_setprinter                 = 0x0;
        r->processor_architecture       = 0x0;
        r->processor_level              = 0x6;          /* 6  ???*/
        r->ref_ic                       = 0;
@@ -3431,36 +3496,6 @@ static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
 }
 
 
-/****************************************************************************
- Create a spoolss_DeviceMode struct. Returns talloced memory.
-****************************************************************************/
-
-struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
-                                             const char *servicename)
-{
-       NT_PRINTER_INFO_LEVEL   *printer = NULL;
-       struct spoolss_DeviceMode *devmode = NULL;
-
-       DEBUG(7,("construct_dev_mode\n"));
-
-       DEBUGADD(8,("getting printer characteristics\n"));
-
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
-               return NULL;
-
-       if (!printer->info_2->devmode) {
-               DEBUG(5, ("BONG! There was no device mode!\n"));
-               goto done;
-       }
-
-        devmode = talloc_steal(mem_ctx, printer->info_2->devmode);
-
-done:
-       free_a_printer(&printer,2);
-
-       return devmode;
-}
-
 /********************************************************************
  * construct_printer_info1
  * fill a spoolss_PrinterInfo1 struct
@@ -3661,9 +3696,19 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
                                      struct spoolss_PrinterInfo7 *r,
                                      int snum)
 {
+       struct auth_serversupplied_info *server_info;
        struct GUID guid;
+       NTSTATUS status;
 
-       if (is_printer_published(print_hnd, snum, &guid)) {
+       status = make_server_info_system(mem_ctx, &server_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("construct_printer_info7: "
+                         "Could not create system server_info\n"));
+               return WERR_NOMEM;
+       }
+
+       if (is_printer_published(mem_ctx, server_info, print_hnd->servername,
+                                lp_servicename(snum), &guid, NULL)) {
                r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
                r->action = DSPRINT_PUBLISH;
        } else {
@@ -3672,6 +3717,7 @@ static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
        }
        W_ERROR_HAVE_NO_MEMORY(r->guid);
 
+       TALLOC_FREE(server_info);
        return WERR_OK;
 }
 
@@ -4199,30 +4245,52 @@ WERROR _spoolss_GetPrinter(pipes_struct *p,
 /********************************************************************
  ********************************************************************/
 
-static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
+#define FILL_DRIVER_STRING(mem_ctx, in, out) \
+       do { \
+               if (in && strlen(in)) { \
+                       out = talloc_strdup(mem_ctx, in); \
+                       W_ERROR_HAVE_NO_MEMORY(out); \
+               } else { \
+                       out = NULL; \
+               } \
+       } while (0);
+
+#define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
+       do { \
+               if (in && strlen(in)) { \
+                       out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
+               } else { \
+                       out = talloc_strdup(mem_ctx, ""); \
+               } \
+               W_ERROR_HAVE_NO_MEMORY(out); \
+       } while (0);
+
+static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
                                                  const char **string_array,
-                                                 const char *cservername)
+                                                 const char ***presult,
+                                                 const char *cservername,
+                                                 const char *arch,
+                                                 int version)
 {
        int i, num_strings = 0;
        const char **array = NULL;
 
-       if (!string_array) {
-               return NULL;
+       if (string_array == NULL) {
+               return WERR_INVALID_PARAMETER;;
        }
 
        for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
+               const char *str = NULL;
 
-               const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
-                                                 cservername, string_array[i]);
-               if (!str) {
-                       TALLOC_FREE(array);
-                       return NULL;
+               if (cservername == NULL || arch == NULL) {
+                       FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
+               } else {
+                       FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
                }
 
-
                if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
                        TALLOC_FREE(array);
-                       return NULL;
+                       return WERR_NOMEM;
                }
        }
 
@@ -4231,28 +4299,12 @@ static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
                             &array, &num_strings);
        }
 
-       return array;
-}
-
-#define FILL_DRIVER_STRING(mem_ctx, in, out) \
-       do { \
-               if (in && strlen(in)) { \
-                       out = talloc_strdup(mem_ctx, in); \
-                       W_ERROR_HAVE_NO_MEMORY(out); \
-               } else { \
-                       out = NULL; \
-               } \
-       } while (0);
+       if (presult) {
+               *presult = array;
+       }
 
-#define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
-       do { \
-               if (in && strlen(in)) { \
-                       out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
-               } else { \
-                       out = talloc_strdup(mem_ctx, ""); \
-               } \
-               W_ERROR_HAVE_NO_MEMORY(out); \
-       } while (0);
+       return WERR_OK;
+}
 
 /********************************************************************
  * fill a spoolss_DriverInfo1 struct
@@ -4289,14 +4341,20 @@ static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
@@ -4322,18 +4380,26 @@ static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->help_file,
                               r->help_file);
 
@@ -4345,10 +4411,12 @@ static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
                           driver->default_datatype,
                           r->default_datatype);
 
-       r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->dependent_files,
-                                                          cservername);
-       return WERR_OK;
+       return string_array_from_driver_info(mem_ctx,
+                                            driver->dependent_files,
+                                            &r->dependent_files,
+                                            cservername,
+                                            driver->architecture,
+                                            driver->version);
 }
 
 /********************************************************************
@@ -4361,6 +4429,7 @@ static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
                                        const char *servername)
 {
        const char *cservername = canon_servername(servername);
+       WERROR result;
 
        r->version              = driver->version;
 
@@ -4370,24 +4439,38 @@ static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->help_file,
                               r->help_file);
 
-       r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->dependent_files,
-                                                          cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->dependent_files,
+                                              &r->dependent_files,
+                                              cservername,
+                                              driver->architecture,
+                                              driver->version);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        FILL_DRIVER_STRING(mem_ctx,
                           driver->monitor_name,
@@ -4397,11 +4480,13 @@ static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
                           driver->default_datatype,
                           r->default_datatype);
 
-       r->previous_names = string_array_from_driver_info(mem_ctx,
-                                                         driver->previous_names,
-                                                         cservername);
 
-       return WERR_OK;
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->previous_names,
+                                              &r->previous_names,
+                                              NULL, NULL, 0);
+
+       return result;
 }
 
 /********************************************************************
@@ -4423,14 +4508,20 @@ static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
@@ -4450,6 +4541,7 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
                                        const char *servername)
 {
        const char *cservername = canon_servername(servername);
+       WERROR result;
 
        r->version              = driver->version;
 
@@ -4459,18 +4551,26 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->help_file,
                               r->help_file);
 
@@ -4482,12 +4582,23 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
                           driver->default_datatype,
                           r->default_datatype);
 
-       r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->dependent_files,
-                                                          cservername);
-       r->previous_names = string_array_from_driver_info(mem_ctx,
-                                                         driver->previous_names,
-                                                         cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->dependent_files,
+                                              &r->dependent_files,
+                                              cservername,
+                                              driver->architecture,
+                                              driver->version);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->previous_names,
+                                              &r->previous_names,
+                                              NULL, NULL, 0);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        r->driver_date          = driver->driver_date;
        r->driver_version       = driver->driver_version;
@@ -4518,6 +4629,7 @@ static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
                                        const char *servername)
 {
        const char *cservername = canon_servername(servername);
+       WERROR result;
 
        r->version              = driver->version;
 
@@ -4527,18 +4639,26 @@ static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->architecture);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->driver_path,
                               r->driver_path);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->data_file,
                               r->data_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->config_file,
                               r->config_file);
 
        FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->architecture,
+                              driver->version,
                               driver->help_file,
                               r->help_file);
 
@@ -4550,12 +4670,23 @@ static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
                           driver->default_datatype,
                           r->default_datatype);
 
-       r->dependent_files = string_array_from_driver_info(mem_ctx,
-                                                          driver->dependent_files,
-                                                          cservername);
-       r->previous_names = string_array_from_driver_info(mem_ctx,
-                                                         driver->previous_names,
-                                                         cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->dependent_files,
+                                              &r->dependent_files,
+                                              cservername,
+                                              driver->architecture,
+                                              driver->version);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->previous_names,
+                                              &r->previous_names,
+                                              NULL, NULL, 0);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        r->driver_date          = driver->driver_date;
        r->driver_version       = driver->driver_version;
@@ -4580,9 +4711,13 @@ static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
                           driver->vendor_setup,
                           r->vendor_setup);
 
-       r->color_profiles = string_array_from_driver_info(mem_ctx,
-                                                         driver->color_profiles,
-                                                         cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->color_profiles,
+                                              &r->color_profiles,
+                                              NULL, NULL, 0);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        FILL_DRIVER_STRING(mem_ctx,
                           driver->inf_path,
@@ -4590,9 +4725,13 @@ static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
 
        r->printer_driver_attributes    = driver->printer_driver_attributes;
 
-       r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
-                                                                   driver->core_driver_dependencies,
-                                                                   cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->core_driver_dependencies,
+                                              &r->core_driver_dependencies,
+                                              NULL, NULL, 0);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
 
        r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
        r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
@@ -4753,9 +4892,14 @@ static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
                           driver->default_datatype,
                           r->default_datatype);
 
-       r->previous_names = string_array_from_driver_info(mem_ctx,
-                                                         driver->previous_names,
-                                                         cservername);
+       result = string_array_from_driver_info(mem_ctx,
+                                              driver->previous_names,
+                                              &r->previous_names,
+                                              NULL, NULL, 0);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
        r->driver_date          = driver->driver_date;
        r->driver_version       = driver->driver_version;
 
@@ -4779,6 +4923,7 @@ static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
+                                                 struct auth_serversupplied_info *server_info,
                                                  uint32_t level,
                                                  union spoolss_DriverInfo *r,
                                                  int snum,
@@ -4786,11 +4931,15 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                                                  const char *architecture,
                                                  uint32_t version)
 {
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        struct spoolss_DriverInfo8 *driver;
        WERROR result;
 
-       result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
+       result = winreg_get_printer(mem_ctx,
+                                   server_info,
+                                   servername,
+                                   lp_const_servicename(snum),
+                                   &pinfo2);
 
        DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
                win_errstr(result)));
@@ -4799,8 +4948,8 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
-                                     architecture, version);
+       result = winreg_get_driver(mem_ctx, server_info, architecture,
+                                  pinfo2->drivername, version, &driver);
 
        DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
                win_errstr(result)));
@@ -4811,18 +4960,19 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                 */
 
                if (version < 3) {
-                       free_a_printer(&printer, 2);
+                       talloc_free(pinfo2);
                        return WERR_UNKNOWN_PRINTER_DRIVER;
                }
 
                /* Yes - try again with a WinNT driver. */
                version = 2;
-               result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
-                                             architecture, version);
+               result = winreg_get_driver(mem_ctx, server_info, architecture,
+                                          pinfo2->drivername,
+                                          version, &driver);
                DEBUG(8,("construct_printer_driver_level: status: %s\n",
                        win_errstr(result)));
                if (!W_ERROR_IS_OK(result)) {
-                       free_a_printer(&printer, 2);
+                       talloc_free(pinfo2);
                        return WERR_UNKNOWN_PRINTER_DRIVER;
                }
        }
@@ -4859,8 +5009,8 @@ static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
                break;
        }
 
-       free_a_printer(&printer, 2);
-       free_a_printer_driver(driver);
+       talloc_free(pinfo2);
+       talloc_free(driver);
 
        return result;
 }
@@ -4875,7 +5025,6 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
        Printer_entry *printer;
        WERROR result;
 
-       const char *servername;
        int snum;
 
        /* that's an [in out] buffer */
@@ -4895,15 +5044,13 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
        *r->out.server_major_version = 0;
        *r->out.server_minor_version = 0;
 
-       servername = get_server_name(printer);
-
        if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
                return WERR_BADFID;
        }
 
-       result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
-                                                    r->out.info, snum,
-                                                    servername,
+       result = construct_printer_driver_info_level(p->mem_ctx, p->server_info,
+                                                    r->in.level, r->out.info,
+                                                    snum, printer->servername,
                                                     r->in.architecture,
                                                     r->in.client_major_version);
        if (!W_ERROR_IS_OK(result)) {
@@ -4974,6 +5121,7 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
        struct spoolss_DocumentInfo1 *info_1;
        int snum;
        Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       WERROR werr;
 
        if (!Printer) {
                DEBUG(2,("_spoolss_StartDocPrinter: "
@@ -4982,6 +5130,13 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
                return WERR_BADFID;
        }
 
+       if (Printer->jobid) {
+               DEBUG(2, ("_spoolss_StartDocPrinter: "
+                         "StartDocPrinter called twice! "
+                         "(existing jobid = %d)\n", Printer->jobid));
+               return WERR_INVALID_HANDLE;
+       }
+
        if (r->in.level != 1) {
                return WERR_UNKNOWN_LEVEL;
        }
@@ -5008,15 +5163,15 @@ WERROR _spoolss_StartDocPrinter(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       Printer->jobid = print_job_start(p->server_info, snum,
-                                        info_1->document_name,
-                                        Printer->devmode);
+       werr = print_job_start(p->server_info, snum,
+                               info_1->document_name, info_1->output_file,
+                               Printer->devmode, &Printer->jobid);
 
        /* An error occured in print_job_start() so return an appropriate
           NT error code. */
 
-       if (Printer->jobid == -1) {
-               return map_werror_from_unix(errno);
+       if (!W_ERROR_IS_OK(werr)) {
+               return werr;
        }
 
        Printer->document_started = true;
@@ -5033,6 +5188,7 @@ WERROR _spoolss_EndDocPrinter(pipes_struct *p,
                              struct spoolss_EndDocPrinter *r)
 {
        Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       NTSTATUS status;
        int snum;
 
        if (!Printer) {
@@ -5046,10 +5202,15 @@ WERROR _spoolss_EndDocPrinter(pipes_struct *p,
        }
 
        Printer->document_started = false;
-       print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
-       /* error codes unhandled so far ... */
+       status = print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(2, ("_spoolss_EndDocPrinter: "
+                         "print_job_end failed [%s]\n",
+                         nt_errstr(status)));
+       }
 
-       return WERR_OK;
+       Printer->jobid = 0;
+       return ntstatus_to_werror(status);
 }
 
 /****************************************************************
@@ -5264,11 +5425,6 @@ static WERROR update_printer_sec(struct policy_handle *handle,
 
 /********************************************************************
  Canonicalize printer info from a client
-
- ATTN: It does not matter what we set the servername to hear
- since we do the necessary work in get_a_printer() to set it to
- the correct value based on what the client sent in the
- _spoolss_open_printer_ex().
  ********************************************************************/
 
 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
@@ -5461,220 +5617,361 @@ bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
        return true;
 }
 
-
-/********************************************************************
- * Called by spoolss_api_setprinter
- * when updating a printer description.
- ********************************************************************/
-
-static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
-                            struct spoolss_SetPrinterInfoCtr *info_ctr,
-                            struct spoolss_DeviceMode *devmode)
+static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
+                              struct auth_serversupplied_info *server_info,
+                              int snum,
+                              struct spoolss_SetPrinterInfo2 *printer,
+                              struct spoolss_PrinterInfo2 *old_printer)
 {
-       uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
-       struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
-       struct spoolss_PrinterInfo2 *old_printer;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-       const char *servername = NULL;
-       int snum;
-       WERROR result;
+       bool force_update = (old_printer == NULL);
+       const char *dnsdomname;
+       const char *longname;
+       const char *uncname;
+       const char *spooling;
        DATA_BLOB buffer;
-       fstring asc_buffer;
+       WERROR result = WERR_OK;
 
-       DEBUG(8,("update_printer\n"));
+       if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
+               push_reg_sz(mem_ctx, &buffer, printer->drivername);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_DRIVERNAME,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
 
-       result = WERR_OK;
+               if (!force_update) {
+                       DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
+                               printer->drivername));
 
-       if (!Printer) {
-               result = WERR_BADFID;
-               goto done;
+                       notify_printer_driver(snum, printer->drivername);
+               }
        }
 
-       if (!get_printer_snum(p, handle, &snum, NULL)) {
-               result = WERR_BADFID;
-               goto done;
-       }
+       if (force_update || !strequal(printer->comment, old_printer->comment)) {
+               push_reg_sz(mem_ctx, &buffer, printer->comment);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_DESCRIPTION,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
 
-       if (Printer != NULL || Printer->servername != NULL) {
-               servername = Printer->servername;
+               if (!force_update) {
+                       notify_printer_comment(snum, printer->comment);
+               }
        }
 
-       result = winreg_get_printer(p->mem_ctx,
-                                   p->server_info,
-                                   servername,
-                                   lp_const_servicename(snum),
-                                   &old_printer);
-       if (!W_ERROR_IS_OK(result)) {
-               result = WERR_BADFID;
-               goto done;
-       }
+       if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
+               push_reg_sz(mem_ctx, &buffer, printer->sharename);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_PRINTSHARENAME,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
 
-       /* Do sanity check on the requested changes for Samba */
-       if (!check_printer_ok(p->mem_ctx, printer, snum)) {
-               result = WERR_INVALID_PARAM;
-               goto done;
+               if (!force_update) {
+                       notify_printer_sharename(snum, printer->sharename);
+               }
        }
 
-       /* FIXME!!! If the driver has changed we really should verify that
-          it is installed before doing much else   --jerry */
+       if (force_update || !strequal(printer->printername, old_printer->printername)) {
+               const char *p;
 
-       /* Check calling user has permission to update printer description */
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
-               DEBUG(3, ("update_printer: printer property change denied by handle\n"));
-               result = WERR_ACCESS_DENIED;
-               goto done;
-       }
+               p = strrchr(printer->printername, '\\' );
+               if (p != NULL) {
+                       p++;
+               } else {
+                       p = printer->printername;
+               }
 
-       /* Call addprinter hook */
-       /* Check changes to see if this is really needed */
+               push_reg_sz(mem_ctx, &buffer, p);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_PRINTERNAME,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
 
-       if (*lp_addprinter_cmd() &&
-                       (!strequal(printer->drivername, old_printer->drivername) ||
-                        !strequal(printer->comment, old_printer->comment) ||
-                        !strequal(printer->portname, old_printer->portname) ||
-                        !strequal(printer->location, old_printer->location)) )
-       {
-               /* add_printer_hook() will call reload_services() */
-               if (!add_printer_hook(p->mem_ctx, p->server_info->ptok,
-                                     printer) ) {
-                       result = WERR_ACCESS_DENIED;
-                       goto done;
+               if (!force_update) {
+                       notify_printer_printername(snum, p);
                }
        }
 
-       /*
-        * When a *new* driver is bound to a printer, the drivername is used to
-        * lookup previously saved driver initialization info, which is then
-        * bound to the printer, simulating what happens in the Windows arch.
-        */
-       if (!strequal(printer->drivername, old_printer->drivername)) {
-               DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
-                       printer->drivername));
+       if (force_update || !strequal(printer->portname, old_printer->portname)) {
+               push_reg_sz(mem_ctx, &buffer, printer->portname);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_PORTNAME,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
 
-               notify_printer_driver(snum, printer->drivername);
+               if (!force_update) {
+                       notify_printer_port(snum, printer->portname);
+               }
        }
 
-       /*
-        * flag which changes actually occured.  This is a small subset of
-        * all the possible changes.  We also have to update things in the
-        * DsSpooler key.
-        */
-       if (!strequal(printer->comment, old_printer->comment)) {
-               push_reg_sz(talloc_tos(), &buffer, printer->comment);
-               winreg_set_printer_dataex(p->mem_ctx,
-                                         p->server_info,
+       if (force_update || !strequal(printer->location, old_printer->location)) {
+               push_reg_sz(mem_ctx, &buffer, printer->location);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
-                                         "description",
+                                         SPOOL_REG_LOCATION,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
 
-               notify_printer_comment(snum, printer->comment);
+               if (!force_update) {
+                       notify_printer_location(snum, printer->location);
+               }
        }
 
-       if (!strequal(printer->sharename, old_printer->sharename)) {
-               push_reg_sz(talloc_tos(), &buffer, printer->sharename);
-               winreg_set_printer_dataex(p->mem_ctx,
-                                         p->server_info,
+       if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
+               push_reg_sz(mem_ctx, &buffer, printer->sepfile);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
-                                         "shareName",
+                                         SPOOL_REG_PRINTSEPARATORFILE,
                                          REG_SZ,
                                          buffer.data,
                                          buffer.length);
 
-               notify_printer_sharename(snum, printer->sharename);
+               if (!force_update) {
+                       notify_printer_location(snum, printer->location);
+               }
        }
 
-       if (!strequal(printer->printername, old_printer->printername)) {
-               const char *pname;
-
-               if ( (pname = strchr_m( printer->printername+2, '\\' )) != NULL )
-                       pname++;
-               else
-                       pname = printer->printername;
-
-               push_reg_sz(talloc_tos(), &buffer, pname);
-               winreg_set_printer_dataex(p->mem_ctx,
-                                         p->server_info,
+       if (force_update || printer->starttime != old_printer->starttime) {
+               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               SIVAL(buffer.data, 0, printer->starttime);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
-                                         "printerName",
-                                         REG_SZ,
+                                         SPOOL_REG_PRINTSTARTTIME,
+                                         REG_DWORD,
                                          buffer.data,
                                          buffer.length);
-
-               notify_printer_printername( snum, pname );
        }
 
-       if (!strequal(printer->portname, old_printer->portname)) {
-               push_reg_sz(talloc_tos(), &buffer, printer->portname);
-               winreg_set_printer_dataex(p->mem_ctx,
-                                         p->server_info,
+       if (force_update || printer->untiltime != old_printer->untiltime) {
+               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               SIVAL(buffer.data, 0, printer->untiltime);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
-                                         "portName",
-                                         REG_SZ,
+                                         SPOOL_REG_PRINTENDTIME,
+                                         REG_DWORD,
                                          buffer.data,
                                          buffer.length);
+       }
 
-               notify_printer_port(snum, printer->portname);
+       if (force_update || printer->priority != old_printer->priority) {
+               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               SIVAL(buffer.data, 0, printer->priority);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_PRIORITY,
+                                         REG_DWORD,
+                                         buffer.data,
+                                         buffer.length);
        }
 
-       if (!strequal(printer->location, old_printer->location)) {
-               push_reg_sz(talloc_tos(), &buffer, printer->location);
-               winreg_set_printer_dataex(p->mem_ctx,
-                                         p->server_info,
+       if (force_update || printer->attributes != old_printer->attributes) {
+               buffer = data_blob_talloc(mem_ctx, NULL, 4);
+               SIVAL(buffer.data, 0, (printer->attributes &
+                                      PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
                                          printer->sharename,
                                          SPOOL_DSSPOOLER_KEY,
-                                         "location",
-                                         REG_SZ,
+                                         SPOOL_REG_PRINTKEEPPRINTEDJOBS,
+                                         REG_DWORD,
                                          buffer.data,
                                          buffer.length);
 
-               notify_printer_location(snum, printer->location);
+               switch (printer->attributes & 0x3) {
+                       case 0:
+                               spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
+                               break;
+                       case 1:
+                               spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
+                               break;
+                       case 2:
+                               spooling = SPOOL_REGVAL_PRINTDIRECT;
+                               break;
+                       default:
+                               spooling = "unknown";
+               }
+               push_reg_sz(mem_ctx, &buffer, spooling);
+               winreg_set_printer_dataex(mem_ctx,
+                                         server_info,
+                                         printer->sharename,
+                                         SPOOL_DSSPOOLER_KEY,
+                                         SPOOL_REG_PRINTSPOOLING,
+                                         REG_SZ,
+                                         buffer.data,
+                                         buffer.length);
        }
 
-       /* here we need to update some more DsSpooler keys */
-       /* uNCName, serverName, shortServerName */
-
-       push_reg_sz(talloc_tos(), &buffer, global_myname());
-       winreg_set_printer_dataex(p->mem_ctx,
-                                 p->server_info,
+       push_reg_sz(mem_ctx, &buffer, global_myname());
+       winreg_set_printer_dataex(mem_ctx,
+                                 server_info,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
-                                 "serverName",
+                                 SPOOL_REG_SHORTSERVERNAME,
                                  REG_SZ,
                                  buffer.data,
                                  buffer.length);
-       winreg_set_printer_dataex(p->mem_ctx,
-                                 p->server_info,
+
+       dnsdomname = get_mydnsfullname();
+       if (dnsdomname != NULL && dnsdomname[0] != '\0') {
+               longname = talloc_strdup(mem_ctx, dnsdomname);
+       } else {
+               longname = talloc_strdup(mem_ctx, global_myname());
+       }
+       if (longname == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+
+       push_reg_sz(mem_ctx, &buffer, longname);
+       winreg_set_printer_dataex(mem_ctx,
+                                 server_info,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
-                                 "shortServerName",
+                                 SPOOL_REG_SERVERNAME,
                                  REG_SZ,
                                  buffer.data,
                                  buffer.length);
 
-       slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
-                 global_myname(), printer->sharename );
-       push_reg_sz(talloc_tos(), &buffer, asc_buffer);
-       winreg_set_printer_dataex(p->mem_ctx,
-                                 p->server_info,
+       uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
+                                 global_myname(), printer->sharename);
+       push_reg_sz(mem_ctx, &buffer, uncname);
+       winreg_set_printer_dataex(mem_ctx,
+                                 server_info,
                                  printer->sharename,
                                  SPOOL_DSSPOOLER_KEY,
-                                 "uNCName",
+                                 SPOOL_REG_UNCNAME,
                                  REG_SZ,
                                  buffer.data,
                                  buffer.length);
 
+done:
+       return result;
+}
+
+/********************************************************************
+ * Called by spoolss_api_setprinter
+ * when updating a printer description.
+ ********************************************************************/
+
+static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
+                            struct spoolss_SetPrinterInfoCtr *info_ctr,
+                            struct spoolss_DeviceMode *devmode)
+{
+       uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
+       struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
+       struct spoolss_PrinterInfo2 *old_printer;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       const char *servername = NULL;
+       int snum;
+       WERROR result = WERR_OK;
+       TALLOC_CTX *tmp_ctx;
+
+       DEBUG(8,("update_printer\n"));
+
+       tmp_ctx = talloc_new(p->mem_ctx);
+       if (tmp_ctx == NULL) {
+               return WERR_NOMEM;
+       }
+
+       if (!Printer) {
+               result = WERR_BADFID;
+               goto done;
+       }
+
+       if (!get_printer_snum(p, handle, &snum, NULL)) {
+               result = WERR_BADFID;
+               goto done;
+       }
+
+       if (Printer != NULL || Printer->servername != NULL) {
+               servername = Printer->servername;
+       }
+
+       result = winreg_get_printer(tmp_ctx,
+                                   p->server_info,
+                                   servername,
+                                   lp_const_servicename(snum),
+                                   &old_printer);
+       if (!W_ERROR_IS_OK(result)) {
+               result = WERR_BADFID;
+               goto done;
+       }
+
+       /* Do sanity check on the requested changes for Samba */
+       if (!check_printer_ok(tmp_ctx, printer, snum)) {
+               result = WERR_INVALID_PARAM;
+               goto done;
+       }
+
+       /* FIXME!!! If the driver has changed we really should verify that
+          it is installed before doing much else   --jerry */
+
+       /* Check calling user has permission to update printer description */
+       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+               DEBUG(3, ("update_printer: printer property change denied by handle\n"));
+               result = WERR_ACCESS_DENIED;
+               goto done;
+       }
+
+       /* Call addprinter hook */
+       /* Check changes to see if this is really needed */
+
+       if (*lp_addprinter_cmd() &&
+                       (!strequal(printer->drivername, old_printer->drivername) ||
+                        !strequal(printer->comment, old_printer->comment) ||
+                        !strequal(printer->portname, old_printer->portname) ||
+                        !strequal(printer->location, old_printer->location)) )
+       {
+               /* add_printer_hook() will call reload_services() */
+               if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
+                                     printer) ) {
+                       result = WERR_ACCESS_DENIED;
+                       goto done;
+               }
+       }
+
+       update_dsspooler(tmp_ctx,
+                        p->server_info,
+                        snum,
+                        printer,
+                        old_printer);
+
        printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
 
        if (devmode == NULL) {
                printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
        }
-       result = winreg_update_printer(p->mem_ctx,
+       result = winreg_update_printer(tmp_ctx,
                                       p->server_info,
                                       printer->sharename,
                                       printer_mask,
@@ -5683,7 +5980,7 @@ static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
                                       NULL);
 
 done:
-       talloc_free(old_printer);
+       talloc_free(tmp_ctx);
 
        return result;
 }
@@ -5695,6 +5992,8 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p,
                                           struct spoolss_SetPrinterInfo7 *info7)
 {
 #ifdef HAVE_ADS
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
+       WERROR result;
        int snum;
        Printer_entry *Printer;
 
@@ -5712,8 +6011,16 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p,
        if (!get_printer_snum(p, handle, &snum, NULL))
                return WERR_BADFID;
 
-       nt_printer_publish(Printer, snum, info7->action);
+       result = winreg_get_printer(p->mem_ctx, p->server_info,
+                                   Printer->servername,
+                                   lp_servicename(snum), &pinfo2);
+       if (!W_ERROR_IS_OK(result)) {
+               return WERR_BADFID;
+       }
+
+       nt_printer_publish(pinfo2, p->server_info, pinfo2, info7->action);
 
+       TALLOC_FREE(pinfo2);
        return WERR_OK;
 #else
        return WERR_UNKNOWN_LEVEL;
@@ -5867,7 +6174,7 @@ static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
                             struct spoolss_JobInfo1 *r,
                             const print_queue_struct *queue,
                             int position, int snum,
-                            const NT_PRINTER_INFO_LEVEL *ntprinter)
+                            struct spoolss_PrinterInfo2 *pinfo2)
 {
        struct tm *t;
 
@@ -5877,7 +6184,7 @@ static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
 
        r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
        W_ERROR_HAVE_NO_MEMORY(r->printer_name);
-       r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
+       r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
        W_ERROR_HAVE_NO_MEMORY(r->server_name);
        r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
        W_ERROR_HAVE_NO_MEMORY(r->user_name);
@@ -5907,7 +6214,7 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
                             struct spoolss_JobInfo2 *r,
                             const print_queue_struct *queue,
                             int position, int snum,
-                            const NT_PRINTER_INFO_LEVEL *ntprinter,
+                            struct spoolss_PrinterInfo2 *pinfo2,
                             struct spoolss_DeviceMode *devmode)
 {
        struct tm *t;
@@ -5918,7 +6225,7 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
 
        r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
        W_ERROR_HAVE_NO_MEMORY(r->printer_name);
-       r->server_name          = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
+       r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
        W_ERROR_HAVE_NO_MEMORY(r->server_name);
        r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
        W_ERROR_HAVE_NO_MEMORY(r->user_name);
@@ -5932,7 +6239,7 @@ static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
        W_ERROR_HAVE_NO_MEMORY(r->print_processor);
        r->parameters           = talloc_strdup(mem_ctx, "");
        W_ERROR_HAVE_NO_MEMORY(r->parameters);
-       r->driver_name          = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
+       r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
 
        r->devmode              = devmode;
@@ -5965,7 +6272,7 @@ static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
                             const print_queue_struct *queue,
                             const print_queue_struct *next_queue,
                             int position, int snum,
-                            const NT_PRINTER_INFO_LEVEL *ntprinter)
+                            struct spoolss_PrinterInfo2 *pinfo2)
 {
        r->job_id               = queue->job;
        r->next_job_id          = 0;
@@ -5984,7 +6291,7 @@ static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
                              const print_queue_struct *queue,
                              uint32_t num_queues, int snum,
-                              const NT_PRINTER_INFO_LEVEL *ntprinter,
+                              struct spoolss_PrinterInfo2 *pinfo2,
                              union spoolss_JobInfo **info_p,
                              uint32_t *count)
 {
@@ -6003,7 +6310,7 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
                                        &queue[i],
                                        i,
                                        snum,
-                                       ntprinter);
+                                       pinfo2);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
@@ -6028,7 +6335,7 @@ static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
                              const print_queue_struct *queue,
                              uint32_t num_queues, int snum,
-                              const NT_PRINTER_INFO_LEVEL *ntprinter,
+                              struct spoolss_PrinterInfo2 *pinfo2,
                              union spoolss_JobInfo **info_p,
                              uint32_t *count)
 {
@@ -6042,12 +6349,13 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
        *count = num_queues;
 
        for (i=0; i<*count; i++) {
-
                struct spoolss_DeviceMode *devmode;
 
-               devmode = construct_dev_mode(info, lp_const_servicename(snum));
-               if (!devmode) {
-                       result = WERR_NOMEM;
+               result = spoolss_create_default_devmode(info,
+                                                       pinfo2->printername,
+                                                       &devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(3, ("Can't proceed w/o a devmode!"));
                        goto out;
                }
 
@@ -6056,7 +6364,7 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
                                        &queue[i],
                                        i,
                                        snum,
-                                       ntprinter,
+                                       pinfo2,
                                        devmode);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
@@ -6082,7 +6390,7 @@ static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
                              const print_queue_struct *queue,
                              uint32_t num_queues, int snum,
-                              const NT_PRINTER_INFO_LEVEL *ntprinter,
+                              struct spoolss_PrinterInfo2 *pinfo2,
                              union spoolss_JobInfo **info_p,
                              uint32_t *count)
 {
@@ -6108,7 +6416,7 @@ static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
                                        next_queue,
                                        i,
                                        snum,
-                                       ntprinter);
+                                       pinfo2);
                if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
@@ -6134,7 +6442,7 @@ WERROR _spoolss_EnumJobs(pipes_struct *p,
                         struct spoolss_EnumJobs *r)
 {
        WERROR result;
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        int snum;
        print_status_struct prt_status;
        print_queue_struct *queue = NULL;
@@ -6158,7 +6466,8 @@ WERROR _spoolss_EnumJobs(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
+       result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
+                                   lp_servicename(snum), &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
@@ -6169,22 +6478,22 @@ WERROR _spoolss_EnumJobs(pipes_struct *p,
 
        if (count == 0) {
                SAFE_FREE(queue);
-               free_a_printer(&ntprinter, 2);
+               TALLOC_FREE(pinfo2);
                return WERR_OK;
        }
 
        switch (r->in.level) {
        case 1:
                result = enumjobs_level1(p->mem_ctx, queue, count, snum,
-                                        ntprinter, r->out.info, r->out.count);
+                                        pinfo2, r->out.info, r->out.count);
                break;
        case 2:
                result = enumjobs_level2(p->mem_ctx, queue, count, snum,
-                                        ntprinter, r->out.info, r->out.count);
+                                        pinfo2, r->out.info, r->out.count);
                break;
        case 3:
                result = enumjobs_level3(p->mem_ctx, queue, count, snum,
-                                        ntprinter, r->out.info, r->out.count);
+                                        pinfo2, r->out.info, r->out.count);
                break;
        default:
                result = WERR_UNKNOWN_LEVEL;
@@ -6192,7 +6501,7 @@ WERROR _spoolss_EnumJobs(pipes_struct *p,
        }
 
        SAFE_FREE(queue);
-       free_a_printer(&ntprinter, 2);
+       TALLOC_FREE(pinfo2);
 
        if (!W_ERROR_IS_OK(result)) {
                return result;
@@ -6315,6 +6624,7 @@ WERROR _spoolss_SetJob(pipes_struct *p,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
+                                                      struct auth_serversupplied_info *server_info,
                                                       const char *servername,
                                                       const char *architecture,
                                                       uint32_t level,
@@ -6322,32 +6632,32 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                                                       uint32_t *count_p)
 {
        int i;
-       int ndrivers;
        uint32_t version;
-       fstring *list = NULL;
        struct spoolss_DriverInfo8 *driver;
        union spoolss_DriverInfo *info = NULL;
        uint32_t count = 0;
        WERROR result = WERR_OK;
+       uint32_t num_drivers;
+       const char **drivers;
 
        *count_p = 0;
        *info_p = NULL;
 
        for (version=0; version<DRIVER_MAX_VERSION; version++) {
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, architecture, version);
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-                       ndrivers, architecture, version));
-
-               if (ndrivers == -1) {
-                       result = WERR_NOMEM;
+               result = winreg_get_driver_list(mem_ctx, server_info,
+                                               architecture, version,
+                                               &num_drivers, &drivers);
+               if (!W_ERROR_IS_OK(result)) {
                        goto out;
                }
+               DEBUG(4, ("we have:[%d] drivers in environment"
+                         " [%s] and version [%d]\n",
+                         num_drivers, architecture, version));
 
-               if (ndrivers != 0) {
+               if (num_drivers != 0) {
                        info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
                                                    union spoolss_DriverInfo,
-                                                   count + ndrivers);
+                                                   count + num_drivers);
                        if (!info) {
                                DEBUG(0,("enumprinterdrivers_level_by_architecture: "
                                        "failed to enlarge driver info buffer!\n"));
@@ -6356,11 +6666,12 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                        }
                }
 
-               for (i=0; i<ndrivers; i++) {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-                       ZERO_STRUCT(driver);
-                       result = get_a_printer_driver(mem_ctx, &driver, list[i],
-                                                     architecture, version);
+               for (i = 0; i < num_drivers; i++) {
+                       DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
+
+                       result = winreg_get_driver(mem_ctx, server_info,
+                                                  architecture, drivers[i],
+                                                  version, &driver);
                        if (!W_ERROR_IS_OK(result)) {
                                goto out;
                        }
@@ -6399,19 +6710,19 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                                break;
                        }
 
-                       free_a_printer_driver(driver);
+                       TALLOC_FREE(driver);
 
                        if (!W_ERROR_IS_OK(result)) {
                                goto out;
                        }
                }
 
-               count += ndrivers;
-               SAFE_FREE(list);
+               count += num_drivers;
+               TALLOC_FREE(drivers);
        }
 
  out:
-       SAFE_FREE(list);
+       TALLOC_FREE(drivers);
 
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(info);
@@ -6429,6 +6740,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
 ****************************************************************************/
 
 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
+                                      struct auth_serversupplied_info *server_info,
                                       const char *servername,
                                       const char *architecture,
                                       uint32_t level,
@@ -6446,6 +6758,7 @@ static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
                        uint32_t count = 0;
 
                        result = enumprinterdrivers_level_by_architecture(mem_ctx,
+                                                                         server_info,
                                                                          servername,
                                                                          archi_table[a].long_archi,
                                                                          level,
@@ -6465,6 +6778,7 @@ static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
        }
 
        return enumprinterdrivers_level_by_architecture(mem_ctx,
+                                                       server_info,
                                                        servername,
                                                        architecture,
                                                        level,
@@ -6500,7 +6814,9 @@ WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
 
-       result = enumprinterdrivers_level(p->mem_ctx, cservername,
+       result = enumprinterdrivers_level(p->mem_ctx,
+                                         p->server_info,
+                                         cservername,
                                          r->in.environment,
                                          r->in.level,
                                          r->out.info,
@@ -6956,6 +7272,12 @@ static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
                info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
        }
 
+       update_dsspooler(p->mem_ctx,
+                        p->server_info,
+                        0,
+                        info2,
+                        NULL);
+
        err = winreg_update_printer(p->mem_ctx,
                                    p->server_info,
                                    info2->sharename,
@@ -6973,8 +7295,6 @@ static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
                return WERR_ACCESS_DENIED;
        }
 
-       update_c_setprinter(false);
-
        return WERR_OK;
 }
 
@@ -7034,7 +7354,7 @@ WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
                                   struct spoolss_AddPrinterDriverEx *r)
 {
        WERROR err = WERR_OK;
-       char *driver_name = NULL;
+       const char *driver_name = NULL;
        uint32_t version;
        const char *fn;
 
@@ -7083,8 +7403,9 @@ WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
                goto done;
        }
 
-       if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
-               err = WERR_ACCESS_DENIED;
+       err = winreg_add_driver(p->mem_ctx, p->server_info,
+                                r->in.info_ctr, &driver_name, &version);
+       if (!W_ERROR_IS_OK(err)) {
                goto done;
        }
 
@@ -8030,7 +8351,7 @@ WERROR _spoolss_EnumMonitors(pipes_struct *p,
 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
                             const print_queue_struct *queue,
                             int count, int snum,
-                            const NT_PRINTER_INFO_LEVEL *ntprinter,
+                            struct spoolss_PrinterInfo2 *pinfo2,
                             uint32_t jobid,
                             struct spoolss_JobInfo1 *r)
 {
@@ -8054,7 +8375,7 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
                              &queue[i],
                              i,
                              snum,
-                             ntprinter);
+                             pinfo2);
 }
 
 /****************************************************************************
@@ -8063,13 +8384,14 @@ static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
                             const print_queue_struct *queue,
                             int count, int snum,
-                            const NT_PRINTER_INFO_LEVEL *ntprinter,
+                            struct spoolss_PrinterInfo2 *pinfo2,
                             uint32_t jobid,
                             struct spoolss_JobInfo2 *r)
 {
        int i = 0;
        bool found = false;
        struct spoolss_DeviceMode *devmode;
+       WERROR result;
 
        for (i=0; i<count; i++) {
                if (queue[i].job == (int)jobid) {
@@ -8092,8 +8414,13 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
 
        devmode = print_job_devmode(lp_const_servicename(snum), jobid);
        if (!devmode) {
-               devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
-               W_ERROR_HAVE_NO_MEMORY(devmode);
+               result = spoolss_create_default_devmode(mem_ctx,
+                                               pinfo2->printername,
+                                               &devmode);
+               if (!W_ERROR_IS_OK(result)) {
+                       DEBUG(3, ("Can't proceed w/o a devmode!"));
+                       return result;
+               }
        }
 
        return fill_job_info2(mem_ctx,
@@ -8101,7 +8428,7 @@ static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
                              &queue[i],
                              i,
                              snum,
-                             ntprinter,
+                             pinfo2,
                              devmode);
 }
 
@@ -8113,7 +8440,7 @@ WERROR _spoolss_GetJob(pipes_struct *p,
                       struct spoolss_GetJob *r)
 {
        WERROR result = WERR_OK;
-       NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
+       struct spoolss_PrinterInfo2 *pinfo2 = NULL;
        int snum;
        int count;
        print_queue_struct      *queue = NULL;
@@ -8133,7 +8460,8 @@ WERROR _spoolss_GetJob(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
+       result = winreg_get_printer(p->mem_ctx, p->server_info, NULL,
+                                   lp_servicename(snum), &pinfo2);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
@@ -8146,12 +8474,12 @@ WERROR _spoolss_GetJob(pipes_struct *p,
        switch (r->in.level) {
        case 1:
                result = getjob_level_1(p->mem_ctx,
-                                       queue, count, snum, ntprinter,
+                                       queue, count, snum, pinfo2,
                                        r->in.job_id, &r->out.info->info1);
                break;
        case 2:
                result = getjob_level_2(p->mem_ctx,
-                                       queue, count, snum, ntprinter,
+                                       queue, count, snum, pinfo2,
                                        r->in.job_id, &r->out.info->info2);
                break;
        default:
@@ -8160,7 +8488,7 @@ WERROR _spoolss_GetJob(pipes_struct *p,
        }
 
        SAFE_FREE(queue);
-       free_a_printer(&ntprinter, 2);
+       TALLOC_FREE(pinfo2);
 
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(r->out.info);