s4-smbtorture: mention architecture of added drivers in debug output.
[metze/samba/wip.git] / source4 / torture / rpc / spoolss.c
index c600d4e4c98c52860d1af2b7213d1e838623f1b5..89de7b0924f3ce66f3c5f79a526d0e40d79c3b0e 100644 (file)
@@ -90,6 +90,31 @@ struct torture_driver_context {
        bool ex;
 };
 
+struct torture_printer_context {
+       struct spoolss_SetPrinterInfo2 info2;
+       struct torture_driver_context driver;
+       bool ex;
+       bool wellknown;
+       bool added_driver;
+       bool have_driver;
+};
+
+static bool upload_printer_driver(struct torture_context *tctx,
+                                 const char *server_name,
+                                 struct torture_driver_context *d);
+static bool remove_printer_driver(struct torture_context *tctx,
+                                 const char *server_name,
+                                 struct torture_driver_context *d);
+static bool fillup_printserver_info(struct torture_context *tctx,
+                                   struct dcerpc_pipe *p,
+                                   struct torture_driver_context *d);
+static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
+                                              struct dcerpc_binding_handle *b,
+                                              const char *server_name,
+                                              struct spoolss_AddDriverInfo8 *r,
+                                              uint32_t flags,
+                                              bool ex);
+
 #define COMPARE_STRING(tctx, c,r,e) \
        torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
 
@@ -5969,58 +5994,6 @@ static bool test_AddPrinter_normal(struct torture_context *tctx,
        return true;
 }
 
-static bool test_AddPrinterEx(struct torture_context *tctx,
-                             struct dcerpc_pipe *p,
-                             struct policy_handle *handle_p,
-                             const char *printername,
-                             const char *drivername,
-                             const char *portname)
-{
-       bool ret = true;
-
-       if (!torture_setting_bool(tctx, "samba3", false)) {
-               if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
-                       torture_comment(tctx, "failed to add printer to well known list\n");
-                       ret = false;
-               }
-       }
-
-       if (!test_AddPrinter_normal(tctx, p, handle_p,
-                                   printername, drivername, portname,
-                                   true)) {
-               torture_comment(tctx, "failed to add printer to printer list\n");
-               ret = false;
-       }
-
-       return ret;
-}
-
-static bool test_AddPrinter(struct torture_context *tctx,
-                           struct dcerpc_pipe *p,
-                           struct policy_handle *handle_p,
-                           const char *printername,
-                           const char *drivername,
-                           const char *portname)
-{
-       bool ret = true;
-
-       if (!torture_setting_bool(tctx, "samba3", false)) {
-               if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
-                       torture_comment(tctx, "failed to add printer to well known list\n");
-                       ret = false;
-               }
-       }
-
-       if (!test_AddPrinter_normal(tctx, p, handle_p,
-                                   printername, drivername, portname,
-                                   false)) {
-               torture_comment(tctx, "failed to add printer to printer list\n");
-               ret = false;
-       }
-
-       return ret;
-}
-
 static bool test_printer_info(struct torture_context *tctx,
                              struct dcerpc_binding_handle *b,
                              struct policy_handle *handle)
@@ -6158,7 +6131,8 @@ static bool test_one_printer(struct torture_context *tctx,
                             struct policy_handle *handle,
                             const char *name,
                             const char *drivername,
-                            const char *environment)
+                            const char *environment,
+                            bool have_driver)
 {
        bool ret = true;
        struct dcerpc_binding_handle *b = p->binding_handle;
@@ -6211,8 +6185,10 @@ static bool test_one_printer(struct torture_context *tctx,
                ret = false;
        }
 
-       if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
-               ret = false;
+       if (have_driver) {
+               if (!test_DriverInfo_winreg(tctx, p, handle, name, drivername, environment)) {
+                       ret = false;
+               }
        }
 
        if (!test_printer_rename(tctx, p, handle, name)) {
@@ -6245,7 +6221,7 @@ static bool test_csetprinter(struct torture_context *tctx,
         * been added */
 
        torture_assert(tctx,
-               test_AddPrinter(tctx, p, &new_handle, printername, drivername, portname),
+               test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, false),
                "failed to add new printer");
        torture_assert(tctx,
                test_GetPrinter_level(tctx, b, handle, 0, &info),
@@ -6285,81 +6261,197 @@ static bool test_csetprinter(struct torture_context *tctx,
        return true;
 }
 
-static bool test_printer(struct torture_context *tctx,
-                        struct dcerpc_pipe *p)
+static bool test_add_printer_args_with_driver(struct torture_context *tctx,
+                                             struct dcerpc_pipe *p,
+                                             struct torture_printer_context *t)
 {
        bool ret = true;
-       struct policy_handle handle[2];
-       struct policy_handle printserver_handle;
+       struct policy_handle handle;
        bool found = false;
-       const char *drivername = "Microsoft XPS Document Writer";
-       const char *portname = "LPT1:";
        struct dcerpc_binding_handle *b = p->binding_handle;
-       const char *environment;
-
-       torture_assert(tctx,
-               test_OpenPrinter_server(tctx, p, &printserver_handle),
-               "failed to open printserver");
-       torture_assert(tctx,
-               test_get_environment(tctx, b, &printserver_handle, &environment),
-               "failed to get environment");
-       torture_assert(tctx,
-               test_ClosePrinter(tctx, b, &printserver_handle),
-               "failed to close printserver");
-
-       /* test printer created via AddPrinter */
+       const char *printer_name = t->info2.printername;
+       const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
+       const char *port_name = t->info2.portname;
+       const char *printer_name2 = talloc_asprintf(tctx, "%s2", printer_name);
 
-       if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
-               return false;
+       if (t->wellknown) {
+               torture_assert(tctx,
+                       test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
+                       "failed to add wellknown printer");
+       } else {
+               torture_assert(tctx,
+                       test_AddPrinter_normal(tctx, p, &handle, printer_name, driver_name, port_name, t->ex),
+                       "failed to add printer");
        }
 
-       if (!test_csetprinter(tctx, p, &handle[0], TORTURE_PRINTER "2", drivername, portname)) {
+       if (!test_csetprinter(tctx, p, &handle, printer_name2, driver_name, port_name)) {
                ret = false;
        }
 
-       if (!test_one_printer(tctx, p, &handle[0], TORTURE_PRINTER, drivername, environment)) {
+       if (!test_one_printer(tctx, p, &handle, printer_name, driver_name, t->driver.remote.environment, t->have_driver)) {
                ret = false;
        }
 
-       if (!test_DeletePrinter(tctx, b, &handle[0])) {
+       if (!test_DeletePrinter(tctx, b, &handle)) {
                ret = false;
        }
 
        if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
-                                       TORTURE_PRINTER, &found)) {
+                                       printer_name, &found)) {
                ret = false;
        }
 
        torture_assert(tctx, !found, "deleted printer still there");
 
-       /* test printer created via AddPrinterEx */
+       return ret;
+}
 
-       if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
-               return false;
+static bool compose_local_driver_directory(struct torture_context *tctx,
+                                          const char *environment,
+                                          const char *local_dir,
+                                          const char **path)
+{
+       char *p;
+
+       p = strrchr(local_dir, '/');
+       if (!p) {
+               return NULL;
        }
+       p++;
 
-       if (!test_csetprinter(tctx, p, &handle[1], TORTURE_PRINTER_EX "2", drivername, portname)) {
-               ret = false;
+       if (strequal(environment, "Windows x64")) {
+               if (!strequal(p, "x64")) {
+                       *path = talloc_asprintf(tctx, "%s/x64", local_dir);
+               }
+       } else if (strequal(environment, "Windows NT x86")) {
+               if (!strequal(p, "i386")) {
+                       *path = talloc_asprintf(tctx, "%s/i386", local_dir);
+               }
+       } else {
+               torture_assert(tctx, "unknown environment: '%s'\n", environment);
        }
 
-       if (!test_one_printer(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, environment)) {
-               ret = false;
+       return true;
+}
+
+static bool test_add_printer_args(struct torture_context *tctx,
+                                 struct dcerpc_pipe *p,
+                                 struct torture_printer_context *t)
+{
+       bool ret = true;
+       struct dcerpc_binding_handle *b = p->binding_handle;
+       const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+
+       if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
+               torture_skip(tctx, "skipping AddPrinter level 1 against samba");
        }
 
-       if (!test_DeletePrinter(tctx, b, &handle[1])) {
-               ret = false;
+       torture_assert(tctx,
+               fillup_printserver_info(tctx, p, &t->driver),
+               "failed to fillup printserver info");
+
+       t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
+
+       torture_assert(tctx,
+               compose_local_driver_directory(tctx, t->driver.remote.environment,
+                                              t->driver.local.driver_directory,
+                                              &t->driver.local.driver_directory),
+               "failed to compose local driver directory");
+
+       if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername)) {
+               t->have_driver = true;
+               goto try_run;
        }
 
-       if (!test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
-                                       TORTURE_PRINTER_EX, &found)) {
-               ret = false;
+       torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
+               t->info2.drivername, t->driver.remote.environment);
+       torture_comment(tctx, "trying to upload own driver\n");
+
+       if (!directory_exist(t->driver.local.driver_directory)) {
+               torture_warning(tctx, "no local driver is available!");
+               t->have_driver = false;
+               goto try_run;
        }
 
-       torture_assert(tctx, !found, "deleted printer still there");
+       torture_assert(tctx,
+               upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
+               "failed to upload printer driver");
+
+       torture_assert(tctx,
+               test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
+               "failed to add driver");
+
+       t->added_driver = true;
+       t->have_driver = true;
+
+ try_run:
+       ret = test_add_printer_args_with_driver(tctx, p, t);
+
+       if (t->added_driver) {
+               torture_assert(tctx,
+                       remove_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
+                       "failed to remove printer driver");
+       }
 
        return ret;
 }
 
+static bool test_add_printer(struct torture_context *tctx,
+                            struct dcerpc_pipe *p,
+                            void *private_data)
+{
+       struct torture_printer_context *t =
+               (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
+
+       t->ex                   = false;
+       t->wellknown            = false;
+       t->info2.printername    = TORTURE_PRINTER;
+
+       return test_add_printer_args(tctx, p, t);
+}
+
+static bool test_add_printer_wellknown(struct torture_context *tctx,
+                                      struct dcerpc_pipe *p,
+                                      void *private_data)
+{
+       struct torture_printer_context *t =
+               (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
+
+       t->ex                   = false;
+       t->wellknown            = true;
+       t->info2.printername    = TORTURE_WELLKNOWN_PRINTER;
+
+       return test_add_printer_args(tctx, p, t);
+}
+
+static bool test_add_printer_ex(struct torture_context *tctx,
+                               struct dcerpc_pipe *p,
+                               void *private_data)
+{
+       struct torture_printer_context *t =
+               (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
+
+       t->ex                   = true;
+       t->wellknown            = false;
+       t->info2.printername    = TORTURE_PRINTER_EX;
+
+       return test_add_printer_args(tctx, p, t);
+}
+
+static bool test_add_printer_ex_wellknown(struct torture_context *tctx,
+                                         struct dcerpc_pipe *p,
+                                         void *private_data)
+{
+       struct torture_printer_context *t =
+               (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
+
+       t->ex                   = true;
+       t->wellknown            = true;
+       t->info2.printername    = TORTURE_WELLKNOWN_PRINTER_EX;
+
+       return test_add_printer_args(tctx, p, t);
+}
+
 static bool test_architecture_buffer(struct torture_context *tctx,
                                     struct dcerpc_pipe *p)
 {
@@ -6481,7 +6573,26 @@ struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
        struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
                                                        "printer", &ndr_table_spoolss);
 
-       torture_rpc_tcase_add_test(tcase, "printer", test_printer);
+       struct torture_printer_context *t;
+
+       t = talloc_zero(mem_ctx, struct torture_printer_context);
+
+       t->driver.info8.version         = SPOOLSS_DRIVER_VERSION_200X;
+       t->driver.info8.driver_name     = TORTURE_DRIVER;
+       t->driver.info8.architecture    = "Windows NT x86";
+       t->driver.info8.driver_path     = "pscript5.dll";
+       t->driver.info8.data_file       = "cups6.ppd";
+       t->driver.info8.config_file     = "cupsui6.dll";
+       t->driver.local.environment     = "Windows NT x86";
+       t->driver.local.driver_directory= "/usr/share/cups/drivers/i386";
+
+       t->info2.drivername             = "Microsoft XPS Document Writer";
+       t->info2.portname               = "LPT1:";
+
+       torture_rpc_tcase_add_test_ex(tcase, "add_printer", test_add_printer, t);
+       torture_rpc_tcase_add_test_ex(tcase, "add_printer_wellknown", test_add_printer_wellknown, t);
+       torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex", test_add_printer_ex, t);
+       torture_rpc_tcase_add_test_ex(tcase, "add_printer_ex_wellknown", test_add_printer_ex_wellknown, t);
 
        return suite;
 }
@@ -6550,6 +6661,29 @@ static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ct
        }
 }
 
+static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
+{
+       if (info_ctr == NULL) {
+               return NULL;
+       }
+
+       switch (info_ctr->level) {
+       case 2:
+               return info_ctr->info.info2->architecture;
+       case 3:
+               return info_ctr->info.info3->architecture;
+       case 4:
+               return info_ctr->info.info4->architecture;
+       case 6:
+               return info_ctr->info.info6->architecture;
+       case 8:
+               return info_ctr->info.info8->architecture;
+       default:
+               return NULL;
+       }
+}
+
+
 static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
                                      struct dcerpc_binding_handle *b,
                                      const char *servername,
@@ -6558,12 +6692,13 @@ static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
 {
        struct spoolss_AddPrinterDriver r;
        const char *drivername = get_driver_from_info(info_ctr);
+       const char *environment = get_environment_from_info(info_ctr);
 
        r.in.servername = servername;
        r.in.info_ctr = info_ctr;
 
-       torture_comment(tctx, "Testing AddPrinterDriver(%s) level %d\n",
-               drivername, info_ctr->level);
+       torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
+               drivername, info_ctr->level, environment);
 
        torture_assert_ntstatus_ok(tctx,
                dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
@@ -6584,13 +6719,14 @@ static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
 {
        struct spoolss_AddPrinterDriverEx r;
        const char *drivername = get_driver_from_info(info_ctr);
+       const char *environment = get_environment_from_info(info_ctr);
 
        r.in.servername = servername;
        r.in.info_ctr = info_ctr;
        r.in.flags = flags;
 
-       torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level %d\n",
-               drivername, info_ctr->level);
+       torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
+               drivername, info_ctr->level, environment);
 
        torture_assert_ntstatus_ok(tctx,
                dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
@@ -6761,14 +6897,17 @@ static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
        struct spoolss_AddDriverInfoCtr info_ctr;
        struct spoolss_AddDriverInfo3 info3;
 
-       ZERO_STRUCT(info3);
-
        info3.driver_name       = r->driver_name;
        info3.version           = r->version;
        info3.architecture      = r->architecture;
        info3.driver_path       = r->driver_path;
        info3.data_file         = r->data_file;
        info3.config_file       = r->config_file;
+       info3.help_file         = r->help_file;
+       info3.monitor_name      = r->monitor_name;
+       info3.default_datatype  = r->default_datatype;
+       info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
+       info3.dependent_files   = r->dependent_files;
 
        info_ctr.level = 3;
        info_ctr.info.info3 = &info3;
@@ -6800,14 +6939,19 @@ static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
        struct spoolss_AddDriverInfoCtr info_ctr;
        struct spoolss_AddDriverInfo4 info4;
 
-       ZERO_STRUCT(info4);
-
-       info4.driver_name       = r->driver_name;
        info4.version           = r->version;
+       info4.driver_name       = r->driver_name;
        info4.architecture      = r->architecture;
        info4.driver_path       = r->driver_path;
        info4.data_file         = r->data_file;
        info4.config_file       = r->config_file;
+       info4.help_file         = r->help_file;
+       info4.monitor_name      = r->monitor_name;
+       info4.default_datatype  = r->default_datatype;
+       info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
+       info4.dependent_files   = r->dependent_files;
+       info4._ndr_size_previous_names = r->_ndr_size_previous_names;
+       info4.previous_names = r->previous_names;
 
        info_ctr.level = 4;
        info_ctr.info.info4 = &info4;
@@ -6839,14 +6983,25 @@ static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
        struct spoolss_AddDriverInfoCtr info_ctr;
        struct spoolss_AddDriverInfo6 info6;
 
-       ZERO_STRUCT(info6);
-
-       info6.driver_name       = r->driver_name;
        info6.version           = r->version;
+       info6.driver_name       = r->driver_name;
        info6.architecture      = r->architecture;
        info6.driver_path       = r->driver_path;
        info6.data_file         = r->data_file;
        info6.config_file       = r->config_file;
+       info6.help_file         = r->help_file;
+       info6.monitor_name      = r->monitor_name;
+       info6.default_datatype  = r->default_datatype;
+       info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
+       info6.dependent_files   = r->dependent_files;
+       info6._ndr_size_previous_names = r->_ndr_size_previous_names;
+       info6.previous_names    = r->previous_names;
+       info6.driver_date       = r->driver_date;
+       info6.driver_version    = r->driver_version;
+       info6.manufacturer_name = r->manufacturer_name;
+       info6.manufacturer_url  = r->manufacturer_url;
+       info6.hardware_id       = r->hardware_id;
+       info6.provider          = r->provider;
 
        info_ctr.level = 6;
        info_ctr.info.info6 = &info6;
@@ -6882,19 +7037,9 @@ static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
                                               bool ex)
 {
        struct spoolss_AddDriverInfoCtr info_ctr;
-       struct spoolss_AddDriverInfo8 info8;
-
-       ZERO_STRUCT(info8);
-
-       info8.driver_name       = r->driver_name;
-       info8.version           = r->version;
-       info8.architecture      = r->architecture;
-       info8.driver_path       = r->driver_path;
-       info8.data_file         = r->data_file;
-       info8.config_file       = r->config_file;
 
        info_ctr.level = 8;
-       info_ctr.info.info8 = &info8;
+       info_ctr.info.info8 = r;
 
        if (ex) {
                torture_assert(tctx,
@@ -7217,7 +7362,8 @@ static bool connect_printer_driver_share(struct torture_context *tctx,
        struct smbcli_options smb_options;
        struct smbcli_session_options smb_session_options;
 
-       torture_comment(tctx, "Connecting printer driver share\n");
+       torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
+               share_name, server_name);
 
        lp_smbcli_options(tctx->lp_ctx, &smb_options);
        lp_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
@@ -7331,6 +7477,12 @@ static bool remove_printer_driver(struct torture_context *tctx,
                "failed to remove help_file");
        if (d->info8.dependent_files) {
                for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
+                       if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
+                           strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
+                           strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
+                           strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
+                               continue;
+                       }
                        torture_assert(tctx,
                                remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
                                "failed to remove dependent_files");