union spoolss_PortInfo *ports[3];
/* for EnumPrinterDrivers */
- uint32_t driver_count[8];
- union spoolss_DriverInfo *drivers[8];
+ uint32_t driver_count[9];
+ union spoolss_DriverInfo *drivers[9];
/* for EnumMonitors */
uint32_t monitor_count[3];
return true;
}
-static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
- struct dcerpc_binding_handle *b,
- const char *server_name,
- const char *environment,
- uint32_t level,
- uint32_t *count_p,
- union spoolss_DriverInfo **info_p)
+static bool test_EnumPrinterDrivers_buffers(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ const char *server_name,
+ const char *environment,
+ uint32_t level,
+ uint32_t offered,
+ uint32_t *count_p,
+ union spoolss_DriverInfo **info_p)
{
struct spoolss_EnumPrinterDrivers r;
uint32_t needed;
uint32_t count;
union spoolss_DriverInfo *info;
+ DATA_BLOB buffer;
+
+ if (offered > 0) {
+ buffer = data_blob_talloc_zero(tctx, offered);
+ }
r.in.server = server_name;
r.in.environment = environment;
r.in.level = level;
- r.in.buffer = NULL;
- r.in.offered = 0;
+ r.in.buffer = offered ? &buffer : NULL;
+ r.in.offered = offered;
r.out.needed = &needed;
r.out.count = &count;
r.out.info = &info;
- torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u\n",
- r.in.environment, r.in.level);
+ torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
+ r.in.environment, r.in.level, r.in.offered);
torture_assert_ntstatus_ok(tctx,
dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
}
+
+static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ const char *server_name,
+ const char *environment,
+ uint32_t level,
+ uint32_t *count_p,
+ union spoolss_DriverInfo **info_p)
+{
+ return test_EnumPrinterDrivers_buffers(tctx, b, server_name,
+ environment, level, 0,
+ count_p, info_p);
+}
+
static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
const char *server_name,
"failed to enumerate printer drivers");
for (i=0; i < count; i++) {
- const char *driver_name_ret;
+ const char *driver_name_ret = "";
switch (level) {
case 1:
driver_name_ret = info[i].info1.driver_name;
struct dcerpc_pipe *p = ctx->spoolss_pipe;
struct dcerpc_binding_handle *b = p->binding_handle;
uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
+ uint16_t buffer_sizes[] = { 0, 1024, 6040, 0xffff };
int i, j, a;
/* FIXME: gd, come back and fix "" as server, and handle
for (a=0;a<ARRAY_SIZE(environments);a++) {
+ for (i=0;i<ARRAY_SIZE(buffer_sizes);i++) {
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_buffers(tctx, b, server_name,
+ environments[a], 3,
+ buffer_sizes[i],
+ NULL, NULL),
+ "failed to enumerate drivers");
+ }
+
for (i=0;i<ARRAY_SIZE(levels);i++) {
int level = levels[i];
uint32_t count;
for (j=0;j<ctx->driver_count[level - 1];j++) {
union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
- union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
+ union spoolss_DriverInfo *ref = &ctx->drivers[7][j];
switch (level) {
case 1:
bool ret = true;
int i;
- torture_skip(tctx, "Printer Info test is currently broken, skipping");
-
uint32_t status_list[] = {
/* these do not stick
PRINTER_STATUS_PAUSED,
0x80000000 */
};
+ torture_skip(tctx, "Printer Info test is currently broken, skipping");
+
+
ZERO_STRUCT(devmode_ctr);
ZERO_STRUCT(secdesc_ctr);
}
#define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
+ void *p; \
torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
q.in.level = lvl1; \
TESTGETCALL(GetPrinter, q) \
info_ctr.level = lvl1; \
- info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
+ p = (void *)&q.out.info->info ## lvl1; \
+ info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
info_ctr.info.info ## lvl1->field1 = value;\
TESTSETCALL_EXP(SetPrinter, s, err) \
info_ctr.info.info ## lvl1->field1 = ""; \
STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
q.in.level = lvl2; \
TESTGETCALL(GetPrinter, q) \
- info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
+ p = (void *)&q.out.info->info ## lvl2; \
+ info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
} while (0)
} while (0);
#define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
+ void *p; \
torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
q.in.level = lvl1; \
TESTGETCALL(GetPrinter, q) \
info_ctr.level = lvl1; \
- info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
+ p = (void *)&q.out.info->info ## lvl1; \
+ info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
info_ctr.info.info ## lvl1->field1 = value; \
TESTSETCALL(SetPrinter, s) \
info_ctr.info.info ## lvl1->field1 = 0; \
TESTGETCALL(GetPrinter, q) \
- info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
+ p = (void *)&q.out.info->info ## lvl1; \
+ info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
q.in.level = lvl2; \
TESTGETCALL(GetPrinter, q) \
- info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)(void *)&q.out.info->info ## lvl2; \
+ p = (void *)&q.out.info->info ## lvl2; \
+ info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
} while (0)
struct spoolss_DevmodeContainer devmode_ctr;
struct sec_desc_buf secdesc_ctr;
union spoolss_SetPrinterInfo sinfo;
+ union spoolss_PrinterInfo info;
+ struct spoolss_SetPrinterInfo3 info3;
ZERO_STRUCT(devmode_ctr);
ZERO_STRUCT(secdesc_ctr);
switch (level) {
case 2: {
- union spoolss_PrinterInfo info;
torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
break;
}
case 3: {
- struct spoolss_SetPrinterInfo3 info3;
info3.sec_desc_ptr = NULL;
{
struct spoolss_SetPrinter s;
struct spoolss_GetPrinter q;
- struct spoolss_GetPrinter q0;
struct spoolss_SetPrinterInfoCtr info_ctr;
struct spoolss_SetPrinterInfo8 info8;
union spoolss_PrinterInfo info;
TESTGETCALL(GetPrinter, q) \
info_ctr.level = lvl1; \
if (lvl1 == 2) {\
- info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)(void *)&q.out.info->info ## lvl1; \
+ void *p = (void *)&q.out.info->info ## lvl1; \
+ info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
} else if (lvl1 == 8) {\
info_ctr.info.info ## lvl1 = &info8; \
}\
q.in.handle = handle;
q.out.info = &info;
- q0 = q;
#if 0
const char *devicename;/* [charset(UTF16)] */
return true;
}
+#if 0
static bool test_GetJob(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
return true;
}
+#endif
static bool test_SetJob(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
uint32_t level,
+ WERROR werr_expected,
uint32_t *count_p,
union spoolss_JobInfo **info_p)
{
status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
- torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
+ torture_assert_werr_equal(tctx, r.out.result, werr_expected,
+ "EnumJobs failed");
torture_assert(tctx, info, "No jobs returned");
CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
} else {
- torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
+ torture_assert_werr_equal(tctx, r.out.result, werr_expected,
+ "EnumJobs failed");
}
if (count_p) {
torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
for (i=1; i < 4; i++) {
+ union spoolss_JobInfo ginfo;
+ bool ok;
+
torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
sp.in.handle = handle;
"dcerpc_spoolss_StartPagePrinter failed");
torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
+ ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
+ if (!ok) {
+ torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
+ }
+
torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
w.in.handle = handle;
uint32_t *job_id)
{
test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
+
+ return true;
}
static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
uint32_t *job_id)
{
test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
+
+ return true;
}
"AddJob failed");
torture_assert(tctx,
- test_EnumJobs_args(tctx, b, handle, 1, &count, &info),
+ test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
"EnumJobs level 1 failed");
torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
return true;
}
+static bool test_printer_purge(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ struct policy_handle *handle)
+{
+ NTSTATUS status;
+ struct spoolss_SetPrinter r;
+ struct spoolss_SetPrinterInfoCtr info_ctr;
+ struct spoolss_DevmodeContainer devmode_ctr;
+ struct sec_desc_buf secdesc_ctr;
+
+ info_ctr.level = 0;
+ info_ctr.info.info0 = NULL;
+
+ ZERO_STRUCT(devmode_ctr);
+ ZERO_STRUCT(secdesc_ctr);
+
+ r.in.handle = handle;
+ r.in.info_ctr = &info_ctr;
+ r.in.devmode_ctr = &devmode_ctr;
+ r.in.secdesc_ctr = &secdesc_ctr;
+ r.in.command = SPOOLSS_PRINTER_CONTROL_PURGE;
+
+ torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
+
+ status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
+ torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
+ torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
+
+ return true;
+}
+
static bool test_GetPrinterData_checktype(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
struct policy_handle *hive_handle,
const char *server_name_slash)
{
- WERROR result;
+ WERROR result = WERR_OK;
union spoolss_DriverInfo info;
const char *driver_key;
struct policy_handle key_handle;
const char *driver_version;
const char *inbox_driver_version;
+ ZERO_STRUCT(key_handle);
+
torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
struct policy_handle *handle)
{
NTSTATUS status;
- struct dcerpc_binding *b;
+ const struct dcerpc_binding *binding2;
struct dcerpc_pipe *p2;
struct spoolss_ClosePrinter cp;
torture_comment(tctx, "Testing close on secondary pipe\n");
- status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
- torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
-
- status = dcerpc_secondary_connection(p, &p2, b);
+ binding2 = p->binding;
+ status = dcerpc_secondary_connection(p, &p2, binding2);
torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
return true;
}
-
+#if 0
static bool test_GetPrinterDriver(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
return true;
}
+#endif
static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
return true;
}
+#if 0
static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
const char *devicename)
{
return r;
}
+#endif
static bool test_architecture_buffer(struct torture_context *tctx,
void *private_data)
return torture_rpc_spoolss_printer_setup_common(tctx, t);
}
+#if 0
static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
{
struct torture_printer_context *t;
return torture_rpc_spoolss_printer_setup_common(tctx, t);
}
+#endif
static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
{
/* check back end spoolss job was created */
torture_assert(tctx,
- test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
+ test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
+ &count, &info),
"EnumJobs level 1 failed");
for (i = 0; i < count; i++) {
return true;
}
+static bool test_print_test_purge(struct torture_context *tctx,
+ void *private_data)
+{
+ struct torture_printer_context *t =
+ (struct torture_printer_context *)talloc_get_type_abort(private_data,
+ struct torture_printer_context);
+ struct dcerpc_pipe *p = t->spoolss_pipe;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ uint32_t num_jobs = 8;
+ uint32_t *job_ids;
+ int i;
+ bool ret = true;
+ uint32_t count;
+ union spoolss_JobInfo *info;
+
+ torture_assert(tctx,
+ test_PausePrinter(tctx, b, &t->handle),
+ "failed to pause printer");
+
+ job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
+ for (i=0; i < num_jobs; i++) {
+ ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
+ "TorturePrintJob",
+ &job_ids[i]);
+ torture_assert(tctx, ret, "failed to add print job");
+ }
+
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
+ &count, &info),
+ "EnumJobs level 1 failed");
+
+ torture_assert_int_equal(tctx, count, num_jobs,
+ "unexpected number of jobs in queue");
+
+ torture_assert(tctx,
+ test_printer_purge(tctx, b, &t->handle),
+ "failed to purge printer");
+
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
+ &count, &info),
+ "EnumJobs level 1 failed");
+
+ torture_assert_int_equal(tctx, count, 0,
+ "unexpected number of jobs in queue");
+
+ torture_assert(tctx,
+ test_ResumePrinter(tctx, b, &t->handle),
+ "failed to resume printer");
+
+ return true;
+}
+
static bool test_printer_sd(struct torture_context *tctx,
void *private_data)
{
return true;
}
+static bool test_print_job_enum(struct torture_context *tctx,
+ void *private_data)
+{
+ struct torture_printer_context *t =
+ (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
+ struct dcerpc_pipe *p = t->spoolss_pipe;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ bool ret = true;
+ uint32_t num_jobs = 8;
+ uint32_t *job_ids;
+ int i;
+ union spoolss_JobInfo *info = NULL;
+ uint32_t count;
+
+ torture_assert(tctx,
+ test_PausePrinter(tctx, b, &t->handle),
+ "failed to pause printer");
+
+ /* purge in case of any jobs from previous tests */
+ torture_assert(tctx,
+ test_printer_purge(tctx, b, &t->handle),
+ "failed to purge printer");
+
+ /* enum before jobs, valid level */
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
+ &count, &info),
+ "EnumJobs with valid level");
+ torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
+ &count, &info),
+ "EnumJobs with valid level");
+ torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
+ /* enum before jobs, invalid level - expect failure */
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 100,
+ WERR_INVALID_LEVEL,
+ &count, &info),
+ "EnumJobs with invalid level");
+
+ job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
+
+ for (i = 0; i < num_jobs; i++) {
+ ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
+ "TorturePrintJob",
+ &job_ids[i]);
+ torture_assert(tctx, ret, "failed to add print job");
+ }
+
+ /* enum after jobs, valid level */
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
+ &count, &info),
+ "EnumJobs with valid level");
+ torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
+ &count, &info),
+ "EnumJobs with valid level");
+ torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
+ /* enum after jobs, invalid level - expect failure */
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 100,
+ WERR_INVALID_LEVEL,
+ &count, &info),
+ "EnumJobs with invalid level");
+
+ for (i = 0; i < num_jobs; i++) {
+ test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
+ SPOOLSS_JOB_CONTROL_DELETE);
+ }
+
+ torture_assert(tctx,
+ test_ResumePrinter(tctx, b, &t->handle),
+ "failed to resume printer");
+
+ return true;
+}
+
void torture_tcase_printer(struct torture_tcase *tcase)
{
torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
+ torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
torture_tcase_add_simple_test(tcase, "publish_toggle",
test_printer_publish_toggle);
+ torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
}
struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)