s3-spoolss: a default printer should have at least a "PrintDriverData" key.
[ira/wip.git] / source3 / printing / nt_printing.c
index 9995dfe4721beda2508217a881e65eba9799cd49..553eed6bcfc726037df875f26730ac20a9472144 100644 (file)
@@ -1442,7 +1442,7 @@ Determine the correct cVersion associated with an architecture and driver
 ****************************************************************************/
 static uint32 get_correct_cversion(struct pipes_struct *p,
                                   const char *architecture,
-                                  fstring driverpath_in,
+                                  const char *driverpath_in,
                                   WERROR *perr)
 {
        int               cversion;
@@ -1600,120 +1600,48 @@ static uint32 get_correct_cversion(struct pipes_struct *p,
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
-                                            NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
-{
-       const char *architecture;
-       fstring new_name;
-       char *p;
-       int i;
-       WERROR err;
-
-       /* clean up the driver name.
-        * we can get .\driver.dll
-        * or worse c:\windows\system\driver.dll !
-        */
-       /* using an intermediate string to not have overlaping memcpy()'s */
-       if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->driverpath, new_name);
-       }
-
-       if ((p = strrchr(driver->datafile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->datafile, new_name);
-       }
-
-       if ((p = strrchr(driver->configfile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->configfile, new_name);
-       }
-
-       if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->helpfile, new_name);
-       }
-
-       if (driver->dependentfiles) {
-               for (i=0; *driver->dependentfiles[i]; i++) {
-                       if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
-                               fstrcpy(new_name, p+1);
-                               fstrcpy(driver->dependentfiles[i], new_name);
-                       }
-               }
-       }
-
-       architecture = get_short_archi(driver->environment);
-       if (!architecture) {
-               return WERR_UNKNOWN_PRINTER_DRIVER;
-       }
-
-       /* jfm:7/16/2000 the client always sends the cversion=0.
-        * The server should check which version the driver is by reading
-        * the PE header of driver->driverpath.
-        *
-        * For Windows 95/98 the version is 0 (so the value sent is correct)
-        * For Windows NT (the architecture doesn't matter)
-        *      NT 3.1: cversion=0
-        *      NT 3.5/3.51: cversion=1
-        *      NT 4: cversion=2
-        *      NT2K: cversion=3
-        */
-       if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
-                                                    driver->driverpath,
-                                                    &err)) == -1)
-               return err;
-
-       return WERR_OK;
-}
 
-/****************************************************************************
-****************************************************************************/
-static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
-                                            NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
+#define strip_driver_path(_mem_ctx, _element) do { \
+       if ((_p = strrchr((_element), '\\')) != NULL) { \
+               (_element) = talloc_asprintf((_mem_ctx), "%s", _p+1); \
+               W_ERROR_HAVE_NO_MEMORY((_element)); \
+       } \
+} while (0);
+
+static WERROR clean_up_driver_struct_level(TALLOC_CTX *mem_ctx,
+                                          struct pipes_struct *rpc_pipe,
+                                          const char *architecture,
+                                          const char **driver_path,
+                                          const char **data_file,
+                                          const char **config_file,
+                                          const char **help_file,
+                                          struct spoolss_StringArray *dependent_files,
+                                          uint32_t *version)
 {
-       const char *architecture;
-       fstring new_name;
-       char *p;
+       const char *short_architecture;
        int i;
        WERROR err;
+       char *_p;
 
        /* clean up the driver name.
         * we can get .\driver.dll
         * or worse c:\windows\system\driver.dll !
         */
        /* using an intermediate string to not have overlaping memcpy()'s */
-       if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->driverpath, new_name);
-       }
 
-       if ((p = strrchr(driver->datafile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->datafile, new_name);
-       }
+       strip_driver_path(mem_ctx, *driver_path);
+       strip_driver_path(mem_ctx, *data_file);
+       strip_driver_path(mem_ctx, *config_file);
+       strip_driver_path(mem_ctx, *help_file);
 
-       if ((p = strrchr(driver->configfile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->configfile, new_name);
-       }
-
-       if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
-               fstrcpy(new_name, p+1);
-               fstrcpy(driver->helpfile, new_name);
-       }
-
-       if (driver->dependentfiles) {
-               for (i=0; *driver->dependentfiles[i]; i++) {
-                       if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
-                               fstrcpy(new_name, p+1);
-                               fstrcpy(driver->dependentfiles[i], new_name);
-                       }
+       if (dependent_files && dependent_files->string) {
+               for (i=0; dependent_files->string[i]; i++) {
+                       strip_driver_path(mem_ctx, dependent_files->string[i]);
                }
        }
 
-       architecture = get_short_archi(driver->environment);
-       if (!architecture) {
+       short_architecture = get_short_archi(architecture);
+       if (!short_architecture) {
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
 
@@ -1729,37 +1657,42 @@ static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
         *      NT2K: cversion=3
         */
 
-       if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
-                                                   driver->driverpath,
-                                                   &err)) == -1)
-                       return err;
+       *version = get_correct_cversion(rpc_pipe, short_architecture,
+                                       *driver_path, &err);
+       if (*version == -1) {
+               return err;
+       }
 
        return WERR_OK;
 }
 
 /****************************************************************************
 ****************************************************************************/
+
 WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
-                             NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
-                             uint32 level)
+                             struct spoolss_AddDriverInfoCtr *r)
 {
-       switch (level) {
-               case 3:
-               {
-                       NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
-                       driver=driver_abstract.info_3;
-                       return clean_up_driver_struct_level_3(rpc_pipe,
-                                                             driver);
-               }
-               case 6:
-               {
-                       NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
-                       driver=driver_abstract.info_6;
-                       return clean_up_driver_struct_level_6(rpc_pipe,
-                                                             driver);
-               }
-               default:
-                       return WERR_INVALID_PARAM;
+       switch (r->level) {
+       case 3:
+               return clean_up_driver_struct_level(r, rpc_pipe,
+                                                   r->info.info3->architecture,
+                                                   &r->info.info3->driver_path,
+                                                   &r->info.info3->data_file,
+                                                   &r->info.info3->config_file,
+                                                   &r->info.info3->help_file,
+                                                   r->info.info3->dependent_files,
+                                                   &r->info.info3->version);
+       case 6:
+               return clean_up_driver_struct_level(r, rpc_pipe,
+                                                   r->info.info6->architecture,
+                                                   &r->info.info6->driver_path,
+                                                   &r->info.info6->data_file,
+                                                   &r->info.info6->config_file,
+                                                   &r->info.info6->help_file,
+                                                   r->info.info6->dependent_files,
+                                                   &r->info.info6->version);
+       default:
+               return WERR_NOT_SUPPORTED;
        }
 }
 
@@ -1767,39 +1700,23 @@ WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
  This function sucks and should be replaced. JRA.
 ****************************************************************************/
 
-static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
+static void convert_level_6_to_level3(struct spoolss_AddDriverInfo3 *dst,
+                                     const struct spoolss_AddDriverInfo6 *src)
 {
-    dst->cversion  = src->version;
-
-    fstrcpy( dst->name, src->name);
-    fstrcpy( dst->environment, src->environment);
-    fstrcpy( dst->driverpath, src->driverpath);
-    fstrcpy( dst->datafile, src->datafile);
-    fstrcpy( dst->configfile, src->configfile);
-    fstrcpy( dst->helpfile, src->helpfile);
-    fstrcpy( dst->monitorname, src->monitorname);
-    fstrcpy( dst->defaultdatatype, src->defaultdatatype);
-    dst->dependentfiles = src->dependentfiles;
+       dst->version            = src->version;
+
+       dst->driver_name        = src->driver_name;
+       dst->architecture       = src->architecture;
+       dst->driver_path        = src->driver_path;
+       dst->data_file          = src->data_file;
+       dst->config_file        = src->config_file;
+       dst->help_file          = src->help_file;
+       dst->monitor_name       = src->monitor_name;
+       dst->default_datatype   = src->default_datatype;
+       dst->_ndr_size_dependent_files = src->_ndr_size_dependent_files;
+       dst->dependent_files    = src->dependent_files;
 }
 
-#if 0 /* Debugging function */
-
-static char* ffmt(unsigned char *c){
-       int i;
-       static char ffmt_str[17];
-
-       for (i=0; i<16; i++) {
-               if ((c[i] < ' ') || (c[i] > '~'))
-                       ffmt_str[i]='.';
-               else
-                       ffmt_str[i]=c[i];
-       }
-    ffmt_str[16]='\0';
-       return ffmt_str;
-}
-
-#endif
-
 /****************************************************************************
 ****************************************************************************/
 
@@ -1872,11 +1789,11 @@ static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
 }
 
 WERROR move_driver_to_download_area(struct pipes_struct *p,
-                                   NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
-                                   uint32 level, WERROR *perr)
+                                   struct spoolss_AddDriverInfoCtr *r,
+                                   WERROR *perr)
 {
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
+       struct spoolss_AddDriverInfo3 *driver;
+       struct spoolss_AddDriverInfo3 converted_driver;
        const char *short_architecture;
        struct smb_filename *smb_dname = NULL;
        char *new_dir = NULL;
@@ -1891,20 +1808,20 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
 
        *perr = WERR_OK;
 
-       switch (level) {
+       switch (r->level) {
        case 3:
-               driver = driver_abstract.info_3;
+               driver = r->info.info3;
                break;
        case 6:
-               convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
+               convert_level_6_to_level3(&converted_driver, r->info.info6);
                driver = &converted_driver;
                break;
        default:
-               DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
+               DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)r->level));
                return WERR_UNKNOWN_LEVEL;
        }
 
-       short_architecture = get_short_archi(driver->environment);
+       short_architecture = get_short_archi(driver->architecture);
        if (!short_architecture) {
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
@@ -1930,7 +1847,7 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        new_dir = talloc_asprintf(ctx,
                                "%s/%d",
                                short_architecture,
-                               driver->cversion);
+                               driver->version);
        if (!new_dir) {
                *perr = WERR_NOMEM;
                goto err_exit;
@@ -1948,14 +1865,14 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
        /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
         * listed for this driver which has already been moved, skip it (note:
         * drivers may list the same file name several times. Then check if the
-        * file already exists in archi\cversion\, if so, check that the version
+        * file already exists in archi\version\, if so, check that the version
         * info (or time stamps if version info is unavailable) is newer (or the
-        * date is later). If it is, move it to archi\cversion\filexxx.yyy.
+        * date is later). If it is, move it to archi\version\filexxx.yyy.
         * Otherwise, delete the file.
         *
-        * If a file is not moved to archi\cversion\ because of an error, all the
+        * If a file is not moved to archi\version\ because of an error, all the
         * rest of the 'unmoved' driver files are removed from archi\. If one or
-        * more of the driver's files was already moved to archi\cversion\, it
+        * more of the driver's files was already moved to archi\version\, it
         * potentially leaves the driver in a partially updated state. Version
         * trauma will most likely occur if an client attempts to use any printer
         * bound to the driver. Perhaps a rewrite to make sure the moves can be
@@ -1964,13 +1881,13 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
 
        DEBUG(5,("Moving files now !\n"));
 
-       if (driver->driverpath && strlen(driver->driverpath)) {
+       if (driver->driver_path && strlen(driver->driver_path)) {
 
                *perr = move_driver_file_to_download_area(ctx,
                                                          conn,
-                                                         driver->driverpath,
+                                                         driver->driver_path,
                                                          short_architecture,
-                                                         driver->cversion,
+                                                         driver->version,
                                                          ver);
                if (!W_ERROR_IS_OK(*perr)) {
                        if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
@@ -1980,14 +1897,14 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                }
        }
 
-       if (driver->datafile && strlen(driver->datafile)) {
-               if (!strequal(driver->datafile, driver->driverpath)) {
+       if (driver->data_file && strlen(driver->data_file)) {
+               if (!strequal(driver->data_file, driver->driver_path)) {
 
                        *perr = move_driver_file_to_download_area(ctx,
                                                                  conn,
-                                                                 driver->datafile,
+                                                                 driver->data_file,
                                                                  short_architecture,
-                                                                 driver->cversion,
+                                                                 driver->version,
                                                                  ver);
                        if (!W_ERROR_IS_OK(*perr)) {
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
@@ -1998,15 +1915,15 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                }
        }
 
-       if (driver->configfile && strlen(driver->configfile)) {
-               if (!strequal(driver->configfile, driver->driverpath) &&
-                   !strequal(driver->configfile, driver->datafile)) {
+       if (driver->config_file && strlen(driver->config_file)) {
+               if (!strequal(driver->config_file, driver->driver_path) &&
+                   !strequal(driver->config_file, driver->data_file)) {
 
                        *perr = move_driver_file_to_download_area(ctx,
                                                                  conn,
-                                                                 driver->configfile,
+                                                                 driver->config_file,
                                                                  short_architecture,
-                                                                 driver->cversion,
+                                                                 driver->version,
                                                                  ver);
                        if (!W_ERROR_IS_OK(*perr)) {
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
@@ -2017,16 +1934,16 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                }
        }
 
-       if (driver->helpfile && strlen(driver->helpfile)) {
-               if (!strequal(driver->helpfile, driver->driverpath) &&
-                   !strequal(driver->helpfile, driver->datafile) &&
-                   !strequal(driver->helpfile, driver->configfile)) {
+       if (driver->help_file && strlen(driver->help_file)) {
+               if (!strequal(driver->help_file, driver->driver_path) &&
+                   !strequal(driver->help_file, driver->data_file) &&
+                   !strequal(driver->help_file, driver->config_file)) {
 
                        *perr = move_driver_file_to_download_area(ctx,
                                                                  conn,
-                                                                 driver->helpfile,
+                                                                 driver->help_file,
                                                                  short_architecture,
-                                                                 driver->cversion,
+                                                                 driver->version,
                                                                  ver);
                        if (!W_ERROR_IS_OK(*perr)) {
                                if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
@@ -2037,24 +1954,24 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
                }
        }
 
-       if (driver->dependentfiles) {
-               for (i=0; *driver->dependentfiles[i]; i++) {
-                       if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
-                           !strequal(driver->dependentfiles[i], driver->datafile) &&
-                           !strequal(driver->dependentfiles[i], driver->configfile) &&
-                           !strequal(driver->dependentfiles[i], driver->helpfile)) {
+       if (driver->dependent_files && driver->dependent_files->string) {
+               for (i=0; driver->dependent_files->string[i]; i++) {
+                       if (!strequal(driver->dependent_files->string[i], driver->driver_path) &&
+                           !strequal(driver->dependent_files->string[i], driver->data_file) &&
+                           !strequal(driver->dependent_files->string[i], driver->config_file) &&
+                           !strequal(driver->dependent_files->string[i], driver->help_file)) {
                                int j;
                                for (j=0; j < i; j++) {
-                                       if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
+                                       if (strequal(driver->dependent_files->string[i], driver->dependent_files->string[j])) {
                                                goto NextDriver;
                                        }
                                }
 
                                *perr = move_driver_file_to_download_area(ctx,
                                                                          conn,
-                                                                         driver->dependentfiles[i],
+                                                                         driver->dependent_files->string[i],
                                                                          short_architecture,
-                                                                         driver->cversion,
+                                                                         driver->version,
                                                                          ver);
                                if (!W_ERROR_IS_OK(*perr)) {
                                        if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
@@ -2087,19 +2004,18 @@ WERROR move_driver_to_download_area(struct pipes_struct *p,
 /****************************************************************************
 ****************************************************************************/
 
-static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
+static uint32 add_a_printer_driver_3(struct spoolss_AddDriverInfo3 *driver)
 {
        TALLOC_CTX *ctx = talloc_tos();
        int len, buflen;
        const char *architecture;
        char *directory = NULL;
-       fstring temp_name;
        char *key = NULL;
        uint8 *buf;
        int i, ret;
        TDB_DATA dbuf;
 
-       architecture = get_short_archi(driver->environment);
+       architecture = get_short_archi(driver->architecture);
        if (!architecture) {
                return (uint32)-1;
        }
@@ -2110,46 +2026,44 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
         */
 
        directory = talloc_asprintf(ctx, "\\print$\\%s\\%d\\",
-                       architecture, driver->cversion);
+                       architecture, driver->version);
        if (!directory) {
                return (uint32)-1;
        }
 
+#define gen_full_driver_unc_path(ctx, directory, file) \
+       do { \
+               if (file && strlen(file)) { \
+                       file = talloc_asprintf(ctx, "%s%s", directory, file); \
+               } else { \
+                       file = talloc_strdup(ctx, ""); \
+               } \
+               if (!file) { \
+                       return (uint32_t)-1; \
+               } \
+       } while (0);
+
        /* .inf files do not always list a file for each of the four standard files.
         * Don't prepend a path to a null filename, or client claims:
         *   "The server on which the printer resides does not have a suitable
         *   <printer driver name> printer driver installed. Click OK if you
         *   wish to install the driver on your local machine."
         */
-       if (strlen(driver->driverpath)) {
-               fstrcpy(temp_name, driver->driverpath);
-               slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
-       }
 
-       if (strlen(driver->datafile)) {
-               fstrcpy(temp_name, driver->datafile);
-               slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
-       }
-
-       if (strlen(driver->configfile)) {
-               fstrcpy(temp_name, driver->configfile);
-               slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
-       }
+       gen_full_driver_unc_path(ctx, directory, driver->driver_path);
+       gen_full_driver_unc_path(ctx, directory, driver->data_file);
+       gen_full_driver_unc_path(ctx, directory, driver->config_file);
+       gen_full_driver_unc_path(ctx, directory, driver->help_file);
 
-       if (strlen(driver->helpfile)) {
-               fstrcpy(temp_name, driver->helpfile);
-               slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
-       }
-
-       if (driver->dependentfiles) {
-               for (i=0; *driver->dependentfiles[i]; i++) {
-                       fstrcpy(temp_name, driver->dependentfiles[i]);
-                       slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
+       if (driver->dependent_files && driver->dependent_files->string) {
+               for (i=0; driver->dependent_files->string[i]; i++) {
+                       gen_full_driver_unc_path(ctx, directory,
+                               driver->dependent_files->string[i]);
                }
        }
 
        key = talloc_asprintf(ctx, "%s%s/%d/%s", DRIVERS_PREFIX,
-                       architecture, driver->cversion, driver->name);
+                       architecture, driver->version, driver->driver_name);
        if (!key) {
                return (uint32)-1;
        }
@@ -2162,20 +2076,20 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
  again:
        len = 0;
        len += tdb_pack(buf+len, buflen-len, "dffffffff",
-                       driver->cversion,
-                       driver->name,
-                       driver->environment,
-                       driver->driverpath,
-                       driver->datafile,
-                       driver->configfile,
-                       driver->helpfile,
-                       driver->monitorname,
-                       driver->defaultdatatype);
-
-       if (driver->dependentfiles) {
-               for (i=0; *driver->dependentfiles[i]; i++) {
+                       driver->version,
+                       driver->driver_name,
+                       driver->architecture,
+                       driver->driver_path,
+                       driver->data_file,
+                       driver->config_file,
+                       driver->help_file,
+                       driver->monitor_name ? driver->monitor_name : "",
+                       driver->default_datatype ? driver->default_datatype : "");
+
+       if (driver->dependent_files && driver->dependent_files->string) {
+               for (i=0; driver->dependent_files->string[i]; i++) {
                        len += tdb_pack(buf+len, buflen-len, "f",
-                                       driver->dependentfiles[i]);
+                                       driver->dependent_files->string[i]);
                }
        }
 
@@ -2205,21 +2119,12 @@ done:
 
 /****************************************************************************
 ****************************************************************************/
-static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
+
+static uint32 add_a_printer_driver_6(struct spoolss_AddDriverInfo6 *driver)
 {
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
-
-       ZERO_STRUCT(info3);
-       info3.cversion = driver->version;
-       fstrcpy(info3.name,driver->name);
-       fstrcpy(info3.environment,driver->environment);
-       fstrcpy(info3.driverpath,driver->driverpath);
-       fstrcpy(info3.datafile,driver->datafile);
-       fstrcpy(info3.configfile,driver->configfile);
-       fstrcpy(info3.helpfile,driver->helpfile);
-       fstrcpy(info3.monitorname,driver->monitorname);
-       fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
-       info3.dependentfiles = driver->dependentfiles;
+       struct spoolss_AddDriverInfo3 info3;
+
+       convert_level_6_to_level3(&info3, driver);
 
        return add_a_printer_driver_3(&info3);
 }
@@ -2227,29 +2132,26 @@ static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, const char *driver, const char *arch)
-{
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
-
-       ZERO_STRUCT(info);
-
-       fstrcpy(info.name, driver);
-       fstrcpy(info.defaultdatatype, "RAW");
-
-       fstrcpy(info.driverpath, "");
-       fstrcpy(info.datafile, "");
-       fstrcpy(info.configfile, "");
-       fstrcpy(info.helpfile, "");
 
-       if ((info.dependentfiles= SMB_MALLOC_ARRAY(fstring, 2)) == NULL)
+static WERROR get_a_printer_driver_3_default(TALLOC_CTX *mem_ctx,
+                                            struct spoolss_DriverInfo3 *info,
+                                            const char *driver, const char *arch)
+{
+       info->driver_name = talloc_strdup(mem_ctx, driver);
+       if (!info->driver_name) {
                return WERR_NOMEM;
+       }
 
-       memset(info.dependentfiles, '\0', 2*sizeof(fstring));
-       fstrcpy(info.dependentfiles[0], "");
+       info->default_datatype = talloc_strdup(mem_ctx, "RAW");
+       if (!info->default_datatype) {
+               return WERR_NOMEM;
+       }
 
-       *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&info, sizeof(info));
-       if (!*info_ptr) {
-               SAFE_FREE(info.dependentfiles);
+       info->driver_path = talloc_strdup(mem_ctx, "");
+       info->data_file = talloc_strdup(mem_ctx, "");
+       info->config_file = talloc_strdup(mem_ctx, "");
+       info->help_file = talloc_strdup(mem_ctx, "");
+       if (!info->driver_path || !info->data_file || !info->config_file || !info->help_file) {
                return WERR_NOMEM;
        }
 
@@ -2258,18 +2160,18 @@ static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **in
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
+
+static WERROR get_a_printer_driver_3(TALLOC_CTX *mem_ctx,
+                                    struct spoolss_DriverInfo3 *driver,
                                     const char *drivername, const char *arch,
                                     uint32_t version)
 {
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
        TDB_DATA dbuf;
        const char *architecture;
        int len = 0;
        int i;
        char *key = NULL;
-
-       ZERO_STRUCT(driver);
+       fstring name, driverpath, environment, datafile, configfile, helpfile, monitorname, defaultdatatype;
 
        architecture = get_short_archi(arch);
        if ( !architecture ) {
@@ -2295,99 +2197,58 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
        }
 
        len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
-                         &driver.cversion,
-                         driver.name,
-                         driver.environment,
-                         driver.driverpath,
-                         driver.datafile,
-                         driver.configfile,
-                         driver.helpfile,
-                         driver.monitorname,
-                         driver.defaultdatatype);
+                         &driver->version,
+                         name,
+                         environment,
+                         driverpath,
+                         datafile,
+                         configfile,
+                         helpfile,
+                         monitorname,
+                         defaultdatatype);
+
+       driver->driver_name     = talloc_strdup(mem_ctx, name);
+       driver->architecture    = talloc_strdup(mem_ctx, environment);
+       driver->driver_path     = talloc_strdup(mem_ctx, driverpath);
+       driver->data_file       = talloc_strdup(mem_ctx, datafile);
+       driver->config_file     = talloc_strdup(mem_ctx, configfile);
+       driver->help_file       = talloc_strdup(mem_ctx, helpfile);
+       driver->monitor_name    = talloc_strdup(mem_ctx, monitorname);
+       driver->default_datatype        = talloc_strdup(mem_ctx, defaultdatatype);
 
        i=0;
+
        while (len < dbuf.dsize) {
-               driver.dependentfiles = SMB_REALLOC_ARRAY(driver.dependentfiles, fstring, i+2);
-               if ( !driver.dependentfiles ) {
+
+               fstring file;
+
+               driver->dependent_files = talloc_realloc(mem_ctx, driver->dependent_files, const char *, i+2);
+               if (!driver->dependent_files ) {
                        DEBUG(0,("get_a_printer_driver_3: failed to enlarge buffer!\n"));
                        break;
                }
 
                len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
-                                 &driver.dependentfiles[i]);
+                                 &file);
+
+               driver->dependent_files[i] = talloc_strdup(mem_ctx, file);
+
                i++;
        }
 
-       if ( driver.dependentfiles )
-               fstrcpy( driver.dependentfiles[i], "" );
+       if (driver->dependent_files)
+               driver->dependent_files[i] = NULL;
 
        SAFE_FREE(dbuf.dptr);
        SAFE_FREE(key);
 
        if (len != dbuf.dsize) {
-               SAFE_FREE(driver.dependentfiles);
-
-               return get_a_printer_driver_3_default(info_ptr, drivername, arch);
-       }
-
-       *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
-       if (!*info_ptr) {
-               SAFE_FREE(driver.dependentfiles);
-               return WERR_NOMEM;
+               return get_a_printer_driver_3_default(mem_ctx, driver, drivername, arch);
        }
 
        return WERR_OK;
 }
 
-/****************************************************************************
- Debugging function, dump at level 6 the struct in the logs.
-****************************************************************************/
-
-static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
-{
-       uint32 result;
-       NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
-       int i;
-
-       DEBUG(20,("Dumping printer driver at level [%d]\n", level));
-
-       switch (level)
-       {
-               case 3:
-               {
-                       if (driver.info_3 == NULL)
-                               result=5;
-                       else {
-                               info3=driver.info_3;
-
-                               DEBUGADD(20,("version:[%d]\n",         info3->cversion));
-                               DEBUGADD(20,("name:[%s]\n",            info3->name));
-                               DEBUGADD(20,("environment:[%s]\n",     info3->environment));
-                               DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
-                               DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
-                               DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
-                               DEBUGADD(20,("helpfile:[%s]\n",        info3->helpfile));
-                               DEBUGADD(20,("monitorname:[%s]\n",     info3->monitorname));
-                               DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
-
-                               for (i=0; info3->dependentfiles &&
-                                         *info3->dependentfiles[i]; i++) {
-                                       DEBUGADD(20,("dependentfile:[%s]\n",
-                                                     info3->dependentfiles[i]));
-                               }
-                               result=0;
-                       }
-                       break;
-               }
-               default:
-                       DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
-                       result=1;
-                       break;
-       }
-
-       return result;
-}
-
 /****************************************************************************
 ****************************************************************************/
 int pack_devicemode(NT_DEVICEMODE *nt_devmode, uint8 *buf, int buflen)
@@ -3972,6 +3833,13 @@ static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 *info,
                goto fail;
        }
 
+       info->data = TALLOC_ZERO_P(info, NT_PRINTER_DATA);
+       if (!info->data) {
+               goto fail;
+       }
+
+       add_new_printer_key(info->data, SPOOL_PRINTERDATA_KEY);
+
        return WERR_OK;
 
 fail:
@@ -4734,24 +4602,38 @@ uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
 
 /****************************************************************************
 ****************************************************************************/
-uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
+uint32_t add_a_printer_driver(TALLOC_CTX *mem_ctx,
+                             struct spoolss_AddDriverInfoCtr *r,
+                             char **driver_name,
+                             uint32_t *version)
 {
        uint32 result;
-       DEBUG(104,("adding a printer at level [%d]\n", level));
-       dump_a_printer_driver(driver, level);
-
-       switch (level) {
-               case 3:
-                       result=add_a_printer_driver_3(driver.info_3);
-                       break;
-
-               case 6:
-                       result=add_a_printer_driver_6(driver.info_6);
-                       break;
+       DEBUG(10,("adding a printer at level [%d]\n", r->level));
 
-               default:
-                       result=1;
-                       break;
+       switch (r->level) {
+       case 3:
+               result = add_a_printer_driver_3(r->info.info3);
+               if (result == 0) {
+                       *driver_name = talloc_strdup(mem_ctx, r->info.info3->driver_name);
+                       if (!*driver_name) {
+                               return -1;
+                       }
+                       *version = r->info.info3->version;
+               }
+               break;
+       case 6:
+               result = add_a_printer_driver_6(r->info.info6);
+               if (result == 0) {
+                       *driver_name = talloc_strdup(mem_ctx, r->info.info6->driver_name);
+                       if (!*driver_name) {
+                               return -1;
+                       }
+                       *version = r->info.info6->version;
+               }
+               break;
+       default:
+               result = 1;
+               break;
        }
 
        return result;
@@ -4759,11 +4641,16 @@ uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 /****************************************************************************
 ****************************************************************************/
 
-WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
+WERROR get_a_printer_driver(TALLOC_CTX *mem_ctx,
+                           union spoolss_DriverInfo **driver_p, uint32_t level,
                            const char *drivername, const char *architecture,
                            uint32_t version)
 {
        WERROR result;
+       union spoolss_DriverInfo *driver;
+
+       driver = talloc_zero(mem_ctx, union spoolss_DriverInfo);
+       W_ERROR_HAVE_NO_MEMORY(driver);
 
        switch (level) {
                case 3:
@@ -4771,16 +4658,23 @@ WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level
 
                        if ( version == DRIVER_ANY_VERSION ) {
                                /* look for Win2k first and then for NT4 */
-                               result = get_a_printer_driver_3(&driver->info_3, drivername,
-                                               architecture, 3);
+                               result = get_a_printer_driver_3(driver,
+                                                               &driver->info3,
+                                                               drivername,
+                                                               architecture, 3);
 
                                if ( !W_ERROR_IS_OK(result) ) {
-                                       result = get_a_printer_driver_3( &driver->info_3,
-                                                       drivername, architecture, 2 );
+                                       result = get_a_printer_driver_3(driver,
+                                                                       &driver->info3,
+                                                                       drivername,
+                                                                       architecture, 2);
                                }
                        } else {
-                               result = get_a_printer_driver_3(&driver->info_3, drivername,
-                                       architecture, version);
+                               result = get_a_printer_driver_3(driver,
+                                                               &driver->info3,
+                                                               drivername,
+                                                               architecture,
+                                                               version);
                        }
                        break;
 
@@ -4789,54 +4683,23 @@ WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level
                        break;
        }
 
-       if (W_ERROR_IS_OK(result))
-               dump_a_printer_driver(*driver, level);
+       if (!W_ERROR_IS_OK(result)) {
+               TALLOC_FREE(driver);
+               return result;
+       }
 
-       return result;
+       *driver_p = driver;
+
+       return WERR_OK;
 }
 
 /****************************************************************************
 ****************************************************************************/
-uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
-{
-       uint32 result;
 
-       switch (level) {
-               case 3:
-               {
-                       NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
-                       if (driver.info_3 != NULL)
-                       {
-                               info3=driver.info_3;
-                               SAFE_FREE(info3->dependentfiles);
-                               ZERO_STRUCTP(info3);
-                               SAFE_FREE(info3);
-                               result=0;
-                       } else {
-                               result=4;
-                       }
-                       break;
-               }
-               case 6:
-               {
-                       NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
-                       if (driver.info_6 != NULL) {
-                               info6=driver.info_6;
-                               SAFE_FREE(info6->dependentfiles);
-                               SAFE_FREE(info6->previousnames);
-                               ZERO_STRUCTP(info6);
-                               SAFE_FREE(info6);
-                               result=0;
-                       } else {
-                               result=4;
-                       }
-                       break;
-               }
-               default:
-                       result=1;
-                       break;
-       }
-       return result;
+uint32_t free_a_printer_driver(union spoolss_DriverInfo *driver)
+{
+       talloc_free(driver);
+       return 0;
 }
 
 
@@ -4845,7 +4708,7 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
   to a printer
 ****************************************************************************/
 
-bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
+bool printer_driver_in_use(const struct spoolss_DriverInfo3 *info_3)
 {
        int snum;
        int n_services = lp_numservices();
@@ -4866,7 +4729,7 @@ bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
                if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
                        continue;
 
-               if ( strequal(info_3->name, printer->info_2->drivername) )
+               if (strequal(info_3->driver_name, printer->info_2->drivername))
                        in_use = True;
 
                free_a_printer( &printer, 2 );
@@ -4875,28 +4738,28 @@ bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
        DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
 
        if ( in_use ) {
-               NT_PRINTER_DRIVER_INFO_LEVEL d;
+               union spoolss_DriverInfo *d;
                WERROR werr;
 
-               DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
+               DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->driver_name));
 
                /* we can still remove the driver if there is one of
                   "Windows NT x86" version 2 or 3 left */
 
-               if ( !strequal( "Windows NT x86", info_3->environment ) ) {
-                       werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
+               if (!strequal("Windows NT x86", info_3->architecture)) {
+                       werr = get_a_printer_driver(talloc_tos(), &d, 3, info_3->driver_name, "Windows NT x86", DRIVER_ANY_VERSION);
                }
                else {
-                       switch ( info_3->cversion ) {
+                       switch (info_3->version) {
                        case 2:
-                               werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
+                               werr = get_a_printer_driver(talloc_tos(), &d, 3, info_3->driver_name, "Windows NT x86", 3);
                                break;
                        case 3:
-                               werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
+                               werr = get_a_printer_driver(talloc_tos(), &d, 3, info_3->driver_name, "Windows NT x86", 2);
                                break;
                        default:
                                DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
-                                       info_3->cversion));
+                                       info_3->version));
                                werr = WERR_UNKNOWN_PRINTER_DRIVER;
                                break;
                        }
@@ -4907,7 +4770,7 @@ bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
                if ( W_ERROR_IS_OK(werr) ) {
                        /* it's ok to remove the driver, we have other architctures left */
                        in_use = False;
-                       free_a_printer_driver( d, 3 );
+                       free_a_printer_driver(d);
                }
        }
 
@@ -4921,7 +4784,7 @@ bool printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
  Check to see if a ogiven file is in use by *info
  *********************************************************************/
 
-static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
+static bool drv_file_in_use(const char *file, const struct spoolss_DriverInfo3 *info)
 {
        int i = 0;
 
@@ -4933,25 +4796,25 @@ static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
                return false;
        }
 
-       if ( strequal(file, info->driverpath) )
+       if (strequal(file, info->driver_path))
                return True;
 
-       if ( strequal(file, info->datafile) )
+       if (strequal(file, info->data_file))
                return True;
 
-       if ( strequal(file, info->configfile) )
+       if (strequal(file, info->config_file))
                return True;
 
-       if ( strequal(file, info->helpfile) )
+       if (strequal(file, info->help_file))
                return True;
 
        /* see of there are any dependent files to examine */
 
-       if ( !info->dependentfiles )
+       if (!info->dependent_files)
                return False;
 
-       while ( *info->dependentfiles[i] ) {
-               if ( strequal(file, info->dependentfiles[i]) )
+       while (info->dependent_files[i] && *info->dependent_files[i]) {
+               if (strequal(file, info->dependent_files[i]))
                        return True;
                i++;
        }
@@ -4965,17 +4828,17 @@ static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
  input parameter from the list
  *********************************************************************/
 
-static void trim_dependent_file( fstring files[], int idx )
+static void trim_dependent_file(TALLOC_CTX *mem_ctx, const char **files, int idx)
 {
 
        /* bump everything down a slot */
 
-       while( *files[idx+1] ) {
-               fstrcpy( files[idx], files[idx+1] );
+       while (files && files[idx+1]) {
+               files[idx] = talloc_strdup(mem_ctx, files[idx+1]);
                idx++;
        }
 
-       *files[idx] = '\0';
+       files[idx] = NULL;
 
        return;
 }
@@ -4984,8 +4847,9 @@ static void trim_dependent_file( fstring files[], int idx )
  Check if any of the files used by src are also used by drv
  *********************************************************************/
 
-static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
-                                      NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
+static bool trim_overlap_drv_files(TALLOC_CTX *mem_ctx,
+                                  struct spoolss_DriverInfo3 *src,
+                                  const struct spoolss_DriverInfo3 *drv)
 {
        bool    in_use = False;
        int     i = 0;
@@ -4995,40 +4859,44 @@ static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
 
        /* check each file.  Remove it from the src structure if it overlaps */
 
-       if ( drv_file_in_use(src->driverpath, drv) ) {
+       if (drv_file_in_use(src->driver_path, drv)) {
                in_use = True;
-               DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
-               fstrcpy( src->driverpath, "" );
+               DEBUG(10,("Removing driverfile [%s] from list\n", src->driver_path));
+               src->driver_path = talloc_strdup(mem_ctx, "");
+               if (!src->driver_path) { return false; }
        }
 
-       if ( drv_file_in_use(src->datafile, drv) ) {
+       if (drv_file_in_use(src->data_file, drv)) {
                in_use = True;
-               DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
-               fstrcpy( src->datafile, "" );
+               DEBUG(10,("Removing datafile [%s] from list\n", src->data_file));
+               src->data_file = talloc_strdup(mem_ctx, "");
+               if (!src->data_file) { return false; }
        }
 
-       if ( drv_file_in_use(src->configfile, drv) ) {
+       if (drv_file_in_use(src->config_file, drv)) {
                in_use = True;
-               DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
-               fstrcpy( src->configfile, "" );
+               DEBUG(10,("Removing configfile [%s] from list\n", src->config_file));
+               src->config_file = talloc_strdup(mem_ctx, "");
+               if (!src->config_file) { return false; }
        }
 
-       if ( drv_file_in_use(src->helpfile, drv) ) {
+       if (drv_file_in_use(src->help_file, drv)) {
                in_use = True;
-               DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
-               fstrcpy( src->helpfile, "" );
+               DEBUG(10,("Removing helpfile [%s] from list\n", src->help_file));
+               src->help_file = talloc_strdup(mem_ctx, "");
+               if (!src->help_file) { return false; }
        }
 
        /* are there any dependentfiles to examine? */
 
-       if ( !src->dependentfiles )
+       if (!src->dependent_files)
                return in_use;
 
-       while ( *src->dependentfiles[i] ) {
-               if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
+       while (src->dependent_files[i] && *src->dependent_files[i]) {
+               if (drv_file_in_use(src->dependent_files[i], drv)) {
                        in_use = True;
-                       DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
-                       trim_dependent_file( src->dependentfiles, i );
+                       DEBUG(10,("Removing [%s] from dependent file list\n", src->dependent_files[i]));
+                       trim_dependent_file(mem_ctx, src->dependent_files, i);
                } else
                        i++;
        }
@@ -5053,19 +4921,20 @@ static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
   match.
 ****************************************************************************/
 
-bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
+bool printer_driver_files_in_use(TALLOC_CTX *mem_ctx,
+                                struct spoolss_DriverInfo3 *info)
 {
        int                             i;
        int                             ndrivers;
        uint32                          version;
        fstring                         *list = NULL;
-       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
+       union spoolss_DriverInfo        *driver;
        bool in_use = false;
 
        if ( !info )
                return False;
 
-       version = info->cversion;
+       version = info->version;
 
        /* loop over all driver versions */
 
@@ -5074,19 +4943,19 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
        /* get the list of drivers */
 
        list = NULL;
-       ndrivers = get_ntdrivers(&list, info->environment, version);
+       ndrivers = get_ntdrivers(&list, info->architecture, version);
 
        DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
-               ndrivers, info->environment, version));
+               ndrivers, info->architecture, version));
 
        /* check each driver for overlap in files */
 
        for (i=0; i<ndrivers; i++) {
                DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
 
-               ZERO_STRUCT(driver);
+               driver = NULL;
 
-               if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
+               if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, 3, list[i], info->architecture, version))) {
                        SAFE_FREE(list);
                        return True;
                }
@@ -5094,8 +4963,8 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
                /* check if d2 uses any files from d1 */
                /* only if this is a different driver than the one being deleted */
 
-               if ( !strequal(info->name, driver.info_3->name) ) {
-                       if ( trim_overlap_drv_files(info, driver.info_3) ) {
+               if (!strequal(info->driver_name, driver->info3.driver_name)) {
+                       if (trim_overlap_drv_files(mem_ctx, info, &driver->info3)) {
                                /* mz: Do not instantly return -
                                 * we need to ensure this file isn't
                                 * also in use by other drivers. */
@@ -5103,18 +4972,13 @@ bool printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
                        }
                }
 
-               free_a_printer_driver(driver, 3);
+               free_a_printer_driver(driver);
        }
 
        SAFE_FREE(list);
 
        DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
 
-       driver.info_3 = info;
-
-       if ( DEBUGLEVEL >= 20 )
-               dump_a_printer_driver( driver, 3 );
-
        return in_use;
 }
 
@@ -5143,7 +5007,7 @@ static NTSTATUS driver_unlink_internals(connection_struct *conn,
 ****************************************************************************/
 
 static bool delete_driver_files(struct pipes_struct *rpc_pipe,
-                               NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
+                               const struct spoolss_DriverInfo3 *info_3)
 {
        int i = 0;
        char *s;
@@ -5158,7 +5022,8 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        if ( !info_3 )
                return False;
 
-       DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
+       DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n",
+               info_3->driver_name, info_3->version));
 
        fstrcpy(printdollar, "print$");
 
@@ -5184,32 +5049,32 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
        /* now delete the files; must strip the '\print$' string from
           fron of path                                                */
 
-       if ( *info_3->driverpath ) {
-               if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
+       if (info_3->driver_path && info_3->driver_path[0]) {
+               if ((s = strchr(&info_3->driver_path[1], '\\')) != NULL) {
                        file = s;
                        DEBUG(10,("deleting driverfile [%s]\n", s));
                        driver_unlink_internals(conn, file);
                }
        }
 
-       if ( *info_3->configfile ) {
-               if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
+       if (info_3->config_file && info_3->config_file[0]) {
+               if ((s = strchr(&info_3->config_file[1], '\\')) != NULL) {
                        file = s;
                        DEBUG(10,("deleting configfile [%s]\n", s));
                        driver_unlink_internals(conn, file);
                }
        }
 
-       if ( *info_3->datafile ) {
-               if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
+       if (info_3->data_file && info_3->data_file[0]) {
+               if ((s = strchr(&info_3->data_file[1], '\\')) != NULL) {
                        file = s;
                        DEBUG(10,("deleting datafile [%s]\n", s));
                        driver_unlink_internals(conn, file);
                }
        }
 
-       if ( *info_3->helpfile ) {
-               if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
+       if (info_3->help_file && info_3->help_file[0]) {
+               if ((s = strchr( &info_3->help_file[1], '\\')) != NULL) {
                        file = s;
                        DEBUG(10,("deleting helpfile [%s]\n", s));
                        driver_unlink_internals(conn, file);
@@ -5218,13 +5083,13 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
 
        /* check if we are done removing files */
 
-       if ( info_3->dependentfiles ) {
-               while ( info_3->dependentfiles[i][0] ) {
+       if (info_3->dependent_files) {
+               while (info_3->dependent_files[i] && info_3->dependent_files[i][0]) {
                        char *p;
 
                        /* bypass the "\print$" portion of the path */
 
-                       if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
+                       if ((p = strchr(info_3->dependent_files[i]+1, '\\')) != NULL) {
                                file = p;
                                DEBUG(10,("deleting dependent file [%s]\n", file));
                                driver_unlink_internals(conn, file);
@@ -5251,31 +5116,27 @@ static bool delete_driver_files(struct pipes_struct *rpc_pipe,
  ***************************************************************************/
 
 WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
-                            NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
+                            const struct spoolss_DriverInfo3 *info_3,
                             uint32 version, bool delete_files )
 {
        char *key = NULL;
        const char     *arch;
        TDB_DATA        dbuf;
-       NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
 
        /* delete the tdb data first */
 
-       arch = get_short_archi(info_3->environment);
+       arch = get_short_archi(info_3->architecture);
        if (!arch) {
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
        if (asprintf(&key, "%s%s/%d/%s", DRIVERS_PREFIX,
-                       arch, version, info_3->name) < 0) {
+                       arch, version, info_3->driver_name) < 0) {
                return WERR_NOMEM;
        }
 
        DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
                key, delete_files ? "TRUE" : "FALSE" ));
 
-       ctr.info_3 = info_3;
-       dump_a_printer_driver( ctr, 3 );
-
        /* check if the driver actually exists for this environment */
 
        dbuf = tdb_fetch_bystring( tdb_drivers, key );