diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/include/structs.h | 2 | ||||
-rw-r--r-- | source4/librpc/idl/spoolss.idl | 51 | ||||
-rw-r--r-- | source4/librpc/ndr/ndr_spoolss_buf.c | 274 | ||||
-rw-r--r-- | source4/torture/rpc/spoolss.c | 633 |
4 files changed, 951 insertions, 9 deletions
diff --git a/source4/include/structs.h b/source4/include/structs.h index c11a2a054b..c69bc87fa7 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -28,6 +28,8 @@ struct spoolss_EnumForms; struct spoolss_EnumJobs; struct spoolss_EnumPrinterDrivers; struct spoolss_EnumPorts; +struct spoolss_EnumMonitors; +struct spoolss_EnumPrintProcessors; struct drsuapi_DsReplicaObjectListItem; struct drsuapi_DsReplicaObjectListItemEx; diff --git a/source4/librpc/idl/spoolss.idl b/source4/librpc/idl/spoolss.idl index 79b8d5b7cc..d5bfd687ac 100644 --- a/source4/librpc/idl/spoolss.idl +++ b/source4/librpc/idl/spoolss.idl @@ -243,6 +243,7 @@ [case(7)] spoolss_PrinterInfo7 info7; [case(8)] spoolss_DeviceModeInfo info8; [case(9)] spoolss_DeviceModeInfo info9; + [default]; } spoolss_PrinterInfo; /******************/ @@ -315,6 +316,7 @@ typedef [nodiscriminant,public] union { [case(1)] spoolss_JobInfo1 info1; + [default]; } spoolss_JobInfo; /******************/ @@ -463,6 +465,7 @@ [case(4)] spoolss_DriverInfo4 info4; [case(5)] spoolss_DriverInfo5 info5; [case(6)] spoolss_DriverInfo6 info6; + [default]; } spoolss_DriverInfo; /******************/ @@ -504,7 +507,25 @@ /******************/ /* Function: 0x0f */ - WERROR spoolss_EnumPrintProcessors( + typedef struct { + [relative] nstring *print_processor_name; + } spoolss_PrintProcessorInfo1; + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_PrintProcessorInfo1 info1; + [default]; + } spoolss_PrintProcessorInfo; + + [noprint,nopull,nopush] WERROR spoolss_EnumPrintProcessors( + [in] unistr *servername, + [in] unistr *environment, + [in] uint32 level, + [in] DATA_BLOB *buffer, + /* [out,subcontext(4),switch_is(level)] spoolss_PrintProcessorInfo *info[count],*/ + [out,subcontext(4),switch_is(level)] spoolss_PrintProcessorInfo **info, + /* [out,subcontext(4),flag(NDR_REMAINING)] DATA_BLOB *info,*/ + [in,out,ref] uint32 *buf_size, + [out] uint32 count ); /******************/ @@ -668,6 +689,7 @@ typedef [nodiscriminant,public] union { [case(1)] spoolss_FormInfo1 info1; + [default]; } spoolss_FormInfo; /******************/ @@ -704,6 +726,7 @@ typedef [nodiscriminant,public] union { [case(1)] spoolss_PortInfo1 info1; [case(2)] spoolss_PortInfo2 info2; + [default]; } spoolss_PortInfo; /******************/ @@ -720,7 +743,31 @@ /******************/ /* Function: 0x24 */ - WERROR spoolss_EnumMonitors( + typedef struct { + [relative] nstring *monitor_name; + } spoolss_MonitorInfo1; + + typedef struct { + [relative] nstring *monitor_name; + [relative] nstring *environment; + [relative] nstring *dll_name; + } spoolss_MonitorInfo2; + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_MonitorInfo1 info1; + [case(2)] spoolss_MonitorInfo2 info2; + [default]; + } spoolss_MonitorInfo; + + [noprint,nopull,nopush] WERROR spoolss_EnumMonitors( + [in] unistr *servername, + [in] uint32 level, + [in] DATA_BLOB *buffer, + /* [out,subcontext(4),switch_is(level)] spoolss_MonitorInfo *info[count], */ + [out,subcontext(4),switch_is(level)] spoolss_MonitorInfo **info, + /* [out,subcontext(4),flag(NDR_REMAINING)] DATA_BLOB *info,*/ + [in,out,ref] uint32 *buf_size, + [out] uint32 count ); /******************/ diff --git a/source4/librpc/ndr/ndr_spoolss_buf.c b/source4/librpc/ndr/ndr_spoolss_buf.c index ecb8f374c6..4da604b187 100644 --- a/source4/librpc/ndr/ndr_spoolss_buf.c +++ b/source4/librpc/ndr/ndr_spoolss_buf.c @@ -711,3 +711,277 @@ void ndr_print_spoolss_EnumPorts(struct ndr_print *ndr, const char *name, int fl } ndr->depth--; } + +/* + spoolss_EnumMonitors +*/ +NTSTATUS ndr_push_spoolss_EnumMonitors(struct ndr_push *ndr, int flags, struct spoolss_EnumMonitors *r) +{ + if (!(flags & NDR_IN)) goto ndr_out; + + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.servername)); + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.servername) { + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.servername)); + } + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.level)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.buffer)); + if (r->in.buffer) { + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, *r->in.buffer)); + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, *r->in.buf_size)); + ndr_out: + if (!(flags & NDR_OUT)) goto done; + + NDR_SPOOLSS_PUSH_ENUM_OUT(spoolss_EnumMonitors,spoolss_MonitorInfo); + + done: + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_spoolss_EnumMonitors(struct ndr_pull *ndr, int flags, struct spoolss_EnumMonitors *r) +{ + uint32_t _ptr_servername; + uint32_t _ptr_buffer; + uint32_t _ptr_info; + if (!(flags & NDR_IN)) goto ndr_out; + + ZERO_STRUCT(r->out); + + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_servername)); + if (_ptr_servername) { + NDR_ALLOC(ndr, r->in.servername); + } else { + r->in.servername = NULL; + } + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.servername) { + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS|NDR_BUFFERS, &r->in.servername)); + } + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, &r->in.level)); + NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_buffer)); + if (_ptr_buffer) { + NDR_ALLOC(ndr, r->in.buffer); + } else { + r->in.buffer = NULL; + } + if (r->in.buffer) { + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.buffer)); + } + NDR_ALLOC(ndr, r->in.buf_size); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.buf_size)); + NDR_ALLOC(ndr, r->out.buf_size); + *r->out.buf_size = *r->in.buf_size; + ndr_out: + if (!(flags & NDR_OUT)) goto done; + + NDR_SPOOLSS_PULL_ENUM_OUT(spoolss_EnumMonitors,spoolss_MonitorInfo); + + done: + + return NT_STATUS_OK; +} + +void ndr_print_spoolss_EnumMonitors(struct ndr_print *ndr, const char *name, int flags, struct spoolss_EnumMonitors *r) +{ + ndr_print_struct(ndr, name, "spoolss_EnumMonitors"); + ndr->depth++; + if (flags & NDR_SET_VALUES) { + ndr->flags |= LIBNDR_PRINT_SET_VALUES; + } + if (flags & NDR_IN) { + ndr_print_struct(ndr, "in", "spoolss_EnumMonitors"); + ndr->depth++; + ndr_print_ptr(ndr, "servername", r->in.servername); + ndr->depth++; + if (r->in.servername) { + ndr_print_string(ndr, "servername", r->in.servername); + } + ndr->depth--; + ndr_print_uint32(ndr, "level", r->in.level); + ndr_print_ptr(ndr, "buffer", r->in.buffer); + ndr->depth++; + if (r->in.buffer) { + ndr_print_DATA_BLOB(ndr, "buffer", *r->in.buffer); + } + ndr->depth--; + ndr_print_ptr(ndr, "buf_size", r->in.buf_size); + ndr->depth++; + ndr_print_uint32(ndr, "buf_size", *r->in.buf_size); + ndr->depth--; + ndr->depth--; + } + if (flags & NDR_OUT) { + NDR_SPOOLSS_PRINT_ENUM_OUT(spoolss_EnumMonitors,spoolss_MonitorInfo); + } + ndr->depth--; +} + +/* + spoolss_EnumPrintProcessors +*/ +NTSTATUS ndr_push_spoolss_EnumPrintProcessors(struct ndr_push *ndr, int flags, struct spoolss_EnumPrintProcessors *r) +{ + if (!(flags & NDR_IN)) goto ndr_out; + + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.servername)); + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.servername) { + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.servername)); + } + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.environment)); + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.environment) { + NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.environment)); + } + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.level)); + NDR_CHECK(ndr_push_unique_ptr(ndr, r->in.buffer)); + if (r->in.buffer) { + NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, *r->in.buffer)); + } + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, *r->in.buf_size)); + ndr_out: + if (!(flags & NDR_OUT)) goto done; + + NDR_SPOOLSS_PUSH_ENUM_OUT(spoolss_EnumPrintProcessors,spoolss_PrintProcessorInfo); + + done: + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_spoolss_EnumPrintProcessors(struct ndr_pull *ndr, int flags, struct spoolss_EnumPrintProcessors *r) +{ + uint32_t _ptr_servername; + uint32_t _ptr_environment; + uint32_t _ptr_buffer; + uint32_t _ptr_info; + if (!(flags & NDR_IN)) goto ndr_out; + + ZERO_STRUCT(r->out); + + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_servername)); + if (_ptr_servername) { + NDR_ALLOC(ndr, r->in.servername); + } else { + r->in.servername = NULL; + } + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.servername) { + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS|NDR_BUFFERS, &r->in.servername)); + } + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_environment)); + if (_ptr_environment) { + NDR_ALLOC(ndr, r->in.environment); + } else { + r->in.environment = NULL; + } + ndr->flags = _flags_save_string; + } + { uint32_t _flags_save_string = ndr->flags; + ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_LEN4); + if (r->in.environment) { + NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS|NDR_BUFFERS, &r->in.environment)); + } + ndr->flags = _flags_save_string; + } + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, &r->in.level)); + NDR_CHECK(ndr_pull_unique_ptr(ndr, &_ptr_buffer)); + if (_ptr_buffer) { + NDR_ALLOC(ndr, r->in.buffer); + } else { + r->in.buffer = NULL; + } + if (r->in.buffer) { + NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.buffer)); + } + NDR_ALLOC(ndr, r->in.buf_size); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS|NDR_BUFFERS, r->in.buf_size)); + NDR_ALLOC(ndr, r->out.buf_size); + *r->out.buf_size = *r->in.buf_size; + ndr_out: + if (!(flags & NDR_OUT)) goto done; + + NDR_SPOOLSS_PULL_ENUM_OUT(spoolss_EnumPrintProcessors,spoolss_PrintProcessorInfo); + + done: + + return NT_STATUS_OK; +} + +void ndr_print_spoolss_EnumPrintProcessors(struct ndr_print *ndr, const char *name, int flags, struct spoolss_EnumPrintProcessors *r) +{ + ndr_print_struct(ndr, name, "spoolss_EnumPrintProcessors"); + ndr->depth++; + if (flags & NDR_SET_VALUES) { + ndr->flags |= LIBNDR_PRINT_SET_VALUES; + } + if (flags & NDR_IN) { + ndr_print_struct(ndr, "in", "spoolss_EnumPrintProcessors"); + ndr->depth++; + ndr_print_ptr(ndr, "servername", r->in.servername); + ndr->depth++; + if (r->in.servername) { + ndr_print_string(ndr, "servername", r->in.servername); + } + ndr->depth--; + ndr_print_ptr(ndr, "environment", r->in.environment); + ndr->depth++; + if (r->in.environment) { + ndr_print_string(ndr, "environment", r->in.environment); + } + ndr->depth--; + ndr_print_uint32(ndr, "level", r->in.level); + ndr_print_ptr(ndr, "buffer", r->in.buffer); + ndr->depth++; + if (r->in.buffer) { + ndr_print_DATA_BLOB(ndr, "buffer", *r->in.buffer); + } + ndr->depth--; + ndr_print_ptr(ndr, "buf_size", r->in.buf_size); + ndr->depth++; + ndr_print_uint32(ndr, "buf_size", *r->in.buf_size); + ndr->depth--; + ndr->depth--; + } + if (flags & NDR_OUT) { + NDR_SPOOLSS_PRINT_ENUM_OUT(spoolss_EnumPrintProcessors,spoolss_PrintProcessorInfo); + } + ndr->depth--; +} diff --git a/source4/torture/rpc/spoolss.c b/source4/torture/rpc/spoolss.c index acaa5828dc..c2be0b5324 100644 --- a/source4/torture/rpc/spoolss.c +++ b/source4/torture/rpc/spoolss.c @@ -3,6 +3,7 @@ test suite for spoolss rpc operations Copyright (C) Tim Potter 2003 + Copyright (C) Stefan Metzmacher 2005 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 @@ -22,6 +23,610 @@ #include "includes.h" #include "librpc/gen_ndr/ndr_spoolss.h" +struct test_spoolss_context { + struct dcerpc_pipe *p; + + /* for EnumPorts */ + uint32_t port_count[3]; + union spoolss_PortInfo **ports[3]; + + /* for EnumPrinterDrivers */ + uint32_t driver_count[7]; + union spoolss_DriverInfo **drivers[7]; + + /* for EnumMonitors */ + uint32_t monitor_count[3]; + union spoolss_MonitorInfo **monitors[3]; + + /* for EnumPrintProcessors */ + uint32_t print_processor_count[2]; + union spoolss_PrintProcessorInfo **print_processors[2]; + + /* for EnumPrinters */ + uint32_t printer_count[6]; + union spoolss_PrinterInfo **printers[6]; +}; + +#define COMPARE_STRING(c,r,e) do {\ + BOOL _ok = True;\ + if (c.e && !r.e) _ok = False;\ + if (!c.e && r.e) _ok = False;\ + if (c.e && r.e && strcmp_safe(c.e, r.e) != 0) _ok = False;\ + if (!_ok){\ + printf("%s: " #c "." #e " [%s] doesn't match " #r "." #e " [%s]\n",\ + __location__, c.e, r.e);\ + ret = False;\ + }\ +} while(0) + +#define COMPARE_UINT16(c,r,e) do {\ + if (c.e != r.e){\ + printf("%s: " #c "." #e " 0x%08X (%u) doesn't match " #r "." #e " 0x%08X (%u)\n",\ + __location__, c.e, c.e, r.e, r.e);\ + ret = False;\ + }\ +} while(0) + +#define COMPARE_UINT32(c,r,e) do {\ + if (c.e != r.e){\ + printf("%s: " #c "." #e " 0x%04X (%u) doesn't match " #r "." #e " 0x%04X (%u)\n",\ + __location__, c.e, c.e, r.e, r.e);\ + ret = False;\ + }\ +} while(0) + +#define COMPARE_UINT64(c,r,e) do {\ + if (c.e != r.e){\ + printf("%s: " #c "." #e " 0x%08X%08X (%llu) doesn't match " #r "." #e " 0x%08X%08X (%llu)\n",\ + __location__, (uint32_t)(c.e >> 32), (uint32_t)(c.e & 0xFFFFFFFF), c.e,\ + (uint32_t)(r.e >> 32), (uint32_t)(r.e & 0xFFFFFFFF), r.e);\ + ret = False;\ + }\ +} while(0) + +/* TODO: ! */ +#define COMPARE_SEC_DESC(c,r,e) +#define COMPARE_SPOOLSS_TIME(c,r,e) +#define COMPARE_STRING_ARRAY(c,r,e) + +static BOOL test_EnumPorts(struct test_spoolss_context *ctx) +{ + NTSTATUS status; + struct spoolss_EnumPorts r; + uint16_t levels[] = { 1, 2 }; + int i, j; + BOOL ret = True; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + DATA_BLOB blob; + uint32_t buf_size = 0; + + r.in.servername = ""; + r.in.level = level; + r.in.buffer = NULL; + buf_size = 0; + r.in.buf_size = &buf_size; + r.out.buf_size = &buf_size; + + printf("Testing EnumPorts level %u\n", r.in.level); + + status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + printf("EnumPorts unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + blob = data_blob_talloc(ctx, NULL, buf_size); + data_blob_clear(&blob); + r.in.buffer = &blob; + + status = dcerpc_spoolss_EnumPorts(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPorts failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_IS_OK(r.out.result)) { + printf("EnumPorts failed - %s\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + ctx->port_count[level] = r.out.count; + ctx->ports[level] = r.out.info; + } + + for (i=1;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + int old_level = levels[i-1]; + if (ctx->port_count[level] != ctx->port_count[old_level]) { + printf("EnumPorts level[%d] returns [%u] ports, but level[%d] returns [%u]\n", + level, ctx->port_count[level], old_level, ctx->port_count[old_level]); + ret = False; + } + } + /* if the array sizes are not the same we would maybe segfault in the following code */ + if (!ret) return ret; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + for (j=0;j<ctx->port_count[level];j++) { + union spoolss_PortInfo *cur = &ctx->ports[level][0][j]; + union spoolss_PortInfo *ref = &ctx->ports[2][0][j]; + switch (level) { + case 1: + COMPARE_STRING(cur->info1, ref->info2, port_name); + break; + case 2: + /* level 2 is our reference, and it makes no sense to compare it to itself */ + break; + } + } + } + + return True; +} + +static BOOL test_EnumPrinterDrivers(struct test_spoolss_context *ctx) +{ + NTSTATUS status; + struct spoolss_EnumPrinterDrivers r; + uint16_t levels[] = { 1, 2, 3, 4, 5, 6 }; + int i, j; + BOOL ret = True; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + DATA_BLOB blob; + uint32_t buf_size = 0; + + r.in.server = ""; + r.in.environment = "Windows NT x86"; + r.in.level = level; + r.in.buffer = NULL; + buf_size = 0; + r.in.buf_size = &buf_size; + r.out.buf_size = &buf_size; + + printf("Testing EnumPrinterDrivers level %u\n", r.in.level); + + status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + printf("EnumPrinterDrivers unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + blob = data_blob_talloc(ctx, NULL, buf_size); + data_blob_clear(&blob); + r.in.buffer = &blob; + + status = dcerpc_spoolss_EnumPrinterDrivers(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrinterDrivers failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_IS_OK(r.out.result)) { + printf("EnumPrinterDrivers failed - %s\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + ctx->driver_count[level] = r.out.count; + ctx->drivers[level] = r.out.info; + } + + for (i=1;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + int old_level = levels[i-1]; + if (ctx->driver_count[level] != ctx->driver_count[old_level]) { + printf("EnumPrinterDrivers level[%d] returns [%u] drivers, but level[%d] returns [%u]\n", + level, ctx->driver_count[level], old_level, ctx->driver_count[old_level]); + ret = False; + } + } + /* if the array sizes are not the same we would maybe segfault in the following code */ + if (!ret) return ret; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + for (j=0;j<ctx->driver_count[level];j++) { + union spoolss_DriverInfo *cur = &ctx->drivers[level][0][j]; + union spoolss_DriverInfo *ref = &ctx->drivers[6][0][j]; + switch (level) { + case 1: + COMPARE_STRING(cur->info1, ref->info6, driver_name); + break; + case 2: + COMPARE_UINT32(cur->info2, ref->info6, version); + COMPARE_STRING(cur->info2, ref->info6, driver_name); + COMPARE_STRING(cur->info2, ref->info6, architecture); + COMPARE_STRING(cur->info2, ref->info6, driver_path); + COMPARE_STRING(cur->info2, ref->info6, data_file); + COMPARE_STRING(cur->info2, ref->info6, config_file); + break; + case 3: + COMPARE_UINT32(cur->info3, ref->info6, version); + COMPARE_STRING(cur->info3, ref->info6, driver_name); + COMPARE_STRING(cur->info3, ref->info6, architecture); + COMPARE_STRING(cur->info3, ref->info6, driver_path); + COMPARE_STRING(cur->info3, ref->info6, data_file); + COMPARE_STRING(cur->info3, ref->info6, config_file); + COMPARE_STRING(cur->info3, ref->info6, help_file); + COMPARE_STRING_ARRAY(cur->info3, ref->info6, dependent_files); + COMPARE_STRING(cur->info3, ref->info6, monitor_name); + COMPARE_STRING(cur->info3, ref->info6, default_datatype); + break; + case 4: + COMPARE_UINT32(cur->info4, ref->info6, version); + COMPARE_STRING(cur->info4, ref->info6, driver_name); + COMPARE_STRING(cur->info4, ref->info6, architecture); + COMPARE_STRING(cur->info4, ref->info6, driver_path); + COMPARE_STRING(cur->info4, ref->info6, data_file); + COMPARE_STRING(cur->info4, ref->info6, config_file); + COMPARE_STRING(cur->info4, ref->info6, help_file); + COMPARE_STRING_ARRAY(cur->info4, ref->info6, dependent_files); + COMPARE_STRING(cur->info4, ref->info6, monitor_name); + COMPARE_STRING(cur->info4, ref->info6, default_datatype); + COMPARE_STRING_ARRAY(cur->info4, ref->info6, previous_names); + break; + case 5: + COMPARE_UINT32(cur->info5, ref->info6, version); + COMPARE_STRING(cur->info5, ref->info6, driver_name); + COMPARE_STRING(cur->info5, ref->info6, architecture); + COMPARE_STRING(cur->info5, ref->info6, driver_path); + COMPARE_STRING(cur->info5, ref->info6, data_file); + COMPARE_STRING(cur->info5, ref->info6, config_file); + /*COMPARE_UINT32(cur->info5, ref->info6, driver_attributes);*/ + /*COMPARE_UINT32(cur->info5, ref->info6, config_version);*/ + /*TODO: ! COMPARE_UINT32(cur->info5, ref->info6, driver_version); */ + break; + case 6: + /* level 6 is our reference, and it makes no sense to compare it to itself */ + break; + } + } + } + + return ret; +} + +static BOOL test_EnumMonitors(struct test_spoolss_context *ctx) +{ + NTSTATUS status; + struct spoolss_EnumMonitors r; + uint16_t levels[] = { 1, 2 }; + int i, j; + BOOL ret = True; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + DATA_BLOB blob; + uint32_t buf_size = 0; + + r.in.servername = ""; + r.in.level = level; + r.in.buffer = NULL; + buf_size = 0; + r.in.buf_size = &buf_size; + r.out.buf_size = &buf_size; + + printf("Testing EnumMonitors level %u\n", r.in.level); + + status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + printf("EnumMonitors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + blob = data_blob_talloc(ctx, NULL, buf_size); + data_blob_clear(&blob); + r.in.buffer = &blob; + + status = dcerpc_spoolss_EnumMonitors(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumMonitors failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_IS_OK(r.out.result)) { + printf("EnumMonitors failed - %s\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + ctx->monitor_count[level] = r.out.count; + ctx->monitors[level] = r.out.info; + } + + for (i=1;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + int old_level = levels[i-1]; + if (ctx->monitor_count[level] != ctx->monitor_count[old_level]) { + printf("EnumMonitors level[%d] returns [%u] monitors, but level[%d] returns [%u]\n", + level, ctx->monitor_count[level], old_level, ctx->monitor_count[old_level]); + ret = False; + } + } + /* if the array sizes are not the same we would maybe segfault in the following code */ + if (!ret) return ret; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + for (j=0;j<ctx->monitor_count[level];j++) { + union spoolss_MonitorInfo *cur = &ctx->monitors[level][0][j]; + union spoolss_MonitorInfo *ref = &ctx->monitors[2][0][j]; + switch (level) { + case 1: + COMPARE_STRING(cur->info1, ref->info2, monitor_name); + break; + case 2: + /* level 2 is our reference, and it makes no sense to compare it to itself */ + break; + } + } + } + + return ret; +} + +static BOOL test_EnumPrintProcessors(struct test_spoolss_context *ctx) +{ + NTSTATUS status; + struct spoolss_EnumPrintProcessors r; + uint16_t levels[] = { 1 }; + int i, j; + BOOL ret = True; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + DATA_BLOB blob; + uint32_t buf_size = 0; + + r.in.servername = ""; + r.in.environment = "Windows NT x86"; + r.in.level = level; + r.in.buffer = NULL; + buf_size = 0; + r.in.buf_size = &buf_size; + r.out.buf_size = &buf_size; + + printf("Testing EnumPrintProcessors level %u\n", r.in.level); + + status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + printf("EnumPrintProcessors unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + blob = data_blob_talloc(ctx, NULL, buf_size); + data_blob_clear(&blob); + r.in.buffer = &blob; + + status = dcerpc_spoolss_EnumPrintProcessors(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrintProcessors failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_IS_OK(r.out.result)) { + printf("EnumPrintProcessors failed - %s\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + ctx->print_processor_count[level] = r.out.count; + ctx->print_processors[level] = r.out.info; + } + + for (i=1;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + int old_level = levels[i-1]; + if (ctx->print_processor_count[level] != ctx->print_processor_count[old_level]) { + printf("EnumPrintProcessors level[%d] returns [%u] print_processors, but level[%d] returns [%u]\n", + level, ctx->print_processor_count[level], old_level, ctx->print_processor_count[old_level]); + ret = False; + } + } + /* if the array sizes are not the same we would maybe segfault in the following code */ + if (!ret) return ret; + + 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][0][j]; + union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][0][j]; +#endif + switch (level) { + case 1: + /* level 1 is our reference, and it makes no sense to compare it to itself */ + break; + } + } + } + + return ret; +} + +static BOOL test_EnumPrinters(struct test_spoolss_context *ctx) +{ + struct spoolss_EnumPrinters r; + NTSTATUS status; + uint16_t levels[] = { 0, 1, 2, 4, 5 }; + int i, j; + BOOL ret = True; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + DATA_BLOB blob; + uint32_t buf_size = 0; + + r.in.flags = PRINTER_ENUM_LOCAL; + r.in.server = ""; + r.in.level = level; + r.in.buffer = NULL; + r.in.buf_size = &buf_size; + r.out.buf_size = &buf_size; + + printf("\nTesting EnumPrinters level %u\n", r.in.level); + + status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) { + printf("EnumPrinters unexspected return code %s, should be WERR_INSUFFICIENT_BUFFER\n", + win_errstr(r.out.result)); + ret = False; + continue; + } + + blob = data_blob_talloc(ctx, NULL, buf_size); + data_blob_clear(&blob); + r.in.buffer = &blob; + status = dcerpc_spoolss_EnumPrinters(ctx->p, ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + printf("dcerpc_spoolss_EnumPrinters failed - %s\n", nt_errstr(status)); + ret = False; + continue; + } + + if (!W_ERROR_IS_OK(r.out.result)) { + printf("EnumPrinters failed - %s\n", + win_errstr(r.out.result)); + continue; + } + + ctx->printer_count[level] = r.out.count; + ctx->printers[level] = r.out.info; + } + + for (i=1;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + int old_level = levels[i-1]; + if (ctx->printer_count[level] != ctx->printer_count[old_level]) { + printf("EnumPrinters level[%d] returns [%u] printers, but level[%d] returns [%u]\n", + level, ctx->printer_count[level], old_level, ctx->printer_count[old_level]); + ret = False; + } + } + /* if the array sizes are not the same we would maybe segfault in the following code */ + if (!ret) return ret; + + for (i=0;i<ARRAY_SIZE(levels);i++) { + int level = levels[i]; + for (j=0;j<ctx->printer_count[level];j++) { + union spoolss_PrinterInfo *cur = &ctx->printers[level][0][j]; + union spoolss_PrinterInfo *ref = &ctx->printers[2][0][j]; + switch (level) { + case 0: + COMPARE_STRING(cur->info0, ref->info2, printername); + COMPARE_STRING(cur->info0, ref->info2, servername); + COMPARE_UINT32(cur->info0, ref->info2, cjobs); + /*COMPARE_UINT32(cur->info0, ref->info2, total_jobs); + COMPARE_UINT32(cur->info0, ref->info2, total_bytes); + COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time); + COMPARE_UINT32(cur->info0, ref->info2, global_counter); + COMPARE_UINT32(cur->info0, ref->info2, total_pages); + COMPARE_UINT32(cur->info0, ref->info2, version); + COMPARE_UINT32(cur->info0, ref->info2, unknown10); + COMPARE_UINT32(cur->info0, ref->info2, unknown11); + COMPARE_UINT32(cur->info0, ref->info2, unknown12); + COMPARE_UINT32(cur->info0, ref->info2, session_counter); + COMPARE_UINT32(cur->info0, ref->info2, unknown14); + COMPARE_UINT32(cur->info0, ref->info2, printer_errors); + COMPARE_UINT32(cur->info0, ref->info2, unknown16); + COMPARE_UINT32(cur->info0, ref->info2, unknown17); + COMPARE_UINT32(cur->info0, ref->info2, unknown18); + COMPARE_UINT32(cur->info0, ref->info2, unknown19); + COMPARE_UINT32(cur->info0, ref->info2, change_id); + COMPARE_UINT32(cur->info0, ref->info2, unknown21);*/ + COMPARE_UINT32(cur->info0, ref->info2, status); + /*COMPARE_UINT32(cur->info0, ref->info2, unknown23); + COMPARE_UINT32(cur->info0, ref->info2, c_setprinter); + COMPARE_UINT16(cur->info0, ref->info2, unknown25); + COMPARE_UINT16(cur->info0, ref->info2, unknown26); + COMPARE_UINT32(cur->info0, ref->info2, unknown27); + COMPARE_UINT32(cur->info0, ref->info2, unknown28); + COMPARE_UINT32(cur->info0, ref->info2, unknown29);*/ + break; + case 1: + /*COMPARE_UINT32(cur->info1, ref->info2, flags);*/ + /*COMPARE_STRING(cur->info1, ref->info2, name);*/ + /*COMPARE_STRING(cur->info1, ref->info2, description);*/ + COMPARE_STRING(cur->info1, ref->info2, comment); + break; + case 2: + /* level 2 is our reference, and it makes no sense to compare it to itself */ + break; + case 4: + COMPARE_STRING(cur->info4, ref->info2, printername); + COMPARE_STRING(cur->info4, ref->info2, servername); + COMPARE_UINT32(cur->info4, ref->info2, attributes); + break; + case 5: + COMPARE_STRING(cur->info5, ref->info2, printername); + COMPARE_STRING(cur->info5, ref->info2, portname); + COMPARE_UINT32(cur->info5, ref->info2, attributes); + /*COMPARE_UINT32(cur->info5, ref->info2, device_not_selected_timeout); + COMPARE_UINT32(cur->info5, ref->info2, transmission_retry_timeout);*/ + break; + } + } + } + + /* TODO: + * - verify that the port of a printer was in the list returned by EnumPorts + */ + + return ret; +} + static BOOL test_GetPrinter(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *handle) { @@ -284,7 +889,7 @@ static BOOL test_AddForm(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } -static BOOL test_EnumPorts(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +static BOOL test_EnumPorts_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { NTSTATUS status; struct spoolss_EnumPorts r; @@ -975,7 +1580,7 @@ static BOOL test_OpenPrinterEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return ret; } -static BOOL test_EnumPrinters(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) +static BOOL test_EnumPrinters_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { struct spoolss_EnumPrinters r; NTSTATUS status; @@ -1095,8 +1700,8 @@ static BOOL test_GetPrinterDriver2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, return True; } #endif - -static BOOL test_EnumPrinterDrivers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) + +static BOOL test_EnumPrinterDrivers_old(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx) { struct spoolss_EnumPrinterDrivers r; NTSTATUS status; @@ -1164,6 +1769,7 @@ BOOL torture_rpc_spoolss(void) struct dcerpc_pipe *p; TALLOC_CTX *mem_ctx; BOOL ret = True; + struct test_spoolss_context *ctx; mem_ctx = talloc_init("torture_rpc_spoolss"); @@ -1177,15 +1783,28 @@ BOOL torture_rpc_spoolss(void) return False; } + ctx = talloc_zero(mem_ctx, struct test_spoolss_context); + ctx->p = p; + + ret &= test_EnumPorts(ctx); + + ret &= test_EnumPrinterDrivers(ctx); + + ret &= test_EnumMonitors(ctx); + + ret &= test_EnumPrintProcessors(ctx); + + ret &= test_EnumPrinters(ctx); + ret &= test_OpenPrinter_badnames(p, mem_ctx); ret &= test_AddPort(p, mem_ctx); - ret &= test_EnumPorts(p, mem_ctx); + ret &= test_EnumPorts_old(p, mem_ctx); - ret &= test_EnumPrinters(p, mem_ctx); + ret &= test_EnumPrinters_old(p, mem_ctx); - ret &= test_EnumPrinterDrivers(p, mem_ctx); + ret &= test_EnumPrinterDrivers_old(p, mem_ctx); talloc_free(mem_ctx); |