Copyright (C) Tim Potter 2003
Copyright (C) Stefan Metzmacher 2005
Copyright (C) Jelmer Vernooij 2007
- Copyright (C) Guenther Deschner 2009-2010
+ Copyright (C) Guenther Deschner 2009-2011,2013
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "libcli/libcli.h"
#include "libcli/raw/raw_proto.h"
#include "libcli/resolve/resolve.h"
+#include "libcli/smb2/smb2.h"
+#include "libcli/smb2/smb2_calls.h"
#include "lib/cmdline/popt_common.h"
#include "system/filesys.h"
+#include "torture/ndr/ndr.h"
+#include "torture/smb2/proto.h"
#define TORTURE_WELLKNOWN_PRINTER "torture_wkn_printer"
#define TORTURE_PRINTER "torture_printer"
#define TORTURE_PRINTER_EX "torture_printer_ex"
#define TORTURE_DRIVER "torture_driver"
#define TORTURE_DRIVER_EX "torture_driver_ex"
+#define TORTURE_DRIVER_ADOBE "torture_driver_adobe"
+#define TORTURE_DRIVER_EX_ADOBE "torture_driver_ex_adobe"
+#define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
+#define TORTURE_DRIVER_TIMESTAMPS "torture_driver_timestamps"
+#define TORTURE_DRIVER_DELETER "torture_driver_deleter"
+#define TORTURE_DRIVER_DELETERIN "torture_driver_deleterin"
+#define TORTURE_PRINTER_STATIC1 "print1"
#define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
#define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex);
+ bool ex,
+ const char *remote_driver_dir);
#define COMPARE_STRING(tctx, c,r,e) \
torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
s->info2->drivername = i->info2.drivername;
s->info2->comment = i->info2.comment;
s->info2->location = i->info2.location;
- s->info2->devmode_ptr = 0;
+ s->info2->devmode_ptr = NULL;
s->info2->sepfile = i->info2.sepfile;
s->info2->printprocessor = i->info2.printprocessor;
s->info2->datatype = i->info2.datatype;
s->info2->parameters = i->info2.parameters;
- s->info2->secdesc_ptr = 0;
+ s->info2->secdesc_ptr = NULL;
s->info2->attributes = i->info2.attributes;
s->info2->priority = i->info2.priority;
s->info2->defaultpriority = i->info2.defaultpriority;
const char *server_name,
const char *environment,
uint32_t level,
- const char *driver_name)
+ const char *driver_name,
+ union spoolss_DriverInfo *info_p)
{
uint32_t count;
union spoolss_DriverInfo *info;
int i;
+ const char *environment_ret = NULL;
torture_assert(tctx,
test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
break;
case 2:
driver_name_ret = info[i].info2.driver_name;
+ environment_ret = info[i].info2.architecture;
break;
case 3:
driver_name_ret = info[i].info3.driver_name;
+ environment_ret = info[i].info3.architecture;
break;
case 4:
driver_name_ret = info[i].info4.driver_name;
+ environment_ret = info[i].info4.architecture;
break;
case 5:
driver_name_ret = info[i].info5.driver_name;
+ environment_ret = info[i].info5.architecture;
break;
case 6:
driver_name_ret = info[i].info6.driver_name;
+ environment_ret = info[i].info6.architecture;
break;
case 7:
driver_name_ret = info[i].info7.driver_name;
break;
case 8:
driver_name_ret = info[i].info8.driver_name;
+ environment_ret = info[i].info8.architecture;
break;
default:
break;
}
+ if (environment_ret) {
+ torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
+ }
if (strequal(driver_name, driver_name_ret)) {
+ if (info_p) {
+ *info_p = info[i];
+ }
return true;
}
}
const char *environment,
uint32_t level,
uint32_t *count_p,
- union spoolss_PrintProcessorInfo **info_p)
+ union spoolss_PrintProcessorInfo **info_p,
+ WERROR expected_result)
{
struct spoolss_EnumPrintProcessors r;
DATA_BLOB blob;
r.out.count = &count;
r.out.info = &info;
- torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
+ torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
+ r.in.environment, r.in.level);
torture_assert_ntstatus_ok(tctx,
dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
"EnumPrintProcessors failed");
}
- torture_assert_werr_ok(tctx, r.out.result,
+ torture_assert_werr_equal(tctx, r.out.result, expected_result,
"EnumPrintProcessors failed");
CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
struct test_spoolss_context *ctx =
talloc_get_type_abort(private_data, struct test_spoolss_context);
- uint16_t levels[] = { 1 };
- int i, j;
+ uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
+ uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
+ int i;
struct dcerpc_pipe *p = ctx->spoolss_pipe;
struct dcerpc_binding_handle *b = p->binding_handle;
+ torture_assert(tctx,
+ test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
+ "test_EnumPrintProcessors_level failed");
+
for (i=0;i<ARRAY_SIZE(levels);i++) {
- int level = levels[i];
union spoolss_PrintProcessorInfo *info;
uint32_t count;
+ WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
torture_assert(tctx,
- test_EnumPrintProcessors_level(tctx, b, ctx->environment, level, &count, &info),
+ test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
"test_EnumPrintProcessors_level failed");
-
- ctx->print_processor_count[level] = count;
- ctx->print_processors[level] = info;
}
- for (i=1;i<ARRAY_SIZE(levels);i++) {
- int level = levels[i];
- int old_level = levels[i-1];
- torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
- "EnumPrintProcessors failed");
+ return true;
+}
+
+static bool test_EnumPrintProcDataTypes_level(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ const char *print_processor_name,
+ uint32_t level,
+ uint32_t *count_p,
+ union spoolss_PrintProcDataTypesInfo **info_p,
+ WERROR expected_result)
+{
+ struct spoolss_EnumPrintProcDataTypes r;
+ DATA_BLOB blob;
+ uint32_t needed;
+ uint32_t count;
+ union spoolss_PrintProcDataTypesInfo *info;
+
+ r.in.servername = "";
+ r.in.print_processor_name = print_processor_name;
+ r.in.level = level;
+ r.in.buffer = NULL;
+ r.in.offered = 0;
+ r.out.needed = &needed;
+ r.out.count = &count;
+ r.out.info = &info;
+
+ torture_comment(tctx, "Testing EnumPrintProcDataTypes(%s) level %u\n",
+ r.in.print_processor_name, r.in.level);
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
+ "EnumPrintProcDataTypes failed");
+ if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ blob = data_blob_talloc_zero(tctx, needed);
+ r.in.buffer = &blob;
+ r.in.offered = needed;
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r),
+ "EnumPrintProcDataTypes failed");
}
+ torture_assert_werr_equal(tctx, r.out.result, expected_result,
+ "EnumPrintProcDataTypes failed");
- for (i=0;i<ARRAY_SIZE(levels);i++) {
- int level = levels[i];
- for (j=0;j<ctx->print_processor_count[level];j++) {
-#if 0
- union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
- union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
-#endif
- switch (level) {
- case 1:
- /* level 1 is our reference, and it makes no sense to compare it to itself */
- break;
- }
- }
+ CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, level, count, needed, 4);
+
+ if (count_p) {
+ *count_p = count;
+ }
+ if (info_p) {
+ *info_p = info;
}
return true;
struct test_spoolss_context *ctx =
talloc_get_type_abort(private_data, struct test_spoolss_context);
- NTSTATUS status;
- struct spoolss_EnumPrintProcDataTypes r;
- uint16_t levels[] = { 1 };
+ uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
+ uint16_t ok[] = {0, 1, 0, 0, 0, 0 };
int i;
struct dcerpc_pipe *p = ctx->spoolss_pipe;
struct dcerpc_binding_handle *b = p->binding_handle;
+ torture_assert(tctx,
+ test_EnumPrintProcDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
+ "test_EnumPrintProcDataTypes_level failed");
+
+ torture_assert(tctx,
+ test_EnumPrintProcDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
+ "test_EnumPrintProcDataTypes_level failed");
+
for (i=0;i<ARRAY_SIZE(levels);i++) {
int level = levels[i];
- DATA_BLOB blob;
- uint32_t needed;
uint32_t count;
union spoolss_PrintProcDataTypesInfo *info;
+ WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
- r.in.servername = "";
- r.in.print_processor_name = "winprint";
- r.in.level = level;
- r.in.buffer = NULL;
- r.in.offered = 0;
- r.out.needed = &needed;
- r.out.count = &count;
- r.out.info = &info;
-
- torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
-
- status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
- torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
- if (W_ERROR_IS_OK(r.out.result)) {
- /* TODO: do some more checks here */
- continue;
- }
- torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
- "EnumPrintProcDataTypes unexpected return code");
-
- blob = data_blob_talloc_zero(tctx, needed);
- r.in.buffer = &blob;
- r.in.offered = needed;
-
- status = dcerpc_spoolss_EnumPrintProcDataTypes_r(b, tctx, &r);
- torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
+ torture_assert(tctx,
+ test_EnumPrintProcDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
+ "test_EnumPrintProcDataTypes_level failed");
+ }
- torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
+ {
+ union spoolss_PrintProcessorInfo *info;
+ uint32_t count;
- CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcDataTypes, info, r.in.level, count, needed, 4);
+ torture_assert(tctx,
+ test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
+ "test_EnumPrintProcessors_level failed");
+ for (i=0; i < count; i++) {
+ torture_assert(tctx,
+ test_EnumPrintProcDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
+ "test_EnumPrintProcDataTypes_level failed");
+ }
}
+
return true;
}
-
static bool test_EnumPrinters(struct torture_context *tctx,
void *private_data)
{
static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
{
if ((r->level == 2) && (r->info.info2)) {
- r->info.info2->secdesc_ptr = 0;
- r->info.info2->devmode_ptr = 0;
+ r->info.info2->secdesc_ptr = NULL;
+ r->info.info2->devmode_ptr = NULL;
}
}
return ret;
}
-#define torture_assert_sid_equal(torture_ctx,got,expected,cmt)\
- do { struct dom_sid *__got = (got), *__expected = (expected); \
- if (!dom_sid_equal(__got, __expected)) { \
- torture_result(torture_ctx, TORTURE_FAIL, \
- __location__": "#got" was %s, expected %s: %s", \
- dom_sid_string(torture_ctx, __got), dom_sid_string(torture_ctx, __expected), cmt); \
- return false; \
- } \
- } while(0)
-
static bool test_security_descriptor_equal(struct torture_context *tctx,
const struct security_descriptor *sd1,
const struct security_descriptor *sd2)
case 3: {
struct spoolss_SetPrinterInfo3 info3;
- info3.sec_desc_ptr = 0;
+ info3.sec_desc_ptr = NULL;
info_ctr.level = 3;
info_ctr.info.info3 = &info3;
case 8: {
struct spoolss_SetPrinterInfo8 info8;
- info8.devmode_ptr = 0;
+ info8.devmode_ptr = NULL;
info_ctr.level = 8;
info_ctr.info.info8 = &info8;
bool ret = true;
NTSTATUS status;
-#define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
+#define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
q.in.level = lvl1; \
TESTGETCALL(GetPrinter, q) \
}\
devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
devmode_ctr.devmode->field1 = value; \
- TESTSETCALL(SetPrinter, s) \
- TESTGETCALL(GetPrinter, q) \
- INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
- q.in.level = lvl2; \
- TESTGETCALL(GetPrinter, q) \
- INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
+ TESTSETCALL_EXP(SetPrinter, s, expected_result) \
+ if (W_ERROR_IS_OK(expected_result)) { \
+ TESTGETCALL(GetPrinter, q) \
+ INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
+ q.in.level = lvl2; \
+ TESTGETCALL(GetPrinter, q) \
+ INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
+ }\
} while (0)
+#define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
+ TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
+ } while (0)
+
#define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
- TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
+ TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
} while (0)
ZERO_STRUCT(devmode_ctr);
const char *devicename;/* [charset(UTF16)] */
enum spoolss_DeviceModeSpecVersion specversion;
uint16_t driverversion;
- uint16_t size;
uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
uint32_t fields;
#endif
+ TEST_DEVMODE_INT_EXP(8, size, 8, size, __LINE__, WERR_INVALID_PARAM);
+ TEST_DEVMODE_INT_EXP(8, size, 8, size, 0, WERR_INVALID_PARAM);
+ TEST_DEVMODE_INT_EXP(8, size, 8, size, 0xffff, WERR_INVALID_PARAM);
+ TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
+ TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
+
+ devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
+ torture_assert(tctx,
+ test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
+ "failed to set devmode");
+
+ TEST_DEVMODE_INT_EXP(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAM : WERR_OK);
+ TEST_DEVMODE_INT(8, size, 8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
TEST_DEVMODE_INT(8, orientation, 8, orientation, __LINE__);
TEST_DEVMODE_INT(8, papersize, 8, papersize, __LINE__);
devmode = info.info8.devmode;
+ if (devmode && devmode->size == 0) {
+ torture_fail(tctx,
+ "devmode of zero size!");
+ }
+
torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
devmode2 = info.info2.devmode;
+ if (devmode2 && devmode2->size == 0) {
+ torture_fail(tctx,
+ "devmode of zero size!");
+ }
+
torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
"DM level 8 != DM level 2");
devmode = info.info8.devmode;
+ if (devmode && devmode->size == 0) {
+ torture_fail(tctx,
+ "devmode of zero size!");
+ }
+
if (addprinter_devmode) {
if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
torture_warning(tctx, "current global DM is != DM provided in addprinter");
WERROR expected_result)
{
struct spoolss_AddForm r;
+ struct spoolss_AddFormInfoCtr info_ctr;
+
+ info_ctr.level = level;
+ info_ctr.info = *info;
if (level != 1) {
torture_skip(tctx, "only level 1 supported");
}
r.in.handle = handle;
- r.in.level = level;
- r.in.info = *info;
+ r.in.info_ctr = &info_ctr;
torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
- r.in.info.info1->form_name, r.in.level,
- r.in.info.info1->flags);
+ r.in.info_ctr->info.info1->form_name, level,
+ r.in.info_ctr->info.info1->flags);
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
"AddForm failed");
union spoolss_AddFormInfo *info)
{
struct spoolss_SetForm r;
+ struct spoolss_AddFormInfoCtr info_ctr;
+
+ info_ctr.level = level;
+ info_ctr.info = *info;
r.in.handle = handle;
r.in.form_name = form_name;
- r.in.level = level;
- r.in.info = *info;
+ r.in.info_ctr = &info_ctr;
torture_comment(tctx, "Testing SetForm(%s) level %d\n",
- form_name, r.in.level);
+ form_name, level);
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
"SetForm failed");
if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
+ struct spoolss_FormInfo1 i1;
+
torture_assert(tctx,
test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
"failed to get form via winreg");
+ i1.size.width = IVAL(w_data, 0);
+ i1.size.height = IVAL(w_data, 4);
+ i1.area.left = IVAL(w_data, 8);
+ i1.area.top = IVAL(w_data, 12);
+ i1.area.right = IVAL(w_data, 16);
+ i1.area.bottom = IVAL(w_data, 20);
+ /* skip index here */
+ i1.flags = IVAL(w_data, 28);
+
torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
- torture_assert_mem_equal(tctx, &w_data[0], &add_info.info1->size.width, 4, "width mismatch");
- torture_assert_mem_equal(tctx, &w_data[4], &add_info.info1->size.height, 4, "height mismatch");
- torture_assert_mem_equal(tctx, &w_data[8], &add_info.info1->area.left, 4, "left mismatch");
- torture_assert_mem_equal(tctx, &w_data[12], &add_info.info1->area.top, 4, "top mismatch");
- torture_assert_mem_equal(tctx, &w_data[16], &add_info.info1->area.right, 4, "right mismatch");
- torture_assert_mem_equal(tctx, &w_data[20], &add_info.info1->area.bottom, 4, "bottom mismatch");
- /* skip index here */
- torture_assert_mem_equal(tctx, &w_data[28], &add_info.info1->flags, 4, "flags mismatch");
+ torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
+ torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
+ torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
+ torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
+ torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
+ torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
+ torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
}
if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
if (winreg_handle && hive_handle) {
- torture_assert_mem_equal(tctx, &w_data[0], &info.info1.size.width, 4, "width mismatch");
- torture_assert_mem_equal(tctx, &w_data[4], &info.info1.size.height, 4, "height mismatch");
- torture_assert_mem_equal(tctx, &w_data[8], &info.info1.area.left, 4, "left mismatch");
- torture_assert_mem_equal(tctx, &w_data[12], &info.info1.area.top, 4, "top mismatch");
- torture_assert_mem_equal(tctx, &w_data[16], &info.info1.area.right, 4, "right mismatch");
- torture_assert_mem_equal(tctx, &w_data[20], &info.info1.area.bottom, 4, "bottom mismatch");
+
+ struct spoolss_FormInfo1 i1;
+
+ i1.size.width = IVAL(w_data, 0);
+ i1.size.height = IVAL(w_data, 4);
+ i1.area.left = IVAL(w_data, 8);
+ i1.area.top = IVAL(w_data, 12);
+ i1.area.right = IVAL(w_data, 16);
+ i1.area.bottom = IVAL(w_data, 20);
/* skip index here */
- torture_assert_mem_equal(tctx, &w_data[28], &info.info1.flags, 4, "flags mismatch");
+ i1.flags = IVAL(w_data, 28);
+
+ torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
+ torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
+ torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
+ torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
+ torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
+ torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
+ torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
}
add_info.info1->size.width = 1234;
static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
+ const char *document_name,
uint32_t *job_id)
{
NTSTATUS status;
struct spoolss_StartDocPrinter s;
+ struct spoolss_DocumentInfoCtr info_ctr;
struct spoolss_DocumentInfo1 info1;
struct spoolss_StartPagePrinter sp;
struct spoolss_WritePrinter w;
torture_comment(tctx, "Testing StartDocPrinter\n");
s.in.handle = handle;
- s.in.level = 1;
- s.in.info.info1 = &info1;
+ s.in.info_ctr = &info_ctr;
s.out.job_id = job_id;
- info1.document_name = "TorturePrintJob";
+
+ info1.document_name = document_name;
info1.output_file = NULL;
info1.datatype = "RAW";
+ info_ctr.level = 1;
+ info_ctr.info.info1 = &info1;
+
status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
if (strequal(ginfo.info1.document_name, document_name)) {
torture_warning(tctx,
- talloc_asprintf(tctx, "document_name did *NOT* change from '%s' to '%s'\n",
- document_name, new_document_name));
+ "document_name did *NOT* change from '%s' to '%s'\n",
+ document_name, new_document_name);
}
}
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, handle, &job_ids[i]);
+ ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
}
for (i=0; i < num_jobs; i++) {
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, handle, &job_ids[i]);
+ ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
}
ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
return true;
}
-static bool test_GetPrinterData(struct torture_context *tctx,
- struct dcerpc_binding_handle *b,
- struct policy_handle *handle,
- const char *value_name,
- enum winreg_Type *type_p,
- uint8_t **data_p,
- uint32_t *needed_p)
+static bool test_GetPrinterData_checktype(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ struct policy_handle *handle,
+ const char *value_name,
+ enum winreg_Type *expected_type,
+ enum winreg_Type *type_p,
+ uint8_t **data_p,
+ uint32_t *needed_p)
{
NTSTATUS status;
struct spoolss_GetPrinterData r;
torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
+ if (expected_type) {
+ torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
+ }
r.in.offered = needed;
r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
return true;
}
-static bool test_GetPrinterDataEx(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- struct policy_handle *handle,
- const char *key_name,
- const char *value_name,
- enum winreg_Type *type_p,
- uint8_t **data_p,
- uint32_t *needed_p)
+static bool test_GetPrinterData(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ struct policy_handle *handle,
+ const char *value_name,
+ enum winreg_Type *type_p,
+ uint8_t **data_p,
+ uint32_t *needed_p)
+{
+ return test_GetPrinterData_checktype(tctx, b, handle, value_name,
+ NULL, type_p, data_p, needed_p);
+}
+
+static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct policy_handle *handle,
+ const char *key_name,
+ const char *value_name,
+ enum winreg_Type *expected_type,
+ enum winreg_Type *type_p,
+ uint8_t **data_p,
+ uint32_t *needed_p)
{
NTSTATUS status;
struct spoolss_GetPrinterDataEx r;
}
if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
+ if (expected_type) {
+ torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
+ }
r.in.offered = needed;
r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
return true;
}
+static bool test_GetPrinterDataEx(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct policy_handle *handle,
+ const char *key_name,
+ const char *value_name,
+ enum winreg_Type *type_p,
+ uint8_t **data_p,
+ uint32_t *needed_p)
+{
+ return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
+ NULL, type_p, data_p, needed_p);
+}
+
static bool test_get_environment(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
} while(0);
+#define test_binary(wname, iname) \
+do {\
+ enum winreg_Type w_type;\
+ uint32_t w_size;\
+ uint32_t w_length;\
+ uint8_t *w_data;\
+ torture_assert(tctx,\
+ test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
+ &w_type, &w_size, &w_length, &w_data),\
+ "failed to query winreg");\
+ torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
+ torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
+ torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
+ "binary unequal");\
+} while(0);
+
+
#define test_dm(wname, iname) \
do {\
DATA_BLOB blob;\
}\
} while(0);
-
if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
TOP_LEVEL_CONTROL_PRINTERS_KEY,
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
torture_warning(tctx, "failed to check for winreg symlink");
}
-
for (i=0; i < ARRAY_SIZE(keys); i++) {
const char *printer_key;
torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
torture_assert(tctx,
- test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info),
+ test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
"failed to enum print processors level 1");
for (i=0; i < count; i++) {
{
time_t t;
struct tm *tm;
+
+ if (nt == 0) {
+ return talloc_strdup(mem_ctx, "01/01/1601");
+ }
+
t = nt_time_to_unix(nt);
tm = localtime(&t);
const char *printer_name,
const char *driver_name,
const char *environment,
+ enum spoolss_DriverOSVersion version,
struct dcerpc_binding_handle *winreg_handle,
- struct policy_handle *hive_handle)
+ struct policy_handle *hive_handle,
+ const char *server_name_slash)
{
WERROR result;
union spoolss_DriverInfo info;
driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
environment,
- 3,
+ version,
driver_name);
torture_assert(tctx,
test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
"failed to open driver key");
- if (torture_setting_bool(tctx, "samba3", false)) {
- goto try_level3;
+ if (torture_setting_bool(tctx, "samba3", false) ||
+ torture_setting_bool(tctx, "w2k3", false)) {
+ goto try_level6;
}
- torture_assert(tctx,
- test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, 3, 0, &info, &result),
- "failed to get driver info level 8");
+ if (handle) {
+ torture_assert(tctx,
+ test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
+ "failed to get driver info level 8");
+ } else {
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
+ "failed to get driver info level 8");
+ }
if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
goto try_level6;
try_level6:
- torture_assert(tctx,
- test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, 3, 0, &info, &result),
- "failed to get driver info level 6");
+ if (handle) {
+ torture_assert(tctx,
+ test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
+ "failed to get driver info level 6");
+ } else {
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
+ "failed to get driver info level 6");
+ }
driver_path = strip_path(info.info6.driver_path);
data_file = strip_path(info.info6.data_file);
test_sz("Data File", data_file);
test_sz("Datatype", info.info6.default_datatype);
test_sz("Driver", driver_path);
- test_sz("DriverDate", driver_date);
- test_sz("DriverVersion", driver_version);
+ if (torture_setting_bool(tctx, "w2k3", false)) {
+ DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
+ push_nttime(blob.data, 0, info.info6.driver_date);
+ test_binary("DriverDate", blob);
+ SBVAL(blob.data, 0, info.info6.driver_version);
+ test_binary("DriverVersion", blob);
+ } else {
+ test_sz("DriverDate", driver_date);
+ test_sz("DriverVersion", driver_version);
+ }
test_sz("HardwareID", info.info6.hardware_id);
test_sz("Help File", help_file);
test_sz("Manufacturer", info.info6.manufacturer_name);
test_dword("Version", info.info6.version);
/* test_dword("TempDir", ?); */
- try_level3:
-
- torture_assert(tctx,
- test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, 3, 0, &info, &result),
- "failed to get driver info level 3");
+ if (handle) {
+ torture_assert(tctx,
+ test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
+ "failed to get driver info level 3");
+ } else {
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
+ "failed to get driver info level 3");
+ }
driver_path = strip_path(info.info3.driver_path);
data_file = strip_path(info.info3.data_file);
for (i=0; i < ARRAY_SIZE(values); i++) {
- enum winreg_Type type;
+ enum winreg_Type type, expected_type = REG_SZ;
DATA_BLOB blob;
uint8_t *data;
uint32_t needed;
"SetPrinterData failed");
torture_assert(tctx,
- test_GetPrinterData(tctx, b, handle, values[i], &type, &data, &needed),
+ test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
"GetPrinterData failed");
torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
struct spoolss_PrinterEnumValues *einfo;
uint32_t needed;
- if (torture_setting_bool(tctx, "samba3", false)) {
- char *q;
- q = strrchr(keys[i], '\\');
- if (q) {
- torture_comment(tctx, "skipping keyname '%s' including '\\' character against Samba3\n",
- keys[i]);
- continue;
- }
- }
-
blob_in = data_blob_talloc(tctx, NULL, 42);
generate_random_buffer(blob_in.data, blob_in.length);
s = 0xffff;
}
- if (torture_setting_bool(tctx, "samba3", false)) {
- if ((types[t] == REG_MULTI_SZ) && s == 0) {
- torture_warning(tctx, "samba3 does not handle 4 byte emtpy REG_MULTI_SZ buffers");
- continue;
- }
- }
-
switch (types[t]) {
case REG_BINARY:
data = blob;
"failed to call SetPrinterDataEx");
torture_assert(tctx,
- test_GetPrinterDataEx(tctx, p, handle, key_name, value_name, &type, &data_out, &needed),
+ test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
"failed to call GetPrinterDataEx");
torture_assert(tctx,
struct policy_handle *handle,
const char *printer_name,
const char *driver_name,
- const char *environment)
+ const char *environment,
+ enum spoolss_DriverOSVersion version)
{
struct dcerpc_binding_handle *b = p->binding_handle;
struct dcerpc_pipe *p2;
torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
- ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, b2, &hive_handle);
+ ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
test_winreg_CloseKey(tctx, b2, &hive_handle);
TEST_SET_SZ("description", comment, "newval");
TEST_SET_SZ("location", location, "newval");
+ TEST_SET_SZ("driverName", drivername, "newval");
/* TEST_SET_DWORD("priority", priority, 25); */
torture_assert(tctx,
"failed to query Printer level 2");
TEST_SZ("description", info.info2.comment);
-/* TEST_SZ("driverName", info.info2.drivername); */
+ TEST_SZ("driverName", info.info2.drivername);
TEST_SZ("location", info.info2.location);
pname = strrchr(info.info2.printername, '\\');
} else {
pname++;
}
-/* TEST_SZ("printerName", pname); */
+ TEST_SZ("printerName", pname);
/* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
/* TEST_SZ("printShareName", info.info2.sharename); */
opEx.in.datatype = NULL;
opEx.in.devmode_ctr.devmode = NULL;
opEx.in.access_mask = 0;
- opEx.in.level = 1;
- opEx.in.userlevel.level1 = NULL;
+ opEx.in.userlevel_ctr.level = 1;
+ opEx.in.userlevel_ctr.user_info.level1 = NULL;
opEx.out.handle = &handle;
torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
static bool test_OpenPrinter(struct torture_context *tctx,
struct dcerpc_pipe *p,
const char *name,
- const char *environment)
+ const char *environment,
+ bool open_only)
{
NTSTATUS status;
struct spoolss_OpenPrinter r;
bool ret = true;
struct dcerpc_binding_handle *b = p->binding_handle;
- r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
+ r.in.printername = name;
r.in.datatype = NULL;
r.in.devmode_ctr.devmode= NULL;
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
+ if (open_only) {
+ goto close_printer;
+ }
+
if (!test_GetPrinter(tctx, b, &handle, environment)) {
ret = false;
}
}
}
+ close_printer:
if (!test_ClosePrinter(tctx, b, &handle)) {
ret = false;
}
return ret;
}
+static bool test_OpenPrinterEx(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ const char *printername,
+ const char *datatype,
+ struct spoolss_DeviceMode *devmode,
+ uint32_t access_mask,
+ struct spoolss_UserLevelCtr *userlevel_ctr,
+ struct policy_handle *handle,
+ WERROR expected_result)
+{
+ struct spoolss_OpenPrinterEx r;
+
+ r.in.printername = printername;
+ r.in.datatype = datatype;
+ r.in.devmode_ctr.devmode= devmode;
+ r.in.access_mask = access_mask;
+ r.in.userlevel_ctr = *userlevel_ctr;
+ r.out.handle = handle;
+
+ torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
+ "OpenPrinterEx failed");
+
+ torture_assert_werr_equal(tctx, r.out.result, expected_result,
+ "OpenPrinterEx failed");
+
+ return true;
+}
+
static bool call_OpenPrinterEx(struct torture_context *tctx,
struct dcerpc_pipe *p,
const char *name,
struct spoolss_DeviceMode *devmode,
struct policy_handle *handle)
{
- struct spoolss_OpenPrinterEx r;
+ struct spoolss_UserLevelCtr userlevel_ctr;
struct spoolss_UserLevel1 userlevel1;
- NTSTATUS status;
struct dcerpc_binding_handle *b = p->binding_handle;
- if (name && name[0]) {
- r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
- dcerpc_server_name(p), name);
- } else {
- r.in.printername = talloc_asprintf(tctx, "\\\\%s",
- dcerpc_server_name(p));
- }
-
- r.in.datatype = NULL;
- r.in.devmode_ctr.devmode= devmode;
- r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- r.in.level = 1;
- r.in.userlevel.level1 = &userlevel1;
- r.out.handle = handle;
-
userlevel1.size = 1234;
userlevel1.client = "hello";
userlevel1.user = "spottyfoot!";
userlevel1.minor = 3;
userlevel1.processor = 4;
- torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
-
- status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r);
-
- torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
+ userlevel_ctr.level = 1;
+ userlevel_ctr.user_info.level1 = &userlevel1;
- torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
-
- return true;
-}
+ return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
+ SEC_FLAG_MAXIMUM_ALLOWED,
+ &userlevel_ctr,
+ handle,
+ WERR_OK);
+}
static bool test_printer_rename(struct torture_context *tctx,
void *private_data)
test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
"failed to call GetPrinter level 2");
- /* FIXME: we openend with servername! */
- printer_name = talloc_asprintf(tctx, "\\\\%s\\%s",
- dcerpc_server_name(p), printer_name_new);
-
- torture_assert_str_equal(tctx, info.info2.printername, printer_name,
+ torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
"new printer name was not set");
torture_assert(tctx,
return ret;
}
+static bool test_openprinter(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ const char *real_printername)
+{
+ struct spoolss_UserLevelCtr userlevel_ctr;
+ struct policy_handle handle;
+ struct spoolss_UserLevel1 userlevel1;
+ const char *printername = NULL;
+ int i;
-static bool test_OpenPrinterEx(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- const char *name,
- const char *environment)
+ struct {
+ const char *suffix;
+ WERROR expected_result;
+ } tests[] = {
+ {
+ .suffix = "rubbish",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", LocalOnl",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", localOnly",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", localonl",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ",LocalOnl",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ",localOnl2",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", DrvConver2t",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", drvconvert",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ",drvconvert",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ", DrvConvert",
+ .expected_result = WERR_OK
+ },{
+ .suffix = " , DrvConvert",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ",DrvConvert",
+ .expected_result = WERR_OK
+ },{
+ .suffix = ", DrvConvertsadfasdf",
+ .expected_result = WERR_OK
+ },{
+ .suffix = ",DrvConvertasdfasd",
+ .expected_result = WERR_OK
+ },{
+ .suffix = ", LocalOnly",
+ .expected_result = WERR_OK
+ },{
+ .suffix = " , LocalOnly",
+ .expected_result = WERR_INVALID_PRINTER_NAME
+ },{
+ .suffix = ",LocalOnly",
+ .expected_result = WERR_OK
+ },{
+ .suffix = ", LocalOnlysagi4gjfkd",
+ .expected_result = WERR_OK
+ },{
+ .suffix = ",LocalOnlysagi4gjfkd",
+ .expected_result = WERR_OK
+ }
+ };
+
+ userlevel1.size = 1234;
+ userlevel1.client = "hello";
+ userlevel1.user = "spottyfoot!";
+ userlevel1.build = 1;
+ userlevel1.major = 2;
+ userlevel1.minor = 3;
+ userlevel1.processor = 4;
+
+ userlevel_ctr.level = 1;
+ userlevel_ctr.user_info.level1 = &userlevel1;
+
+ torture_comment(tctx, "Testing openprinterex printername pattern\n");
+
+ torture_assert(tctx,
+ test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
+ &userlevel_ctr, &handle,
+ WERR_OK),
+ "OpenPrinterEx failed");
+ test_ClosePrinter(tctx, b, &handle);
+
+ for (i=0; i < ARRAY_SIZE(tests); i++) {
+
+ printername = talloc_asprintf(tctx, "%s%s",
+ real_printername,
+ tests[i].suffix);
+
+ torture_assert(tctx,
+ test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
+ &userlevel_ctr, &handle,
+ tests[i].expected_result),
+ "OpenPrinterEx failed");
+ if (W_ERROR_IS_OK(tests[i].expected_result)) {
+ test_ClosePrinter(tctx, b, &handle);
+ }
+ }
+
+ return true;
+}
+
+
+static bool test_existing_printer_openprinterex(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ const char *name,
+ const char *environment)
{
struct policy_handle handle;
bool ret = true;
struct dcerpc_binding_handle *b = p->binding_handle;
+ if (!test_openprinter(tctx, b, name)) {
+ return false;
+ }
+
if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
return false;
}
for (j=0;j<count;j++) {
if (r.in.level == 1) {
char *unc = talloc_strdup(tctx, info[j].info1.name);
- char *slash, *name;
+ char *slash, *name, *full_name;
name = unc;
if (unc[0] == '\\' && unc[1] == '\\') {
unc +=2;
slash++;
name = slash;
}
- if (!test_OpenPrinter(tctx, p, name, ctx->environment)) {
+ full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
+ dcerpc_server_name(p), name);
+ if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
+ ret = false;
+ }
+ if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
ret = false;
}
- if (!test_OpenPrinterEx(tctx, p, name, ctx->environment)) {
+ if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
+ ret = false;
+ }
+ if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
ret = false;
}
}
return ret;
}
+static bool test_EnumPrinters_level(struct torture_context *tctx,
+ struct dcerpc_binding_handle *b,
+ uint32_t flags,
+ const char *servername,
+ uint32_t level,
+ uint32_t *count_p,
+ union spoolss_PrinterInfo **info_p)
+{
+ struct spoolss_EnumPrinters r;
+ union spoolss_PrinterInfo *info;
+ uint32_t needed;
+ uint32_t count;
+
+ r.in.flags = flags;
+ r.in.server = servername;
+ r.in.level = level;
+ r.in.buffer = NULL;
+ r.in.offered = 0;
+ r.out.needed = &needed;
+ r.out.count = &count;
+ r.out.info = &info;
+
+ torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
+ r.in.server, r.in.level);
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
+ "EnumPrinters failed");
+ if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
+ r.in.buffer = &blob;
+ r.in.offered = needed;
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
+ "EnumPrinters failed");
+ }
+
+ torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
+
+ CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
+
+ if (count_p) {
+ *count_p = count;
+ }
+ if (info_p) {
+ *info_p = info;
+ }
+
+ return true;
+}
+
+static const char *get_short_printername(struct torture_context *tctx,
+ const char *name)
+{
+ const char *short_name;
+
+ if (name[0] == '\\' && name[1] == '\\') {
+ name += 2;
+ short_name = strchr(name, '\\');
+ if (short_name) {
+ return talloc_strdup(tctx, short_name+1);
+ }
+ }
+
+ return name;
+}
+
+static const char *get_full_printername(struct torture_context *tctx,
+ const char *name)
+{
+ const char *full_name = talloc_strdup(tctx, name);
+ char *p;
+
+ if (name && name[0] == '\\' && name[1] == '\\') {
+ name += 2;
+ p = strchr(name, '\\');
+ if (p) {
+ return full_name;
+ }
+ }
+
+ return NULL;
+}
+
+static bool test_OnePrinter_servername(struct torture_context *tctx,
+ struct dcerpc_pipe *p,
+ struct dcerpc_binding_handle *b,
+ const char *servername,
+ const char *printername)
+{
+ union spoolss_PrinterInfo info;
+ const char *short_name = get_short_printername(tctx, printername);
+ const char *full_name = get_full_printername(tctx, printername);
+
+ if (short_name) {
+ struct policy_handle handle;
+ torture_assert(tctx,
+ call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
+ "failed to open printer");
+
+ torture_assert(tctx,
+ test_GetPrinter_level(tctx, b, &handle, 2, &info),
+ "failed to get printer info");
+
+ torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
+ "unexpected servername");
+ torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
+ "unexpected printername");
+
+ if (info.info2.devmode) {
+ const char *expected_devicename;
+ expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
+ torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
+ "unexpected devicemode devicename");
+ }
+
+ torture_assert(tctx,
+ test_ClosePrinter(tctx, b, &handle),
+ "failed to close printer");
+ }
+
+ if (full_name) {
+ struct policy_handle handle;
+
+ torture_assert(tctx,
+ call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
+ "failed to open printer");
+
+ torture_assert(tctx,
+ test_GetPrinter_level(tctx, b, &handle, 2, &info),
+ "failed to get printer info");
+
+ torture_assert_casestr_equal(tctx, info.info2.servername, servername,
+ "unexpected servername");
+ torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
+ "unexpected printername");
+
+ if (info.info2.devmode) {
+ const char *expected_devicename;
+ expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
+ torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
+ "unexpected devicemode devicename");
+ }
+
+ torture_assert(tctx,
+ test_ClosePrinter(tctx, b, &handle),
+ "failed to close printer");
+ }
+
+ return true;
+}
+
+static bool test_EnumPrinters_servername(struct torture_context *tctx,
+ void *private_data)
+{
+ struct test_spoolss_context *ctx =
+ talloc_get_type_abort(private_data, struct test_spoolss_context);
+ int i;
+ struct dcerpc_pipe *p = ctx->spoolss_pipe;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ uint32_t count;
+ union spoolss_PrinterInfo *info;
+ const char *servername;
+ uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
+
+ torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
+
+ servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+
+ torture_assert(tctx,
+ test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
+ "failed to enumerate printers");
+
+ for (i=0; i < count; i++) {
+
+ torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
+ "unexpected servername");
+
+ torture_assert(tctx,
+ test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
+ "failed to check printer");
+ }
+
+ servername = "";
+
+ torture_assert(tctx,
+ test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
+ "failed to enumerate printers");
+
+ for (i=0; i < count; i++) {
+
+ torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
+ "unexpected servername");
+
+ torture_assert(tctx,
+ test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
+ "failed to check printer");
+ }
+
+
+ return true;
+}
+
+
static bool test_GetPrinterDriver(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
struct policy_handle *handle,
return true;
}
+static bool test_openprinter_wrap(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;
+ const char *printername = t->info2.printername;
+
+ return test_openprinter(tctx, b, printername);
+}
+
static bool test_csetprinter(struct torture_context *tctx,
void *private_data)
{
r.in.datatype = NULL;
r.in.devmode_ctr.devmode= NULL;
r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
- r.in.level = 1;
- r.in.userlevel.level1 = &u1;
+ r.in.userlevel_ctr.level = 1;
+ r.in.userlevel_ctr.user_info.level1 = &u1;
r.out.handle = &handle;
torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
&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)) {
+ if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
t->info2.drivername, t->driver.remote.environment);
t->have_driver = true;
"failed to upload printer driver");
torture_assert(tctx,
- test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false),
+ test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
"failed to add driver");
t->added_driver = true;
t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
t->devmode = NULL;
- if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
- torture_skip(tctx, "skipping AddPrinter level 1 against samba");
+ /* FIXME */
+ if (t->wellknown) {
+ torture_skip(tctx, "skipping AddPrinter level 1");
}
return torture_rpc_spoolss_printer_setup_common(tctx, t);
t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
t->devmode = NULL;
- if (t->wellknown && torture_setting_bool(tctx, "samba3", false)) {
- torture_skip(tctx, "skipping AddPrinter level 1 against samba");
+ /* FIXME */
+ if (t->wellknown) {
+ torture_skip(tctx, "skipping AddPrinterEx level 1");
}
return torture_rpc_spoolss_printer_setup_common(tctx, t);
"failed to remove printer driver");
}
- if (p) {
+ if (p && !t->wellknown) {
b = p->binding_handle;
- }
- if (!t->wellknown) {
torture_assert(tctx,
test_DeletePrinter(tctx, b, &t->handle),
"failed to delete printer");
return ret;
}
+/* use smbd file IO to spool a print job */
+static bool test_print_test_smbd(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;
+ NTSTATUS status;
+ uint32_t count;
+ union spoolss_JobInfo *info = NULL;
+ int i;
+
+ struct smb2_tree *tree;
+ struct smb2_handle job_h;
+ struct cli_credentials *credentials = cmdline_credentials;
+ struct smbcli_options options;
+ TALLOC_CTX *mem_ctx = talloc_new(tctx);
+ /*
+ * Do not test against the dynamically added printers, printing via
+ * smbd means that a different spoolss process may handle the
+ * OpenPrinter request to the one that handled the AddPrinter request.
+ * This currently leads to an ugly race condition where one process
+ * sees the new printer and one doesn't.
+ */
+ const char *share = TORTURE_PRINTER_STATIC1;
+
+ torture_comment(tctx, "Testing smbd job spooling\n");
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+
+ status = smb2_connect_ext(mem_ctx,
+ torture_setting_string(tctx, "host", NULL),
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share,
+ lpcfg_resolve_context(tctx->lp_ctx),
+ credentials,
+ 0,
+ &tree,
+ tctx->ev,
+ &options,
+ lpcfg_socket_options(tctx->lp_ctx),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("Failed to connect to SMB2 printer %s - %s\n",
+ share, nt_errstr(status));
+ return false;
+ }
+
+ status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
+ torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
+
+ status = smb2_util_write(tree, job_h, "exciting print job data", 0,
+ sizeof("exciting print job data"));
+ torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
+
+ /* check back end spoolss job was created */
+ torture_assert(tctx,
+ test_EnumJobs_args(tctx, b, &t->handle, 1, &count, &info),
+ "EnumJobs level 1 failed");
+
+ for (i = 0; i < count; i++) {
+ if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
+ break;
+ }
+ }
+ torture_assert(tctx, (i != count), "smbd_spooler_job not found");
+
+ status = smb2_util_close(tree, job_h);
+ torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
+
+ /* disconnect from printer share */
+ talloc_free(mem_ctx);
+
+ return true;
+}
+
static bool test_printer_sd(struct torture_context *tctx,
void *private_data)
{
return true;
}
-static bool test_driver_info_winreg(struct torture_context *tctx,
- void *private_data)
+static bool test_printer_ic(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);
+ talloc_get_type_abort(private_data,
+ struct torture_printer_context);
struct dcerpc_pipe *p = t->spoolss_pipe;
- const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ struct policy_handle gdi_handle;
- if (!t->have_driver) {
- torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
+ if (torture_setting_bool(tctx, "samba3", false)) {
+ torture_skip(tctx, "skip printer information context tests against samba");
}
- torture_assert(tctx,
- test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment),
- "failed to test driver info winreg");
+ {
+ struct spoolss_CreatePrinterIC r;
+ struct spoolss_DevmodeContainer devmode_ctr;
- return true;
-}
+ ZERO_STRUCT(devmode_ctr);
-void torture_tcase_printer(struct torture_tcase *tcase)
-{
- torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
- torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
- torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
- 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, "printer_info_winreg", test_printer_info_winreg);
- torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
- torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
- torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
- torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
- torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
- torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
- torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
- torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
- torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
- torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
-}
+ r.in.handle = &t->handle;
+ r.in.devmode_ctr = &devmode_ctr;
+ r.out.gdi_handle = &gdi_handle;
-struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
-{
- struct torture_suite *suite = torture_suite_create(mem_ctx, "PRINTER");
- struct torture_tcase *tcase;
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
+ "CreatePrinterIC failed");
+ torture_assert_werr_ok(tctx, r.out.result,
+ "CreatePrinterIC failed");
+ }
- tcase = torture_suite_add_tcase(suite, "addprinter");
+ {
+ struct spoolss_PlayGDIScriptOnPrinterIC r;
+ DATA_BLOB in,out;
+ int i;
+ uint32_t num_fonts = 0;
+
+ in = data_blob_string_const("");
+
+ r.in.gdi_handle = &gdi_handle;
+ r.in.pIn = in.data;
+ r.in.cIn = in.length;
+ r.in.ul = 0;
+
+ for (i = 0; i < 4; i++) {
+
+ out = data_blob_talloc_zero(tctx, i);
+
+ r.in.cOut = out.length;
+ r.out.pOut = out.data;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
+ "PlayGDIScriptOnPrinterIC failed");
+ torture_assert_werr_equal(tctx, r.out.result, WERR_NOMEM,
+ "PlayGDIScriptOnPrinterIC failed");
+ }
+
+ out = data_blob_talloc_zero(tctx, 4);
+
+ r.in.cOut = out.length;
+ r.out.pOut = out.data;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
+ "PlayGDIScriptOnPrinterIC failed");
+ torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
+ "PlayGDIScriptOnPrinterIC failed");
+
+ /* now we should have the required length, so retry with a
+ * buffer which is large enough to carry all font ids */
+
+ num_fonts = IVAL(r.out.pOut, 0);
+
+ torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
+
+ out = data_blob_talloc_zero(tctx,
+ num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
+
+ r.in.cOut = out.length;
+ r.out.pOut = out.data;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
+ "PlayGDIScriptOnPrinterIC failed");
+ torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
+ "PlayGDIScriptOnPrinterIC failed");
+
+ }
+
+ {
+ struct spoolss_DeletePrinterIC r;
+
+ r.in.gdi_handle = &gdi_handle;
+ r.out.gdi_handle = &gdi_handle;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
+ "DeletePrinterIC failed");
+ torture_assert_werr_ok(tctx, r.out.result,
+ "DeletePrinterIC failed");
+
+ }
+
+ return true;
+}
+
+
+static bool test_driver_info_winreg(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;
+ const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
+
+ if (!t->have_driver) {
+ torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
+ }
+
+ torture_assert(tctx,
+ test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
+ "failed to test driver info winreg");
+
+ 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, "csetprinter", test_csetprinter);
+ torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
+ 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, "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, "printer_info_winreg", test_printer_info_winreg);
+ torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
+ torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
+ torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
+ torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
+ torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
+ torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
+ torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
+ torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
+ torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
+ torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
+ torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
+}
+
+struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
+ struct torture_tcase *tcase;
+
+ tcase = torture_suite_add_tcase(suite, "addprinter");
torture_tcase_set_fixture(tcase,
torture_rpc_spoolss_printer_setup,
struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
{
- struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS");
- struct torture_tcase *tcase = torture_suite_add_tcase(suite, "PRINTSERVER");
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
+ struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
torture_tcase_set_fixture(tcase,
torture_rpc_spoolss_setup,
torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
+ torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
return true;
}
+#define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
+ if (path && strlen(path)) {\
+ torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
+ }
+
static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
struct spoolss_AddDriverInfo1 info1;
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
struct spoolss_AddDriverInfo2 info2;
+ union spoolss_DriverInfo info;
ZERO_STRUCT(info2);
}
torture_assert(tctx,
- test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name),
+ test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
"failed to find added printer driver");
+ if (remote_driver_dir) {
+ ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
+ }
+
return true;
}
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
struct spoolss_AddDriverInfo3 info3;
+ union spoolss_DriverInfo info;
info3.driver_name = r->driver_name;
info3.version = r->version;
}
torture_assert(tctx,
- test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name),
+ test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
"failed to find added printer driver");
+ if (remote_driver_dir) {
+ int i;
+ ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
+ for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
+ ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
+ }
+ }
+
return true;
}
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
struct spoolss_AddDriverInfo4 info4;
+ union spoolss_DriverInfo info;
info4.version = r->version;
info4.driver_name = r->driver_name;
}
torture_assert(tctx,
- test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name),
+ test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
"failed to find added printer driver");
+ if (remote_driver_dir) {
+ int i;
+ ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
+ for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
+ ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
+ }
+ }
+
return true;
}
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
struct spoolss_AddDriverInfo6 info6;
+ union spoolss_DriverInfo info;
info6.version = r->version;
info6.driver_name = r->driver_name;
}
torture_assert(tctx,
- test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name),
+ test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
"failed to find added printer driver");
+ if (remote_driver_dir) {
+ int i;
+ ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
+ for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
+ ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
+ }
+ }
+
+ torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
+ torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
+
return true;
}
const char *server_name,
struct spoolss_AddDriverInfo8 *r,
uint32_t flags,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
struct spoolss_AddDriverInfoCtr info_ctr;
+ union spoolss_DriverInfo info;
info_ctr.level = 8;
info_ctr.info.info8 = r;
}
torture_assert(tctx,
- test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name),
+ test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
"failed to find added printer driver");
+ if (remote_driver_dir) {
+ int i;
+ ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
+ ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
+ for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
+ ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
+ }
+ }
+
+ torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
+ torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
+
return true;
}
+#undef ASSERT_DRIVER_PATH
+
static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
struct dcerpc_binding_handle *b,
const char *server,
test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
"failed to delete driver");
- if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
+ if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
torture_fail(tctx, "deleted driver still enumerated");
}
test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
"failed to delete driver");
- if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver)) {
+ if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
torture_fail(tctx, "deleted driver still enumerated");
}
uint32_t add_flags,
uint32_t delete_flags,
uint32_t delete_version,
- bool ex)
+ bool ex,
+ const char *remote_driver_dir)
{
bool ret = true;
switch (level) {
case 1:
- ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
case 2:
- ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
case 3:
- ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
case 4:
- ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
case 6:
- ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
case 8:
- ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex);
+ ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
break;
default:
return false;
return ret;
}
+ {
+ struct dcerpc_pipe *p2;
+ struct policy_handle hive_handle;
+ struct dcerpc_binding_handle *b2;
+
+ torture_assert_ntstatus_ok(tctx,
+ torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
+ "could not open winreg pipe");
+ b2 = p2->binding_handle;
+
+ torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
+
+ ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
+
+ test_winreg_CloseKey(tctx, b2, &hive_handle);
+
+ talloc_free(p2);
+ }
+
if (ex) {
return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
} else {
const char *local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, file_name);
const char *remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
- if (!file_name) {
+ if (!file_name || strlen(file_name) == 0) {
return true;
}
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);
+ lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
+ lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
torture_assert_ntstatus_ok(tctx,
smbcli_full_connection(tctx, cli, server_name,
- lp_smb_ports(tctx->lp_ctx),
+ lpcfg_smb_ports(tctx->lp_ctx),
share_name, NULL,
- lp_socket_options(tctx->lp_ctx),
+ lpcfg_socket_options(tctx->lp_ctx),
cmdline_credentials,
- lp_resolve_context(tctx->lp_ctx),
+ lpcfg_resolve_context(tctx->lp_ctx),
tctx->ev,
&smb_options,
&smb_session_options,
- lp_gensec_settings(tctx, tctx->lp_ctx)),
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
"failed to open driver share");
return true;
return true;
}
+static bool check_printer_driver_file(struct torture_context *tctx,
+ struct smbcli_state *cli,
+ struct torture_driver_context *d,
+ const char *file_name)
+{
+ const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
+ const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
+ remote_arch_dir,
+ d->info8.version,
+ file_name);
+ int fnum;
+
+ torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
+
+ torture_comment(tctx, "checking for driver file at %s\n", remote_name);
+
+ fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
+ if (fnum == -1) {
+ return false;
+ }
+
+ torture_assert_ntstatus_ok(tctx,
+ smbcli_close(cli->tree, fnum),
+ "failed to close driver file");
+
+ return true;
+}
+
+static bool check_printer_driver_files(struct torture_context *tctx,
+ const char *server_name,
+ struct torture_driver_context *d,
+ bool expect_exist)
+{
+ struct smbcli_state *cli;
+ const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
+ int i;
+
+ torture_assert(tctx,
+ connect_printer_driver_share(tctx, server_name, share_name, &cli),
+ "failed to connect to driver share");
+
+ torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
+ (expect_exist ? "": "non-"),
+ server_name, share_name);
+
+ if (d->info8.driver_path && d->info8.driver_path[0]) {
+ torture_assert(tctx,
+ check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
+ "failed driver_path check");
+ }
+ if (d->info8.data_file && d->info8.data_file[0]) {
+ torture_assert(tctx,
+ check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
+ "failed data_file check");
+ }
+ if (d->info8.config_file && d->info8.config_file[0]) {
+ torture_assert(tctx,
+ check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
+ "failed config_file check");
+ }
+ if (d->info8.help_file && d->info8.help_file[0]) {
+ torture_assert(tctx,
+ check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
+ "failed help_file check");
+ }
+ if (d->info8.dependent_files) {
+ for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
+ torture_assert(tctx,
+ check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
+ "failed dependent_files check");
+ }
+ }
+
+ talloc_free(cli);
+
+ return true;
+}
+
static bool remove_printer_driver_file(struct torture_context *tctx,
struct smbcli_state *cli,
struct torture_driver_context *d,
const char *remote_name;
const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
- if (!file_name) {
+ if (!file_name || strlen(file_name) == 0) {
return true;
}
torture_assert(tctx,
remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
"failed to remove data_file");
- torture_assert(tctx,
- remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
- "failed to remove config_file");
+ if (!strequal(d->info8.config_file, d->info8.driver_path)) {
+ torture_assert(tctx,
+ remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
+ "failed to remove config_file");
+ }
torture_assert(tctx,
remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
"failed to remove help_file");
upload_printer_driver(tctx, dcerpc_server_name(p), d),
"failed to upload printer driver");
- info8.version = d->info8.version;
- info8.driver_name = d->info8.driver_name;
- info8.architecture = d->local.environment;
- info8.driver_path = d->info8.driver_path;
- info8.data_file = d->info8.data_file;
- info8.config_file = d->info8.config_file;
+ info8 = d->info8;
+ if (d->info8.dependent_files) {
+ info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
+ if (d->info8.dependent_files->string) {
+ for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
+ }
+ info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
+ for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
+ info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
+ }
+ }
+ }
+ info8.architecture = d->local.environment;
for (i=0; i < ARRAY_SIZE(levels); i++) {
break;
}
}
+ if (torture_setting_bool(tctx, "w2k3", false)) {
+ switch (levels[i]) {
+ case 8:
+ torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
+ continue;
+ default:
+ break;
+ }
+ }
torture_comment(tctx,
"Testing PrinterDriver%s '%s' add & delete level %d\n",
d->ex ? "Ex" : "", info8.driver_name, levels[i]);
- ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
+ ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
}
info8.driver_path = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
info8.data_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
- info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
+ if (d->info8.config_file) {
+ info8.config_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
+ }
+ if (d->info8.help_file) {
+ info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
+ }
+ if (d->info8.dependent_files && d->info8.dependent_files->string) {
+ for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
+ info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
+ }
+ }
for (i=0; i < ARRAY_SIZE(levels); i++) {
break;
}
}
-
+ if (torture_setting_bool(tctx, "w2k3", false)) {
+ switch (levels[i]) {
+ case 8:
+ torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
+ continue;
+ default:
+ break;
+ }
+ }
torture_comment(tctx,
"Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
d->ex ? "Ex" : "", info8.driver_name, levels[i]);
- ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex);
+ ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
}
torture_assert(tctx,
}
static bool test_add_driver_ex_64(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- void *private_data)
+ struct dcerpc_pipe *p)
{
- struct torture_driver_context *d =
- (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
+ struct torture_driver_context *d;
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER_EX;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
d->local.environment = talloc_strdup(d, "Windows x64");
d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
- d->info8.driver_name = TORTURE_DRIVER_EX;
d->ex = true;
return test_add_driver_arg(tctx, p, d);
}
static bool test_add_driver_ex_32(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- void *private_data)
+ struct dcerpc_pipe *p)
{
- struct torture_driver_context *d =
- (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
+ struct torture_driver_context *d;
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER_EX;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
d->local.environment = talloc_strdup(d, "Windows NT x86");
d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
- d->info8.driver_name = TORTURE_DRIVER_EX;
d->ex = true;
return test_add_driver_arg(tctx, p, d);
}
static bool test_add_driver_64(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- void *private_data)
+ struct dcerpc_pipe *p)
{
- struct torture_driver_context *d =
- (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
+ struct torture_driver_context *d;
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
d->local.environment = talloc_strdup(d, "Windows x64");
d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
- d->info8.driver_name = TORTURE_DRIVER;
d->ex = false;
return test_add_driver_arg(tctx, p, d);
}
static bool test_add_driver_32(struct torture_context *tctx,
- struct dcerpc_pipe *p,
- void *private_data)
+ struct dcerpc_pipe *p)
{
- struct torture_driver_context *d =
- (struct torture_driver_context *)talloc_get_type_abort(private_data, struct torture_driver_context);
+ struct torture_driver_context *d;
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
d->local.environment = talloc_strdup(d, "Windows NT x86");
d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
- d->info8.driver_name = TORTURE_DRIVER;
d->ex = false;
return test_add_driver_arg(tctx, p, d);
}
+static bool test_add_driver_adobe(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d;
+
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ torture_skip(tctx, "skipping adobe test which only works against samba3");
+ }
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
+ d->info8.driver_name = TORTURE_DRIVER_ADOBE;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
+ d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
+ d->info8.config_file = talloc_strdup(d, "ADOBEPS4.DRV");
+#if 0
+ d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
+ d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
+#endif
+ d->local.environment = talloc_strdup(d, "Windows 4.0");
+ d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
+ d->ex = false;
+
+ return test_add_driver_arg(tctx, p, d);
+}
+
+static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d;
+ struct spoolss_StringArray *a;
+
+ if (!torture_setting_bool(tctx, "samba3", false)) {
+ torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
+ }
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->info8.version = SPOOLSS_DRIVER_VERSION_9X;
+ d->info8.driver_name = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "ADOBEPS4.DRV");
+ d->info8.data_file = talloc_strdup(d, "DEFPRTR2.PPD");
+ d->info8.config_file = NULL;
+ d->info8.help_file = talloc_strdup(d, "ADOBEPS4.HLP");
+ d->info8.monitor_name = talloc_strdup(d, "PSMON.DLL");
+ d->info8.default_datatype = talloc_strdup(d, "RAW");
+
+ a = talloc_zero(d, struct spoolss_StringArray);
+ a->string = talloc_zero_array(a, const char *, 7);
+ a->string[0] = talloc_strdup(a->string, "ADOBEPS4.DRV");
+ a->string[1] = talloc_strdup(a->string, "DEFPRTR2.PPD");
+ a->string[2] = talloc_strdup(a->string, "ADOBEPS4.HLP");
+ a->string[3] = talloc_strdup(a->string, "PSMON.DLL");
+ a->string[4] = talloc_strdup(a->string, "ADFONTS.MFM");
+ a->string[5] = talloc_strdup(a->string, "ICONLIB.DLL");
+
+ d->info8.dependent_files = a;
+ d->local.environment = talloc_strdup(d, "Windows 4.0");
+ d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
+ d->ex = false;
+
+ return test_add_driver_arg(tctx, p, d);
+}
+
+static bool test_add_driver_timestamps(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d;
+ struct timeval t = timeval_current();
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER_TIMESTAMPS;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
+ d->info8.driver_date = timeval_to_nttime(&t);
+ d->local.environment = talloc_strdup(d, "Windows NT x86");
+ d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
+ d->ex = true;
+
+ torture_assert(tctx,
+ test_add_driver_arg(tctx, p, d),
+ "");
+
+ unix_to_nt_time(&d->info8.driver_date, 1);
+
+ torture_assert(tctx,
+ test_add_driver_arg(tctx, p, d),
+ "");
+
+ return true;
+}
+
+static bool test_multiple_drivers(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+ int i;
+ struct spoolss_AddDriverInfo8 info8;
+ uint32_t add_flags = APD_COPY_NEW_FILES;
+ uint32_t delete_flags = 0;
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
+ d->local.environment = talloc_strdup(d, "Windows NT x86");
+ d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/i386");
+ d->ex = true;
+
+ torture_assert(tctx,
+ fillup_printserver_info(tctx, p, d),
+ "failed to fillup printserver info");
+
+ if (!directory_exist(d->local.driver_directory)) {
+ torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
+ }
+
+ torture_assert(tctx,
+ upload_printer_driver(tctx, dcerpc_server_name(p), d),
+ "failed to upload printer driver");
+
+ info8 = d->info8;
+ info8.architecture = d->local.environment;
+
+ for (i=0; i < 3; i++) {
+ info8.driver_name = talloc_asprintf(d, "torture_test_driver_%d", i);
+
+ torture_assert(tctx,
+ test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
+ "failed to add driver");
+ }
+
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
+ "failed to delete driver");
+
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
+ "torture_test_driver_1 no longer on the server");
+
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
+ "torture_test_driver_2 no longer on the server");
+
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
+ "failed to delete driver");
+
+ torture_assert(tctx,
+ test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
+ "torture_test_driver_2 no longer on the server");
+
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
+ "failed to delete driver");
+
+ torture_assert(tctx,
+ remove_printer_driver(tctx, dcerpc_server_name(p), d),
+ "failed to remove printer driver");
+
+ return true;
+}
+
+static bool test_del_driver_all_files(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d;
+ struct spoolss_StringArray *a;
+ uint32_t add_flags = APD_COPY_NEW_FILES;
+ uint32_t delete_flags = DPD_DELETE_ALL_FILES;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+
+ d = talloc_zero(tctx, struct torture_driver_context);
+
+ d->ex = true;
+ d->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d->info8.driver_name = TORTURE_DRIVER_DELETER;
+ d->info8.architecture = NULL;
+ d->info8.driver_path = talloc_strdup(d, "pscript5.dll");
+ d->info8.data_file = talloc_strdup(d, "cups6.ppd");
+ d->info8.config_file = talloc_strdup(d, "cupsui6.dll");
+ d->info8.help_file = talloc_strdup(d, "pscript.hlp");
+ d->local.environment = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
+ d->local.driver_directory = talloc_strdup(d, "/usr/share/cups/drivers/x64");
+
+ a = talloc_zero(d, struct spoolss_StringArray);
+ a->string = talloc_zero_array(a, const char *, 3);
+ a->string[0] = talloc_strdup(a->string, "cups6.inf");
+ a->string[1] = talloc_strdup(a->string, "cups6.ini");
+
+ d->info8.dependent_files = a;
+ d->info8.architecture = d->local.environment;
+
+ torture_assert(tctx,
+ fillup_printserver_info(tctx, p, d),
+ "failed to fillup printserver info");
+
+ if (!directory_exist(d->local.driver_directory)) {
+ torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
+ }
+
+ torture_assert(tctx,
+ upload_printer_driver(tctx, dcerpc_server_name(p), d),
+ "failed to upload printer driver");
+
+ torture_assert(tctx,
+ test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
+ "failed to add driver");
+
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx(tctx, b, server_name_slash,
+ d->info8.driver_name,
+ d->local.environment,
+ delete_flags,
+ d->info8.version),
+ "failed to delete driver");
+
+ torture_assert(tctx,
+ check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
+ "printer driver file check failed");
+
+ talloc_free(d);
+ return true;
+}
+
+static bool test_del_driver_unused_files(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct torture_driver_context *d1;
+ struct torture_driver_context *d2;
+ uint32_t add_flags = APD_COPY_NEW_FILES;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+ const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
+
+ d1 = talloc_zero(tctx, struct torture_driver_context);
+ d1->ex = true;
+ d1->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d1->info8.driver_name = TORTURE_DRIVER_DELETER;
+ d1->info8.architecture = NULL;
+ d1->info8.driver_path = talloc_strdup(d1, "pscript5.dll");
+ d1->info8.data_file = talloc_strdup(d1, "cups6.ppd");
+ d1->info8.config_file = talloc_strdup(d1, "cupsui6.dll");
+ d1->info8.help_file = talloc_strdup(d1, "pscript.hlp");
+ d1->local.environment = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
+ d1->local.driver_directory = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
+ d1->info8.architecture = d1->local.environment;
+
+ d2 = talloc_zero(tctx, struct torture_driver_context);
+ d2->ex = true;
+ d2->info8.version = SPOOLSS_DRIVER_VERSION_200X;
+ d2->info8.driver_name = TORTURE_DRIVER_DELETERIN;
+ d2->info8.architecture = NULL;
+ d2->info8.driver_path = talloc_strdup(d2, "pscript5.dll"); /* overlapping */
+ d2->info8.data_file = talloc_strdup(d2, "cupsps6.dll");
+ d2->info8.config_file = talloc_strdup(d2, "cups6.ini");
+ d2->info8.help_file = talloc_strdup(d2, "pscript.hlp"); /* overlapping */
+ d2->local.environment = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
+ d2->local.driver_directory = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
+ d2->info8.architecture = d2->local.environment;
+
+ torture_assert(tctx,
+ fillup_printserver_info(tctx, p, d1),
+ "failed to fillup printserver info");
+ torture_assert(tctx,
+ fillup_printserver_info(tctx, p, d2),
+ "failed to fillup printserver info");
+
+ if (!directory_exist(d1->local.driver_directory)) {
+ torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
+ }
+
+ torture_assert(tctx,
+ upload_printer_driver(tctx, dcerpc_server_name(p), d1),
+ "failed to upload printer driver");
+ torture_assert(tctx,
+ test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
+ "failed to add driver");
+
+ torture_assert(tctx,
+ upload_printer_driver(tctx, dcerpc_server_name(p), d2),
+ "failed to upload printer driver");
+ torture_assert(tctx,
+ test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
+ "failed to add driver");
+
+ /* some files are in use by a separate driver, should fail */
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
+ d1->info8.driver_name,
+ d1->local.environment,
+ DPD_DELETE_ALL_FILES,
+ d1->info8.version,
+ WERR_PRINTER_DRIVER_IN_USE),
+ "invalid delete driver response");
+
+ /* should only delete files not in use by other driver */
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
+ d1->info8.driver_name,
+ d1->local.environment,
+ DPD_DELETE_UNUSED_FILES,
+ d1->info8.version,
+ WERR_OK),
+ "failed to delete driver (unused files)");
+
+ /* check non-overlapping were deleted */
+ d1->info8.driver_path = NULL;
+ d1->info8.help_file = NULL;
+ torture_assert(tctx,
+ check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
+ "printer driver file check failed");
+ /* d2 files should be uneffected */
+ torture_assert(tctx,
+ check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
+ "printer driver file check failed");
+
+ torture_assert(tctx,
+ test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
+ d2->info8.driver_name,
+ d2->local.environment,
+ DPD_DELETE_ALL_FILES,
+ d2->info8.version,
+ WERR_OK),
+ "failed to delete driver");
+
+ torture_assert(tctx,
+ check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
+ "printer driver file check failed");
+
+ talloc_free(d1);
+ talloc_free(d2);
+ return true;
+}
+
struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
{
- struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-DRIVER");
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
"driver", &ndr_table_spoolss);
- struct torture_driver_context *t;
+ torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
+ torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
+
+ torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
+ torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
+
+ torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
+
+ torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
- t = talloc_zero(mem_ctx, struct torture_driver_context);
+ torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
- t->info8.version = SPOOLSS_DRIVER_VERSION_200X;
- t->info8.driver_name = NULL;
- t->info8.architecture = NULL;
- t->info8.driver_path = talloc_strdup(t, "pscript5.dll");
- t->info8.data_file = talloc_strdup(t, "cups6.ppd");
- t->info8.config_file = talloc_strdup(t, "cupsui6.dll");
+ torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
- torture_rpc_tcase_add_test_ex(tcase, "add_driver_64", test_add_driver_64, t);
- torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_64", test_add_driver_ex_64, t);
+ torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
- torture_rpc_tcase_add_test_ex(tcase, "add_driver_32", test_add_driver_32, t);
- torture_rpc_tcase_add_test_ex(tcase, "add_driver_ex_32", test_add_driver_ex_32, t);
+ torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
return suite;
}