s3-spoolss: stricter name checks when opening back-channel notify connection.
[ira/wip.git] / source3 / rpc_server / srv_spoolss_nt.c
index 1dec824e9dfecd44cdaf72cd6c9439b785b188c4..b1513dd329d30861dcefe10d4c14906b1fc6ab72 100644 (file)
@@ -2340,27 +2340,30 @@ static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
        NTSTATUS ret;
        struct cli_state *the_cli;
        struct sockaddr_storage rm_addr;
+       char addr[INET6_ADDRSTRLEN];
 
        if ( is_zero_addr((struct sockaddr *)client_ss) ) {
+               DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
+                       remote_machine));
                if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
                        DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
                        return false;
                }
-
-               if (ismyaddr((struct sockaddr *)&rm_addr)) {
-                       DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
-                       return false;
-               }
+               print_sockaddr(addr, sizeof(addr), &rm_addr);
        } else {
-               char addr[INET6_ADDRSTRLEN];
                rm_addr = *client_ss;
                print_sockaddr(addr, sizeof(addr), &rm_addr);
                DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
                        addr));
        }
 
-       /* setup the connection */
+       if (ismyaddr((struct sockaddr *)&rm_addr)) {
+               DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
+                       addr));
+               return false;
+       }
 
+       /* setup the connection */
        ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
                &rm_addr, 0, "IPC$", "IPC",
                "", /* username */
@@ -2549,6 +2552,9 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
                        !get_printer_snum(p, r->in.handle, &snum, NULL) )
                return WERR_BADFID;
 
+       DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
+               "client_address is %s\n", p->client_address));
+
        if (!interpret_string_addr(&client_ss, p->client_address,
                                   AI_NUMERICHOST)) {
                return WERR_SERVER_UNAVAILABLE;
@@ -4498,8 +4504,7 @@ static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
                                        struct spoolss_DriverInfo1 *r,
                                        const struct spoolss_DriverInfo8 *driver,
-                                       const char *servername,
-                                       const char *architecture)
+                                       const char *servername)
 {
        r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
        W_ERROR_HAVE_NO_MEMORY(r->driver_name);
@@ -4746,6 +4751,97 @@ static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
        return WERR_OK;
 }
 
+/********************************************************************
+ * fill a spoolss_DriverInfo8 struct
+ ********************************************************************/
+
+static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
+                                       struct spoolss_DriverInfo8 *r,
+                                       const struct spoolss_DriverInfo8 *driver,
+                                       const char *servername)
+{
+       const char *cservername = canon_servername(servername);
+
+       r->version              = driver->version;
+
+       r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
+       W_ERROR_HAVE_NO_MEMORY(r->driver_name);
+       r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
+       W_ERROR_HAVE_NO_MEMORY(r->architecture);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->driver_path,
+                              r->driver_path);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->data_file,
+                              r->data_file);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->config_file,
+                              r->config_file);
+
+       FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
+                              driver->help_file,
+                              r->help_file);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->monitor_name,
+                          r->monitor_name);
+
+       FILL_DRIVER_STRING(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);
+
+       r->driver_date          = driver->driver_date;
+       r->driver_version       = driver->driver_version;
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_name,
+                          r->manufacturer_name);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->manufacturer_url,
+                          r->manufacturer_url);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->hardware_id,
+                          r->hardware_id);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->provider,
+                          r->provider);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->print_processor,
+                          r->print_processor);
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->vendor_setup,
+                          r->vendor_setup);
+
+       r->color_profiles = string_array_from_driver_info(mem_ctx,
+                                                         driver->color_profiles,
+                                                         cservername);
+
+       FILL_DRIVER_STRING(mem_ctx,
+                          driver->inf_path,
+                          r->inf_path);
+
+       r->printer_driver_attributes    = driver->printer_driver_attributes;
+
+       r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
+                                                                   driver->core_driver_dependencies,
+                                                                   cservername);
+
+       r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
+       r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
+
+       return WERR_OK;
+}
 /********************************************************************
  ********************************************************************/
 
@@ -4921,210 +5017,23 @@ static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
 }
 
 /********************************************************************
- * construct_printer_driver_info_1
- ********************************************************************/
-
-static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo1 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
-{
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       struct spoolss_DriverInfo8 *driver;
-       WERROR result;
-
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
-               return WERR_INVALID_PRINTER_NAME;
-
-       if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername, architecture, version))) {
-               free_a_printer(&printer, 2);
-               return WERR_UNKNOWN_PRINTER_DRIVER;
-       }
-
-       result = fill_printer_driver_info1(mem_ctx, r, driver, servername, architecture);
-
-       free_a_printer_driver(driver);
-       free_a_printer(&printer,2);
-
-       return result;
-}
-
-/********************************************************************
- * construct_printer_driver_info_2
- * fill a printer_info_2 struct
  ********************************************************************/
 
-static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo2 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
+static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
+                                                 uint32_t level,
+                                                 union spoolss_DriverInfo *r,
+                                                 int snum,
+                                                 const char *servername,
+                                                 const char *architecture,
+                                                 uint32_t version)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        struct spoolss_DriverInfo8 *driver;
        WERROR result;
 
-       ZERO_STRUCT(printer);
-
-       if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
-               return WERR_INVALID_PRINTER_NAME;
-
-       if (!W_ERROR_IS_OK(get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername, architecture, version))) {
-               free_a_printer(&printer, 2);
-               return WERR_UNKNOWN_PRINTER_DRIVER;
-       }
-
-       result = fill_printer_driver_info2(mem_ctx, r, driver, servername);
-
-       free_a_printer_driver(driver);
-       free_a_printer(&printer,2);
-
-       return result;
-}
-
-/********************************************************************
- * construct_printer_info_3
- * fill a printer_info_3 struct
- ********************************************************************/
-
-static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo3 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
-{
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       struct spoolss_DriverInfo8 *driver;
-       WERROR status;
-       ZERO_STRUCT(driver);
-
-       status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
-       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
-       if (!W_ERROR_IS_OK(status))
-               return WERR_INVALID_PRINTER_NAME;
-
-       status = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername, architecture, version);
-       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
-
-#if 0  /* JERRY */
-
-       /*
-        * I put this code in during testing.  Helpful when commenting out the
-        * support for DRIVER_INFO_6 in regards to win2k.  Not needed in general
-        * as win2k always queries the driver using an infor level of 6.
-        * I've left it in (but ifdef'd out) because I'll probably
-        * use it in experimentation again in the future.   --jerry 22/01/2002
-        */
-
-       if (!W_ERROR_IS_OK(status)) {
-               /*
-                * Is this a W2k client ?
-                */
-               if (version == 3) {
-                       /* Yes - try again with a WinNT driver. */
-                       version = 2;
-                       status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
-                       DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
-               }
-#endif
-
-               if (!W_ERROR_IS_OK(status)) {
-                       free_a_printer(&printer,2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
-               }
-
-#if 0  /* JERRY */
-       }
-#endif
-
-
-       status = fill_printer_driver_info3(mem_ctx, r, driver, servername);
-
-       free_a_printer_driver(driver);
-       free_a_printer(&printer,2);
-
-       return status;
-}
-
-/********************************************************************
- * construct_printer_info_6
- * fill a printer_info_6 struct
- ********************************************************************/
-
-static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
-                                             struct spoolss_DriverInfo6 *r,
-                                             int snum,
-                                             const char *servername,
-                                             const char *architecture,
-                                             uint32_t version)
-{
-       NT_PRINTER_INFO_LEVEL           *printer = NULL;
-       struct spoolss_DriverInfo8 *driver;
-       WERROR                          status;
-
-       status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
-
-       DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
-
-       if (!W_ERROR_IS_OK(status))
-               return WERR_INVALID_PRINTER_NAME;
-
-       status = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername, architecture, version);
-
-       DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
-
-       if (!W_ERROR_IS_OK(status))
-       {
-               /*
-                * Is this a W2k client ?
-                */
-
-               if (version < 3) {
-                       free_a_printer(&printer,2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
-               }
-
-               /* Yes - try again with a WinNT driver. */
-               version = 2;
-               status = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername, architecture, version);
-               DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
-               if (!W_ERROR_IS_OK(status)) {
-                       free_a_printer(&printer,2);
-                       return WERR_UNKNOWN_PRINTER_DRIVER;
-               }
-       }
-
-       status = fill_printer_driver_info6(mem_ctx, r, driver, servername);
-
-       free_a_printer(&printer,2);
-       free_a_printer_driver(driver);
-
-       return status;
-}
-
-/********************************************************************
- * construct_printer_info_101
- * fill a printer_info_101 struct
- ********************************************************************/
-
-static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
-                                               struct spoolss_DriverInfo101 *r,
-                                               int snum,
-                                               const char *servername,
-                                               const char *architecture,
-                                               uint32_t version)
-{
-       NT_PRINTER_INFO_LEVEL           *printer = NULL;
-       struct spoolss_DriverInfo8 *driver;
-       WERROR                          result;
-
        result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
 
-       DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
+       DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
                win_errstr(result)));
 
        if (!W_ERROR_IS_OK(result)) {
@@ -5134,7 +5043,7 @@ static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
        result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
                                      architecture, version);
 
-       DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
+       DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
                win_errstr(result)));
 
        if (!W_ERROR_IS_OK(result)) {
@@ -5151,7 +5060,7 @@ static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
                version = 2;
                result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
                                              architecture, version);
-               DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
+               DEBUG(8,("construct_printer_driver_level: status: %s\n",
                        win_errstr(result)));
                if (!W_ERROR_IS_OK(result)) {
                        free_a_printer(&printer, 2);
@@ -5159,7 +5068,35 @@ static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
                }
        }
 
-       result = fill_printer_driver_info101(mem_ctx, r, driver, servername);
+       switch (level) {
+       case 1:
+               result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
+               break;
+       case 2:
+               result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
+               break;
+       case 3:
+               result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
+               break;
+       case 4:
+               result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
+               break;
+       case 5:
+               result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
+               break;
+       case 6:
+               result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
+               break;
+       case 8:
+               result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
+               break;
+       case 101:
+               result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
+               break;
+       default:
+               result = WERR_UNKNOWN_LEVEL;
+               break;
+       }
 
        free_a_printer(&printer, 2);
        free_a_printer_driver(driver);
@@ -5203,52 +5140,11 @@ WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
                return WERR_BADFID;
        }
 
-       switch (r->in.level) {
-       case 1:
-               result = construct_printer_driver_info_1(p->mem_ctx,
-                                                        &r->out.info->info1,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 2:
-               result = construct_printer_driver_info_2(p->mem_ctx,
-                                                        &r->out.info->info2,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 3:
-               result = construct_printer_driver_info_3(p->mem_ctx,
-                                                        &r->out.info->info3,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 6:
-               result = construct_printer_driver_info_6(p->mem_ctx,
-                                                        &r->out.info->info6,
-                                                        snum,
-                                                        servername,
-                                                        r->in.architecture,
-                                                        r->in.client_major_version);
-               break;
-       case 101:
-               result = construct_printer_driver_info_101(p->mem_ctx,
-                                                          &r->out.info->info101,
-                                                          snum,
-                                                          servername,
-                                                          r->in.architecture,
-                                                          r->in.client_major_version);
-               break;
-       default:
-               result = WERR_UNKNOWN_LEVEL;
-               break;
-       }
-
+       result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
+                                                    r->out.info, snum,
+                                                    servername,
+                                                    r->in.architecture,
+                                                    r->in.client_major_version);
        if (!W_ERROR_IS_OK(result)) {
                TALLOC_FREE(r->out.info);
                return result;
@@ -6482,7 +6378,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                                                    union spoolss_DriverInfo,
                                                    count + ndrivers);
                        if (!info) {
-                               DEBUG(0,("enumprinterdrivers_level1: "
+                               DEBUG(0,("enumprinterdrivers_level_by_architecture: "
                                        "failed to enlarge driver info buffer!\n"));
                                result = WERR_NOMEM;
                                goto out;
@@ -6501,8 +6397,7 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                        switch (level) {
                        case 1:
                                result = fill_printer_driver_info1(info, &info[count+i].info1,
-                                                                  driver, servername,
-                                                                  architecture);
+                                                                  driver, servername);
                                break;
                        case 2:
                                result = fill_printer_driver_info2(info, &info[count+i].info2,
@@ -6524,6 +6419,10 @@ static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
                                result = fill_printer_driver_info6(info, &info[count+i].info6,
                                                                   driver, servername);
                                break;
+                       case 8:
+                               result = fill_printer_driver_info8(info, &info[count+i].info8,
+                                                                  driver, servername);
+                               break;
                        default:
                                result = WERR_UNKNOWN_LEVEL;
                                break;
@@ -6568,7 +6467,7 @@ static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
        uint32_t a,i;
        WERROR result = WERR_OK;
 
-       if (strequal(architecture, "all")) {
+       if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
 
                for (a=0; archi_table[a].long_archi != NULL; a++) {
 
@@ -6602,91 +6501,6 @@ static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
                                                        count_p);
 }
 
-/****************************************************************************
- Enumerates all printer drivers at level 1.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
-                                       info_p, count);
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 2.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
-                                       info_p, count);
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 3.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
-                                       info_p, count);
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 4.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
-                                       info_p, count);
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 5.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
-                                       info_p, count);
-}
-
-/****************************************************************************
- Enumerates all printer drivers at level 6.
-****************************************************************************/
-
-static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
-                                       const char *servername,
-                                       const char *architecture,
-                                       union spoolss_DriverInfo **info_p,
-                                       uint32_t *count)
-{
-       return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
-                                       info_p, count);
-}
-
-
 /****************************************************************
  _spoolss_EnumPrinterDrivers
 ****************************************************************/
@@ -6715,41 +6529,11 @@ WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
 
-       switch (r->in.level) {
-       case 1:
-               result = enumprinterdrivers_level1(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 2:
-               result = enumprinterdrivers_level2(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 3:
-               result = enumprinterdrivers_level3(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 4:
-               result = enumprinterdrivers_level4(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 5:
-               result = enumprinterdrivers_level5(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       case 6:
-               result = enumprinterdrivers_level6(p->mem_ctx, cservername,
-                                                  r->in.environment,
-                                                  r->out.info, r->out.count);
-               break;
-       default:
-               return WERR_UNKNOWN_LEVEL;
-       }
-
+       result = enumprinterdrivers_level(p->mem_ctx, cservername,
+                                         r->in.environment,
+                                         r->in.level,
+                                         r->out.info,
+                                         r->out.count);
        if (!W_ERROR_IS_OK(result)) {
                return result;
        }
@@ -9008,12 +8792,20 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
                goto done;
        }
 
-       array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
+       array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
        if (!array) {
                result = WERR_NOMEM;
                goto done;
        }
 
+       if (!num_keys) {
+               array[0] = talloc_strdup(array, "");
+               if (!array[0]) {
+                       result = WERR_NOMEM;
+                       goto done;
+               }
+       }
+
        for (i=0; i < num_keys; i++) {
 
                DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
@@ -9031,13 +8823,14 @@ WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
                goto done;
        }
 
+       *r->out._ndr_size = r->in.offered / 2;
        *r->out.needed = blob.length;
 
        if (r->in.offered < *r->out.needed) {
                result = WERR_MORE_DATA;
        } else {
                result = WERR_OK;
-               r->out.key_buffer->string = array;
+               r->out.key_buffer->string_array = array;
        }
 
  done: