LCOV - code coverage report
Current view: top level - source4/torture/rpc - spoolss.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 3111 4546 68.4 %
Date: 2021-09-23 10:06:22 Functions: 191 251 76.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    test suite for spoolss rpc operations
       4             : 
       5             :    Copyright (C) Tim Potter 2003
       6             :    Copyright (C) Stefan Metzmacher 2005
       7             :    Copyright (C) Jelmer Vernooij 2007
       8             :    Copyright (C) Guenther Deschner 2009-2011,2013
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "torture/torture.h"
      26             : #include "librpc/gen_ndr/ndr_misc.h"
      27             : #include "librpc/gen_ndr/ndr_spoolss.h"
      28             : #include "librpc/gen_ndr/ndr_spoolss_c.h"
      29             : #include "librpc/gen_ndr/ndr_winreg_c.h"
      30             : #include "librpc/gen_ndr/ndr_security.h"
      31             : #include "libcli/security/security.h"
      32             : #include "torture/rpc/torture_rpc.h"
      33             : #include "param/param.h"
      34             : #include "lib/registry/registry.h"
      35             : #include "libcli/libcli.h"
      36             : #include "libcli/raw/raw_proto.h"
      37             : #include "libcli/resolve/resolve.h"
      38             : #include "libcli/smb2/smb2.h"
      39             : #include "libcli/smb2/smb2_calls.h"
      40             : #include "lib/cmdline/cmdline.h"
      41             : #include "system/filesys.h"
      42             : #include "torture/ndr/ndr.h"
      43             : #include "torture/smb2/proto.h"
      44             : 
      45             : #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
      46             : #define TORTURE_PRINTER                 "torture_printer"
      47             : #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
      48             : #define TORTURE_PRINTER_EX              "torture_printer_ex"
      49             : #define TORTURE_DRIVER                  "torture_driver"
      50             : #define TORTURE_DRIVER_ADD              "torture_driver_add"
      51             : #define TORTURE_DRIVER_EX               "torture_driver_ex"
      52             : #define TORTURE_DRIVER_ADOBE            "torture_driver_adobe"
      53             : #define TORTURE_DRIVER_EX_ADOBE         "torture_driver_ex_adobe"
      54             : #define TORTURE_DRIVER_ADOBE_CUPSADDSMB "torture_driver_adobe_cupsaddsmb"
      55             : #define TORTURE_DRIVER_TIMESTAMPS       "torture_driver_timestamps"
      56             : #define TORTURE_DRIVER_DELETER          "torture_driver_deleter"
      57             : #define TORTURE_DRIVER_COPY_DIR         "torture_driver_copy_from_directory"
      58             : #define TORTURE_DRIVER_DELETERIN        "torture_driver_deleterin"
      59             : #define TORTURE_PRINTER_STATIC1         "print1"
      60             : 
      61             : #define TOP_LEVEL_PRINT_KEY "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print"
      62             : #define TOP_LEVEL_PRINT_PRINTERS_KEY TOP_LEVEL_PRINT_KEY "\\Printers"
      63             : #define TOP_LEVEL_CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control\\Print"
      64             : #define TOP_LEVEL_CONTROL_FORMS_KEY TOP_LEVEL_CONTROL_KEY "\\Forms"
      65             : #define TOP_LEVEL_CONTROL_PRINTERS_KEY TOP_LEVEL_CONTROL_KEY "\\Printers"
      66             : #define TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY TOP_LEVEL_CONTROL_KEY "\\Environments"
      67             : 
      68             : struct test_spoolss_context {
      69             :         struct dcerpc_pipe *spoolss_pipe;
      70             : 
      71             :         /* server environment */
      72             :         const char *environment;
      73             : 
      74             :         /* print server handle */
      75             :         struct policy_handle server_handle;
      76             : 
      77             :         /* for EnumPorts */
      78             :         uint32_t port_count[3];
      79             :         union spoolss_PortInfo *ports[3];
      80             : 
      81             :         /* for EnumPrinterDrivers */
      82             :         uint32_t driver_count[9];
      83             :         union spoolss_DriverInfo *drivers[9];
      84             : 
      85             :         /* for EnumMonitors */
      86             :         uint32_t monitor_count[3];
      87             :         union spoolss_MonitorInfo *monitors[3];
      88             : 
      89             :         /* for EnumPrintProcessors */
      90             :         uint32_t print_processor_count[2];
      91             :         union spoolss_PrintProcessorInfo *print_processors[2];
      92             : 
      93             :         /* for EnumPrinters */
      94             :         uint32_t printer_count[6];
      95             :         union spoolss_PrinterInfo *printers[6];
      96             : };
      97             : 
      98             : struct torture_driver_context {
      99             :         struct {
     100             :                 const char *driver_directory;
     101             :                 const char *environment;
     102             :         } local;
     103             :         struct {
     104             :                 const char *driver_directory;
     105             :                 const char *driver_upload_directory;
     106             :                 const char *environment;
     107             :         } remote;
     108             :         struct spoolss_AddDriverInfo8 info8;
     109             :         bool ex;
     110             : };
     111             : 
     112             : struct torture_printer_context {
     113             :         struct dcerpc_pipe *spoolss_pipe;
     114             :         struct spoolss_SetPrinterInfo2 info2;
     115             :         struct torture_driver_context driver;
     116             :         bool ex;
     117             :         bool wellknown;
     118             :         bool added_driver;
     119             :         bool have_driver;
     120             :         struct spoolss_DeviceMode *devmode;
     121             :         struct policy_handle handle;
     122             : };
     123             : 
     124             : static bool upload_printer_driver(struct torture_context *tctx,
     125             :                                   const char *server_name,
     126             :                                   struct torture_driver_context *d);
     127             : static bool remove_printer_driver(struct torture_context *tctx,
     128             :                                   const char *server_name,
     129             :                                   struct torture_driver_context *d);
     130             : static bool fillup_printserver_info(struct torture_context *tctx,
     131             :                                     struct dcerpc_pipe *p,
     132             :                                     struct torture_driver_context *d);
     133             : static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
     134             :                                                struct dcerpc_binding_handle *b,
     135             :                                                const char *server_name,
     136             :                                                struct spoolss_AddDriverInfo8 *r,
     137             :                                                uint32_t flags,
     138             :                                                bool ex,
     139             :                                                const char *remote_driver_dir);
     140             : 
     141             : #define COMPARE_STRING(tctx, c,r,e) \
     142             :         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
     143             : 
     144             : /* not every compiler supports __typeof__() */
     145             : #if (__GNUC__ >= 3)
     146             : #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
     147             :         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
     148             :                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
     149             :         }\
     150             :         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
     151             :                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
     152             :         }\
     153             : } while(0)
     154             : #else
     155             : #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
     156             : #endif
     157             : 
     158             : #define COMPARE_UINT32(tctx, c, r, e) do {\
     159             :         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
     160             :         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
     161             : } while(0)
     162             : 
     163             : #define COMPARE_UINT64(tctx, c, r, e) do {\
     164             :         _CHECK_FIELD_SIZE(c, r, e, uint64_t); \
     165             :         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
     166             : } while(0)
     167             : 
     168             : 
     169             : #define COMPARE_NTTIME(tctx, c, r, e) do {\
     170             :         _CHECK_FIELD_SIZE(c, r, e, NTTIME); \
     171             :         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
     172             : } while(0)
     173             : 
     174             : #define COMPARE_STRING_ARRAY(tctx, c,r,e) do {\
     175             :         int __i; \
     176             :         if (!c.e && !r.e) { \
     177             :                 break; \
     178             :         } \
     179             :         if (c.e && !r.e) { \
     180             :                 torture_fail(tctx, #r "." #e " field is NULL and " #c "." #e " is not\n"); \
     181             :         } \
     182             :         if (!c.e && r.e) { \
     183             :                 torture_fail(tctx, #c "." #e " field is NULL and " #r "." #e " is not\n"); \
     184             :         } \
     185             :         for (__i=0;c.e[__i] != NULL; __i++) { \
     186             :                 torture_assert_str_equal(tctx, c.e[__i], r.e[__i], "invalid value"); \
     187             :         } \
     188             : } while(0)
     189             : 
     190             : #define CHECK_ALIGN(size, n) do {\
     191             :         if (size % n) {\
     192             :                 torture_warning(tctx, "%d is *NOT* %d byte aligned, should be %d",\
     193             :                         size, n, size + n - (size % n));\
     194             :         }\
     195             : } while(0)
     196             : 
     197             : #define DO_ROUND(size, n) (((size)+((n)-1)) & ~((n)-1))
     198             : 
     199             : #define CHECK_NEEDED_SIZE_ENUM_LEVEL(fn, info, level, count, needed, align) do { \
     200             :         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
     201             :         uint32_t size = ndr_size_##fn##_info(tctx, level, count, info);\
     202             :         uint32_t round_size = DO_ROUND(size, align);\
     203             :         if (round_size != needed) {\
     204             :                 torture_warning(tctx, __location__": "#fn" level %d (count: %d) got unexpected needed size: %d, we calculated: %d", level, count, needed, round_size);\
     205             :                 CHECK_ALIGN(size, align);\
     206             :         }\
     207             :         }\
     208             : } while(0)
     209             : 
     210             : #define CHECK_NEEDED_SIZE_ENUM(fn, info, count, needed, align) do { \
     211             :         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
     212             :         uint32_t size = ndr_size_##fn##_info(tctx, count, info);\
     213             :         uint32_t round_size = DO_ROUND(size, align);\
     214             :         if (round_size != needed) {\
     215             :                 torture_warning(tctx, __location__": "#fn" (count: %d) got unexpected needed size: %d, we calculated: %d", count, needed, round_size);\
     216             :                 CHECK_ALIGN(size, align);\
     217             :         }\
     218             :         }\
     219             : } while(0)
     220             : 
     221             : #define CHECK_NEEDED_SIZE_LEVEL(fn, info, level, needed, align) do { \
     222             :         if (torture_setting_bool(tctx, "spoolss_check_size", false)) {\
     223             :         uint32_t size = ndr_size_##fn(info, level, 0);\
     224             :         uint32_t round_size = DO_ROUND(size, align);\
     225             :         if (round_size != needed) {\
     226             :                 torture_warning(tctx, __location__": "#fn" level %d got unexpected needed size: %d, we calculated: %d", level, needed, round_size);\
     227             :                 CHECK_ALIGN(size, align);\
     228             :         }\
     229             :         }\
     230             : } while(0)
     231             : 
     232          60 : static bool PrinterInfo_to_SetPrinterInfo(struct torture_context *tctx,
     233             :                                           const union spoolss_PrinterInfo *i,
     234             :                                           uint32_t level,
     235             :                                           union spoolss_SetPrinterInfo *s)
     236             : {
     237          60 :         switch (level) {
     238           0 :         case 0:
     239           0 :                 s->info0                     = talloc(tctx, struct spoolss_SetPrinterInfo0);
     240           0 :                 break;
     241          60 :         case 2:
     242          60 :                 s->info2                     = talloc(tctx, struct spoolss_SetPrinterInfo2);
     243          60 :                 s->info2->servername              = i->info2.servername;
     244          60 :                 s->info2->printername             = i->info2.printername;
     245          60 :                 s->info2->sharename               = i->info2.sharename;
     246          60 :                 s->info2->portname                = i->info2.portname;
     247          60 :                 s->info2->drivername              = i->info2.drivername;
     248          60 :                 s->info2->comment         = i->info2.comment;
     249          60 :                 s->info2->location                = i->info2.location;
     250          60 :                 s->info2->devmode_ptr             = 0;
     251          60 :                 s->info2->sepfile         = i->info2.sepfile;
     252          60 :                 s->info2->printprocessor  = i->info2.printprocessor;
     253          60 :                 s->info2->datatype                = i->info2.datatype;
     254          60 :                 s->info2->parameters              = i->info2.parameters;
     255          60 :                 s->info2->secdesc_ptr             = 0;
     256          60 :                 s->info2->attributes              = i->info2.attributes;
     257          60 :                 s->info2->priority                = i->info2.priority;
     258          60 :                 s->info2->defaultpriority = i->info2.defaultpriority;
     259          60 :                 s->info2->starttime               = i->info2.starttime;
     260          60 :                 s->info2->untiltime               = i->info2.untiltime;
     261          60 :                 s->info2->status          = i->info2.status;
     262          60 :                 s->info2->cjobs                   = i->info2.cjobs;
     263          60 :                 s->info2->averageppm              = i->info2.averageppm;
     264          60 :                 break;
     265           0 :         case 3:
     266             :         case 4:
     267             :         case 5:
     268             :         case 6:
     269             :         case 7:
     270             :         case 8:
     271             :         case 9:
     272             :         default:
     273           0 :                 return false;
     274             :         }
     275             : 
     276          60 :         return true;
     277             : }
     278             : 
     279          76 : static bool test_OpenPrinter_server(struct torture_context *tctx,
     280             :                                     struct dcerpc_pipe *p,
     281             :                                     struct policy_handle *server_handle)
     282             : {
     283             :         NTSTATUS status;
     284             :         struct spoolss_OpenPrinter op;
     285          76 :         struct dcerpc_binding_handle *b = p->binding_handle;
     286             : 
     287          76 :         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     288          76 :         op.in.datatype          = NULL;
     289          76 :         op.in.devmode_ctr.devmode= NULL;
     290          76 :         op.in.access_mask       = SEC_FLAG_MAXIMUM_ALLOWED;
     291          76 :         op.out.handle           = server_handle;
     292             : 
     293          76 :         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
     294             : 
     295          76 :         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
     296          76 :         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
     297          76 :         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
     298             : 
     299          76 :         return true;
     300             : }
     301             : 
     302           4 : static bool test_EnumPorts(struct torture_context *tctx,
     303             :                            void *private_data)
     304             : {
     305           3 :         struct test_spoolss_context *ctx =
     306           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     307           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     308           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     309             :         NTSTATUS status;
     310             :         struct spoolss_EnumPorts r;
     311           4 :         uint16_t levels[] = { 1, 2 };
     312             :         int i, j;
     313             : 
     314          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     315           8 :                 int level = levels[i];
     316             :                 DATA_BLOB blob;
     317             :                 uint32_t needed;
     318             :                 uint32_t count;
     319             :                 union spoolss_PortInfo *info;
     320             : 
     321           8 :                 r.in.servername = "";
     322           8 :                 r.in.level = level;
     323           8 :                 r.in.buffer = NULL;
     324           8 :                 r.in.offered = 0;
     325           8 :                 r.out.needed = &needed;
     326           8 :                 r.out.count = &count;
     327           8 :                 r.out.info = &info;
     328             : 
     329           8 :                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
     330             : 
     331           8 :                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
     332           8 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
     333           8 :                 if (W_ERROR_IS_OK(r.out.result)) {
     334             :                         /* TODO: do some more checks here */
     335           0 :                         continue;
     336             :                 }
     337           8 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
     338             :                         "EnumPorts unexpected return code");
     339             : 
     340           8 :                 blob = data_blob_talloc_zero(ctx, needed);
     341           8 :                 r.in.buffer = &blob;
     342           8 :                 r.in.offered = needed;
     343             : 
     344           8 :                 status = dcerpc_spoolss_EnumPorts_r(b, ctx, &r);
     345           8 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
     346             : 
     347           8 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
     348             : 
     349           8 :                 torture_assert(tctx, info, "EnumPorts returned no info");
     350             : 
     351           8 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, r.in.level, count, needed, 4);
     352             : 
     353           8 :                 ctx->port_count[level]       = count;
     354           8 :                 ctx->ports[level]    = info;
     355             :         }
     356             : 
     357           8 :         for (i=1;i<ARRAY_SIZE(levels);i++) {
     358           4 :                 int level = levels[i];
     359           4 :                 int old_level = levels[i-1];
     360           4 :                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
     361             :                         "EnumPorts invalid value");
     362             :         }
     363             :         /* if the array sizes are not the same we would maybe segfault in the following code */
     364             : 
     365          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     366           8 :                 int level = levels[i];
     367          16 :                 for (j=0;j<ctx->port_count[level];j++) {
     368           8 :                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
     369           8 :                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
     370           8 :                         switch (level) {
     371           4 :                         case 1:
     372           4 :                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
     373           4 :                                 break;
     374           4 :                         case 2:
     375             :                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
     376           4 :                                 break;
     377             :                         }
     378             :                 }
     379             :         }
     380             : 
     381           4 :         return true;
     382             : }
     383             : 
     384           4 : static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
     385             :                                             void *private_data)
     386             : {
     387           3 :         struct test_spoolss_context *ctx =
     388           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     389             : 
     390             :         NTSTATUS status;
     391           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     392           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     393             :         struct spoolss_GetPrintProcessorDirectory r;
     394             :         struct {
     395             :                 uint16_t level;
     396             :                 const char *server;
     397          12 :         } levels[] = {{
     398             :                         .level  = 1,
     399             :                         .server = NULL
     400             :                 },{
     401             :                         .level  = 1,
     402             :                         .server = ""
     403             :                 },{
     404             :                         .level  = 78,
     405             :                         .server = ""
     406             :                 },{
     407             :                         .level  = 1,
     408           4 :                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
     409             :                 },{
     410             :                         .level  = 1024,
     411           4 :                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
     412             :                 }
     413             :         };
     414             :         int i;
     415             :         uint32_t needed;
     416             : 
     417          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     418          20 :                 int level = levels[i].level;
     419             :                 DATA_BLOB blob;
     420             : 
     421          20 :                 r.in.server             = levels[i].server;
     422          20 :                 r.in.environment        = ctx->environment;
     423          20 :                 r.in.level              = level;
     424          20 :                 r.in.buffer             = NULL;
     425          20 :                 r.in.offered            = 0;
     426          20 :                 r.out.needed            = &needed;
     427             : 
     428          20 :                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
     429             : 
     430          20 :                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
     431          20 :                 torture_assert_ntstatus_ok(tctx, status,
     432             :                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
     433          20 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
     434             :                         "GetPrintProcessorDirectory unexpected return code");
     435             : 
     436          20 :                 blob = data_blob_talloc_zero(tctx, needed);
     437          20 :                 r.in.buffer = &blob;
     438          20 :                 r.in.offered = needed;
     439             : 
     440          20 :                 status = dcerpc_spoolss_GetPrintProcessorDirectory_r(b, tctx, &r);
     441          20 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
     442             : 
     443          20 :                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
     444             : 
     445          20 :                 CHECK_NEEDED_SIZE_LEVEL(spoolss_PrintProcessorDirectoryInfo, r.out.info, r.in.level, needed, 2);
     446             :         }
     447             : 
     448           4 :         return true;
     449             : }
     450             : 
     451             : 
     452           4 : static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
     453             :                                            void *private_data)
     454             : {
     455           3 :         struct test_spoolss_context *ctx =
     456           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     457             : 
     458             :         NTSTATUS status;
     459           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     460           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     461             :         struct spoolss_GetPrinterDriverDirectory r;
     462             :         struct {
     463             :                 uint16_t level;
     464             :                 const char *server;
     465          12 :         } levels[] = {{
     466             :                         .level  = 1,
     467             :                         .server = NULL
     468             :                 },{
     469             :                         .level  = 1,
     470             :                         .server = ""
     471             :                 },{
     472             :                         .level  = 78,
     473             :                         .server = ""
     474             :                 },{
     475             :                         .level  = 1,
     476           4 :                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
     477             :                 },{
     478             :                         .level  = 1024,
     479           4 :                         .server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p))
     480             :                 }
     481             :         };
     482             :         int i;
     483             :         uint32_t needed;
     484             : 
     485          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     486          20 :                 int level = levels[i].level;
     487             :                 DATA_BLOB blob;
     488             : 
     489          20 :                 r.in.server             = levels[i].server;
     490          20 :                 r.in.environment        = ctx->environment;
     491          20 :                 r.in.level              = level;
     492          20 :                 r.in.buffer             = NULL;
     493          20 :                 r.in.offered            = 0;
     494          20 :                 r.out.needed            = &needed;
     495             : 
     496          20 :                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
     497             : 
     498          20 :                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
     499          20 :                 torture_assert_ntstatus_ok(tctx, status,
     500             :                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
     501          20 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
     502             :                         "GetPrinterDriverDirectory unexpected return code");
     503             : 
     504          20 :                 blob = data_blob_talloc_zero(tctx, needed);
     505          20 :                 r.in.buffer = &blob;
     506          20 :                 r.in.offered = needed;
     507             : 
     508          20 :                 status = dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r);
     509          20 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
     510             : 
     511          20 :                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
     512             : 
     513          20 :                 CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverDirectoryInfo, r.out.info, r.in.level, needed, 2);
     514             :         }
     515             : 
     516           4 :         return true;
     517             : }
     518             : 
     519         108 : static bool test_EnumPrinterDrivers_buffers(struct torture_context *tctx,
     520             :                                             struct dcerpc_binding_handle *b,
     521             :                                             const char *server_name,
     522             :                                             const char *environment,
     523             :                                             uint32_t level,
     524             :                                             uint32_t offered,
     525             :                                             uint32_t *count_p,
     526             :                                             union spoolss_DriverInfo **info_p)
     527             : {
     528             :         struct spoolss_EnumPrinterDrivers r;
     529             :         uint32_t needed;
     530             :         uint32_t count;
     531             :         union spoolss_DriverInfo *info;
     532             :         DATA_BLOB buffer;
     533             : 
     534         108 :         if (offered > 0) {
     535          24 :                 buffer = data_blob_talloc_zero(tctx, offered);
     536             :         }
     537             : 
     538         108 :         r.in.server             = server_name;
     539         108 :         r.in.environment        = environment;
     540         108 :         r.in.level              = level;
     541         108 :         r.in.buffer             = offered ? &buffer : NULL;
     542         108 :         r.in.offered            = offered;
     543         108 :         r.out.needed            = &needed;
     544         108 :         r.out.count             = &count;
     545         108 :         r.out.info              = &info;
     546             : 
     547         108 :         torture_comment(tctx, "Testing EnumPrinterDrivers(%s) level %u, offered: %u\n",
     548             :                 r.in.environment, r.in.level, r.in.offered);
     549             : 
     550         108 :         torture_assert_ntstatus_ok(tctx,
     551             :                 dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
     552             :                 "EnumPrinterDrivers failed");
     553         108 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     554           0 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
     555           0 :                 r.in.buffer = &blob;
     556           0 :                 r.in.offered = needed;
     557             : 
     558           0 :                 torture_assert_ntstatus_ok(tctx,
     559             :                         dcerpc_spoolss_EnumPrinterDrivers_r(b, tctx, &r),
     560             :                         "EnumPrinterDrivers failed");
     561             :         }
     562             : 
     563         108 :         torture_assert_werr_ok(tctx, r.out.result,
     564             :                 "EnumPrinterDrivers failed");
     565             : 
     566         108 :         if (count_p) {
     567          76 :                 *count_p = count;
     568             :         }
     569         108 :         if (info_p) {
     570          76 :                 *info_p = info;
     571             :         }
     572             : 
     573         108 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinterDrivers, info, r.in.level, count, needed, 4);
     574             : 
     575         108 :         return true;
     576             : 
     577             : }
     578             : 
     579             : 
     580          76 : static bool test_EnumPrinterDrivers_args(struct torture_context *tctx,
     581             :                                          struct dcerpc_binding_handle *b,
     582             :                                          const char *server_name,
     583             :                                          const char *environment,
     584             :                                          uint32_t level,
     585             :                                          uint32_t *count_p,
     586             :                                          union spoolss_DriverInfo **info_p)
     587             : {
     588          76 :         return test_EnumPrinterDrivers_buffers(tctx, b, server_name,
     589             :                                                environment, level, 0,
     590             :                                                count_p, info_p);
     591             : }
     592             : 
     593          16 : static bool test_EnumPrinterDrivers_findone(struct torture_context *tctx,
     594             :                                             struct dcerpc_binding_handle *b,
     595             :                                             const char *server_name,
     596             :                                             const char *environment,
     597             :                                             uint32_t level,
     598             :                                             const char *driver_name,
     599             :                                             union spoolss_DriverInfo *info_p)
     600             : {
     601             :         uint32_t count;
     602             :         union spoolss_DriverInfo *info;
     603             :         int i;
     604          16 :         const char *environment_ret = NULL;
     605             : 
     606          16 :         torture_assert(tctx,
     607             :                 test_EnumPrinterDrivers_args(tctx, b, server_name, environment, level, &count, &info),
     608             :                 "failed to enumerate printer drivers");
     609             : 
     610          16 :         for (i=0; i < count; i++) {
     611           0 :                 const char *driver_name_ret = "";
     612           0 :                 switch (level) {
     613           0 :                 case 1:
     614           0 :                         driver_name_ret = info[i].info1.driver_name;
     615           0 :                         break;
     616           0 :                 case 2:
     617           0 :                         driver_name_ret = info[i].info2.driver_name;
     618           0 :                         environment_ret = info[i].info2.architecture;
     619           0 :                         break;
     620           0 :                 case 3:
     621           0 :                         driver_name_ret = info[i].info3.driver_name;
     622           0 :                         environment_ret = info[i].info3.architecture;
     623           0 :                         break;
     624           0 :                 case 4:
     625           0 :                         driver_name_ret = info[i].info4.driver_name;
     626           0 :                         environment_ret = info[i].info4.architecture;
     627           0 :                         break;
     628           0 :                 case 5:
     629           0 :                         driver_name_ret = info[i].info5.driver_name;
     630           0 :                         environment_ret = info[i].info5.architecture;
     631           0 :                         break;
     632           0 :                 case 6:
     633           0 :                         driver_name_ret = info[i].info6.driver_name;
     634           0 :                         environment_ret = info[i].info6.architecture;
     635           0 :                         break;
     636           0 :                 case 7:
     637           0 :                         driver_name_ret = info[i].info7.driver_name;
     638           0 :                         break;
     639           0 :                 case 8:
     640           0 :                         driver_name_ret = info[i].info8.driver_name;
     641           0 :                         environment_ret = info[i].info8.architecture;
     642           0 :                         break;
     643           0 :                 default:
     644           0 :                         break;
     645             :                 }
     646           0 :                 if (environment_ret) {
     647           0 :                         torture_assert_str_equal(tctx, environment, environment_ret, "architecture mismatch");
     648             :                 }
     649           0 :                 if (strequal(driver_name, driver_name_ret)) {
     650           0 :                         if (info_p) {
     651           0 :                                 *info_p = info[i];
     652             :                         }
     653           0 :                         return true;
     654             :                 }
     655             :         }
     656             : 
     657          16 :         return false;
     658             : }
     659             : 
     660           4 : static bool test_EnumPrinterDrivers(struct torture_context *tctx,
     661             :                                     void *private_data)
     662             : {
     663           3 :         struct test_spoolss_context *ctx =
     664           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     665           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     666           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     667           4 :         uint16_t levels[] = { 1, 2, 3, 4, 5, 6, 8 };
     668           4 :         uint16_t buffer_sizes[] = { 0, 1024, 6040, 0xffff };
     669             :         int i, j, a;
     670             : 
     671             :         /* FIXME: gd, come back and fix "" as server, and handle
     672             :          * priority of returned error codes in torture test and samba 3
     673             :          * server */
     674           4 :         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
     675             :         const char *environments[2];
     676             : 
     677           4 :         environments[0] = SPOOLSS_ARCHITECTURE_ALL;
     678           4 :         environments[1] = ctx->environment;
     679             : 
     680          12 :         for (a=0;a<ARRAY_SIZE(environments);a++) {
     681             : 
     682          40 :         for (i=0;i<ARRAY_SIZE(buffer_sizes);i++) {
     683          32 :                 torture_assert(tctx,
     684             :                         test_EnumPrinterDrivers_buffers(tctx, b, server_name,
     685             :                                                         environments[a], 3,
     686             :                                                         buffer_sizes[i],
     687             :                                                         NULL, NULL),
     688             :                         "failed to enumerate drivers");
     689             :         }
     690             : 
     691          64 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     692          56 :                 int level = levels[i];
     693             :                 uint32_t count;
     694             :                 union spoolss_DriverInfo *info;
     695             : 
     696          56 :                 torture_assert(tctx,
     697             :                         test_EnumPrinterDrivers_args(tctx, b, server_name, environments[a], level, &count, &info),
     698             :                         "failed to enumerate drivers");
     699             : 
     700          56 :                 ctx->driver_count[level]     = count;
     701          56 :                 ctx->drivers[level]          = info;
     702             :         }
     703             : 
     704          56 :         for (i=1;i<ARRAY_SIZE(levels);i++) {
     705          48 :                 int level = levels[i];
     706          48 :                 int old_level = levels[i-1];
     707             : 
     708          48 :                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
     709             :                         "EnumPrinterDrivers invalid value");
     710             :         }
     711             : 
     712          64 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     713          56 :                 int level = levels[i];
     714             : 
     715          56 :                 for (j=0;j<ctx->driver_count[level - 1];j++) {
     716           0 :                         union spoolss_DriverInfo *cur = &ctx->drivers[level - 1][j];
     717           0 :                         union spoolss_DriverInfo *ref = &ctx->drivers[8][j];
     718             : 
     719           0 :                         switch (level) {
     720           0 :                         case 1:
     721           0 :                                 COMPARE_STRING(tctx, cur->info1, ref->info8, driver_name);
     722           0 :                                 break;
     723           0 :                         case 2:
     724           0 :                                 COMPARE_UINT32(tctx, cur->info2, ref->info8, version);
     725           0 :                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_name);
     726           0 :                                 COMPARE_STRING(tctx, cur->info2, ref->info8, architecture);
     727           0 :                                 COMPARE_STRING(tctx, cur->info2, ref->info8, driver_path);
     728           0 :                                 COMPARE_STRING(tctx, cur->info2, ref->info8, data_file);
     729           0 :                                 COMPARE_STRING(tctx, cur->info2, ref->info8, config_file);
     730           0 :                                 break;
     731           0 :                         case 3:
     732           0 :                                 COMPARE_UINT32(tctx, cur->info3, ref->info8, version);
     733           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_name);
     734           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, architecture);
     735           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, driver_path);
     736           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, data_file);
     737           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, config_file);
     738           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, help_file);
     739           0 :                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info8, dependent_files);
     740           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, monitor_name);
     741           0 :                                 COMPARE_STRING(tctx, cur->info3, ref->info8, default_datatype);
     742           0 :                                 break;
     743           0 :                         case 4:
     744           0 :                                 COMPARE_UINT32(tctx, cur->info4, ref->info8, version);
     745           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_name);
     746           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, architecture);
     747           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, driver_path);
     748           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, data_file);
     749           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, config_file);
     750           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, help_file);
     751           0 :                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, dependent_files);
     752           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, monitor_name);
     753           0 :                                 COMPARE_STRING(tctx, cur->info4, ref->info8, default_datatype);
     754           0 :                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info8, previous_names);
     755           0 :                                 break;
     756           0 :                         case 5:
     757           0 :                                 COMPARE_UINT32(tctx, cur->info5, ref->info8, version);
     758           0 :                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_name);
     759           0 :                                 COMPARE_STRING(tctx, cur->info5, ref->info8, architecture);
     760           0 :                                 COMPARE_STRING(tctx, cur->info5, ref->info8, driver_path);
     761           0 :                                 COMPARE_STRING(tctx, cur->info5, ref->info8, data_file);
     762           0 :                                 COMPARE_STRING(tctx, cur->info5, ref->info8, config_file);
     763             :                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_attributes);*/
     764             :                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info8, config_version);*/
     765             :                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info8, driver_version); */
     766           0 :                                 break;
     767           0 :                         case 6:
     768           0 :                                 COMPARE_UINT32(tctx, cur->info6, ref->info8, version);
     769           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_name);
     770           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, architecture);
     771           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, driver_path);
     772           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, data_file);
     773           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, config_file);
     774           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, help_file);
     775           0 :                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, dependent_files);
     776           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, monitor_name);
     777           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, default_datatype);
     778           0 :                                 COMPARE_STRING_ARRAY(tctx, cur->info6, ref->info8, previous_names);
     779           0 :                                 COMPARE_NTTIME(tctx, cur->info6, ref->info8, driver_date);
     780           0 :                                 COMPARE_UINT64(tctx, cur->info6, ref->info8, driver_version);
     781           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_name);
     782           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, manufacturer_url);
     783           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, hardware_id);
     784           0 :                                 COMPARE_STRING(tctx, cur->info6, ref->info8, provider);
     785           0 :                                 break;
     786           0 :                         case 8:
     787             :                                 /* level 8 is our reference, and it makes no sense to compare it to itself */
     788           0 :                                 break;
     789             :                         }
     790             :                 }
     791             :         }
     792             :         }
     793             : 
     794           4 :         return true;
     795             : }
     796             : 
     797           4 : static bool test_EnumMonitors(struct torture_context *tctx,
     798             :                               void *private_data)
     799             : {
     800           3 :         struct test_spoolss_context *ctx =
     801           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     802           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     803           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     804             :         NTSTATUS status;
     805             :         struct spoolss_EnumMonitors r;
     806           4 :         uint16_t levels[] = { 1, 2 };
     807             :         int i, j;
     808             : 
     809          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     810           8 :                 int level = levels[i];
     811             :                 DATA_BLOB blob;
     812             :                 uint32_t needed;
     813             :                 uint32_t count;
     814             :                 union spoolss_MonitorInfo *info;
     815             : 
     816           8 :                 r.in.servername = "";
     817           8 :                 r.in.level = level;
     818           8 :                 r.in.buffer = NULL;
     819           8 :                 r.in.offered = 0;
     820           8 :                 r.out.needed = &needed;
     821           8 :                 r.out.count = &count;
     822           8 :                 r.out.info = &info;
     823             : 
     824           8 :                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
     825             : 
     826           8 :                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
     827           8 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
     828           8 :                 if (W_ERROR_IS_OK(r.out.result)) {
     829             :                         /* TODO: do some more checks here */
     830           0 :                         continue;
     831             :                 }
     832           8 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
     833             :                         "EnumMonitors failed");
     834             : 
     835           8 :                 blob = data_blob_talloc_zero(ctx, needed);
     836           8 :                 r.in.buffer = &blob;
     837           8 :                 r.in.offered = needed;
     838             : 
     839           8 :                 status = dcerpc_spoolss_EnumMonitors_r(b, ctx, &r);
     840           8 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
     841             : 
     842           8 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
     843             : 
     844           8 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumMonitors, info, r.in.level, count, needed, 4);
     845             : 
     846           8 :                 ctx->monitor_count[level]    = count;
     847           8 :                 ctx->monitors[level]         = info;
     848             :         }
     849             : 
     850           8 :         for (i=1;i<ARRAY_SIZE(levels);i++) {
     851           4 :                 int level = levels[i];
     852           4 :                 int old_level = levels[i-1];
     853           4 :                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
     854             :                                          "EnumMonitors invalid value");
     855             :         }
     856             : 
     857          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     858           8 :                 int level = levels[i];
     859          24 :                 for (j=0;j<ctx->monitor_count[level];j++) {
     860          16 :                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
     861          16 :                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
     862          16 :                         switch (level) {
     863           8 :                         case 1:
     864           8 :                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
     865           8 :                                 break;
     866           8 :                         case 2:
     867           8 :                                 torture_assert_str_equal(tctx, ref->info2.environment, ctx->environment, "invalid environment");
     868             :                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
     869           8 :                                 break;
     870             :                         }
     871             :                 }
     872             :         }
     873             : 
     874           4 :         return true;
     875             : }
     876             : 
     877          36 : static bool test_EnumPrintProcessors_level(struct torture_context *tctx,
     878             :                                            struct dcerpc_binding_handle *b,
     879             :                                            const char *environment,
     880             :                                            uint32_t level,
     881             :                                            uint32_t *count_p,
     882             :                                            union spoolss_PrintProcessorInfo **info_p,
     883             :                                            WERROR expected_result)
     884             : {
     885             :         struct spoolss_EnumPrintProcessors r;
     886             :         DATA_BLOB blob;
     887             :         uint32_t needed;
     888             :         uint32_t count;
     889             :         union spoolss_PrintProcessorInfo *info;
     890             : 
     891          36 :         r.in.servername = "";
     892          36 :         r.in.environment = environment;
     893          36 :         r.in.level = level;
     894          36 :         r.in.buffer = NULL;
     895          36 :         r.in.offered = 0;
     896          36 :         r.out.needed = &needed;
     897          36 :         r.out.count = &count;
     898          36 :         r.out.info = &info;
     899             : 
     900          36 :         torture_comment(tctx, "Testing EnumPrintProcessors(%s) level %u\n",
     901             :                 r.in.environment, r.in.level);
     902             : 
     903          36 :         torture_assert_ntstatus_ok(tctx,
     904             :                 dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
     905             :                 "EnumPrintProcessors failed");
     906          36 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     907          12 :                 blob = data_blob_talloc_zero(tctx, needed);
     908          12 :                 r.in.buffer = &blob;
     909          12 :                 r.in.offered = needed;
     910          12 :                 torture_assert_ntstatus_ok(tctx,
     911             :                         dcerpc_spoolss_EnumPrintProcessors_r(b, tctx, &r),
     912             :                         "EnumPrintProcessors failed");
     913             :         }
     914          36 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
     915             :                 "EnumPrintProcessors failed");
     916             : 
     917          36 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessors, info, level, count, needed, 4);
     918             : 
     919          36 :         if (count_p) {
     920          32 :                 *count_p = count;
     921             :         }
     922          36 :         if (info_p) {
     923          32 :                 *info_p = info;
     924             :         }
     925             : 
     926          36 :         return true;
     927             : }
     928             : 
     929           4 : static bool test_EnumPrintProcessors(struct torture_context *tctx,
     930             :                                      void *private_data)
     931             : {
     932           3 :         struct test_spoolss_context *ctx =
     933           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     934             : 
     935           4 :         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
     936           4 :         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
     937             :         int i;
     938           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     939           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     940             : 
     941           4 :         torture_assert(tctx,
     942             :                 test_EnumPrintProcessors_level(tctx, b, "phantasy", 1, NULL, NULL, WERR_INVALID_ENVIRONMENT),
     943             :                 "test_EnumPrintProcessors_level failed");
     944             : 
     945          28 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     946             :                 union spoolss_PrintProcessorInfo *info;
     947             :                 uint32_t count;
     948          24 :                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
     949             : 
     950          24 :                 torture_assert(tctx,
     951             :                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, levels[i], &count, &info, expected_result),
     952             :                         "test_EnumPrintProcessors_level failed");
     953             :         }
     954             : 
     955           4 :         return true;
     956             : }
     957             : 
     958          36 : static bool test_EnumPrintProcessorDataTypes_level(struct torture_context *tctx,
     959             :                                                    struct dcerpc_binding_handle *b,
     960             :                                                    const char *print_processor_name,
     961             :                                                    uint32_t level,
     962             :                                                    uint32_t *count_p,
     963             :                                                    union spoolss_PrintProcDataTypesInfo **info_p,
     964             :                                                    WERROR expected_result)
     965             : {
     966             :         struct spoolss_EnumPrintProcessorDataTypes r;
     967             :         DATA_BLOB blob;
     968             :         uint32_t needed;
     969             :         uint32_t count;
     970             :         union spoolss_PrintProcDataTypesInfo *info;
     971             : 
     972          36 :         r.in.servername = "";
     973          36 :         r.in.print_processor_name = print_processor_name;
     974          36 :         r.in.level = level;
     975          36 :         r.in.buffer = NULL;
     976          36 :         r.in.offered = 0;
     977          36 :         r.out.needed = &needed;
     978          36 :         r.out.count = &count;
     979          36 :         r.out.info = &info;
     980             : 
     981          36 :         torture_comment(tctx, "Testing EnumPrintProcessorDataTypes(%s) level %u\n",
     982             :                 r.in.print_processor_name, r.in.level);
     983             : 
     984          36 :         torture_assert_ntstatus_ok(tctx,
     985             :                 dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b, tctx, &r),
     986             :                 "EnumPrintProcessorDataTypes failed");
     987          36 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
     988           8 :                 blob = data_blob_talloc_zero(tctx, needed);
     989           8 :                 r.in.buffer = &blob;
     990           8 :                 r.in.offered = needed;
     991           8 :                 torture_assert_ntstatus_ok(tctx,
     992             :                         dcerpc_spoolss_EnumPrintProcessorDataTypes_r(b, tctx, &r),
     993             :                         "EnumPrintProcessorDataTypes failed");
     994             :         }
     995          36 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
     996             :                 "EnumPrintProcessorDataTypes failed");
     997             : 
     998          36 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrintProcessorDataTypes, info, level, count, needed, 4);
     999             : 
    1000          36 :         if (count_p) {
    1001          24 :                 *count_p = count;
    1002             :         }
    1003          36 :         if (info_p) {
    1004          24 :                 *info_p = info;
    1005             :         }
    1006             : 
    1007          36 :         return true;
    1008             : }
    1009             : 
    1010           4 : static bool test_EnumPrintProcessorDataTypes(struct torture_context *tctx,
    1011             :                                              void *private_data)
    1012             : {
    1013           3 :         struct test_spoolss_context *ctx =
    1014           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    1015             : 
    1016           4 :         uint16_t levels[] = {0, 1, 2, 3, 32, 256 };
    1017           4 :         uint16_t     ok[] = {0, 1, 0, 0, 0, 0 };
    1018             :         int i;
    1019           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    1020           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    1021             : 
    1022           4 :         torture_assert(tctx,
    1023             :                 test_EnumPrintProcessorDataTypes_level(tctx, b, NULL, 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
    1024             :                 "test_EnumPrintProcessorDataTypes_level failed");
    1025             : 
    1026           4 :         torture_assert(tctx,
    1027             :                 test_EnumPrintProcessorDataTypes_level(tctx, b, "nonexisting", 1, NULL, NULL, WERR_UNKNOWN_PRINTPROCESSOR),
    1028             :                 "test_EnumPrintProcessorDataTypes_level failed");
    1029             : 
    1030          28 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1031          24 :                 int level = levels[i];
    1032             :                 uint32_t count;
    1033             :                 union spoolss_PrintProcDataTypesInfo *info;
    1034          24 :                 WERROR expected_result = ok[i] ? WERR_OK : WERR_INVALID_LEVEL;
    1035             : 
    1036          24 :                 torture_assert(tctx,
    1037             :                         test_EnumPrintProcessorDataTypes_level(tctx, b, "winprint", level, &count, &info, expected_result),
    1038             :                         "test_EnumPrintProcessorDataTypes_level failed");
    1039             :         }
    1040             : 
    1041             :         {
    1042             :                 union spoolss_PrintProcessorInfo *info;
    1043             :                 uint32_t count;
    1044             : 
    1045           4 :                 torture_assert(tctx,
    1046             :                         test_EnumPrintProcessors_level(tctx, b, ctx->environment, 1, &count, &info, WERR_OK),
    1047             :                         "test_EnumPrintProcessors_level failed");
    1048             : 
    1049           8 :                 for (i=0; i < count; i++) {
    1050           4 :                         torture_assert(tctx,
    1051             :                                 test_EnumPrintProcessorDataTypes_level(tctx, b, info[i].info1.print_processor_name, 1, NULL, NULL, WERR_OK),
    1052             :                                 "test_EnumPrintProcessorDataTypes_level failed");
    1053             :                 }
    1054             :         }
    1055             : 
    1056             : 
    1057           4 :         return true;
    1058             : }
    1059             : 
    1060           4 : static bool test_EnumPrinters(struct torture_context *tctx,
    1061             :                               void *private_data)
    1062             : {
    1063           3 :         struct test_spoolss_context *ctx =
    1064           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    1065           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    1066           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    1067             :         struct spoolss_EnumPrinters r;
    1068             :         NTSTATUS status;
    1069           4 :         uint16_t levels[] = { 0, 1, 2, 4, 5 };
    1070             :         int i, j;
    1071             : 
    1072          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1073          20 :                 int level = levels[i];
    1074             :                 DATA_BLOB blob;
    1075             :                 uint32_t needed;
    1076             :                 uint32_t count;
    1077             :                 union spoolss_PrinterInfo *info;
    1078             : 
    1079          20 :                 r.in.flags      = PRINTER_ENUM_LOCAL;
    1080          20 :                 r.in.server     = "";
    1081          20 :                 r.in.level      = level;
    1082          20 :                 r.in.buffer     = NULL;
    1083          20 :                 r.in.offered    = 0;
    1084          20 :                 r.out.needed    = &needed;
    1085          20 :                 r.out.count     = &count;
    1086          20 :                 r.out.info      = &info;
    1087             : 
    1088          20 :                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
    1089             : 
    1090          20 :                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
    1091          20 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
    1092          20 :                 if (W_ERROR_IS_OK(r.out.result)) {
    1093             :                         /* TODO: do some more checks here */
    1094           0 :                         continue;
    1095             :                 }
    1096          20 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
    1097             :                         "EnumPrinters unexpected return code");
    1098             : 
    1099          20 :                 blob = data_blob_talloc_zero(ctx, needed);
    1100          20 :                 r.in.buffer = &blob;
    1101          20 :                 r.in.offered = needed;
    1102             : 
    1103          20 :                 status = dcerpc_spoolss_EnumPrinters_r(b, ctx, &r);
    1104          20 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
    1105             : 
    1106          20 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
    1107             : 
    1108          20 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
    1109             : 
    1110          20 :                 ctx->printer_count[level]    = count;
    1111          20 :                 ctx->printers[level]         = info;
    1112             :         }
    1113             : 
    1114          20 :         for (i=1;i<ARRAY_SIZE(levels);i++) {
    1115          16 :                 int level = levels[i];
    1116          16 :                 int old_level = levels[i-1];
    1117          16 :                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
    1118             :                                          "EnumPrinters invalid value");
    1119             :         }
    1120             : 
    1121          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1122          20 :                 int level = levels[i];
    1123         120 :                 for (j=0;j<ctx->printer_count[level];j++) {
    1124         100 :                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
    1125         100 :                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
    1126         100 :                         switch (level) {
    1127          20 :                         case 0:
    1128          20 :                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
    1129          20 :                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
    1130          20 :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
    1131             :                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
    1132             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
    1133             :                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
    1134             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
    1135             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
    1136             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
    1137             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
    1138             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
    1139             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
    1140             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
    1141             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
    1142             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
    1143             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
    1144             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
    1145             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
    1146             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
    1147             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
    1148             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
    1149          20 :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
    1150             :                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
    1151             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
    1152             :                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
    1153             :                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
    1154             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
    1155             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
    1156             :                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
    1157          20 :                                 break;
    1158          20 :                         case 1:
    1159             :                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
    1160             :                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
    1161             :                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
    1162          20 :                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
    1163          20 :                                 break;
    1164          20 :                         case 2:
    1165             :                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
    1166          20 :                                 break;
    1167          20 :                         case 4:
    1168          20 :                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
    1169          20 :                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
    1170          20 :                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
    1171          20 :                                 break;
    1172          20 :                         case 5:
    1173          20 :                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
    1174          20 :                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
    1175          20 :                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
    1176             :                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
    1177             :                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
    1178          20 :                                 break;
    1179             :                         }
    1180             :                 }
    1181             :         }
    1182             : 
    1183             :         /* TODO:
    1184             :          *      - verify that the port of a printer was in the list returned by EnumPorts
    1185             :          */
    1186             : 
    1187           4 :         return true;
    1188             : }
    1189             : 
    1190             : static bool test_GetPrinterDriver2(struct torture_context *tctx,
    1191             :                                    struct dcerpc_binding_handle *b,
    1192             :                                    struct policy_handle *handle,
    1193             :                                    const char *driver_name,
    1194             :                                    const char *environment);
    1195             : 
    1196         956 : bool test_GetPrinter_level_exp(struct torture_context *tctx,
    1197             :                                struct dcerpc_binding_handle *b,
    1198             :                                struct policy_handle *handle,
    1199             :                                uint32_t level,
    1200             :                                WERROR expected_werror,
    1201             :                                union spoolss_PrinterInfo *info)
    1202             : {
    1203             :         struct spoolss_GetPrinter r;
    1204             :         uint32_t needed;
    1205             : 
    1206         956 :         r.in.handle = handle;
    1207         956 :         r.in.level = level;
    1208         956 :         r.in.buffer = NULL;
    1209         956 :         r.in.offered = 0;
    1210         956 :         r.out.needed = &needed;
    1211             : 
    1212         956 :         torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
    1213             : 
    1214         956 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
    1215             :                 "GetPrinter failed");
    1216             : 
    1217         956 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    1218         924 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    1219         924 :                 r.in.buffer = &blob;
    1220         924 :                 r.in.offered = needed;
    1221             : 
    1222         924 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinter_r(b, tctx, &r),
    1223             :                         "GetPrinter failed");
    1224             :         }
    1225             : 
    1226         956 :         torture_assert_werr_equal(tctx,
    1227             :                 r.out.result, expected_werror,
    1228             :                 "GetPrinter failed");
    1229             : 
    1230         956 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterInfo, r.out.info, r.in.level, needed, 4);
    1231             : 
    1232         956 :         if (info && r.out.info) {
    1233         920 :                 *info = *r.out.info;
    1234             :         }
    1235             : 
    1236         956 :         return true;
    1237             : }
    1238             : 
    1239         924 : bool test_GetPrinter_level(struct torture_context *tctx,
    1240             :                            struct dcerpc_binding_handle *b,
    1241             :                            struct policy_handle *handle,
    1242             :                            uint32_t level,
    1243             :                            union spoolss_PrinterInfo *info)
    1244             : {
    1245         924 :         return test_GetPrinter_level_exp(tctx, b, handle, level, WERR_OK, info);
    1246             : }
    1247             : 
    1248          40 : static bool test_GetPrinter(struct torture_context *tctx,
    1249             :                             struct dcerpc_binding_handle *b,
    1250             :                             struct policy_handle *handle,
    1251             :                             const char *environment)
    1252             : {
    1253          40 :         uint32_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
    1254             :         int i;
    1255             : 
    1256         700 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1257             : 
    1258             :                 union spoolss_PrinterInfo info;
    1259             : 
    1260         360 :                 ZERO_STRUCT(info);
    1261             : 
    1262         360 :                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, levels[i], &info),
    1263             :                         "failed to call GetPrinter");
    1264             : 
    1265         360 :                 if ((levels[i] == 2) && info.info2.drivername && strlen(info.info2.drivername)) {
    1266           0 :                         torture_assert(tctx,
    1267             :                                 test_GetPrinterDriver2(tctx, b, handle, info.info2.drivername, environment),
    1268             :                                 "failed to call test_GetPrinterDriver2");
    1269             :                 }
    1270             :         }
    1271             : 
    1272          40 :         return true;
    1273             : }
    1274             : 
    1275         208 : static bool test_SetPrinter(struct torture_context *tctx,
    1276             :                             struct dcerpc_binding_handle *b,
    1277             :                             struct policy_handle *handle,
    1278             :                             struct spoolss_SetPrinterInfoCtr *info_ctr,
    1279             :                             struct spoolss_DevmodeContainer *devmode_ctr,
    1280             :                             struct sec_desc_buf *secdesc_ctr,
    1281             :                             enum spoolss_PrinterControl command)
    1282             : {
    1283             :         struct spoolss_SetPrinter r;
    1284             : 
    1285         208 :         r.in.handle = handle;
    1286         208 :         r.in.info_ctr = info_ctr;
    1287         208 :         r.in.devmode_ctr = devmode_ctr;
    1288         208 :         r.in.secdesc_ctr = secdesc_ctr;
    1289         208 :         r.in.command = command;
    1290             : 
    1291         208 :         torture_comment(tctx, "Testing SetPrinter level %d\n", r.in.info_ctr->level);
    1292             : 
    1293         208 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
    1294             :                 "failed to call SetPrinter");
    1295         208 :         torture_assert(tctx, (W_ERROR_EQUAL(r.out.result, WERR_OK)
    1296             :                            || W_ERROR_EQUAL(r.out.result, WERR_IO_PENDING)),
    1297             :                        "SetPrinter failed");
    1298             : 
    1299         200 :         return true;
    1300             : }
    1301             : 
    1302           0 : static bool test_SetPrinter_errors(struct torture_context *tctx,
    1303             :                                    struct dcerpc_binding_handle *b,
    1304             :                                    struct policy_handle *handle)
    1305             : {
    1306             :         struct spoolss_SetPrinter r;
    1307           0 :         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    1308             :         int i;
    1309             : 
    1310             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1311             :         struct spoolss_DevmodeContainer devmode_ctr;
    1312             :         struct sec_desc_buf secdesc_ctr;
    1313             : 
    1314           0 :         info_ctr.level = 0;
    1315           0 :         info_ctr.info.info0 = NULL;
    1316             : 
    1317           0 :         ZERO_STRUCT(devmode_ctr);
    1318           0 :         ZERO_STRUCT(secdesc_ctr);
    1319             : 
    1320           0 :         r.in.handle = handle;
    1321           0 :         r.in.info_ctr = &info_ctr;
    1322           0 :         r.in.devmode_ctr = &devmode_ctr;
    1323           0 :         r.in.secdesc_ctr = &secdesc_ctr;
    1324           0 :         r.in.command = 0;
    1325             : 
    1326           0 :         torture_comment(tctx, "Testing SetPrinter all zero\n");
    1327             : 
    1328           0 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
    1329             :                 "failed to call SetPrinter");
    1330           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    1331             :                 "failed to call SetPrinter");
    1332             : 
    1333           0 :  again:
    1334           0 :         for (i=0; i < ARRAY_SIZE(levels); i++) {
    1335             : 
    1336             :                 struct spoolss_SetPrinterInfo0 info0;
    1337             :                 struct spoolss_SetPrinterInfo1 info1;
    1338             :                 struct spoolss_SetPrinterInfo2 info2;
    1339             :                 struct spoolss_SetPrinterInfo3 info3;
    1340             :                 struct spoolss_SetPrinterInfo4 info4;
    1341             :                 struct spoolss_SetPrinterInfo5 info5;
    1342             :                 struct spoolss_SetPrinterInfo6 info6;
    1343             :                 struct spoolss_SetPrinterInfo7 info7;
    1344             :                 struct spoolss_SetPrinterInfo8 info8;
    1345             :                 struct spoolss_SetPrinterInfo9 info9;
    1346             : 
    1347             : 
    1348           0 :                 info_ctr.level = levels[i];
    1349           0 :                 switch (levels[i]) {
    1350           0 :                 case 0:
    1351           0 :                         ZERO_STRUCT(info0);
    1352           0 :                         info_ctr.info.info0 = &info0;
    1353           0 :                         break;
    1354           0 :                 case 1:
    1355           0 :                         ZERO_STRUCT(info1);
    1356           0 :                         info_ctr.info.info1 = &info1;
    1357           0 :                         break;
    1358           0 :                 case 2:
    1359           0 :                         ZERO_STRUCT(info2);
    1360           0 :                         info_ctr.info.info2 = &info2;
    1361           0 :                         break;
    1362           0 :                 case 3:
    1363           0 :                         ZERO_STRUCT(info3);
    1364           0 :                         info_ctr.info.info3 = &info3;
    1365           0 :                         break;
    1366           0 :                 case 4:
    1367           0 :                         ZERO_STRUCT(info4);
    1368           0 :                         info_ctr.info.info4 = &info4;
    1369           0 :                         break;
    1370           0 :                 case 5:
    1371           0 :                         ZERO_STRUCT(info5);
    1372           0 :                         info_ctr.info.info5 = &info5;
    1373           0 :                         break;
    1374           0 :                 case 6:
    1375           0 :                         ZERO_STRUCT(info6);
    1376           0 :                         info_ctr.info.info6 = &info6;
    1377           0 :                         break;
    1378           0 :                 case 7:
    1379           0 :                         ZERO_STRUCT(info7);
    1380           0 :                         info_ctr.info.info7 = &info7;
    1381           0 :                         break;
    1382           0 :                 case 8:
    1383           0 :                         ZERO_STRUCT(info8);
    1384           0 :                         info_ctr.info.info8 = &info8;
    1385           0 :                         break;
    1386           0 :                 case 9:
    1387           0 :                         ZERO_STRUCT(info9);
    1388           0 :                         info_ctr.info.info9 = &info9;
    1389           0 :                         break;
    1390             :                 }
    1391             : 
    1392           0 :                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
    1393           0 :                         info_ctr.level, r.in.command);
    1394             : 
    1395           0 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter_r(b, tctx, &r),
    1396             :                         "failed to call SetPrinter");
    1397             : 
    1398           0 :                 switch (r.in.command) {
    1399           0 :                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
    1400             :                         /* is ignored for all levels other then 0 */
    1401           0 :                         if (info_ctr.level > 0) {
    1402             :                                 /* ignored then */
    1403           0 :                                 break;
    1404             :                         }
    1405             : 
    1406             :                         FALL_THROUGH;
    1407             :                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
    1408             :                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
    1409             :                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
    1410           0 :                         if (info_ctr.level > 0) {
    1411             :                                 /* is invalid for all levels other then 0 */
    1412           0 :                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
    1413             :                                         "unexpected error code returned");
    1414           0 :                                 continue;
    1415             :                         } else {
    1416           0 :                                 torture_assert_werr_ok(tctx, r.out.result,
    1417             :                                         "failed to call SetPrinter with non 0 command");
    1418           0 :                                 continue;
    1419             :                         }
    1420             :                         break;
    1421             : 
    1422           0 :                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
    1423             :                         /* FIXME: gd needs further investigation */
    1424             :                 default:
    1425           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
    1426             :                                 "unexpected error code returned");
    1427           0 :                         continue;
    1428             :                 }
    1429             : 
    1430           0 :                 switch (info_ctr.level) {
    1431           0 :                 case 1:
    1432           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL,
    1433             :                                 "unexpected error code returned");
    1434           0 :                         break;
    1435           0 :                 case 2:
    1436           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
    1437             :                                 "unexpected error code returned");
    1438           0 :                         break;
    1439           0 :                 case 3:
    1440             :                 case 4:
    1441             :                 case 5:
    1442             :                 case 7:
    1443           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    1444             :                                 "unexpected error code returned");
    1445           0 :                         break;
    1446           0 :                 case 9:
    1447           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
    1448             :                                 "unexpected error code returned");
    1449           0 :                         break;
    1450           0 :                 default:
    1451           0 :                         torture_assert_werr_ok(tctx, r.out.result,
    1452             :                                 "failed to call SetPrinter");
    1453           0 :                         break;
    1454             :                 }
    1455             :         }
    1456             : 
    1457           0 :         if (r.in.command < 5) {
    1458           0 :                 r.in.command++;
    1459           0 :                 goto again;
    1460             :         }
    1461             : 
    1462           0 :         return true;
    1463             : }
    1464             : 
    1465         272 : static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
    1466             : {
    1467         272 :         if ((r->level == 2) && (r->info.info2)) {
    1468           0 :                 r->info.info2->secdesc_ptr = 0;
    1469           0 :                 r->info.info2->devmode_ptr = 0;
    1470             :         }
    1471         272 : }
    1472             : 
    1473           0 : static bool test_PrinterInfo(struct torture_context *tctx,
    1474             :                              struct dcerpc_binding_handle *b,
    1475             :                              struct policy_handle *handle)
    1476             : {
    1477             :         NTSTATUS status;
    1478             :         struct spoolss_SetPrinter s;
    1479             :         struct spoolss_GetPrinter q;
    1480             :         struct spoolss_GetPrinter q0;
    1481             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1482             :         union spoolss_PrinterInfo info;
    1483             :         struct spoolss_DevmodeContainer devmode_ctr;
    1484             :         struct sec_desc_buf secdesc_ctr;
    1485             :         uint32_t needed;
    1486           0 :         bool ret = true;
    1487             :         int i;
    1488             : 
    1489           0 :         uint32_t status_list[] = {
    1490             :                 /* these do not stick
    1491             :                 PRINTER_STATUS_PAUSED,
    1492             :                 PRINTER_STATUS_ERROR,
    1493             :                 PRINTER_STATUS_PENDING_DELETION, */
    1494             :                 PRINTER_STATUS_PAPER_JAM,
    1495             :                 PRINTER_STATUS_PAPER_OUT,
    1496             :                 PRINTER_STATUS_MANUAL_FEED,
    1497             :                 PRINTER_STATUS_PAPER_PROBLEM,
    1498             :                 PRINTER_STATUS_OFFLINE,
    1499             :                 PRINTER_STATUS_IO_ACTIVE,
    1500             :                 PRINTER_STATUS_BUSY,
    1501             :                 PRINTER_STATUS_PRINTING,
    1502             :                 PRINTER_STATUS_OUTPUT_BIN_FULL,
    1503             :                 PRINTER_STATUS_NOT_AVAILABLE,
    1504             :                 PRINTER_STATUS_WAITING,
    1505             :                 PRINTER_STATUS_PROCESSING,
    1506             :                 PRINTER_STATUS_INITIALIZING,
    1507             :                 PRINTER_STATUS_WARMING_UP,
    1508             :                 PRINTER_STATUS_TONER_LOW,
    1509             :                 PRINTER_STATUS_NO_TONER,
    1510             :                 PRINTER_STATUS_PAGE_PUNT,
    1511             :                 PRINTER_STATUS_USER_INTERVENTION,
    1512             :                 PRINTER_STATUS_OUT_OF_MEMORY,
    1513             :                 PRINTER_STATUS_DOOR_OPEN,
    1514             :                 PRINTER_STATUS_SERVER_UNKNOWN,
    1515             :                 PRINTER_STATUS_POWER_SAVE,
    1516             :                 /* these do not stick
    1517             :                 0x02000000,
    1518             :                 0x04000000,
    1519             :                 0x08000000,
    1520             :                 0x10000000,
    1521             :                 0x20000000,
    1522             :                 0x40000000,
    1523             :                 0x80000000 */
    1524             :         };
    1525           0 :         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
    1526           0 :         uint32_t attribute_list[] = {
    1527             :                 PRINTER_ATTRIBUTE_QUEUED,
    1528             :                 /* fails with WERR_INVALID_DATATYPE:
    1529             :                 PRINTER_ATTRIBUTE_DIRECT, */
    1530             :                 /* does not stick
    1531             :                 PRINTER_ATTRIBUTE_DEFAULT, */
    1532             :                 PRINTER_ATTRIBUTE_SHARED,
    1533             :                 /* does not stick
    1534             :                 PRINTER_ATTRIBUTE_NETWORK, */
    1535             :                 PRINTER_ATTRIBUTE_HIDDEN,
    1536             :                 PRINTER_ATTRIBUTE_LOCAL,
    1537             :                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
    1538             :                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
    1539             :                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
    1540             :                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
    1541             :                 /* does not stick
    1542             :                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
    1543             :                 /* fails with WERR_INVALID_DATATYPE:
    1544             :                 PRINTER_ATTRIBUTE_RAW_ONLY, */
    1545             :                 /* these do not stick
    1546             :                 PRINTER_ATTRIBUTE_PUBLISHED,
    1547             :                 PRINTER_ATTRIBUTE_FAX,
    1548             :                 PRINTER_ATTRIBUTE_TS,
    1549             :                 0x00010000,
    1550             :                 0x00020000,
    1551             :                 0x00040000,
    1552             :                 0x00080000,
    1553             :                 0x00100000,
    1554             :                 0x00200000,
    1555             :                 0x00400000,
    1556             :                 0x00800000,
    1557             :                 0x01000000,
    1558             :                 0x02000000,
    1559             :                 0x04000000,
    1560             :                 0x08000000,
    1561             :                 0x10000000,
    1562             :                 0x20000000,
    1563             :                 0x40000000,
    1564             :                 0x80000000 */
    1565             :         };
    1566             : 
    1567           0 :         torture_skip(tctx, "Printer Info test is currently broken, skipping");
    1568             : 
    1569             : 
    1570             :         ZERO_STRUCT(devmode_ctr);
    1571             :         ZERO_STRUCT(secdesc_ctr);
    1572             : 
    1573             :         s.in.handle = handle;
    1574             :         s.in.command = 0;
    1575             :         s.in.info_ctr = &info_ctr;
    1576             :         s.in.devmode_ctr = &devmode_ctr;
    1577             :         s.in.secdesc_ctr = &secdesc_ctr;
    1578             : 
    1579             :         q.in.handle = handle;
    1580             :         q.out.info = &info;
    1581             :         q0 = q;
    1582             : 
    1583             : #define TESTGETCALL(call, r) \
    1584             :                 r.in.buffer = NULL; \
    1585             :                 r.in.offered = 0;\
    1586             :                 r.out.needed = &needed; \
    1587             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1588             :                 if (!NT_STATUS_IS_OK(status)) { \
    1589             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1590             :                                r.in.level, nt_errstr(status), __location__); \
    1591             :                         ret = false; \
    1592             :                         break; \
    1593             :                 }\
    1594             :                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
    1595             :                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed); \
    1596             :                         r.in.buffer = &blob; \
    1597             :                         r.in.offered = needed; \
    1598             :                 }\
    1599             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1600             :                 if (!NT_STATUS_IS_OK(status)) { \
    1601             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1602             :                                r.in.level, nt_errstr(status), __location__); \
    1603             :                         ret = false; \
    1604             :                         break; \
    1605             :                 } \
    1606             :                 if (!W_ERROR_IS_OK(r.out.result)) { \
    1607             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1608             :                                r.in.level, win_errstr(r.out.result), __location__); \
    1609             :                         ret = false; \
    1610             :                         break; \
    1611             :                 }
    1612             : 
    1613             : 
    1614             : #define TESTSETCALL_EXP(call, r, err) \
    1615             :                 clear_info2(&info_ctr);\
    1616             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1617             :                 if (!NT_STATUS_IS_OK(status)) { \
    1618             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1619             :                                r.in.info_ctr->level, nt_errstr(status), __location__); \
    1620             :                         ret = false; \
    1621             :                         break; \
    1622             :                 } \
    1623             :                 if (!W_ERROR_IS_OK(err)) { \
    1624             :                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
    1625             :                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
    1626             :                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
    1627             :                                 ret = false; \
    1628             :                         } \
    1629             :                         break; \
    1630             :                 } \
    1631             :                 if (!W_ERROR_IS_OK(r.out.result)) { \
    1632             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1633             :                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
    1634             :                         ret = false; \
    1635             :                         break; \
    1636             :                 }
    1637             : 
    1638             : #define TESTSETCALL(call, r) \
    1639             :         TESTSETCALL_EXP(call, r, WERR_OK)
    1640             : 
    1641             : #define STRING_EQUAL(s1, s2, field) \
    1642             :                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
    1643             :                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
    1644             :                                #field, s2, __location__); \
    1645             :                         ret = false; \
    1646             :                         break; \
    1647             :                 }
    1648             : 
    1649             : #define MEM_EQUAL(s1, s2, length, field) \
    1650             :                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
    1651             :                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
    1652             :                                #field, (const char *)s2, __location__); \
    1653             :                         ret = false; \
    1654             :                         break; \
    1655             :                 }
    1656             : 
    1657             : #define INT_EQUAL(i1, i2, field) \
    1658             :                 if (i1 != i2) { \
    1659             :                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
    1660             :                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
    1661             :                         ret = false; \
    1662             :                         break; \
    1663             :                 }
    1664             : 
    1665             : #define SD_EQUAL(sd1, sd2, field) \
    1666             :                 if (!security_descriptor_equal(sd1, sd2)) { \
    1667             :                         torture_comment(tctx, "Failed to set %s (%s)\n", \
    1668             :                                #field, __location__); \
    1669             :                         ret = false; \
    1670             :                         break; \
    1671             :                 }
    1672             : 
    1673             : #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
    1674             :                 void *p; \
    1675             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    1676             :                 q.in.level = lvl1; \
    1677             :                 TESTGETCALL(GetPrinter, q) \
    1678             :                 info_ctr.level = lvl1; \
    1679             :                 p = (void *)&q.out.info->info ## lvl1; \
    1680             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1681             :                 info_ctr.info.info ## lvl1->field1 = value;\
    1682             :                 TESTSETCALL_EXP(SetPrinter, s, err) \
    1683             :                 info_ctr.info.info ## lvl1->field1 = ""; \
    1684             :                 TESTGETCALL(GetPrinter, q) \
    1685             :                 info_ctr.info.info ## lvl1->field1 = value; \
    1686             :                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
    1687             :                 q.in.level = lvl2; \
    1688             :                 TESTGETCALL(GetPrinter, q) \
    1689             :                 p = (void *)&q.out.info->info ## lvl2; \
    1690             :                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
    1691             :                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
    1692             :         } while (0)
    1693             : 
    1694             : #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
    1695             :         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
    1696             :         } while (0);
    1697             : 
    1698             : #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
    1699             :                 void *p; \
    1700             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    1701             :                 q.in.level = lvl1; \
    1702             :                 TESTGETCALL(GetPrinter, q) \
    1703             :                 info_ctr.level = lvl1; \
    1704             :                 p = (void *)&q.out.info->info ## lvl1; \
    1705             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1706             :                 info_ctr.info.info ## lvl1->field1 = value; \
    1707             :                 TESTSETCALL(SetPrinter, s) \
    1708             :                 info_ctr.info.info ## lvl1->field1 = 0; \
    1709             :                 TESTGETCALL(GetPrinter, q) \
    1710             :                 p = (void *)&q.out.info->info ## lvl1; \
    1711             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1712             :                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
    1713             :                 q.in.level = lvl2; \
    1714             :                 TESTGETCALL(GetPrinter, q) \
    1715             :                 p = (void *)&q.out.info->info ## lvl2; \
    1716             :                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
    1717             :                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
    1718             :         } while (0)
    1719             : 
    1720             : #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
    1721             :         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
    1722             :         } while (0)
    1723             : 
    1724             :         q0.in.level = 0;
    1725             :         do { TESTGETCALL(GetPrinter, q0) } while (0);
    1726             : 
    1727             :         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
    1728             :         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
    1729             : 
    1730             :         /* level 0 printername does not stick */
    1731             : /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
    1732             :         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
    1733             :         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
    1734             :         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
    1735             :         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
    1736             : /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
    1737             :         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
    1738             :         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
    1739             :         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
    1740             :         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
    1741             : /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
    1742             :         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
    1743             :         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
    1744             :         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
    1745             :         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
    1746             : 
    1747             :         /* servername can be set but does not stick
    1748             :         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
    1749             :         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
    1750             :         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
    1751             :         */
    1752             : 
    1753             :         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
    1754             :         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
    1755             :         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
    1756             :         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
    1757             :         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
    1758             : 
    1759             :         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
    1760             :         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
    1761             :         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
    1762             :         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
    1763             :         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
    1764             :         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
    1765             :         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
    1766             :         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
    1767             :         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
    1768             :         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
    1769             : 
    1770             :         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
    1771             : /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
    1772             :                         attribute_list[i],
    1773             :                         (attribute_list[i] | default_attribute)
    1774             :                         ); */
    1775             :                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
    1776             :                         attribute_list[i],
    1777             :                         (attribute_list[i] | default_attribute)
    1778             :                         );
    1779             :                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
    1780             :                         attribute_list[i],
    1781             :                         (attribute_list[i] | default_attribute)
    1782             :                         );
    1783             :                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
    1784             :                         attribute_list[i],
    1785             :                         (attribute_list[i] | default_attribute)
    1786             :                         );
    1787             : /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
    1788             :                         attribute_list[i],
    1789             :                         (attribute_list[i] | default_attribute)
    1790             :                         ); */
    1791             :                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
    1792             :                         attribute_list[i],
    1793             :                         (attribute_list[i] | default_attribute)
    1794             :                         );
    1795             :                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
    1796             :                         attribute_list[i],
    1797             :                         (attribute_list[i] | default_attribute)
    1798             :                         );
    1799             :                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
    1800             :                         attribute_list[i],
    1801             :                         (attribute_list[i] | default_attribute)
    1802             :                         );
    1803             : /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
    1804             :                         attribute_list[i],
    1805             :                         (attribute_list[i] | default_attribute)
    1806             :                         ); */
    1807             :                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
    1808             :                         attribute_list[i],
    1809             :                         (attribute_list[i] | default_attribute)
    1810             :                         );
    1811             :                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
    1812             :                         attribute_list[i],
    1813             :                         (attribute_list[i] | default_attribute)
    1814             :                         );
    1815             :                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
    1816             :                         attribute_list[i],
    1817             :                         (attribute_list[i] | default_attribute)
    1818             :                         );
    1819             :         }
    1820             : 
    1821             :         for (i=0; i < ARRAY_SIZE(status_list); i++) {
    1822             :                 /* level 2 sets do not stick
    1823             :                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
    1824             :                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
    1825             :                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
    1826             :                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
    1827             :                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
    1828             :                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
    1829             :         }
    1830             : 
    1831             :         /* priorities need to be between 0 and 99
    1832             :            passing an invalid priority will result in WERR_INVALID_PRIORITY */
    1833             :         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
    1834             :         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
    1835             :         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
    1836             :         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
    1837             :         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
    1838             :         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
    1839             :         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
    1840             :         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
    1841             : 
    1842             :         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
    1843             :         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
    1844             : 
    1845             :         /* does not stick
    1846             :         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
    1847             :         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
    1848             : 
    1849             :         /* does not stick
    1850             :         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
    1851             :         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
    1852             : 
    1853             :         /* FIXME: gd also test devmode and secdesc behavior */
    1854             : 
    1855             :         {
    1856             :                 /* verify composition of level 1 description field */
    1857             :                 const char *description;
    1858             :                 const char *tmp;
    1859             : 
    1860             :                 q0.in.level = 1;
    1861             :                 do { TESTGETCALL(GetPrinter, q0) } while (0);
    1862             : 
    1863             :                 description = talloc_strdup(tctx, q0.out.info->info1.description);
    1864             : 
    1865             :                 q0.in.level = 2;
    1866             :                 do { TESTGETCALL(GetPrinter, q0) } while (0);
    1867             : 
    1868             :                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
    1869             :                         q0.out.info->info2.printername,
    1870             :                         q0.out.info->info2.drivername,
    1871             :                         q0.out.info->info2.location);
    1872             : 
    1873             :                 do { STRING_EQUAL(description, tmp, "description")} while (0);
    1874             :         }
    1875             : 
    1876             :         return ret;
    1877             : }
    1878             : 
    1879         132 : static bool test_security_descriptor_equal(struct torture_context *tctx,
    1880             :                                            const struct security_descriptor *sd1,
    1881             :                                            const struct security_descriptor *sd2)
    1882             : {
    1883         132 :         if (sd1 == sd2) {
    1884           0 :                 return true;
    1885             :         }
    1886             : 
    1887         132 :         if (!sd1 || !sd2) {
    1888           0 :                 torture_comment(tctx, "%s\n", __location__);
    1889           0 :                 return false;
    1890             :         }
    1891             : 
    1892         132 :         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
    1893         132 :         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
    1894             : 
    1895         132 :         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
    1896         132 :         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
    1897             : 
    1898         132 :         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
    1899           0 :                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
    1900           0 :                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
    1901           0 :                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
    1902           0 :                 return false;
    1903             :         }
    1904         132 :         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
    1905           0 :                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
    1906           0 :                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
    1907           0 :                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
    1908           0 :                 return false;
    1909             :         }
    1910             : 
    1911         132 :         return true;
    1912             : }
    1913             : 
    1914         112 : static bool test_sd_set_level(struct torture_context *tctx,
    1915             :                               struct dcerpc_binding_handle *b,
    1916             :                               struct policy_handle *handle,
    1917             :                               uint32_t level,
    1918             :                               struct security_descriptor *sd)
    1919             : {
    1920             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1921             :         struct spoolss_DevmodeContainer devmode_ctr;
    1922             :         struct sec_desc_buf secdesc_ctr;
    1923             :         union spoolss_SetPrinterInfo sinfo;
    1924             :         union spoolss_PrinterInfo info;
    1925             :         struct spoolss_SetPrinterInfo3 info3;
    1926             : 
    1927         112 :         ZERO_STRUCT(devmode_ctr);
    1928         112 :         ZERO_STRUCT(secdesc_ctr);
    1929             : 
    1930         112 :         switch (level) {
    1931          28 :         case 2: {
    1932          28 :                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1933          28 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    1934             : 
    1935          28 :                 info_ctr.level = 2;
    1936          28 :                 info_ctr.info = sinfo;
    1937             : 
    1938          28 :                 break;
    1939             :         }
    1940          84 :         case 3: {
    1941             : 
    1942          84 :                 info3.sec_desc_ptr = 0;
    1943             : 
    1944          84 :                 info_ctr.level = 3;
    1945          84 :                 info_ctr.info.info3 = &info3;
    1946             : 
    1947          84 :                 break;
    1948             :         }
    1949           0 :         default:
    1950           0 :                 return false;
    1951             :         }
    1952             : 
    1953         112 :         secdesc_ctr.sd = sd;
    1954             : 
    1955         112 :         torture_assert(tctx,
    1956             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
    1957             : 
    1958         112 :         return true;
    1959             : }
    1960             : 
    1961          28 : static bool test_PrinterInfo_SDs(struct torture_context *tctx,
    1962             :                                  struct dcerpc_binding_handle *b,
    1963             :                                  struct policy_handle *handle)
    1964             : {
    1965             :         union spoolss_PrinterInfo info;
    1966             :         struct security_descriptor *sd1, *sd2;
    1967             :         int i;
    1968             : 
    1969             :         /* just compare level 2 and level 3 */
    1970             : 
    1971          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1972             : 
    1973          28 :         sd1 = info.info2.secdesc;
    1974             : 
    1975          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
    1976             : 
    1977          28 :         sd2 = info.info3.secdesc;
    1978             : 
    1979          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    1980             :                 "SD level 2 != SD level 3");
    1981             : 
    1982             : 
    1983             :         /* query level 2, set level 2, query level 2 */
    1984             : 
    1985          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1986             : 
    1987          28 :         sd1 = info.info2.secdesc;
    1988             : 
    1989          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
    1990             : 
    1991          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1992             : 
    1993          28 :         sd2 = info.info2.secdesc;
    1994          28 :         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
    1995           0 :                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
    1996           0 :                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
    1997             :         }
    1998             : 
    1999          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2000             :                 "SD level 2 != SD level 2 after SD has been set via level 2");
    2001             : 
    2002             : 
    2003             :         /* query level 2, set level 3, query level 2 */
    2004             : 
    2005          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2006             : 
    2007          28 :         sd1 = info.info2.secdesc;
    2008             : 
    2009          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
    2010             : 
    2011          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2012             : 
    2013          28 :         sd2 = info.info2.secdesc;
    2014             : 
    2015          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2016             :                 "SD level 2 != SD level 2 after SD has been set via level 3");
    2017             : 
    2018             :         /* set modified sd level 3, query level 2 */
    2019             : 
    2020        2632 :         for (i=0; i < 93; i++) {
    2021             :                 struct security_ace a;
    2022        2604 :                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
    2023        2604 :                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
    2024        2604 :                 a.flags = 0;
    2025        2604 :                 a.size = 0; /* autogenerated */
    2026        2604 :                 a.access_mask = 0;
    2027        2604 :                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
    2028        2604 :                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
    2029             :         }
    2030             : 
    2031          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
    2032             : 
    2033          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2034          28 :         sd2 = info.info2.secdesc;
    2035             : 
    2036          28 :         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
    2037           0 :                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
    2038           0 :                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
    2039             :         }
    2040             : 
    2041          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2042             :                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
    2043             : 
    2044             : 
    2045          28 :         return true;
    2046             : }
    2047             : 
    2048             : /*
    2049             :  * wrapper call that saves original sd, runs tests, and restores sd
    2050             :  */
    2051             : 
    2052          28 : static bool test_PrinterInfo_SD(struct torture_context *tctx,
    2053             :                                 struct dcerpc_binding_handle *b,
    2054             :                                 struct policy_handle *handle)
    2055             : {
    2056             :         union spoolss_PrinterInfo info;
    2057             :         struct security_descriptor *sd;
    2058          28 :         bool ret = true;
    2059             : 
    2060          28 :         torture_comment(tctx, "Testing Printer Security Descriptors\n");
    2061             : 
    2062             :         /* save original sd */
    2063             : 
    2064          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    2065             :                 "failed to get initial security descriptor");
    2066             : 
    2067          28 :         sd = security_descriptor_copy(tctx, info.info2.secdesc);
    2068             : 
    2069             :         /* run tests */
    2070             : 
    2071          28 :         ret = test_PrinterInfo_SDs(tctx, b, handle);
    2072             : 
    2073             :         /* restore original sd */
    2074             : 
    2075          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
    2076             :                 "failed to restore initial security descriptor");
    2077             : 
    2078          28 :         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
    2079             :                 ret ? "succeeded" : "failed");
    2080             : 
    2081             : 
    2082          28 :         return ret;
    2083             : }
    2084             : 
    2085          32 : static bool test_devmode_set_level(struct torture_context *tctx,
    2086             :                                    struct dcerpc_binding_handle *b,
    2087             :                                    struct policy_handle *handle,
    2088             :                                    uint32_t level,
    2089             :                                    struct spoolss_DeviceMode *devmode)
    2090             : {
    2091             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    2092             :         struct spoolss_DevmodeContainer devmode_ctr;
    2093             :         struct sec_desc_buf secdesc_ctr;
    2094             :         union spoolss_SetPrinterInfo sinfo;
    2095             : 
    2096          32 :         ZERO_STRUCT(devmode_ctr);
    2097          32 :         ZERO_STRUCT(secdesc_ctr);
    2098             : 
    2099          32 :         switch (level) {
    2100           8 :         case 2: {
    2101             :                 union spoolss_PrinterInfo info;
    2102           8 :                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2103           8 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    2104             : 
    2105           8 :                 info_ctr.level = 2;
    2106           8 :                 info_ctr.info = sinfo;
    2107             : 
    2108           8 :                 break;
    2109             :         }
    2110          24 :         case 8: {
    2111             :                 struct spoolss_SetPrinterInfo8 info8;
    2112             : 
    2113          24 :                 info8.devmode_ptr = 0;
    2114             : 
    2115          24 :                 info_ctr.level = 8;
    2116          24 :                 info_ctr.info.info8 = &info8;
    2117             : 
    2118          24 :                 break;
    2119             :         }
    2120           0 :         default:
    2121           0 :                 return false;
    2122             :         }
    2123             : 
    2124          32 :         devmode_ctr.devmode = devmode;
    2125             : 
    2126          32 :         torture_assert(tctx,
    2127             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
    2128             : 
    2129          32 :         return true;
    2130             : }
    2131             : 
    2132             : 
    2133          56 : static bool test_devicemode_equal(struct torture_context *tctx,
    2134             :                                   const struct spoolss_DeviceMode *d1,
    2135             :                                   const struct spoolss_DeviceMode *d2)
    2136             : {
    2137          56 :         if (d1 == d2) {
    2138           0 :                 return true;
    2139             :         }
    2140             : 
    2141          56 :         if (!d1 || !d2) {
    2142           0 :                 torture_comment(tctx, "%s\n", __location__);
    2143           0 :                 return false;
    2144             :         }
    2145          56 :         torture_assert_str_equal(tctx, d1->devicename, d2->devicename, "devicename mismatch");
    2146          56 :         torture_assert_int_equal(tctx, d1->specversion, d2->specversion, "specversion mismatch");
    2147          56 :         torture_assert_int_equal(tctx, d1->driverversion, d2->driverversion, "driverversion mismatch");
    2148          56 :         torture_assert_int_equal(tctx, d1->size, d2->size, "size mismatch");
    2149          56 :         torture_assert_int_equal(tctx, d1->__driverextra_length, d2->__driverextra_length, "__driverextra_length mismatch");
    2150          56 :         torture_assert_int_equal(tctx, d1->fields, d2->fields, "fields mismatch");
    2151          56 :         torture_assert_int_equal(tctx, d1->orientation, d2->orientation, "orientation mismatch");
    2152          56 :         torture_assert_int_equal(tctx, d1->papersize, d2->papersize, "papersize mismatch");
    2153          56 :         torture_assert_int_equal(tctx, d1->paperlength, d2->paperlength, "paperlength mismatch");
    2154          56 :         torture_assert_int_equal(tctx, d1->paperwidth, d2->paperwidth, "paperwidth mismatch");
    2155          56 :         torture_assert_int_equal(tctx, d1->scale, d2->scale, "scale mismatch");
    2156          56 :         torture_assert_int_equal(tctx, d1->copies, d2->copies, "copies mismatch");
    2157          56 :         torture_assert_int_equal(tctx, d1->defaultsource, d2->defaultsource, "defaultsource mismatch");
    2158          56 :         torture_assert_int_equal(tctx, d1->printquality, d2->printquality, "printquality mismatch");
    2159          56 :         torture_assert_int_equal(tctx, d1->color, d2->color, "color mismatch");
    2160          56 :         torture_assert_int_equal(tctx, d1->duplex, d2->duplex, "duplex mismatch");
    2161          56 :         torture_assert_int_equal(tctx, d1->yresolution, d2->yresolution, "yresolution mismatch");
    2162          56 :         torture_assert_int_equal(tctx, d1->ttoption, d2->ttoption, "ttoption mismatch");
    2163          56 :         torture_assert_int_equal(tctx, d1->collate, d2->collate, "collate mismatch");
    2164          56 :         torture_assert_str_equal(tctx, d1->formname, d2->formname, "formname mismatch");
    2165          56 :         torture_assert_int_equal(tctx, d1->logpixels, d2->logpixels, "logpixels mismatch");
    2166          56 :         torture_assert_int_equal(tctx, d1->bitsperpel, d2->bitsperpel, "bitsperpel mismatch");
    2167          56 :         torture_assert_int_equal(tctx, d1->pelswidth, d2->pelswidth, "pelswidth mismatch");
    2168          56 :         torture_assert_int_equal(tctx, d1->pelsheight, d2->pelsheight, "pelsheight mismatch");
    2169          56 :         torture_assert_int_equal(tctx, d1->displayflags, d2->displayflags, "displayflags mismatch");
    2170          56 :         torture_assert_int_equal(tctx, d1->displayfrequency, d2->displayfrequency, "displayfrequency mismatch");
    2171          56 :         torture_assert_int_equal(tctx, d1->icmmethod, d2->icmmethod, "icmmethod mismatch");
    2172          56 :         torture_assert_int_equal(tctx, d1->icmintent, d2->icmintent, "icmintent mismatch");
    2173          56 :         torture_assert_int_equal(tctx, d1->mediatype, d2->mediatype, "mediatype mismatch");
    2174          56 :         torture_assert_int_equal(tctx, d1->dithertype, d2->dithertype, "dithertype mismatch");
    2175          56 :         torture_assert_int_equal(tctx, d1->reserved1, d2->reserved1, "reserved1 mismatch");
    2176          56 :         torture_assert_int_equal(tctx, d1->reserved2, d2->reserved2, "reserved2 mismatch");
    2177          56 :         torture_assert_int_equal(tctx, d1->panningwidth, d2->panningwidth, "panningwidth mismatch");
    2178          56 :         torture_assert_int_equal(tctx, d1->panningheight, d2->panningheight, "panningheight mismatch");
    2179          56 :         torture_assert_data_blob_equal(tctx, d1->driverextra_data, d2->driverextra_data, "driverextra_data mismatch");
    2180             : 
    2181          56 :         return true;
    2182             : }
    2183             : 
    2184           8 : static bool test_devicemode_full(struct torture_context *tctx,
    2185             :                                  struct dcerpc_binding_handle *b,
    2186             :                                  struct policy_handle *handle)
    2187             : {
    2188             :         struct spoolss_SetPrinter s;
    2189             :         struct spoolss_GetPrinter q;
    2190             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    2191             :         struct spoolss_SetPrinterInfo8 info8;
    2192             :         union spoolss_PrinterInfo info;
    2193             :         struct spoolss_DevmodeContainer devmode_ctr;
    2194             :         struct sec_desc_buf secdesc_ctr;
    2195             :         uint32_t needed;
    2196           8 :         bool ret = true;
    2197             :         NTSTATUS status;
    2198             : 
    2199             : #define TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
    2200             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    2201             :                 q.in.level = lvl1; \
    2202             :                 TESTGETCALL(GetPrinter, q) \
    2203             :                 info_ctr.level = lvl1; \
    2204             :                 if (lvl1 == 2) {\
    2205             :                         void *p = (void *)&q.out.info->info ## lvl1; \
    2206             :                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    2207             :                 } else if (lvl1 == 8) {\
    2208             :                         info_ctr.info.info ## lvl1 = &info8; \
    2209             :                 }\
    2210             :                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
    2211             :                 devmode_ctr.devmode->field1 = value; \
    2212             :                 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
    2213             :                 if (W_ERROR_IS_OK(expected_result)) { \
    2214             :                         TESTGETCALL(GetPrinter, q) \
    2215             :                         INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
    2216             :                         q.in.level = lvl2; \
    2217             :                         TESTGETCALL(GetPrinter, q) \
    2218             :                         INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
    2219             :                 }\
    2220             :         } while (0)
    2221             : 
    2222             : #define TEST_DEVMODE_INT_EXP(lvl1, field1, lvl2, field2, value, expected_result) do { \
    2223             :         TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, expected_result); \
    2224             :         } while (0)
    2225             : 
    2226             : #define TEST_DEVMODE_INT(lvl1, field1, lvl2, field2, value) do { \
    2227             :         TEST_DEVMODE_INT_EXP_RESULT(lvl1, field1, lvl2, field2, value, value, WERR_OK); \
    2228             :         } while (0)
    2229             : 
    2230           8 :         ZERO_STRUCT(devmode_ctr);
    2231           8 :         ZERO_STRUCT(secdesc_ctr);
    2232           8 :         ZERO_STRUCT(info8);
    2233             : 
    2234           8 :         s.in.handle = handle;
    2235           8 :         s.in.command = 0;
    2236           8 :         s.in.info_ctr = &info_ctr;
    2237           8 :         s.in.devmode_ctr = &devmode_ctr;
    2238           8 :         s.in.secdesc_ctr = &secdesc_ctr;
    2239             : 
    2240           8 :         q.in.handle = handle;
    2241           8 :         q.out.info = &info;
    2242             : 
    2243             : #if 0
    2244             :         const char *devicename;/* [charset(UTF16)] */
    2245             :         enum spoolss_DeviceModeSpecVersion specversion;
    2246             :         uint16_t driverversion;
    2247             :         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
    2248             :         uint32_t fields;
    2249             : #endif
    2250           8 :         TEST_DEVMODE_INT_EXP(8, size,           8, size, __LINE__, WERR_INVALID_PARAMETER);
    2251           8 :         TEST_DEVMODE_INT_EXP(8, size,           8, size, 0, WERR_INVALID_PARAMETER);
    2252           8 :         TEST_DEVMODE_INT_EXP(8, size,           8, size, 0xffff, WERR_INVALID_PARAMETER);
    2253           8 :         TEST_DEVMODE_INT_EXP(8, size,           8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
    2254           8 :         TEST_DEVMODE_INT(8, size,               8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
    2255             : 
    2256           8 :         devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
    2257           8 :         torture_assert(tctx,
    2258             :                 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
    2259             :                 "failed to set devmode");
    2260             : 
    2261           8 :         TEST_DEVMODE_INT_EXP(8, size,           8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
    2262           8 :         TEST_DEVMODE_INT(8, size,               8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
    2263             : 
    2264           8 :         TEST_DEVMODE_INT(8, orientation,        8, orientation, __LINE__);
    2265           8 :         TEST_DEVMODE_INT(8, papersize,          8, papersize, __LINE__);
    2266           8 :         TEST_DEVMODE_INT(8, paperlength,        8, paperlength, __LINE__);
    2267           8 :         TEST_DEVMODE_INT(8, paperwidth,         8, paperwidth, __LINE__);
    2268           8 :         TEST_DEVMODE_INT(8, scale,              8, scale, __LINE__);
    2269           8 :         TEST_DEVMODE_INT(8, copies,             8, copies, __LINE__);
    2270           8 :         TEST_DEVMODE_INT(8, defaultsource,      8, defaultsource, __LINE__);
    2271           8 :         TEST_DEVMODE_INT(8, printquality,       8, printquality, __LINE__);
    2272           8 :         TEST_DEVMODE_INT(8, color,              8, color, __LINE__);
    2273           8 :         TEST_DEVMODE_INT(8, duplex,             8, duplex, __LINE__);
    2274           8 :         TEST_DEVMODE_INT(8, yresolution,        8, yresolution, __LINE__);
    2275           8 :         TEST_DEVMODE_INT(8, ttoption,           8, ttoption, __LINE__);
    2276           8 :         TEST_DEVMODE_INT(8, collate,            8, collate, __LINE__);
    2277             : #if 0
    2278             :         const char *formname;/* [charset(UTF16)] */
    2279             : #endif
    2280           8 :         TEST_DEVMODE_INT(8, logpixels,          8, logpixels, __LINE__);
    2281           8 :         TEST_DEVMODE_INT(8, bitsperpel,         8, bitsperpel, __LINE__);
    2282           8 :         TEST_DEVMODE_INT(8, pelswidth,          8, pelswidth, __LINE__);
    2283           8 :         TEST_DEVMODE_INT(8, pelsheight,         8, pelsheight, __LINE__);
    2284           8 :         TEST_DEVMODE_INT(8, displayflags,       8, displayflags, __LINE__);
    2285           8 :         TEST_DEVMODE_INT(8, displayfrequency,   8, displayfrequency, __LINE__);
    2286           8 :         TEST_DEVMODE_INT(8, icmmethod,          8, icmmethod, __LINE__);
    2287           8 :         TEST_DEVMODE_INT(8, icmintent,          8, icmintent, __LINE__);
    2288           8 :         TEST_DEVMODE_INT(8, mediatype,          8, mediatype, __LINE__);
    2289           8 :         TEST_DEVMODE_INT(8, dithertype,         8, dithertype, __LINE__);
    2290           8 :         TEST_DEVMODE_INT(8, reserved1,          8, reserved1, __LINE__);
    2291           8 :         TEST_DEVMODE_INT(8, reserved2,          8, reserved2, __LINE__);
    2292           8 :         TEST_DEVMODE_INT(8, panningwidth,       8, panningwidth, __LINE__);
    2293           8 :         TEST_DEVMODE_INT(8, panningheight,      8, panningheight, __LINE__);
    2294             : 
    2295           8 :         return ret;
    2296             : }
    2297             : 
    2298             : static bool call_OpenPrinterEx(struct torture_context *tctx,
    2299             :                                struct dcerpc_pipe *p,
    2300             :                                const char *name,
    2301             :                                struct spoolss_DeviceMode *devmode,
    2302             :                                struct policy_handle *handle);
    2303             : 
    2304           8 : static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
    2305             :                                       struct dcerpc_pipe *p,
    2306             :                                       struct policy_handle *handle,
    2307             :                                       const char *name)
    2308             : {
    2309             :         union spoolss_PrinterInfo info;
    2310             :         struct spoolss_DeviceMode *devmode;
    2311             :         struct spoolss_DeviceMode *devmode2;
    2312             :         struct policy_handle handle_devmode;
    2313           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    2314             : 
    2315             :         /* simply compare level8 and level2 devmode */
    2316             : 
    2317           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2318             : 
    2319           8 :         devmode = info.info8.devmode;
    2320             : 
    2321           8 :         if (devmode && devmode->size == 0) {
    2322           0 :                 torture_fail(tctx,
    2323             :                         "devmode of zero size!");
    2324             :         }
    2325             : 
    2326           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2327             : 
    2328           8 :         devmode2 = info.info2.devmode;
    2329             : 
    2330           8 :         if (devmode2 && devmode2->size == 0) {
    2331           0 :                 torture_fail(tctx,
    2332             :                         "devmode of zero size!");
    2333             :         }
    2334             : 
    2335           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2336             :                 "DM level 8 != DM level 2");
    2337             : 
    2338             : 
    2339             :         /* set devicemode level 8 and see if it persists */
    2340             : 
    2341           8 :         devmode->copies = 93;
    2342           8 :         devmode->formname = talloc_strdup(tctx, "Legal");
    2343             : 
    2344           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
    2345             : 
    2346           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2347             : 
    2348           8 :         devmode2 = info.info8.devmode;
    2349             : 
    2350           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2351             :                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
    2352             : 
    2353           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2354             : 
    2355           8 :         devmode2 = info.info2.devmode;
    2356             : 
    2357           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2358             :                 "modified DM level 8 != DM level 2");
    2359             : 
    2360             : 
    2361             :         /* set devicemode level 2 and see if it persists */
    2362             : 
    2363           8 :         devmode->copies = 39;
    2364           8 :         devmode->formname = talloc_strdup(tctx, "Executive");
    2365             : 
    2366           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
    2367             : 
    2368           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2369             : 
    2370           8 :         devmode2 = info.info8.devmode;
    2371             : 
    2372           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2373             :                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
    2374             : 
    2375           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2376             : 
    2377           8 :         devmode2 = info.info2.devmode;
    2378             : 
    2379           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2380             :                 "modified DM level 8 != DM level 2");
    2381             : 
    2382             : 
    2383             :         /* check every single bit in public part of devicemode */
    2384             : 
    2385           8 :         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
    2386             :                 "failed to set every single devicemode component");
    2387             : 
    2388             : 
    2389             :         /* change formname upon open and see if it persists in getprinter calls */
    2390             : 
    2391           8 :         devmode->formname = talloc_strdup(tctx, "A4");
    2392           8 :         devmode->copies = 42;
    2393             : 
    2394           8 :         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
    2395             :                 "failed to open printer handle");
    2396             : 
    2397           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
    2398             : 
    2399           8 :         devmode2 = info.info8.devmode;
    2400             : 
    2401           8 :         if (strequal(devmode->devicename, devmode2->devicename)) {
    2402           0 :                 torture_warning(tctx, "devicenames are the same\n");
    2403             :         } else {
    2404           8 :                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
    2405           8 :                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
    2406             :         }
    2407             : 
    2408           8 :         if (strequal(devmode->formname, devmode2->formname)) {
    2409           0 :                 torture_warning(tctx, "formname are the same\n");
    2410             :         } else {
    2411           8 :                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
    2412           8 :                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
    2413             :         }
    2414             : 
    2415           8 :         if (devmode->copies == devmode2->copies) {
    2416           0 :                 torture_warning(tctx, "copies are the same\n");
    2417             :         } else {
    2418           8 :                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
    2419           8 :                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
    2420             :         }
    2421             : 
    2422           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
    2423             : 
    2424           8 :         devmode2 = info.info2.devmode;
    2425             : 
    2426           8 :         if (strequal(devmode->devicename, devmode2->devicename)) {
    2427           0 :                 torture_warning(tctx, "devicenames are the same\n");
    2428             :         } else {
    2429           8 :                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
    2430           8 :                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
    2431             :         }
    2432             : 
    2433           8 :         if (strequal(devmode->formname, devmode2->formname)) {
    2434           0 :                 torture_warning(tctx, "formname is the same\n");
    2435             :         } else {
    2436           8 :                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
    2437           8 :                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
    2438             :         }
    2439             : 
    2440           8 :         if (devmode->copies == devmode2->copies) {
    2441           0 :                 torture_warning(tctx, "copies are the same\n");
    2442             :         } else {
    2443           8 :                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
    2444           8 :                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
    2445             :         }
    2446             : 
    2447           8 :         test_ClosePrinter(tctx, b, &handle_devmode);
    2448             : 
    2449           8 :         return true;
    2450             : }
    2451             : 
    2452             : /*
    2453             :  * wrapper call that saves original devmode, runs tests, and restores devmode
    2454             :  */
    2455             : 
    2456           8 : static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
    2457             :                                      struct dcerpc_pipe *p,
    2458             :                                      struct policy_handle *handle,
    2459             :                                      const char *name,
    2460             :                                      struct spoolss_DeviceMode *addprinter_devmode)
    2461             : {
    2462             :         union spoolss_PrinterInfo info;
    2463             :         struct spoolss_DeviceMode *devmode;
    2464           8 :         bool ret = true;
    2465           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    2466             : 
    2467           8 :         torture_comment(tctx, "Testing Printer Devicemodes\n");
    2468             : 
    2469             :         /* save original devmode */
    2470             : 
    2471           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
    2472             :                 "failed to get initial global devicemode");
    2473             : 
    2474           8 :         devmode = info.info8.devmode;
    2475             : 
    2476           8 :         if (devmode && devmode->size == 0) {
    2477           0 :                 torture_fail(tctx,
    2478             :                         "devmode of zero size!");
    2479             :         }
    2480             : 
    2481           8 :         if (addprinter_devmode) {
    2482           0 :                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
    2483           0 :                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
    2484             :                 }
    2485             :         }
    2486             : 
    2487             :         /* run tests */
    2488             : 
    2489           8 :         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
    2490             : 
    2491             :         /* restore original devmode */
    2492             : 
    2493           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
    2494             :                 "failed to restore initial global device mode");
    2495             : 
    2496           8 :         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
    2497             :                 ret ? "succeeded" : "failed");
    2498             : 
    2499             : 
    2500           8 :         return ret;
    2501             : }
    2502             : 
    2503         574 : bool test_ClosePrinter(struct torture_context *tctx,
    2504             :                        struct dcerpc_binding_handle *b,
    2505             :                        struct policy_handle *handle)
    2506             : {
    2507             :         NTSTATUS status;
    2508             :         struct spoolss_ClosePrinter r;
    2509             : 
    2510         574 :         r.in.handle = handle;
    2511         574 :         r.out.handle = handle;
    2512             : 
    2513         574 :         torture_comment(tctx, "Testing ClosePrinter\n");
    2514             : 
    2515         574 :         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
    2516         574 :         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
    2517         574 :         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
    2518             : 
    2519         574 :         return true;
    2520             : }
    2521             : 
    2522        2520 : static bool test_GetForm_args(struct torture_context *tctx,
    2523             :                               struct dcerpc_binding_handle *b,
    2524             :                               struct policy_handle *handle,
    2525             :                               const char *form_name,
    2526             :                               uint32_t level,
    2527             :                               union spoolss_FormInfo *info_p)
    2528             : {
    2529             :         NTSTATUS status;
    2530             :         struct spoolss_GetForm r;
    2531             :         uint32_t needed;
    2532             : 
    2533        2520 :         r.in.handle = handle;
    2534        2520 :         r.in.form_name = form_name;
    2535        2520 :         r.in.level = level;
    2536        2520 :         r.in.buffer = NULL;
    2537        2520 :         r.in.offered = 0;
    2538        2520 :         r.out.needed = &needed;
    2539             : 
    2540        2520 :         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
    2541             : 
    2542        2520 :         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
    2543        2520 :         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
    2544             : 
    2545        2520 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    2546        2520 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    2547        2520 :                 r.in.buffer = &blob;
    2548        2520 :                 r.in.offered = needed;
    2549        2520 :                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
    2550        2520 :                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
    2551             : 
    2552        2520 :                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
    2553             : 
    2554        2520 :                 torture_assert(tctx, r.out.info, "No form info returned");
    2555             :         }
    2556             : 
    2557        2520 :         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
    2558             : 
    2559        2520 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
    2560             : 
    2561        2520 :         if (info_p) {
    2562         160 :                 *info_p = *r.out.info;
    2563             :         }
    2564             : 
    2565        2520 :         return true;
    2566             : }
    2567             : 
    2568        2360 : static bool test_GetForm(struct torture_context *tctx,
    2569             :                          struct dcerpc_binding_handle *b,
    2570             :                          struct policy_handle *handle,
    2571             :                          const char *form_name,
    2572             :                          uint32_t level)
    2573             : {
    2574        2360 :         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
    2575             : }
    2576             : 
    2577         288 : static bool test_EnumForms(struct torture_context *tctx,
    2578             :                            struct dcerpc_binding_handle *b,
    2579             :                            struct policy_handle *handle,
    2580             :                            bool print_server,
    2581             :                            uint32_t level,
    2582             :                            uint32_t *count_p,
    2583             :                            union spoolss_FormInfo **info_p)
    2584             : {
    2585             :         struct spoolss_EnumForms r;
    2586             :         uint32_t needed;
    2587             :         uint32_t count;
    2588             :         union spoolss_FormInfo *info;
    2589             : 
    2590         288 :         r.in.handle = handle;
    2591         288 :         r.in.level = level;
    2592         288 :         r.in.buffer = NULL;
    2593         288 :         r.in.offered = 0;
    2594         288 :         r.out.needed = &needed;
    2595         288 :         r.out.count = &count;
    2596         288 :         r.out.info = &info;
    2597             : 
    2598         288 :         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
    2599             : 
    2600         288 :         torture_assert_ntstatus_ok(tctx,
    2601             :                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
    2602             :                 "EnumForms failed");
    2603             : 
    2604         288 :         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL))) {
    2605          24 :                 torture_skip(tctx, "EnumForms level 2 not supported");
    2606             :         }
    2607             : 
    2608         264 :         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_INVALID_HANDLE)) {
    2609           0 :                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
    2610             :         }
    2611             : 
    2612         264 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    2613         264 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    2614         264 :                 r.in.buffer = &blob;
    2615         264 :                 r.in.offered = needed;
    2616             : 
    2617         264 :                 torture_assert_ntstatus_ok(tctx,
    2618             :                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
    2619             :                         "EnumForms failed");
    2620             : 
    2621         264 :                 torture_assert(tctx, info, "No forms returned");
    2622             :         }
    2623             : 
    2624         264 :         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
    2625             : 
    2626         264 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
    2627             : 
    2628         264 :         if (info_p) {
    2629         264 :                 *info_p = info;
    2630             :         }
    2631         264 :         if (count_p) {
    2632         264 :                 *count_p = count;
    2633             :         }
    2634             : 
    2635         264 :         return true;
    2636             : }
    2637             : 
    2638          24 : static bool test_EnumForms_all(struct torture_context *tctx,
    2639             :                                struct dcerpc_binding_handle *b,
    2640             :                                struct policy_handle *handle,
    2641             :                                bool print_server)
    2642             : {
    2643          24 :         uint32_t levels[] = { 1, 2 };
    2644             :         int i, j;
    2645             : 
    2646         126 :         for (i=0; i<ARRAY_SIZE(levels); i++) {
    2647             : 
    2648          48 :                 uint32_t count = 0;
    2649          48 :                 union spoolss_FormInfo *info = NULL;
    2650             : 
    2651          48 :                 torture_assert(tctx,
    2652             :                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
    2653             :                         "failed to enum forms");
    2654             : 
    2655        2880 :                 for (j = 0; j < count; j++) {
    2656        2832 :                         if (!print_server) {
    2657        2360 :                                 torture_assert(tctx,
    2658             :                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
    2659             :                                         "failed to get form");
    2660             :                         }
    2661             :                 }
    2662             :         }
    2663             : 
    2664          24 :         return true;
    2665             : }
    2666             : 
    2667         240 : static bool test_EnumForms_find_one(struct torture_context *tctx,
    2668             :                                     struct dcerpc_binding_handle *b,
    2669             :                                     struct policy_handle *handle,
    2670             :                                     bool print_server,
    2671             :                                     const char *form_name)
    2672             : {
    2673         240 :         union spoolss_FormInfo *info = NULL;
    2674         240 :         uint32_t count = 0;
    2675         240 :         bool found = false;
    2676             :         int i;
    2677             : 
    2678         240 :         torture_assert(tctx,
    2679             :                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
    2680             :                 "failed to enumerate forms");
    2681             : 
    2682       11568 :         for (i=0; i<count; i++) {
    2683       11568 :                 if (strequal(form_name, info[i].info1.form_name)) {
    2684         240 :                         found = true;
    2685         240 :                         break;
    2686             :                 }
    2687             :         }
    2688             : 
    2689         240 :         return found;
    2690             : }
    2691             : 
    2692         288 : static bool test_DeleteForm(struct torture_context *tctx,
    2693             :                             struct dcerpc_binding_handle *b,
    2694             :                             struct policy_handle *handle,
    2695             :                             const char *form_name,
    2696             :                             WERROR expected_result)
    2697             : {
    2698             :         struct spoolss_DeleteForm r;
    2699             : 
    2700         288 :         r.in.handle = handle;
    2701         288 :         r.in.form_name = form_name;
    2702             : 
    2703         288 :         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
    2704             : 
    2705         288 :         torture_assert_ntstatus_ok(tctx,
    2706             :                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
    2707             :                 "DeleteForm failed");
    2708         288 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    2709             :                 "DeleteForm gave unexpected result");
    2710         288 :         if (W_ERROR_IS_OK(r.out.result)) {
    2711          96 :                 torture_assert_ntstatus_ok(tctx,
    2712             :                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
    2713             :                         "2nd DeleteForm failed");
    2714          96 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
    2715             :                         "2nd DeleteForm failed");
    2716             :         }
    2717             : 
    2718         288 :         return true;
    2719             : }
    2720             : 
    2721         288 : static bool test_AddForm(struct torture_context *tctx,
    2722             :                          struct dcerpc_binding_handle *b,
    2723             :                          struct policy_handle *handle,
    2724             :                          uint32_t level,
    2725             :                          union spoolss_AddFormInfo *info,
    2726             :                          WERROR expected_result)
    2727             : {
    2728             :         struct spoolss_AddForm r;
    2729             :         struct spoolss_AddFormInfoCtr info_ctr;
    2730             : 
    2731         288 :         info_ctr.level = level;
    2732         288 :         info_ctr.info = *info;
    2733             : 
    2734         288 :         if (level != 1) {
    2735           0 :                 torture_skip(tctx, "only level 1 supported");
    2736             :         }
    2737             : 
    2738         288 :         r.in.handle     = handle;
    2739         288 :         r.in.info_ctr   = &info_ctr;
    2740             : 
    2741         288 :         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
    2742         288 :                 r.in.info_ctr->info.info1->form_name, level,
    2743         288 :                 r.in.info_ctr->info.info1->flags);
    2744             : 
    2745         288 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
    2746             :                 "AddForm failed");
    2747         288 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    2748             :                 "AddForm gave unexpected result");
    2749             : 
    2750         288 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
    2751             :                 "2nd AddForm failed");
    2752         288 :         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAMETER)) {
    2753          48 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    2754             :                         "2nd AddForm gave unexpected result");
    2755             :         } else {
    2756         240 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
    2757             :                         "2nd AddForm gave unexpected result");
    2758             :         }
    2759             : 
    2760         288 :         return true;
    2761             : }
    2762             : 
    2763          80 : static bool test_SetForm(struct torture_context *tctx,
    2764             :                          struct dcerpc_binding_handle *b,
    2765             :                          struct policy_handle *handle,
    2766             :                          const char *form_name,
    2767             :                          uint32_t level,
    2768             :                          union spoolss_AddFormInfo *info)
    2769             : {
    2770             :         struct spoolss_SetForm r;
    2771             :         struct spoolss_AddFormInfoCtr info_ctr;
    2772             : 
    2773          80 :         info_ctr.level  = level;
    2774          80 :         info_ctr.info   = *info;
    2775             : 
    2776          80 :         r.in.handle     = handle;
    2777          80 :         r.in.form_name  = form_name;
    2778          80 :         r.in.info_ctr   = &info_ctr;
    2779             : 
    2780          80 :         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
    2781             :                 form_name, level);
    2782             : 
    2783          80 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
    2784             :                 "SetForm failed");
    2785             : 
    2786          80 :         torture_assert_werr_ok(tctx, r.out.result,
    2787             :                 "SetForm failed");
    2788             : 
    2789          80 :         return true;
    2790             : }
    2791             : 
    2792             : static bool test_GetForm_winreg(struct torture_context *tctx,
    2793             :                                 struct dcerpc_binding_handle *b,
    2794             :                                 struct policy_handle *handle,
    2795             :                                 const char *key_name,
    2796             :                                 const char *form_name,
    2797             :                                 enum winreg_Type *w_type,
    2798             :                                 uint32_t *w_size,
    2799             :                                 uint32_t *w_length,
    2800             :                                 uint8_t **w_data);
    2801             : 
    2802         288 : static bool test_Forms_args(struct torture_context *tctx,
    2803             :                             struct dcerpc_binding_handle *b,
    2804             :                             struct policy_handle *handle,
    2805             :                             bool print_server,
    2806             :                             const char *printer_name,
    2807             :                             struct dcerpc_binding_handle *winreg_handle,
    2808             :                             struct policy_handle *hive_handle,
    2809             :                             const char *form_name,
    2810             :                             struct spoolss_AddFormInfo1 *info1,
    2811             :                             WERROR expected_add_result,
    2812             :                             WERROR expected_delete_result)
    2813             : {
    2814             :         union spoolss_FormInfo info;
    2815             :         union spoolss_AddFormInfo add_info;
    2816             : 
    2817             :         enum winreg_Type w_type;
    2818             :         uint32_t w_size;
    2819             :         uint32_t w_length;
    2820             :         uint8_t *w_data;
    2821             : 
    2822         288 :         add_info.info1 = info1;
    2823             : 
    2824         288 :         torture_assert(tctx,
    2825             :                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
    2826             :                 "failed to add form");
    2827             : 
    2828         288 :         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
    2829             : 
    2830             :                 struct spoolss_FormInfo1 i1;
    2831             : 
    2832          48 :                 torture_assert(tctx,
    2833             :                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
    2834             :                         "failed to get form via winreg");
    2835             : 
    2836          48 :                 i1.size.width   = IVAL(w_data, 0);
    2837          48 :                 i1.size.height  = IVAL(w_data, 4);
    2838          48 :                 i1.area.left    = IVAL(w_data, 8);
    2839          48 :                 i1.area.top     = IVAL(w_data, 12);
    2840          48 :                 i1.area.right   = IVAL(w_data, 16);
    2841          48 :                 i1.area.bottom  = IVAL(w_data, 20);
    2842             :                 /* skip index here */
    2843          48 :                 i1.flags        = IVAL(w_data, 28);
    2844             : 
    2845          48 :                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
    2846          48 :                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
    2847          48 :                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
    2848          48 :                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
    2849          48 :                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
    2850          48 :                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
    2851          48 :                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
    2852          48 :                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
    2853          48 :                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
    2854          48 :                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
    2855             :         }
    2856             : 
    2857         288 :         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
    2858          80 :                 torture_assert(tctx,
    2859             :                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
    2860             :                         "failed to get added form");
    2861             : 
    2862          80 :                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
    2863          80 :                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
    2864          80 :                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
    2865          80 :                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
    2866          80 :                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
    2867          80 :                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
    2868          80 :                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
    2869             : 
    2870          80 :                 if (winreg_handle && hive_handle) {
    2871             : 
    2872             :                         struct spoolss_FormInfo1 i1;
    2873             : 
    2874          40 :                         i1.size.width   = IVAL(w_data, 0);
    2875          40 :                         i1.size.height  = IVAL(w_data, 4);
    2876          40 :                         i1.area.left    = IVAL(w_data, 8);
    2877          40 :                         i1.area.top     = IVAL(w_data, 12);
    2878          40 :                         i1.area.right   = IVAL(w_data, 16);
    2879          40 :                         i1.area.bottom  = IVAL(w_data, 20);
    2880             :                         /* skip index here */
    2881          40 :                         i1.flags        = IVAL(w_data, 28);
    2882             : 
    2883          40 :                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
    2884          40 :                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
    2885          40 :                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
    2886          40 :                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
    2887          40 :                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
    2888          40 :                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
    2889          40 :                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
    2890             :                 }
    2891             : 
    2892          80 :                 add_info.info1->size.width = 1234;
    2893             : 
    2894          80 :                 torture_assert(tctx,
    2895             :                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
    2896             :                         "failed to set form");
    2897          80 :                 torture_assert(tctx,
    2898             :                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
    2899             :                         "failed to get set form");
    2900             : 
    2901          80 :                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
    2902             :         }
    2903             : 
    2904         288 :         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAMETER)) {
    2905         240 :                 torture_assert(tctx,
    2906             :                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
    2907             :                         "Newly added form not found in enum call");
    2908             :         }
    2909             : 
    2910         288 :         torture_assert(tctx,
    2911             :                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
    2912             :                 "failed to delete form");
    2913             : 
    2914         288 :         return true;
    2915             : }
    2916             : 
    2917          48 : static bool test_Forms(struct torture_context *tctx,
    2918             :                        struct dcerpc_binding_handle *b,
    2919             :                        struct policy_handle *handle,
    2920             :                        bool print_server,
    2921             :                        const char *printer_name,
    2922             :                        struct dcerpc_binding_handle *winreg_handle,
    2923             :                        struct policy_handle *hive_handle)
    2924             : {
    2925             :         const struct spoolss_FormSize size = {
    2926             :                 .width  = 50,
    2927             :                 .height = 25
    2928             :         };
    2929             :         const struct spoolss_FormArea area = {
    2930             :                 .left   = 5,
    2931             :                 .top    = 10,
    2932             :                 .right  = 45,
    2933             :                 .bottom = 15
    2934             :         };
    2935             :         int i;
    2936             : 
    2937             :         struct {
    2938             :                 struct spoolss_AddFormInfo1 info1;
    2939             :                 WERROR expected_add_result;
    2940             :                 WERROR expected_delete_result;
    2941          48 :         } forms[] = {
    2942             :                 {
    2943             :                         .info1 = {
    2944             :                                 .flags          = SPOOLSS_FORM_USER,
    2945             :                                 .form_name      = "testform_user",
    2946             :                                 .size           = size,
    2947             :                                 .area           = area,
    2948             :                         },
    2949             :                         .expected_add_result    = WERR_OK,
    2950             :                         .expected_delete_result = WERR_OK
    2951             :                 },
    2952             : /*
    2953             :                 weird, we can add a builtin form but we can never remove it
    2954             :                 again - gd
    2955             : 
    2956             :                 {
    2957             :                         .info1 = {
    2958             :                                 .flags          = SPOOLSS_FORM_BUILTIN,
    2959             :                                 .form_name      = "testform_builtin",
    2960             :                                 .size           = size,
    2961             :                                 .area           = area,
    2962             :                         },
    2963             :                         .expected_add_result    = WERR_OK,
    2964             :                         .expected_delete_result = WERR_INVALID_PARAMETER,
    2965             :                 },
    2966             : */
    2967             :                 {
    2968             :                         .info1 = {
    2969             :                                 .flags          = SPOOLSS_FORM_PRINTER,
    2970             :                                 .form_name      = "testform_printer",
    2971             :                                 .size           = size,
    2972             :                                 .area           = area,
    2973             :                         },
    2974             :                         .expected_add_result    = WERR_OK,
    2975             :                         .expected_delete_result = WERR_OK
    2976             :                 },
    2977             :                 {
    2978             :                         .info1 = {
    2979             :                                 .flags          = SPOOLSS_FORM_USER,
    2980             :                                 .form_name      = "Letter",
    2981             :                                 .size           = size,
    2982             :                                 .area           = area,
    2983             :                         },
    2984             :                         .expected_add_result    = WERR_FILE_EXISTS,
    2985             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    2986             :                 },
    2987             :                 {
    2988             :                         .info1 = {
    2989             :                                 .flags          = SPOOLSS_FORM_BUILTIN,
    2990             :                                 .form_name      = "Letter",
    2991             :                                 .size           = size,
    2992             :                                 .area           = area,
    2993             :                         },
    2994             :                         .expected_add_result    = WERR_FILE_EXISTS,
    2995             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    2996             :                 },
    2997             :                 {
    2998             :                         .info1 = {
    2999             :                                 .flags          = SPOOLSS_FORM_PRINTER,
    3000             :                                 .form_name      = "Letter",
    3001             :                                 .size           = size,
    3002             :                                 .area           = area,
    3003             :                         },
    3004             :                         .expected_add_result    = WERR_FILE_EXISTS,
    3005             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    3006             :                 },
    3007             :                 {
    3008             :                         .info1 = {
    3009             :                                 .flags          = 12345,
    3010             :                                 .form_name      = "invalid_flags",
    3011             :                                 .size           = size,
    3012             :                                 .area           = area,
    3013             :                         },
    3014             :                         .expected_add_result    = WERR_INVALID_PARAMETER,
    3015             :                         .expected_delete_result = WERR_INVALID_FORM_NAME
    3016             :                 }
    3017             : 
    3018             :         };
    3019             : 
    3020         336 :         for (i=0; i < ARRAY_SIZE(forms); i++) {
    3021         288 :                 torture_assert(tctx,
    3022             :                         test_Forms_args(tctx, b, handle, print_server, printer_name,
    3023             :                                         winreg_handle, hive_handle,
    3024             :                                         forms[i].info1.form_name,
    3025             :                                         &forms[i].info1,
    3026             :                                         forms[i].expected_add_result,
    3027             :                                         forms[i].expected_delete_result),
    3028             :                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
    3029             :         }
    3030             : 
    3031          48 :         return true;
    3032             : }
    3033             : 
    3034           4 : static bool test_EnumPorts_old(struct torture_context *tctx,
    3035             :                                void *private_data)
    3036             : {
    3037           3 :         struct test_spoolss_context *ctx =
    3038           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    3039             : 
    3040             :         NTSTATUS status;
    3041             :         struct spoolss_EnumPorts r;
    3042             :         uint32_t needed;
    3043             :         uint32_t count;
    3044             :         union spoolss_PortInfo *info;
    3045           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    3046           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    3047             : 
    3048           4 :         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
    3049             :                                           dcerpc_server_name(p));
    3050           4 :         r.in.level = 2;
    3051           4 :         r.in.buffer = NULL;
    3052           4 :         r.in.offered = 0;
    3053           4 :         r.out.needed = &needed;
    3054           4 :         r.out.count = &count;
    3055           4 :         r.out.info = &info;
    3056             : 
    3057           4 :         torture_comment(tctx, "Testing EnumPorts\n");
    3058             : 
    3059           4 :         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
    3060             : 
    3061           4 :         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
    3062             : 
    3063           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3064           4 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3065           4 :                 r.in.buffer = &blob;
    3066           4 :                 r.in.offered = needed;
    3067             : 
    3068           4 :                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
    3069           4 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
    3070           4 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
    3071             : 
    3072           4 :                 torture_assert(tctx, info, "No ports returned");
    3073             :         }
    3074             : 
    3075           4 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
    3076             : 
    3077           4 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
    3078             : 
    3079           4 :         return true;
    3080             : }
    3081             : 
    3082           4 : static bool test_AddPort(struct torture_context *tctx,
    3083             :                          void *private_data)
    3084             : {
    3085           3 :         struct test_spoolss_context *ctx =
    3086           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    3087             : 
    3088             :         NTSTATUS status;
    3089             :         struct spoolss_AddPort r;
    3090           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    3091           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    3092             : 
    3093           4 :         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
    3094             :                                            dcerpc_server_name(p));
    3095           4 :         r.in.unknown = 0;
    3096           4 :         r.in.monitor_name = "foo";
    3097             : 
    3098           4 :         torture_comment(tctx, "Testing AddPort\n");
    3099             : 
    3100           4 :         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
    3101             : 
    3102           4 :         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
    3103             : 
    3104             :         /* win2k3 returns WERR_NOT_SUPPORTED */
    3105             : 
    3106             : #if 0
    3107             : 
    3108             :         if (!W_ERROR_IS_OK(r.out.result)) {
    3109             :                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
    3110             :                 return false;
    3111             :         }
    3112             : 
    3113             : #endif
    3114             : 
    3115           4 :         return true;
    3116             : }
    3117             : 
    3118        1984 : static bool test_GetJob_args(struct torture_context *tctx,
    3119             :                              struct dcerpc_binding_handle *b,
    3120             :                              struct policy_handle *handle,
    3121             :                              uint32_t job_id,
    3122             :                              uint32_t level,
    3123             :                              union spoolss_JobInfo *info_p)
    3124             : {
    3125             :         NTSTATUS status;
    3126             :         struct spoolss_GetJob r;
    3127             :         union spoolss_JobInfo info;
    3128             :         uint32_t needed;
    3129             : 
    3130        1984 :         r.in.handle = handle;
    3131        1984 :         r.in.job_id = job_id;
    3132        1984 :         r.in.level = level;
    3133        1984 :         r.in.buffer = NULL;
    3134        1984 :         r.in.offered = 0;
    3135        1984 :         r.out.needed = &needed;
    3136        1984 :         r.out.info = &info;
    3137             : 
    3138        1984 :         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
    3139             : 
    3140        1984 :         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
    3141        1984 :         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
    3142        1984 :         if (level == 0) {
    3143           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "Unexpected return code");
    3144             :         }
    3145             : 
    3146        1984 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3147          64 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3148          64 :                 r.in.buffer = &blob;
    3149          64 :                 r.in.offered = needed;
    3150             : 
    3151          64 :                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
    3152          64 :                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
    3153             :         }
    3154             : 
    3155        1984 :         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
    3156          64 :         torture_assert(tctx, r.out.info, "No job info returned");
    3157             : 
    3158          64 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
    3159             : 
    3160          64 :         if (info_p) {
    3161          64 :                 *info_p = *r.out.info;
    3162             :         }
    3163             : 
    3164          64 :         return true;
    3165             : }
    3166             : 
    3167             : #if 0
    3168             : static bool test_GetJob(struct torture_context *tctx,
    3169             :                         struct dcerpc_binding_handle *b,
    3170             :                         struct policy_handle *handle,
    3171             :                         uint32_t job_id)
    3172             : {
    3173             :         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
    3174             :         uint32_t i;
    3175             : 
    3176             :         for (i=0; i < ARRAY_SIZE(levels); i++) {
    3177             :                 torture_assert(tctx,
    3178             :                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
    3179             :                         "GetJob failed");
    3180             :         }
    3181             : 
    3182             :         return true;
    3183             : }
    3184             : #endif
    3185             : 
    3186         640 : static bool test_SetJob(struct torture_context *tctx,
    3187             :                         struct dcerpc_binding_handle *b,
    3188             :                         struct policy_handle *handle,
    3189             :                         uint32_t job_id,
    3190             :                         struct spoolss_JobInfoContainer *ctr,
    3191             :                         enum spoolss_JobControl command)
    3192             : {
    3193             :         NTSTATUS status;
    3194             :         struct spoolss_SetJob r;
    3195             : 
    3196         640 :         r.in.handle     = handle;
    3197         640 :         r.in.job_id     = job_id;
    3198         640 :         r.in.ctr        = ctr;
    3199         640 :         r.in.command    = command;
    3200             : 
    3201         640 :         switch (command) {
    3202          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    3203          32 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
    3204          32 :                 break;
    3205          32 :         case SPOOLSS_JOB_CONTROL_RESUME:
    3206          32 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
    3207          32 :                 break;
    3208           0 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    3209           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
    3210           0 :                 break;
    3211           0 :         case SPOOLSS_JOB_CONTROL_RESTART:
    3212           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
    3213           0 :                 break;
    3214         544 :         case SPOOLSS_JOB_CONTROL_DELETE:
    3215         544 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
    3216         544 :                 break;
    3217           0 :         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
    3218           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
    3219           0 :                 break;
    3220           0 :         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
    3221           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
    3222           0 :                 break;
    3223           0 :         case SPOOLSS_JOB_CONTROL_RETAIN:
    3224           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
    3225           0 :                 break;
    3226           0 :         case SPOOLSS_JOB_CONTROL_RELEASE:
    3227           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
    3228           0 :                 break;
    3229          32 :         default:
    3230          32 :                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
    3231          32 :                 break;
    3232             :         }
    3233             : 
    3234         640 :         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
    3235         640 :         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
    3236         640 :         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
    3237             : 
    3238         389 :         return true;
    3239             : }
    3240             : 
    3241           8 : static bool test_AddJob(struct torture_context *tctx,
    3242             :                         struct dcerpc_binding_handle *b,
    3243             :                         struct policy_handle *handle)
    3244             : {
    3245             :         NTSTATUS status;
    3246             :         struct spoolss_AddJob r;
    3247             :         uint32_t needed;
    3248             : 
    3249           8 :         r.in.level = 0;
    3250           8 :         r.in.handle = handle;
    3251           8 :         r.in.offered = 0;
    3252           8 :         r.out.needed = &needed;
    3253           8 :         r.in.buffer = r.out.buffer = NULL;
    3254             : 
    3255           8 :         torture_comment(tctx, "Testing AddJob\n");
    3256             : 
    3257           8 :         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
    3258           8 :         torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
    3259           8 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "AddJob failed");
    3260             : 
    3261           8 :         r.in.level = 1;
    3262             : 
    3263           8 :         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
    3264           8 :         torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
    3265           8 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER, "AddJob failed");
    3266             : 
    3267           8 :         return true;
    3268             : }
    3269             : 
    3270             : 
    3271          68 : static bool test_EnumJobs_args(struct torture_context *tctx,
    3272             :                                struct dcerpc_binding_handle *b,
    3273             :                                struct policy_handle *handle,
    3274             :                                uint32_t level,
    3275             :                                WERROR werr_expected,
    3276             :                                uint32_t *count_p,
    3277             :                                union spoolss_JobInfo **info_p)
    3278             : {
    3279             :         NTSTATUS status;
    3280             :         struct spoolss_EnumJobs r;
    3281             :         uint32_t needed;
    3282             :         uint32_t count;
    3283             :         union spoolss_JobInfo *info;
    3284             : 
    3285          68 :         r.in.handle = handle;
    3286          68 :         r.in.firstjob = 0;
    3287          68 :         r.in.numjobs = 0xffffffff;
    3288          68 :         r.in.level = level;
    3289          68 :         r.in.buffer = NULL;
    3290          68 :         r.in.offered = 0;
    3291          68 :         r.out.needed = &needed;
    3292          68 :         r.out.count = &count;
    3293          68 :         r.out.info = &info;
    3294             : 
    3295          68 :         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
    3296             : 
    3297          68 :         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
    3298             : 
    3299          68 :         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
    3300             : 
    3301          68 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3302          16 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3303          16 :                 r.in.buffer = &blob;
    3304          16 :                 r.in.offered = needed;
    3305             : 
    3306          16 :                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
    3307             : 
    3308          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
    3309          16 :                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
    3310             :                                           "EnumJobs failed");
    3311          16 :                 torture_assert(tctx, info, "No jobs returned");
    3312             : 
    3313          16 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
    3314             : 
    3315             :         } else {
    3316          52 :                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
    3317             :                                           "EnumJobs failed");
    3318             :         }
    3319             : 
    3320          68 :         if (count_p) {
    3321          68 :                 *count_p = count;
    3322             :         }
    3323          68 :         if (info_p) {
    3324          68 :                 *info_p = info;
    3325             :         }
    3326             : 
    3327          68 :         return true;
    3328             : }
    3329             : 
    3330           0 : static bool test_JobPropertiesEnum(struct torture_context *tctx,
    3331             :                                    struct dcerpc_binding_handle *b,
    3332             :                                    struct policy_handle *handle,
    3333             :                                    uint32_t job_id)
    3334             : {
    3335             :         struct spoolss_EnumJobNamedProperties r;
    3336           0 :         uint32_t pcProperties = 0;
    3337           0 :         struct spoolss_PrintNamedProperty *ppProperties = NULL;
    3338             : 
    3339           0 :         r.in.hPrinter = handle;
    3340           0 :         r.in.JobId = job_id;
    3341           0 :         r.out.pcProperties = &pcProperties;
    3342           0 :         r.out.ppProperties = &ppProperties;
    3343             : 
    3344           0 :         torture_comment(tctx, "Testing EnumJobNamedProperties(%d)\n", job_id);
    3345             : 
    3346           0 :         torture_assert_ntstatus_ok(tctx,
    3347             :                 dcerpc_spoolss_EnumJobNamedProperties_r(b, tctx, &r),
    3348             :                 "spoolss_EnumJobNamedProperties failed");
    3349           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3350             :                 "spoolss_EnumJobNamedProperties failed");
    3351             : 
    3352           0 :         return true;
    3353             : }
    3354             : 
    3355           0 : static bool test_JobPropertySet(struct torture_context *tctx,
    3356             :                                 struct dcerpc_binding_handle *b,
    3357             :                                 struct policy_handle *handle,
    3358             :                                 uint32_t job_id,
    3359             :                                 struct spoolss_PrintNamedProperty *property)
    3360             : {
    3361             :         struct spoolss_SetJobNamedProperty r;
    3362             : 
    3363           0 :         r.in.hPrinter = handle;
    3364           0 :         r.in.JobId = job_id;
    3365           0 :         r.in.pProperty = property;
    3366             : 
    3367           0 :         torture_comment(tctx, "Testing SetJobNamedProperty(%d) %s - %d\n",
    3368             :                 job_id, property->propertyName,
    3369           0 :                 property->propertyValue.ePropertyType);
    3370             : 
    3371           0 :         torture_assert_ntstatus_ok(tctx,
    3372             :                 dcerpc_spoolss_SetJobNamedProperty_r(b, tctx, &r),
    3373             :                 "spoolss_SetJobNamedProperty failed");
    3374           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3375             :                 "spoolss_SetJobNamedProperty failed");
    3376             : 
    3377           0 :         return true;
    3378             : }
    3379             : 
    3380           0 : static bool test_JobPropertyGetValue(struct torture_context *tctx,
    3381             :                                      struct dcerpc_binding_handle *b,
    3382             :                                      struct policy_handle *handle,
    3383             :                                      uint32_t job_id,
    3384             :                                      const char *property_name,
    3385             :                                      struct spoolss_PrintPropertyValue *value)
    3386             : {
    3387             :         struct spoolss_GetJobNamedPropertyValue r;
    3388             : 
    3389           0 :         r.in.hPrinter = handle;
    3390           0 :         r.in.JobId = job_id;
    3391           0 :         r.in.pszName = property_name;
    3392           0 :         r.out.pValue = value;
    3393             : 
    3394           0 :         torture_comment(tctx, "Testing GetJobNamedPropertyValue(%d) %s\n",
    3395             :                 job_id, property_name);
    3396             : 
    3397           0 :         torture_assert_ntstatus_ok(tctx,
    3398             :                 dcerpc_spoolss_GetJobNamedPropertyValue_r(b, tctx, &r),
    3399             :                 "spoolss_GetJobNamedPropertyValue failed");
    3400           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3401             :                 "spoolss_GetJobNamedPropertyValue failed");
    3402             : 
    3403           0 :         return true;
    3404             : }
    3405             : 
    3406           0 : static bool test_JobPropertyDelete(struct torture_context *tctx,
    3407             :                                    struct dcerpc_binding_handle *b,
    3408             :                                    struct policy_handle *handle,
    3409             :                                    uint32_t job_id,
    3410             :                                    const char *property_name)
    3411             : {
    3412             :         struct spoolss_DeleteJobNamedProperty r;
    3413             : 
    3414           0 :         r.in.hPrinter = handle;
    3415           0 :         r.in.JobId = job_id;
    3416           0 :         r.in.pszName = property_name;
    3417             : 
    3418           0 :         torture_comment(tctx, "Testing DeleteJobNamedProperty(%d) %s\n",
    3419             :                 job_id, property_name);
    3420             : 
    3421           0 :         torture_assert_ntstatus_ok(tctx,
    3422             :                 dcerpc_spoolss_DeleteJobNamedProperty_r(b, tctx, &r),
    3423             :                 "spoolss_DeleteJobNamedProperty failed");
    3424           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3425             :                 "spoolss_DeleteJobNamedProperty failed");
    3426             : 
    3427           0 :         return true;
    3428             : }
    3429             : 
    3430         640 : static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
    3431             :                                          struct dcerpc_binding_handle *b,
    3432             :                                          struct policy_handle *handle,
    3433             :                                          const char *document_name,
    3434             :                                          const char *datatype,
    3435             :                                          uint32_t *job_id)
    3436             : {
    3437             :         NTSTATUS status;
    3438             :         struct spoolss_StartDocPrinter s;
    3439             :         struct spoolss_DocumentInfoCtr info_ctr;
    3440             :         struct spoolss_DocumentInfo1 info1;
    3441             :         struct spoolss_StartPagePrinter sp;
    3442             :         struct spoolss_WritePrinter w;
    3443             :         struct spoolss_EndPagePrinter ep;
    3444             :         struct spoolss_EndDocPrinter e;
    3445             :         int i;
    3446             :         uint32_t num_written;
    3447             : 
    3448         640 :         torture_comment(tctx, "Testing StartDocPrinter\n");
    3449             : 
    3450         640 :         s.in.handle             = handle;
    3451         640 :         s.in.info_ctr           = &info_ctr;
    3452         640 :         s.out.job_id            = job_id;
    3453             : 
    3454         640 :         info1.document_name     = document_name;
    3455         640 :         info1.output_file       = NULL;
    3456         640 :         info1.datatype          = datatype;
    3457             : 
    3458         640 :         info_ctr.level          = 1;
    3459         640 :         info_ctr.info.info1     = &info1;
    3460             : 
    3461         640 :         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
    3462         640 :         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
    3463         640 :         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
    3464             : 
    3465        2560 :         for (i=1; i < 4; i++) {
    3466             :                 union spoolss_JobInfo ginfo;
    3467             :                 bool ok;
    3468             : 
    3469        1920 :                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3470             : 
    3471        1920 :                 sp.in.handle            = handle;
    3472             : 
    3473        1920 :                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
    3474        1920 :                 torture_assert_ntstatus_ok(tctx, status,
    3475             :                                            "dcerpc_spoolss_StartPagePrinter failed");
    3476        1920 :                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
    3477             : 
    3478        1920 :                 ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
    3479        1920 :                 if (!ok) {
    3480        1920 :                         torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
    3481             :                 }
    3482             : 
    3483        1920 :                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3484             : 
    3485        1920 :                 w.in.handle             = handle;
    3486        1920 :                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
    3487        1920 :                 w.out.num_written       = &num_written;
    3488             : 
    3489        1920 :                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
    3490        1920 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
    3491        1920 :                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
    3492             : 
    3493        1920 :                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3494             : 
    3495        1920 :                 ep.in.handle            = handle;
    3496             : 
    3497        1920 :                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
    3498        1920 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
    3499        1920 :                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
    3500             :         }
    3501             : 
    3502         640 :         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
    3503             : 
    3504         640 :         e.in.handle = handle;
    3505             : 
    3506         640 :         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
    3507         640 :         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
    3508         640 :         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
    3509             : 
    3510         352 :         return true;
    3511             : }
    3512             : 
    3513         416 : static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
    3514             :                                          struct dcerpc_binding_handle *b,
    3515             :                                          struct policy_handle *handle,
    3516             :                                          const char *document_name,
    3517             :                                          uint32_t *job_id)
    3518             : {
    3519         416 :         test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
    3520             : 
    3521         416 :         return true;
    3522             : }
    3523             : 
    3524         224 : static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
    3525             :                                          struct dcerpc_binding_handle *b,
    3526             :                                          struct policy_handle *handle,
    3527             :                                          const char *document_name,
    3528             :                                          uint32_t *job_id)
    3529             : {
    3530         224 :         test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
    3531             : 
    3532         224 :         return true;
    3533             : }
    3534             : 
    3535             : 
    3536           8 : static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
    3537             :                                         struct dcerpc_binding_handle *b,
    3538             :                                         struct policy_handle *handle,
    3539             :                                         uint32_t num_jobs,
    3540             :                                         uint32_t *job_ids)
    3541             : {
    3542             :         uint32_t count;
    3543           8 :         union spoolss_JobInfo *info = NULL;
    3544             :         int i;
    3545             : 
    3546           8 :         torture_assert(tctx,
    3547             :                 test_AddJob(tctx, b, handle),
    3548             :                 "AddJob failed");
    3549             : 
    3550           8 :         torture_assert(tctx,
    3551             :                 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
    3552             :                 "EnumJobs level 1 failed");
    3553             : 
    3554           8 :         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
    3555             : 
    3556          54 :         for (i=0; i < num_jobs; i++) {
    3557             :                 union spoolss_JobInfo ginfo;
    3558             :                 const char *document_name;
    3559          32 :                 const char *new_document_name = "any_other_docname";
    3560             :                 struct spoolss_JobInfoContainer ctr;
    3561             :                 struct spoolss_SetJobInfo1 info1;
    3562             : 
    3563          32 :                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
    3564             : 
    3565          32 :                 torture_assert(tctx,
    3566             :                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
    3567             :                         "failed to call test_GetJob");
    3568             : 
    3569          32 :                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
    3570             : 
    3571          32 :                 document_name = ginfo.info1.document_name;
    3572             : 
    3573          32 :                 info1.job_id            = ginfo.info1.job_id;
    3574          32 :                 info1.printer_name      = ginfo.info1.printer_name;
    3575          32 :                 info1.server_name       = ginfo.info1.server_name;
    3576          32 :                 info1.user_name         = ginfo.info1.user_name;
    3577          32 :                 info1.document_name     = new_document_name;
    3578          32 :                 info1.data_type         = ginfo.info1.data_type;
    3579          32 :                 info1.text_status       = ginfo.info1.text_status;
    3580          32 :                 info1.status            = ginfo.info1.status;
    3581          32 :                 info1.priority          = ginfo.info1.priority;
    3582          32 :                 info1.position          = ginfo.info1.position;
    3583          32 :                 info1.total_pages       = ginfo.info1.total_pages;
    3584          32 :                 info1.pages_printed     = ginfo.info1.pages_printed;
    3585          32 :                 info1.submitted         = ginfo.info1.submitted;
    3586             : 
    3587          32 :                 ctr.level = 1;
    3588          32 :                 ctr.info.info1 = &info1;
    3589             : 
    3590          32 :                 torture_assert(tctx,
    3591             :                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
    3592             :                         "failed to call test_SetJob level 1");
    3593             : 
    3594          32 :                 torture_assert(tctx,
    3595             :                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
    3596             :                         "failed to call test_GetJob");
    3597             : 
    3598          32 :                 if (strequal(ginfo.info1.document_name, document_name)) {
    3599          30 :                         torture_warning(tctx,
    3600             :                                         "document_name did *NOT* change from '%s' to '%s'\n",
    3601             :                                         document_name, new_document_name);
    3602             :                 }
    3603             :         }
    3604             : 
    3605          36 :         for (i=0; i < num_jobs; i++) {
    3606          32 :                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
    3607           0 :                         torture_warning(tctx, "failed to pause printjob\n");
    3608             :                 }
    3609          32 :                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
    3610           0 :                         torture_warning(tctx, "failed to resume printjob\n");
    3611             :                 }
    3612             :         }
    3613             : 
    3614           4 :         return true;
    3615             : }
    3616             : 
    3617          28 : static bool test_DoPrintTest(struct torture_context *tctx,
    3618             :                              struct dcerpc_binding_handle *b,
    3619             :                              struct policy_handle *handle)
    3620             : {
    3621          28 :         bool ret = true;
    3622          28 :         uint32_t num_jobs = 8;
    3623             :         uint32_t *job_ids;
    3624             :         int i;
    3625             : 
    3626          28 :         torture_comment(tctx, "Testing real print operations\n");
    3627             : 
    3628          28 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3629             : 
    3630         252 :         for (i=0; i < num_jobs; i++) {
    3631         224 :                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
    3632             :         }
    3633             : 
    3634         252 :         for (i=0; i < num_jobs; i++) {
    3635         224 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3636             :         }
    3637             : 
    3638         252 :         for (i=0; i < num_jobs; i++) {
    3639         224 :                 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
    3640             :         }
    3641             : 
    3642         252 :         for (i=0; i < num_jobs; i++) {
    3643         224 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3644             :         }
    3645             : 
    3646          28 :         if (ret == true) {
    3647          14 :                 torture_comment(tctx, "real print operations test succeeded\n\n");
    3648             :         }
    3649             : 
    3650          28 :         return ret;
    3651             : }
    3652             : 
    3653           8 : static bool test_DoPrintTest_extended(struct torture_context *tctx,
    3654             :                                       struct dcerpc_binding_handle *b,
    3655             :                                       struct policy_handle *handle)
    3656             : {
    3657           8 :         bool ret = true;
    3658           8 :         uint32_t num_jobs = 8;
    3659             :         uint32_t *job_ids;
    3660             :         int i;
    3661           8 :         torture_comment(tctx, "Testing real print operations (extended)\n");
    3662             : 
    3663           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3664             : 
    3665          72 :         for (i=0; i < num_jobs; i++) {
    3666          64 :                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
    3667             :         }
    3668             : 
    3669           8 :         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
    3670             : 
    3671          72 :         for (i=0; i < num_jobs; i++) {
    3672          64 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3673             :         }
    3674             : 
    3675           8 :         if (ret == true) {
    3676           4 :                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
    3677             :         }
    3678             : 
    3679           8 :         return ret;
    3680             : }
    3681             : 
    3682           0 : static bool test_JobPrintProperties_equal(struct torture_context *tctx,
    3683             :                                           struct spoolss_PrintPropertyValue *got,
    3684             :                                           struct spoolss_PrintNamedProperty *exp)
    3685             : {
    3686           0 :         torture_assert_int_equal(tctx,
    3687             :                                  got->ePropertyType,
    3688             :                                  exp->propertyValue.ePropertyType,
    3689             :                                  "ePropertyType");
    3690             : 
    3691           0 :         switch (exp->propertyValue.ePropertyType) {
    3692           0 :         case kRpcPropertyTypeString:
    3693           0 :                 torture_assert_str_equal(tctx,
    3694             :                                          got->value.propertyString,
    3695             :                                          exp->propertyValue.value.propertyString,
    3696             :                                          "propertyString");
    3697           0 :                 break;
    3698           0 :         case kRpcPropertyTypeInt32:
    3699           0 :                 torture_assert_int_equal(tctx,
    3700             :                                          got->value.propertyInt32,
    3701             :                                          exp->propertyValue.value.propertyInt32,
    3702             :                                          "propertyInt32");
    3703           0 :                 break;
    3704           0 :         case kRpcPropertyTypeInt64:
    3705           0 :                 torture_assert_u64_equal(tctx,
    3706             :                                          got->value.propertyInt64,
    3707             :                                          exp->propertyValue.value.propertyInt64,
    3708             :                                          "propertyInt64");
    3709           0 :                 break;
    3710           0 :         case kRpcPropertyTypeByte:
    3711           0 :                 torture_assert_int_equal(tctx,
    3712             :                                          got->value.propertyByte,
    3713             :                                          exp->propertyValue.value.propertyByte,
    3714             :                                          "propertyByte");
    3715           0 :                 break;
    3716           0 :         case kRpcPropertyTypeBuffer:
    3717           0 :                 torture_assert_int_equal(tctx,
    3718             :                                          got->value.propertyBlob.cbBuf,
    3719             :                                          exp->propertyValue.value.propertyBlob.cbBuf,
    3720             :                                          "propertyBlob.cbBuf");
    3721           0 :                 torture_assert_mem_equal(tctx,
    3722             :                                          got->value.propertyBlob.pBuf,
    3723             :                                          exp->propertyValue.value.propertyBlob.pBuf,
    3724             :                                          exp->propertyValue.value.propertyBlob.cbBuf,
    3725             :                                          "propertyBlob.pBuf");
    3726             : 
    3727           0 :                 break;
    3728             : 
    3729             :         }
    3730             : 
    3731           0 :         return true;
    3732             : }
    3733             : 
    3734           0 : static bool test_JobPrintProperties(struct torture_context *tctx,
    3735             :                                     struct dcerpc_binding_handle *b,
    3736             :                                     struct policy_handle *handle,
    3737             :                                     uint32_t job_id)
    3738             : {
    3739             :         struct spoolss_PrintNamedProperty in;
    3740             :         struct spoolss_PrintPropertyValue out;
    3741             :         int i;
    3742           0 :         DATA_BLOB blob = data_blob_string_const("blob");
    3743             :         struct {
    3744             :                 const char *property_name;
    3745             :                 enum spoolss_EPrintPropertyType type;
    3746             :                 union spoolss_PrintPropertyValueUnion value;
    3747             :                 WERROR expected_result;
    3748           0 :         } tests[] = {
    3749             :                 {
    3750             :                         .property_name                  = "torture_property_string",
    3751             :                         .type                           = kRpcPropertyTypeString,
    3752             :                         .value.propertyString           = "torture_property_value_string",
    3753             :                 },{
    3754             :                         .property_name                  = "torture_property_int32",
    3755             :                         .type                           = kRpcPropertyTypeInt32,
    3756             :                         .value.propertyInt32            = 42,
    3757             :                 },{
    3758             :                         .property_name                  = "torture_property_int64",
    3759             :                         .type                           = kRpcPropertyTypeInt64,
    3760             :                         .value.propertyInt64            = 0xaffe,
    3761             :                 },{
    3762             :                         .property_name                  = "torture_property_byte",
    3763             :                         .type                           = kRpcPropertyTypeByte,
    3764             :                         .value.propertyByte             = 0xab,
    3765             :                 },{
    3766             :                         .property_name                  = "torture_property_buffer",
    3767             :                         .type                           = kRpcPropertyTypeBuffer,
    3768           0 :                         .value.propertyBlob.cbBuf       = blob.length,
    3769           0 :                         .value.propertyBlob.pBuf        = blob.data,
    3770             :                 }
    3771             :         };
    3772             : 
    3773           0 :         torture_assert(tctx,
    3774             :                 test_JobPropertiesEnum(tctx, b, handle, job_id),
    3775             :                 "failed to enum properties");
    3776             : 
    3777           0 :         for (i=0; i <ARRAY_SIZE(tests); i++) {
    3778             : 
    3779           0 :                 in.propertyName                 = tests[i].property_name;
    3780           0 :                 in.propertyValue.ePropertyType  = tests[i].type;
    3781           0 :                 in.propertyValue.value          = tests[i].value;
    3782             : 
    3783           0 :                 torture_assert(tctx,
    3784             :                         test_JobPropertySet(tctx, b, handle, job_id, &in),
    3785             :                         "failed to set property");
    3786             : 
    3787           0 :                 torture_assert(tctx,
    3788             :                         test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
    3789             :                         "failed to get property");
    3790             : 
    3791           0 :                 torture_assert(tctx,
    3792             :                         test_JobPrintProperties_equal(tctx, &out, &in),
    3793             :                         "property unequal");
    3794             : 
    3795           0 :                 torture_assert(tctx,
    3796             :                         test_JobPropertiesEnum(tctx, b, handle, job_id),
    3797             :                         "failed to enum properties");
    3798             : 
    3799           0 :                 torture_assert(tctx,
    3800             :                         test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
    3801             :                         "failed to delete job property");
    3802             :         }
    3803             : 
    3804           0 :         torture_assert(tctx,
    3805             :                 test_JobPropertiesEnum(tctx, b, handle, job_id),
    3806             :                 "failed to enum properties");
    3807             : 
    3808           0 :         return true;
    3809             : }
    3810             : 
    3811           0 : static bool test_DoPrintTest_properties(struct torture_context *tctx,
    3812             :                                         struct dcerpc_binding_handle *b,
    3813             :                                         struct policy_handle *handle)
    3814             : {
    3815           0 :         uint32_t num_jobs = 8;
    3816             :         uint32_t *job_ids;
    3817             :         int i;
    3818           0 :         torture_comment(tctx, "Testing real print operations (properties)\n");
    3819             : 
    3820           0 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3821             : 
    3822           0 :         for (i=0; i < num_jobs; i++) {
    3823           0 :                 torture_assert(tctx,
    3824             :                         test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
    3825             :                         "failed to create print job");
    3826             :         }
    3827             : 
    3828           0 :         for (i=0; i < num_jobs; i++) {
    3829           0 :                 torture_assert(tctx,
    3830             :                         test_JobPrintProperties(tctx, b, handle, job_ids[i]),
    3831             :                         "failed to test job properties");
    3832             :         }
    3833             : 
    3834             : 
    3835           0 :         for (i=0; i < num_jobs; i++) {
    3836           0 :                 torture_assert(tctx,
    3837             :                         test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
    3838             :                         "failed to delete printjob");
    3839             :         }
    3840             : 
    3841           0 :         torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
    3842             : 
    3843           0 :         return true;
    3844             : }
    3845             : 
    3846          52 : static bool test_PausePrinter(struct torture_context *tctx,
    3847             :                               struct dcerpc_binding_handle *b,
    3848             :                               struct policy_handle *handle)
    3849             : {
    3850             :         NTSTATUS status;
    3851             :         struct spoolss_SetPrinter r;
    3852             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3853             :         struct spoolss_DevmodeContainer devmode_ctr;
    3854             :         struct sec_desc_buf secdesc_ctr;
    3855             : 
    3856          52 :         info_ctr.level = 0;
    3857          52 :         info_ctr.info.info0 = NULL;
    3858             : 
    3859          52 :         ZERO_STRUCT(devmode_ctr);
    3860          52 :         ZERO_STRUCT(secdesc_ctr);
    3861             : 
    3862          52 :         r.in.handle             = handle;
    3863          52 :         r.in.info_ctr           = &info_ctr;
    3864          52 :         r.in.devmode_ctr        = &devmode_ctr;
    3865          52 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3866          52 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
    3867             : 
    3868          52 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
    3869             : 
    3870          52 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3871             : 
    3872          52 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3873             : 
    3874          52 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3875             : 
    3876          52 :         return true;
    3877             : }
    3878             : 
    3879          40 : static bool test_ResumePrinter(struct torture_context *tctx,
    3880             :                                struct dcerpc_binding_handle *b,
    3881             :                                struct policy_handle *handle)
    3882             : {
    3883             :         NTSTATUS status;
    3884             :         struct spoolss_SetPrinter r;
    3885             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3886             :         struct spoolss_DevmodeContainer devmode_ctr;
    3887             :         struct sec_desc_buf secdesc_ctr;
    3888             : 
    3889          40 :         info_ctr.level = 0;
    3890          40 :         info_ctr.info.info0 = NULL;
    3891             : 
    3892          40 :         ZERO_STRUCT(devmode_ctr);
    3893          40 :         ZERO_STRUCT(secdesc_ctr);
    3894             : 
    3895          40 :         r.in.handle             = handle;
    3896          40 :         r.in.info_ctr           = &info_ctr;
    3897          40 :         r.in.devmode_ctr        = &devmode_ctr;
    3898          40 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3899          40 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
    3900             : 
    3901          40 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
    3902             : 
    3903          40 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3904             : 
    3905          40 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3906             : 
    3907          40 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3908             : 
    3909          40 :         return true;
    3910             : }
    3911             : 
    3912          12 : static bool test_printer_purge(struct torture_context *tctx,
    3913             :                                struct dcerpc_binding_handle *b,
    3914             :                                struct policy_handle *handle)
    3915             : {
    3916             :         NTSTATUS status;
    3917             :         struct spoolss_SetPrinter r;
    3918             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3919             :         struct spoolss_DevmodeContainer devmode_ctr;
    3920             :         struct sec_desc_buf secdesc_ctr;
    3921             : 
    3922          12 :         info_ctr.level = 0;
    3923          12 :         info_ctr.info.info0 = NULL;
    3924             : 
    3925          12 :         ZERO_STRUCT(devmode_ctr);
    3926          12 :         ZERO_STRUCT(secdesc_ctr);
    3927             : 
    3928          12 :         r.in.handle             = handle;
    3929          12 :         r.in.info_ctr           = &info_ctr;
    3930          12 :         r.in.devmode_ctr        = &devmode_ctr;
    3931          12 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3932          12 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_PURGE;
    3933             : 
    3934          12 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
    3935             : 
    3936          12 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3937          12 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3938          12 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3939             : 
    3940          12 :         return true;
    3941             : }
    3942             : 
    3943         232 : static bool test_GetPrinterData_checktype(struct torture_context *tctx,
    3944             :                                           struct dcerpc_binding_handle *b,
    3945             :                                           struct policy_handle *handle,
    3946             :                                           const char *value_name,
    3947             :                                           enum winreg_Type *expected_type,
    3948             :                                           enum winreg_Type *type_p,
    3949             :                                           uint8_t **data_p,
    3950             :                                           uint32_t *needed_p)
    3951             : {
    3952             :         NTSTATUS status;
    3953             :         struct spoolss_GetPrinterData r;
    3954             :         uint32_t needed;
    3955             :         enum winreg_Type type;
    3956             :         union spoolss_PrinterData data;
    3957             : 
    3958         232 :         r.in.handle = handle;
    3959         232 :         r.in.value_name = value_name;
    3960         232 :         r.in.offered = 0;
    3961         232 :         r.out.needed = &needed;
    3962         232 :         r.out.type = &type;
    3963         232 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    3964             : 
    3965         232 :         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
    3966             : 
    3967         232 :         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
    3968         232 :         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
    3969             : 
    3970         232 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    3971         232 :                 if (expected_type) {
    3972          84 :                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
    3973             :                 }
    3974         232 :                 r.in.offered = needed;
    3975         232 :                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    3976         232 :                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
    3977         232 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
    3978             :         }
    3979             : 
    3980         232 :         torture_assert_werr_ok(tctx, r.out.result,
    3981             :                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
    3982             : 
    3983         232 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
    3984             : 
    3985         232 :         if (type_p) {
    3986         224 :                 *type_p = type;
    3987             :         }
    3988             : 
    3989         232 :         if (data_p) {
    3990         232 :                 *data_p = r.out.data;
    3991             :         }
    3992             : 
    3993         232 :         if (needed_p) {
    3994         232 :                 *needed_p = needed;
    3995             :         }
    3996             : 
    3997         232 :         return true;
    3998             : }
    3999             : 
    4000         140 : static bool test_GetPrinterData(struct torture_context *tctx,
    4001             :                                 struct dcerpc_binding_handle *b,
    4002             :                                 struct policy_handle *handle,
    4003             :                                 const char *value_name,
    4004             :                                 enum winreg_Type *type_p,
    4005             :                                 uint8_t **data_p,
    4006             :                                 uint32_t *needed_p)
    4007             : {
    4008         140 :         return test_GetPrinterData_checktype(tctx, b, handle, value_name,
    4009             :                                              NULL, type_p, data_p, needed_p);
    4010             : }
    4011             : 
    4012        1368 : static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
    4013             :                                             struct dcerpc_pipe *p,
    4014             :                                             struct policy_handle *handle,
    4015             :                                             const char *key_name,
    4016             :                                             const char *value_name,
    4017             :                                             enum winreg_Type *expected_type,
    4018             :                                             enum winreg_Type *type_p,
    4019             :                                             uint8_t **data_p,
    4020             :                                             uint32_t *needed_p)
    4021             : {
    4022             :         NTSTATUS status;
    4023             :         struct spoolss_GetPrinterDataEx r;
    4024             :         enum winreg_Type type;
    4025             :         uint32_t needed;
    4026             :         union spoolss_PrinterData data;
    4027        1368 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4028             : 
    4029        1368 :         r.in.handle = handle;
    4030        1368 :         r.in.key_name = key_name;
    4031        1368 :         r.in.value_name = value_name;
    4032        1368 :         r.in.offered = 0;
    4033        1368 :         r.out.type = &type;
    4034        1368 :         r.out.needed = &needed;
    4035        1368 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    4036             : 
    4037        1368 :         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
    4038             :                 r.in.key_name, r.in.value_name);
    4039             : 
    4040        1368 :         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
    4041        1368 :         if (!NT_STATUS_IS_OK(status)) {
    4042           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
    4043           0 :                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
    4044             :                 }
    4045           0 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
    4046             :         }
    4047             : 
    4048        1368 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4049        1332 :                 if (expected_type) {
    4050         972 :                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
    4051             :                 }
    4052        1332 :                 r.in.offered = needed;
    4053        1332 :                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    4054        1332 :                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
    4055        1332 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
    4056             :         }
    4057             : 
    4058        1368 :         torture_assert_werr_ok(tctx, r.out.result,
    4059             :                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
    4060             : 
    4061        1368 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
    4062             : 
    4063        1368 :         if (type_p) {
    4064        1368 :                 *type_p = type;
    4065             :         }
    4066             : 
    4067        1368 :         if (data_p) {
    4068        1368 :                 *data_p = r.out.data;
    4069             :         }
    4070             : 
    4071        1368 :         if (needed_p) {
    4072        1368 :                 *needed_p = needed;
    4073             :         }
    4074             : 
    4075        1368 :         return true;
    4076             : }
    4077             : 
    4078         360 : static bool test_GetPrinterDataEx(struct torture_context *tctx,
    4079             :                                   struct dcerpc_pipe *p,
    4080             :                                   struct policy_handle *handle,
    4081             :                                   const char *key_name,
    4082             :                                   const char *value_name,
    4083             :                                   enum winreg_Type *type_p,
    4084             :                                   uint8_t **data_p,
    4085             :                                   uint32_t *needed_p)
    4086             : {
    4087         360 :         return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
    4088             :                                                NULL, type_p, data_p, needed_p);
    4089             : }
    4090             : 
    4091          68 : static bool test_get_environment(struct torture_context *tctx,
    4092             :                                  struct dcerpc_binding_handle *b,
    4093             :                                  struct policy_handle *handle,
    4094             :                                  const char **architecture)
    4095             : {
    4096             :         DATA_BLOB blob;
    4097             :         enum winreg_Type type;
    4098             :         uint8_t *data;
    4099             :         uint32_t needed;
    4100             : 
    4101          68 :         torture_assert(tctx,
    4102             :                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
    4103             :                 "failed to get Architecture");
    4104             : 
    4105          68 :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
    4106             : 
    4107          68 :         blob = data_blob_const(data, needed);
    4108          68 :         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
    4109             : 
    4110          68 :         return true;
    4111             : }
    4112             : 
    4113           4 : static bool test_GetPrinterData_list(struct torture_context *tctx,
    4114             :                                      void *private_data)
    4115             : {
    4116           3 :         struct test_spoolss_context *ctx =
    4117           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    4118           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    4119           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4120           4 :         const char *list[] = {
    4121             :                 "W3SvcInstalled",
    4122             :                 "BeepEnabled",
    4123             :                 "EventLog",
    4124             :                 /* "NetPopup", not on w2k8 */
    4125             :                 /* "NetPopupToComputer", not on w2k8 */
    4126             :                 "MajorVersion",
    4127             :                 "MinorVersion",
    4128             :                 "DefaultSpoolDirectory",
    4129             :                 "Architecture",
    4130             :                 "DsPresent",
    4131             :                 "OSVersion",
    4132             :                 /* "OSVersionEx", not on s3 */
    4133             :                 "DNSMachineName"
    4134             :         };
    4135             :         int i;
    4136             : 
    4137          77 :         for (i=0; i < ARRAY_SIZE(list); i++) {
    4138          40 :                 enum winreg_Type type = REG_NONE;
    4139          40 :                 enum winreg_Type type_ex1 = REG_NONE;
    4140          40 :                 enum winreg_Type type_ex2 = REG_NONE;
    4141             :                 uint8_t *data;
    4142          40 :                 uint8_t *data_ex1 = NULL;
    4143          40 :                 uint8_t *data_ex2 = NULL;
    4144             :                 uint32_t needed;
    4145          40 :                 uint32_t needed_ex1 = 0;
    4146          40 :                 uint32_t needed_ex2 = 0;
    4147             : 
    4148          40 :                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
    4149             :                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
    4150          40 :                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex1, &data_ex1, &needed_ex1),
    4151             :                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
    4152          40 :                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "", list[i], &type_ex2, &data_ex2, &needed_ex2),
    4153             :                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
    4154          40 :                 torture_assert_int_equal(tctx, type, type_ex1, "type mismatch");
    4155          40 :                 torture_assert_int_equal(tctx, type, type_ex2, "type mismatch");
    4156          40 :                 torture_assert_int_equal(tctx, needed, needed_ex1, "needed mismatch");
    4157          40 :                 torture_assert_int_equal(tctx, needed, needed_ex2, "needed mismatch");
    4158          40 :                 torture_assert_mem_equal(tctx, data, data_ex1, needed, "data mismatch");
    4159          40 :                 torture_assert_mem_equal(tctx, data, data_ex2, needed, "data mismatch");
    4160             :         }
    4161             : 
    4162           4 :         return true;
    4163             : }
    4164             : 
    4165         152 : static bool test_EnumPrinterData(struct torture_context *tctx,
    4166             :                                  struct dcerpc_pipe *p,
    4167             :                                  struct policy_handle *handle,
    4168             :                                  uint32_t enum_index,
    4169             :                                  uint32_t value_offered,
    4170             :                                  uint32_t data_offered,
    4171             :                                  enum winreg_Type *type_p,
    4172             :                                  uint32_t *value_needed_p,
    4173             :                                  uint32_t *data_needed_p,
    4174             :                                  const char **value_name_p,
    4175             :                                  uint8_t **data_p,
    4176             :                                  WERROR *result_p)
    4177             : {
    4178             :         struct spoolss_EnumPrinterData r;
    4179             :         uint32_t data_needed;
    4180             :         uint32_t value_needed;
    4181             :         enum winreg_Type type;
    4182         152 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4183             : 
    4184         152 :         r.in.handle = handle;
    4185         152 :         r.in.enum_index = enum_index;
    4186         152 :         r.in.value_offered = value_offered;
    4187         152 :         r.in.data_offered = data_offered;
    4188         152 :         r.out.data_needed = &data_needed;
    4189         152 :         r.out.value_needed = &value_needed;
    4190         152 :         r.out.type = &type;
    4191         152 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
    4192         152 :         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
    4193             : 
    4194         152 :         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
    4195             : 
    4196         152 :         torture_assert_ntstatus_ok(tctx,
    4197             :                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
    4198             :                 "EnumPrinterData failed");
    4199             : 
    4200         152 :         if (type_p) {
    4201         124 :                 *type_p = type;
    4202             :         }
    4203         152 :         if (value_needed_p) {
    4204         152 :                 *value_needed_p = value_needed;
    4205             :         }
    4206         152 :         if (data_needed_p) {
    4207         152 :                 *data_needed_p = data_needed;
    4208             :         }
    4209         152 :         if (value_name_p) {
    4210         124 :                 *value_name_p = r.out.value_name;
    4211             :         }
    4212         152 :         if (data_p) {
    4213         124 :                 *data_p = r.out.data;
    4214             :         }
    4215         152 :         if (result_p) {
    4216         152 :                 *result_p = r.out.result;
    4217             :         }
    4218             : 
    4219         152 :         return true;
    4220             : }
    4221             : 
    4222             : 
    4223          20 : static bool test_EnumPrinterData_all(struct torture_context *tctx,
    4224             :                                      struct dcerpc_pipe *p,
    4225             :                                      struct policy_handle *handle)
    4226             : {
    4227          20 :         uint32_t enum_index = 0;
    4228             :         enum winreg_Type type;
    4229             :         uint32_t value_needed;
    4230             :         uint32_t data_needed;
    4231             :         uint8_t *data;
    4232             :         const char *value_name;
    4233             :         WERROR result;
    4234             : 
    4235          20 :         torture_comment(tctx, "Testing EnumPrinterData\n");
    4236             : 
    4237             :         do {
    4238          20 :                 torture_assert(tctx,
    4239             :                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
    4240             :                                              &type, &value_needed, &data_needed,
    4241             :                                              &value_name, &data, &result),
    4242             :                         "EnumPrinterData failed");
    4243             : 
    4244          20 :                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
    4245           0 :                         break;
    4246             :                 }
    4247             : 
    4248          20 :                 torture_assert(tctx,
    4249             :                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
    4250             :                                              &type, &value_needed, &data_needed,
    4251             :                                              &value_name, &data, &result),
    4252             :                         "EnumPrinterData failed");
    4253             : 
    4254          20 :                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
    4255          20 :                         break;
    4256             :                 }
    4257             : 
    4258           0 :                 enum_index++;
    4259             : 
    4260           0 :         } while (W_ERROR_IS_OK(result));
    4261             : 
    4262          20 :         torture_comment(tctx, "EnumPrinterData test succeeded\n");
    4263             : 
    4264          20 :         return true;
    4265             : }
    4266             : 
    4267        1316 : static bool test_EnumPrinterDataEx(struct torture_context *tctx,
    4268             :                                    struct dcerpc_binding_handle *b,
    4269             :                                    struct policy_handle *handle,
    4270             :                                    const char *key_name,
    4271             :                                    uint32_t *count_p,
    4272             :                                    struct spoolss_PrinterEnumValues **info_p)
    4273             : {
    4274             :         struct spoolss_EnumPrinterDataEx r;
    4275             :         struct spoolss_PrinterEnumValues *info;
    4276             :         uint32_t needed;
    4277             :         uint32_t count;
    4278             : 
    4279        1316 :         r.in.handle = handle;
    4280        1316 :         r.in.key_name = key_name;
    4281        1316 :         r.in.offered = 0;
    4282        1316 :         r.out.needed = &needed;
    4283        1316 :         r.out.count = &count;
    4284        1316 :         r.out.info = &info;
    4285             : 
    4286        1316 :         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
    4287             : 
    4288        1316 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
    4289             :                 "EnumPrinterDataEx failed");
    4290        1316 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4291        1256 :                 r.in.offered = needed;
    4292        1256 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
    4293             :                         "EnumPrinterDataEx failed");
    4294             :         }
    4295             : 
    4296        1316 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
    4297             : 
    4298        1316 :         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
    4299             : 
    4300        1316 :         if (count_p) {
    4301        1228 :                 *count_p = count;
    4302             :         }
    4303        1316 :         if (info_p) {
    4304        1228 :                 *info_p = info;
    4305             :         }
    4306             : 
    4307        1316 :         return true;
    4308             : }
    4309             : 
    4310             : static bool test_SetPrinterData(struct torture_context *tctx,
    4311             :                                 struct dcerpc_binding_handle *b,
    4312             :                                 struct policy_handle *handle,
    4313             :                                 const char *value_name,
    4314             :                                 enum winreg_Type type,
    4315             :                                 uint8_t *data,
    4316             :                                 uint32_t offered);
    4317             : static bool test_DeletePrinterData(struct torture_context *tctx,
    4318             :                                    struct dcerpc_binding_handle *b,
    4319             :                                    struct policy_handle *handle,
    4320             :                                    const char *value_name);
    4321             : 
    4322          28 : static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
    4323             :                                              struct dcerpc_pipe *p,
    4324             :                                              struct policy_handle *handle)
    4325             : {
    4326             :         uint32_t count;
    4327             :         struct spoolss_PrinterEnumValues *info;
    4328             :         int i;
    4329             :         uint32_t value_needed, data_needed;
    4330             :         uint32_t value_offered, data_offered;
    4331             :         WERROR result;
    4332          28 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4333             : 
    4334             :         enum winreg_Type type;
    4335             :         DATA_BLOB blob;
    4336             : 
    4337          28 :         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
    4338             : 
    4339          28 :         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
    4340          28 :         type = REG_SZ;
    4341             : 
    4342          28 :         torture_assert(tctx,
    4343             :                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
    4344             :                 "SetPrinterData failed");
    4345             : 
    4346          28 :         blob = data_blob_string_const("torture_data2");
    4347             : 
    4348          28 :         torture_assert(tctx,
    4349             :                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
    4350             :                 "SetPrinterData failed");
    4351             : 
    4352          28 :         blob = data_blob_talloc(tctx, NULL, 4);
    4353          28 :         SIVAL(blob.data, 0, 0x11223344);
    4354             : 
    4355          28 :         torture_assert(tctx,
    4356             :                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
    4357             :                 "SetPrinterData failed");
    4358             : 
    4359          28 :         torture_assert(tctx,
    4360             :                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
    4361             :                 "failed to call EnumPrinterDataEx");
    4362             : 
    4363             :         /* get the max sizes for value and data */
    4364             : 
    4365          28 :         torture_assert(tctx,
    4366             :                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
    4367             :                                      NULL, &value_needed, &data_needed,
    4368             :                                      NULL, NULL, &result),
    4369             :                 "EnumPrinterData failed");
    4370          28 :         torture_assert_werr_ok(tctx, result, "unexpected result");
    4371             : 
    4372             :         /* check if the reply from the EnumPrinterData really matches max values */
    4373             : 
    4374         112 :         for (i=0; i < count; i++) {
    4375          84 :                 if (info[i].value_name_len > value_needed) {
    4376           0 :                         torture_fail(tctx,
    4377             :                                 talloc_asprintf(tctx,
    4378             :                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
    4379             :                                 info[i].value_name_len, value_needed));
    4380             :                 }
    4381          84 :                 if (info[i].data_length > data_needed) {
    4382           0 :                         torture_fail(tctx,
    4383             :                                 talloc_asprintf(tctx,
    4384             :                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
    4385             :                                 info[i].data_length, data_needed));
    4386             :                 }
    4387             :         }
    4388             : 
    4389             :         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
    4390             :          * sort or not sort the replies by value name, we should be able to do
    4391             :          * the following entry comparison */
    4392             : 
    4393          28 :         data_offered = data_needed;
    4394          28 :         value_offered = value_needed;
    4395             : 
    4396         196 :         for (i=0; i < count; i++) {
    4397             : 
    4398             :                 const char *value_name;
    4399             :                 uint8_t *data;
    4400             : 
    4401          84 :                 torture_assert(tctx,
    4402             :                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
    4403             :                                              &type, &value_needed, &data_needed,
    4404             :                                              &value_name, &data, &result),
    4405             :                         "EnumPrinterData failed");
    4406             : 
    4407          84 :                 if (i -1 == count) {
    4408           0 :                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
    4409             :                                 "unexpected result");
    4410           0 :                         break;
    4411             :                 } else {
    4412          84 :                         torture_assert_werr_ok(tctx, result, "unexpected result");
    4413             :                 }
    4414             : 
    4415          84 :                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
    4416          84 :                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
    4417          84 :                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
    4418          84 :                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
    4419          84 :                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
    4420             :         }
    4421             : 
    4422          28 :         torture_assert(tctx,
    4423             :                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
    4424             :                 "DeletePrinterData failed");
    4425          28 :         torture_assert(tctx,
    4426             :                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
    4427             :                 "DeletePrinterData failed");
    4428          28 :         torture_assert(tctx,
    4429             :                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
    4430             :                 "DeletePrinterData failed");
    4431             : 
    4432          28 :         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
    4433             : 
    4434          28 :         return true;
    4435             : }
    4436             : 
    4437         168 : static bool test_DeletePrinterData(struct torture_context *tctx,
    4438             :                                    struct dcerpc_binding_handle *b,
    4439             :                                    struct policy_handle *handle,
    4440             :                                    const char *value_name)
    4441             : {
    4442             :         NTSTATUS status;
    4443             :         struct spoolss_DeletePrinterData r;
    4444             : 
    4445         168 :         r.in.handle = handle;
    4446         168 :         r.in.value_name = value_name;
    4447             : 
    4448         168 :         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
    4449             :                 r.in.value_name);
    4450             : 
    4451         168 :         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
    4452             : 
    4453         168 :         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
    4454         168 :         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
    4455             : 
    4456         168 :         return true;
    4457             : }
    4458             : 
    4459        1200 : static bool test_DeletePrinterDataEx(struct torture_context *tctx,
    4460             :                                      struct dcerpc_binding_handle *b,
    4461             :                                      struct policy_handle *handle,
    4462             :                                      const char *key_name,
    4463             :                                      const char *value_name)
    4464             : {
    4465             :         struct spoolss_DeletePrinterDataEx r;
    4466             : 
    4467        1200 :         r.in.handle = handle;
    4468        1200 :         r.in.key_name = key_name;
    4469        1200 :         r.in.value_name = value_name;
    4470             : 
    4471        1200 :         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
    4472             :                 r.in.key_name, r.in.value_name);
    4473             : 
    4474        1200 :         torture_assert_ntstatus_ok(tctx,
    4475             :                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
    4476             :                 "DeletePrinterDataEx failed");
    4477        1200 :         torture_assert_werr_ok(tctx, r.out.result,
    4478             :                 "DeletePrinterDataEx failed");
    4479             : 
    4480        1200 :         return true;
    4481             : }
    4482             : 
    4483         216 : static bool test_DeletePrinterKey(struct torture_context *tctx,
    4484             :                                   struct dcerpc_binding_handle *b,
    4485             :                                   struct policy_handle *handle,
    4486             :                                   const char *key_name)
    4487             : {
    4488             :         struct spoolss_DeletePrinterKey r;
    4489             : 
    4490         216 :         r.in.handle = handle;
    4491         216 :         r.in.key_name = key_name;
    4492             : 
    4493         216 :         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
    4494             : 
    4495         216 :         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
    4496           0 :                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
    4497             :                 return true;
    4498             :         }
    4499             : 
    4500         216 :         torture_assert_ntstatus_ok(tctx,
    4501             :                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
    4502             :                 "DeletePrinterKey failed");
    4503         216 :         torture_assert_werr_ok(tctx, r.out.result,
    4504             :                 "DeletePrinterKey failed");
    4505             : 
    4506         216 :         return true;
    4507             : }
    4508             : 
    4509          48 : static bool test_winreg_OpenHKLM(struct torture_context *tctx,
    4510             :                                  struct dcerpc_binding_handle *b,
    4511             :                                  struct policy_handle *handle)
    4512             : {
    4513             :         struct winreg_OpenHKLM r;
    4514             : 
    4515          48 :         r.in.system_name = NULL;
    4516          48 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    4517          48 :         r.out.handle = handle;
    4518             : 
    4519          48 :         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
    4520             : 
    4521          48 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
    4522          48 :         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
    4523             : 
    4524          48 :         return true;
    4525             : }
    4526             : 
    4527        3626 : static void init_winreg_String(struct winreg_String *name, const char *s)
    4528             : {
    4529        3626 :         name->name = s;
    4530        3626 :         if (s) {
    4531        3626 :                 name->name_len = 2 * (strlen_m(s) + 1);
    4532        3626 :                 name->name_size = name->name_len;
    4533             :         } else {
    4534           0 :                 name->name_len = 0;
    4535           0 :                 name->name_size = 0;
    4536             :         }
    4537        3626 : }
    4538             : 
    4539         320 : static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
    4540             :                                      struct dcerpc_binding_handle *b,
    4541             :                                      struct policy_handle *hive_handle,
    4542             :                                      const char *keyname,
    4543             :                                      uint32_t options,
    4544             :                                      struct policy_handle *key_handle)
    4545             : {
    4546             :         struct winreg_OpenKey r;
    4547             : 
    4548         320 :         r.in.parent_handle = hive_handle;
    4549         320 :         init_winreg_String(&r.in.keyname, keyname);
    4550         320 :         r.in.options = options;
    4551         320 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    4552         320 :         r.out.handle = key_handle;
    4553             : 
    4554         320 :         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
    4555             : 
    4556         320 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
    4557         320 :         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
    4558             : 
    4559         320 :         return true;
    4560             : }
    4561             : 
    4562         320 : static bool test_winreg_OpenKey(struct torture_context *tctx,
    4563             :                                 struct dcerpc_binding_handle *b,
    4564             :                                 struct policy_handle *hive_handle,
    4565             :                                 const char *keyname,
    4566             :                                 struct policy_handle *key_handle)
    4567             : {
    4568         320 :         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
    4569             :                                         REG_OPTION_NON_VOLATILE, key_handle);
    4570             : }
    4571             : 
    4572         368 : static bool test_winreg_CloseKey(struct torture_context *tctx,
    4573             :                                  struct dcerpc_binding_handle *b,
    4574             :                                  struct policy_handle *handle)
    4575             : {
    4576             :         struct winreg_CloseKey r;
    4577             : 
    4578         368 :         r.in.handle = handle;
    4579         368 :         r.out.handle = handle;
    4580             : 
    4581         368 :         torture_comment(tctx, "Testing winreg_CloseKey\n");
    4582             : 
    4583         368 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
    4584         368 :         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
    4585             : 
    4586         368 :         return true;
    4587             : }
    4588             : 
    4589        3306 : bool test_winreg_QueryValue(struct torture_context *tctx,
    4590             :                             struct dcerpc_binding_handle *b,
    4591             :                             struct policy_handle *handle,
    4592             :                             const char *value_name,
    4593             :                             enum winreg_Type *type_p,
    4594             :                             uint32_t *data_size_p,
    4595             :                             uint32_t *data_length_p,
    4596             :                             uint8_t **data_p)
    4597             : {
    4598             :         struct winreg_QueryValue r;
    4599        3306 :         enum winreg_Type type = REG_NONE;
    4600        3306 :         uint32_t data_size = 0;
    4601        3306 :         uint32_t data_length = 0;
    4602             :         struct winreg_String valuename;
    4603        3306 :         uint8_t *data = NULL;
    4604             : 
    4605        3306 :         init_winreg_String(&valuename, value_name);
    4606             : 
    4607        3306 :         data = talloc_zero_array(tctx, uint8_t, 0);
    4608             : 
    4609        3306 :         r.in.handle = handle;
    4610        3306 :         r.in.value_name = &valuename;
    4611        3306 :         r.in.type = &type;
    4612        3306 :         r.in.data_size = &data_size;
    4613        3306 :         r.in.data_length = &data_length;
    4614        3306 :         r.in.data = data;
    4615        3306 :         r.out.type = &type;
    4616        3306 :         r.out.data = data;
    4617        3306 :         r.out.data_size = &data_size;
    4618        3306 :         r.out.data_length = &data_length;
    4619             : 
    4620        3306 :         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
    4621             : 
    4622        3306 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
    4623        3306 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4624        3222 :                 *r.in.data_size = *r.out.data_size;
    4625        3222 :                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
    4626        3222 :                 r.in.data = data;
    4627        3222 :                 r.out.data = data;
    4628        3222 :                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
    4629             :         }
    4630        3306 :         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
    4631             : 
    4632        3306 :         if (type_p) {
    4633        3306 :                 *type_p = *r.out.type;
    4634             :         }
    4635        3306 :         if (data_size_p) {
    4636        3306 :                 *data_size_p = *r.out.data_size;
    4637             :         }
    4638        3306 :         if (data_length_p) {
    4639        3306 :                 *data_length_p = *r.out.data_length;
    4640             :         }
    4641        3306 :         if (data_p) {
    4642        3306 :                 *data_p = r.out.data;
    4643             :         }
    4644             : 
    4645        3306 :         return true;
    4646             : }
    4647             : 
    4648         248 : static bool test_winreg_query_printerdata(struct torture_context *tctx,
    4649             :                                           struct dcerpc_binding_handle *b,
    4650             :                                           struct policy_handle *handle,
    4651             :                                           const char *printer_name,
    4652             :                                           const char *key_name,
    4653             :                                           const char *value_name,
    4654             :                                           enum winreg_Type *w_type,
    4655             :                                           uint32_t *w_size,
    4656             :                                           uint32_t *w_length,
    4657             :                                           uint8_t **w_data)
    4658             : {
    4659             :         const char *printer_key;
    4660             :         struct policy_handle key_handle;
    4661             : 
    4662         248 :         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
    4663             :                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
    4664             : 
    4665         248 :         torture_assert(tctx,
    4666             :                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
    4667             : 
    4668         248 :         torture_assert(tctx,
    4669             :                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
    4670             : 
    4671         248 :         torture_assert(tctx,
    4672             :                 test_winreg_CloseKey(tctx, b, &key_handle), "");
    4673             : 
    4674         248 :         return true;
    4675             : }
    4676             : 
    4677          48 : static bool test_GetForm_winreg(struct torture_context *tctx,
    4678             :                                 struct dcerpc_binding_handle *b,
    4679             :                                 struct policy_handle *handle,
    4680             :                                 const char *key_name,
    4681             :                                 const char *form_name,
    4682             :                                 enum winreg_Type *w_type,
    4683             :                                 uint32_t *w_size,
    4684             :                                 uint32_t *w_length,
    4685             :                                 uint8_t **w_data)
    4686             : {
    4687             :         struct policy_handle key_handle;
    4688             : 
    4689          48 :         torture_assert(tctx,
    4690             :                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
    4691             : 
    4692          48 :         torture_assert(tctx,
    4693             :                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
    4694             : 
    4695          48 :         torture_assert(tctx,
    4696             :                 test_winreg_CloseKey(tctx, b, &key_handle), "");
    4697             : 
    4698          48 :         return true;
    4699             : }
    4700             : 
    4701           8 : static bool test_winreg_symbolic_link(struct torture_context *tctx,
    4702             :                                       struct dcerpc_binding_handle *b,
    4703             :                                       struct policy_handle *handle,
    4704             :                                       const char *symlink_keyname,
    4705             :                                       const char *symlink_destination)
    4706             : {
    4707             :         /* check if the first key is a symlink to the second key */
    4708             : 
    4709             :         enum winreg_Type w_type;
    4710             :         uint32_t w_size;
    4711             :         uint32_t w_length;
    4712             :         uint8_t *w_data;
    4713             :         struct policy_handle key_handle;
    4714             :         DATA_BLOB blob;
    4715             :         const char *str;
    4716             : 
    4717           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    4718           8 :                 torture_skip(tctx, "skip winreg symlink test against samba");
    4719             :         }
    4720             : 
    4721           0 :         torture_assert(tctx,
    4722             :                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
    4723             :                         "failed to open key link");
    4724             : 
    4725           0 :         torture_assert(tctx,
    4726             :                 test_winreg_QueryValue(tctx, b, &key_handle,
    4727             :                                        "SymbolicLinkValue",
    4728             :                                        &w_type, &w_size, &w_length, &w_data),
    4729             :                 "failed to query for 'SymbolicLinkValue' attribute");
    4730             : 
    4731           0 :         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
    4732             : 
    4733           0 :         blob = data_blob(w_data, w_size);
    4734           0 :         str = reg_val_data_string(tctx, REG_SZ, blob);
    4735             : 
    4736           0 :         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
    4737             : 
    4738           0 :         torture_assert(tctx,
    4739             :                 test_winreg_CloseKey(tctx, b, &key_handle),
    4740             :                 "failed to close key link");
    4741             : 
    4742           0 :         return true;
    4743             : }
    4744             : 
    4745          16 : static const char *strip_unc(const char *unc)
    4746             : {
    4747             :         char *name;
    4748             : 
    4749          16 :         if (!unc) {
    4750           0 :                 return NULL;
    4751             :         }
    4752             : 
    4753          16 :         if (unc[0] == '\\' && unc[1] == '\\') {
    4754           8 :                 unc +=2;
    4755             :         }
    4756             : 
    4757          16 :         name = strchr(unc, '\\');
    4758          16 :         if (name) {
    4759           8 :                 return name+1;
    4760             :         }
    4761             : 
    4762           8 :         return unc;
    4763             : }
    4764             : 
    4765           8 : static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
    4766             :                                        struct dcerpc_binding_handle *b,
    4767             :                                        struct policy_handle *handle,
    4768             :                                        const char *printer_name,
    4769             :                                        struct dcerpc_binding_handle *winreg_handle,
    4770             :                                        struct policy_handle *hive_handle)
    4771             : {
    4772             :         union spoolss_PrinterInfo info;
    4773           8 :         const char *keys[] = {
    4774             :                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
    4775             :                 TOP_LEVEL_PRINT_PRINTERS_KEY
    4776             :         };
    4777             :         int i;
    4778             :         const char *printername, *sharename;
    4779             : 
    4780           8 :         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
    4781             : 
    4782           8 :         torture_assert(tctx,
    4783             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    4784             :                 "failed to get printer info level 2");
    4785             : 
    4786           8 :         printername = strip_unc(info.info2.printername);
    4787           8 :         sharename = strip_unc(info.info2.sharename);
    4788             : 
    4789             : #define test_sz(wname, iname) \
    4790             : do {\
    4791             :         DATA_BLOB blob;\
    4792             :         const char *str;\
    4793             :         enum winreg_Type w_type;\
    4794             :         uint32_t w_size;\
    4795             :         uint32_t w_length;\
    4796             :         uint8_t *w_data;\
    4797             :         torture_assert(tctx,\
    4798             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4799             :                                        &w_type, &w_size, &w_length, &w_data),\
    4800             :                 "failed to query winreg");\
    4801             :         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
    4802             :         blob = data_blob(w_data, w_size);\
    4803             :         str = reg_val_data_string(tctx, REG_SZ, blob);\
    4804             :         if (w_size == 2 && iname == NULL) {\
    4805             :                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
    4806             :         } else {\
    4807             :                 torture_assert_str_equal(tctx, str, iname,\
    4808             :                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
    4809             :         }\
    4810             : } while(0);
    4811             : 
    4812             : #define test_dword(wname, iname) \
    4813             : do {\
    4814             :         uint32_t value;\
    4815             :         enum winreg_Type w_type;\
    4816             :         uint32_t w_size;\
    4817             :         uint32_t w_length;\
    4818             :         uint8_t *w_data;\
    4819             :         torture_assert(tctx,\
    4820             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4821             :                                        &w_type, &w_size, &w_length, &w_data),\
    4822             :                 "failed to query winreg");\
    4823             :         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
    4824             :         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
    4825             :         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
    4826             :         value = IVAL(w_data, 0);\
    4827             :         torture_assert_int_equal(tctx, value, iname,\
    4828             :                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
    4829             : } while(0);
    4830             : 
    4831             : #define test_binary(wname, iname) \
    4832             : do {\
    4833             :         enum winreg_Type w_type;\
    4834             :         uint32_t w_size;\
    4835             :         uint32_t w_length;\
    4836             :         uint8_t *w_data;\
    4837             :         torture_assert(tctx,\
    4838             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4839             :                                        &w_type, &w_size, &w_length, &w_data),\
    4840             :                 "failed to query winreg");\
    4841             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4842             :         torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
    4843             :         torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
    4844             :                 "binary unequal");\
    4845             : } while(0);
    4846             : 
    4847             : 
    4848             : #define test_dm(wname, iname) \
    4849             : do {\
    4850             :         DATA_BLOB blob;\
    4851             :         struct spoolss_DeviceMode dm;\
    4852             :         enum ndr_err_code ndr_err;\
    4853             :         enum winreg_Type w_type;\
    4854             :         uint32_t w_size;\
    4855             :         uint32_t w_length;\
    4856             :         uint8_t *w_data;\
    4857             :         torture_assert(tctx,\
    4858             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4859             :                                        &w_type, &w_size, &w_length, &w_data),\
    4860             :                 "failed to query winreg");\
    4861             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4862             :         blob = data_blob(w_data, w_size);\
    4863             :         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
    4864             :                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
    4865             :         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
    4866             :         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
    4867             :                 "dm unequal");\
    4868             : } while(0);
    4869             : 
    4870             : #define test_sd(wname, iname) \
    4871             : do {\
    4872             :         DATA_BLOB blob;\
    4873             :         struct security_descriptor sd;\
    4874             :         enum ndr_err_code ndr_err;\
    4875             :         enum winreg_Type w_type;\
    4876             :         uint32_t w_size;\
    4877             :         uint32_t w_length;\
    4878             :         uint8_t *w_data;\
    4879             :         torture_assert(tctx,\
    4880             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4881             :                                        &w_type, &w_size, &w_length, &w_data),\
    4882             :                 "failed to query winreg");\
    4883             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4884             :         blob = data_blob(w_data, w_size);\
    4885             :         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
    4886             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
    4887             :         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
    4888             :         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
    4889             :                 "sd unequal");\
    4890             : } while(0);
    4891             : 
    4892             : #define test_multi_sz(wname, iname) \
    4893             : do {\
    4894             :         DATA_BLOB blob;\
    4895             :         const char **array;\
    4896             :         enum winreg_Type w_type;\
    4897             :         uint32_t w_size;\
    4898             :         uint32_t w_length;\
    4899             :         uint8_t *w_data;\
    4900             :         int i;\
    4901             :         torture_assert(tctx,\
    4902             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4903             :                                        &w_type, &w_size, &w_length, &w_data),\
    4904             :                 "failed to query winreg");\
    4905             :         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
    4906             :         blob = data_blob(w_data, w_size);\
    4907             :         torture_assert(tctx, \
    4908             :                 pull_reg_multi_sz(tctx, &blob, &array),\
    4909             :                 "failed to pull multi sz");\
    4910             :         for (i=0; array[i] != NULL; i++) {\
    4911             :                 torture_assert_str_equal(tctx, array[i], iname[i],\
    4912             :                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
    4913             :         }\
    4914             : } while(0);
    4915             : 
    4916           8 :         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
    4917             :                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
    4918             :                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
    4919             :         {
    4920           0 :                 torture_warning(tctx, "failed to check for winreg symlink");
    4921             :         }
    4922             : 
    4923          42 :         for (i=0; i < ARRAY_SIZE(keys); i++) {
    4924             : 
    4925             :                 const char *printer_key;
    4926             :                 struct policy_handle key_handle;
    4927             : 
    4928          16 :                 printer_key = talloc_asprintf(tctx, "%s\\%s",
    4929             :                         keys[i], printer_name);
    4930             : 
    4931          16 :                 torture_assert(tctx,
    4932             :                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
    4933             : 
    4934          16 :                 test_sz("Name", printername);
    4935          16 :                 test_sz("Share Name", sharename);
    4936          16 :                 test_sz("Port", info.info2.portname);
    4937          16 :                 test_sz("Printer Driver", info.info2.drivername);
    4938          16 :                 test_sz("Description", info.info2.comment);
    4939          16 :                 test_sz("Location", info.info2.location);
    4940          16 :                 test_sz("Separator File", info.info2.sepfile);
    4941          16 :                 test_sz("Print Processor", info.info2.printprocessor);
    4942          16 :                 test_sz("Datatype", info.info2.datatype);
    4943          16 :                 test_sz("Parameters", info.info2.parameters);
    4944             :                 /* winreg: 0, spoolss not */
    4945             : /*              test_dword("Attributes", info.info2.attributes); */
    4946          16 :                 test_dword("Priority", info.info2.priority);
    4947          16 :                 test_dword("Default Priority", info.info2.defaultpriority);
    4948             :                 /* winreg: 60, spoolss: 0 */
    4949             : /*              test_dword("StartTime", info.info2.starttime); */
    4950             : /*              test_dword("UntilTime", info.info2.untiltime); */
    4951             :                 /* winreg != spoolss */
    4952             : /*              test_dword("Status", info.info2.status); */
    4953          16 :                 test_dm("Default DevMode", info.info2.devmode);
    4954          16 :                 test_sd("Security", info.info2.secdesc);
    4955             : 
    4956          16 :                 torture_assert(tctx,
    4957             :                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    4958             :         }
    4959             : 
    4960             : #undef test_dm
    4961             : 
    4962           8 :         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
    4963             : 
    4964           8 :         return true;
    4965             : }
    4966             : 
    4967           4 : static bool test_GetPrintserverInfo_winreg(struct torture_context *tctx,
    4968             :                                            struct dcerpc_binding_handle *b,
    4969             :                                            struct policy_handle *handle,
    4970             :                                            struct dcerpc_binding_handle *winreg_handle,
    4971             :                                            struct policy_handle *hive_handle)
    4972             : {
    4973             :         union spoolss_PrinterInfo info;
    4974             :         struct policy_handle key_handle;
    4975             : 
    4976           4 :         torture_comment(tctx,
    4977             :                 "Testing Printserver Info and winreg consistency\n");
    4978             : 
    4979           4 :         torture_assert(tctx,
    4980             :                 test_GetPrinter_level(tctx, b, handle, 3, &info),
    4981             :                 "failed to get printer info level 2");
    4982             : 
    4983           4 :         torture_assert(tctx,
    4984             :                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle,
    4985             :                                     TOP_LEVEL_CONTROL_KEY, &key_handle), "");
    4986             : 
    4987           4 :         test_sd("ServerSecurityDescriptor", info.info3.secdesc);
    4988             : 
    4989           4 :         torture_assert(tctx,
    4990             :                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    4991             : 
    4992             : #undef test_sd
    4993             : 
    4994           4 :         torture_comment(tctx,
    4995             :                 "Printserver Info and winreg consistency test succeeded\n\n");
    4996             : 
    4997           4 :         return true;
    4998             : }
    4999             : 
    5000             : 
    5001           4 : static bool test_PrintProcessors(struct torture_context *tctx,
    5002             :                                  struct dcerpc_binding_handle *b,
    5003             :                                  const char *environment,
    5004             :                                  struct dcerpc_binding_handle *winreg_handle,
    5005             :                                  struct policy_handle *hive_handle)
    5006             : {
    5007             :         union spoolss_PrintProcessorInfo *info;
    5008             :         uint32_t count;
    5009             :         int i;
    5010             : 
    5011           4 :         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
    5012             : 
    5013           4 :         torture_assert(tctx,
    5014             :                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
    5015             :                 "failed to enum print processors level 1");
    5016             : 
    5017          14 :         for (i=0; i < count; i++) {
    5018             : 
    5019             :                 const char *processor_key;
    5020             :                 struct policy_handle key_handle;
    5021             : 
    5022           4 :                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
    5023             :                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
    5024             :                                                 environment,
    5025           4 :                                                 info[i].info1.print_processor_name);
    5026             : 
    5027           4 :                 torture_assert(tctx,
    5028             :                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
    5029             : 
    5030             :                 /* nothing to check in there so far */
    5031             : 
    5032           4 :                 torture_assert(tctx,
    5033             :                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    5034             :         }
    5035             : 
    5036           4 :         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
    5037             : 
    5038           4 :         return true;
    5039             : }
    5040             : 
    5041             : static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
    5042             :                                          struct dcerpc_binding_handle *b,
    5043             :                                          struct policy_handle *handle,
    5044             :                                          const char *driver_name,
    5045             :                                          const char *architecture,
    5046             :                                          uint32_t level,
    5047             :                                          uint32_t client_major_version,
    5048             :                                          uint32_t client_minor_version,
    5049             :                                          union spoolss_DriverInfo *info_p,
    5050             :                                          WERROR *result);
    5051             : 
    5052           0 : static const char *strip_path(const char *path)
    5053             : {
    5054             :         char *p;
    5055             : 
    5056           0 :         if (path == NULL) {
    5057           0 :                 return NULL;
    5058             :         }
    5059             : 
    5060           0 :         p = strrchr(path, '\\');
    5061           0 :         if (p) {
    5062           0 :                 return p+1;
    5063             :         }
    5064             : 
    5065           0 :         return path;
    5066             : }
    5067             : 
    5068           0 : static const char **strip_paths(const char **path_array)
    5069             : {
    5070             :         int i;
    5071             : 
    5072           0 :         if (path_array == NULL) {
    5073           0 :                 return NULL;
    5074             :         }
    5075             : 
    5076           0 :         for (i=0; path_array[i] != NULL; i++) {
    5077           0 :                 path_array[i] = strip_path(path_array[i]);
    5078             :         }
    5079             : 
    5080           0 :         return path_array;
    5081             : }
    5082             : 
    5083           0 : static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
    5084             : {
    5085             :         time_t t;
    5086             :         struct tm *tm;
    5087             : 
    5088           0 :         if (nt == 0) {
    5089           0 :                 return talloc_strdup(mem_ctx, "01/01/1601");
    5090             :         }
    5091             : 
    5092           0 :         t = nt_time_to_unix(nt);
    5093           0 :         tm = localtime(&t);
    5094             : 
    5095           0 :         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
    5096           0 :                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
    5097             : }
    5098             : 
    5099           0 : static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
    5100             : {
    5101           0 :         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
    5102           0 :                 (unsigned)((v >> 48) & 0xFFFF),
    5103           0 :                 (unsigned)((v >> 32) & 0xFFFF),
    5104           0 :                 (unsigned)((v >> 16) & 0xFFFF),
    5105             :                 (unsigned)(v & 0xFFFF));
    5106             : }
    5107             : 
    5108           0 : static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
    5109             :                                       struct dcerpc_binding_handle *b,
    5110             :                                       struct policy_handle *handle,
    5111             :                                       const char *printer_name,
    5112             :                                       const char *driver_name,
    5113             :                                       const char *environment,
    5114             :                                       enum spoolss_DriverOSVersion version,
    5115             :                                       struct dcerpc_binding_handle *winreg_handle,
    5116             :                                       struct policy_handle *hive_handle,
    5117             :                                       const char *server_name_slash)
    5118             : {
    5119           0 :         WERROR result = WERR_OK;
    5120             :         union spoolss_DriverInfo info;
    5121             :         const char *driver_key;
    5122             :         struct policy_handle key_handle;
    5123             : 
    5124             :         const char *driver_path;
    5125             :         const char *data_file;
    5126             :         const char *config_file;
    5127             :         const char *help_file;
    5128             :         const char **dependent_files;
    5129             : 
    5130             :         const char *driver_date;
    5131             :         const char *inbox_driver_date;
    5132             : 
    5133             :         const char *driver_version;
    5134             :         const char *inbox_driver_version;
    5135             : 
    5136           0 :         ZERO_STRUCT(key_handle);
    5137             : 
    5138           0 :         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
    5139             : 
    5140           0 :         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
    5141             :                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
    5142             :                                      environment,
    5143             :                                      version,
    5144             :                                      driver_name);
    5145             : 
    5146           0 :         torture_assert(tctx,
    5147             :                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
    5148             :                 "failed to open driver key");
    5149             : 
    5150           0 :         if (torture_setting_bool(tctx, "samba3", false) ||
    5151           0 :             torture_setting_bool(tctx, "w2k3", false)) {
    5152           0 :                 goto try_level6;
    5153             :         }
    5154             : 
    5155           0 :         if (handle) {
    5156           0 :                 torture_assert(tctx,
    5157             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
    5158             :                         "failed to get driver info level 8");
    5159             :         } else {
    5160           0 :                 torture_assert(tctx,
    5161             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
    5162             :                         "failed to get driver info level 8");
    5163             :         }
    5164             : 
    5165           0 :         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
    5166           0 :                 goto try_level6;
    5167             :         }
    5168             : 
    5169           0 :         driver_path     = strip_path(info.info8.driver_path);
    5170           0 :         data_file       = strip_path(info.info8.data_file);
    5171           0 :         config_file     = strip_path(info.info8.config_file);
    5172           0 :         help_file       = strip_path(info.info8.help_file);
    5173           0 :         dependent_files = strip_paths(info.info8.dependent_files);
    5174             : 
    5175           0 :         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
    5176           0 :         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
    5177             : 
    5178           0 :         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
    5179           0 :         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
    5180             : 
    5181           0 :         test_sz("Configuration File",         config_file);
    5182           0 :         test_sz("Data File",                  data_file);
    5183           0 :         test_sz("Datatype",                   info.info8.default_datatype);
    5184           0 :         test_sz("Driver",                     driver_path);
    5185           0 :         test_sz("DriverDate",                 driver_date);
    5186           0 :         test_sz("DriverVersion",              driver_version);
    5187           0 :         test_sz("HardwareID",                 info.info8.hardware_id);
    5188           0 :         test_sz("Help File",                  help_file);
    5189           0 :         test_sz("InfPath",                    info.info8.inf_path);
    5190           0 :         test_sz("Manufacturer",                       info.info8.manufacturer_name);
    5191           0 :         test_sz("MinInboxDriverVerDate",      inbox_driver_date);
    5192           0 :         test_sz("MinInboxDriverVerVersion",   inbox_driver_version);
    5193           0 :         test_sz("Monitor",                    info.info8.monitor_name);
    5194           0 :         test_sz("OEM URL",                    info.info8.manufacturer_url);
    5195           0 :         test_sz("Print Processor",            info.info8.print_processor);
    5196           0 :         test_sz("Provider",                   info.info8.provider);
    5197           0 :         test_sz("VendorSetup",                        info.info8.vendor_setup);
    5198           0 :         test_multi_sz("ColorProfiles",                info.info8.color_profiles);
    5199           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5200           0 :         test_multi_sz("CoreDependencies",     info.info8.core_driver_dependencies);
    5201           0 :         test_multi_sz("Previous Names",               info.info8.previous_names);
    5202             : /*      test_dword("Attributes",              ?); */
    5203           0 :         test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
    5204           0 :         test_dword("Version",                 info.info8.version);
    5205             : /*      test_dword("TempDir",                 ?); */
    5206             : 
    5207           0 :  try_level6:
    5208             : 
    5209           0 :         if (handle) {
    5210           0 :                 torture_assert(tctx,
    5211             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
    5212             :                         "failed to get driver info level 6");
    5213             :         } else {
    5214           0 :                 torture_assert(tctx,
    5215             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
    5216             :                         "failed to get driver info level 6");
    5217             :         }
    5218             : 
    5219           0 :         driver_path     = strip_path(info.info6.driver_path);
    5220           0 :         data_file       = strip_path(info.info6.data_file);
    5221           0 :         config_file     = strip_path(info.info6.config_file);
    5222           0 :         help_file       = strip_path(info.info6.help_file);
    5223           0 :         dependent_files = strip_paths(info.info6.dependent_files);
    5224             : 
    5225           0 :         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
    5226             : 
    5227           0 :         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
    5228             : 
    5229           0 :         test_sz("Configuration File",         config_file);
    5230           0 :         test_sz("Data File",                  data_file);
    5231           0 :         test_sz("Datatype",                   info.info6.default_datatype);
    5232           0 :         test_sz("Driver",                     driver_path);
    5233           0 :         if (torture_setting_bool(tctx, "w2k3", false)) {
    5234           0 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
    5235           0 :                 push_nttime(blob.data, 0, info.info6.driver_date);
    5236           0 :                 test_binary("DriverDate",     blob);
    5237           0 :                 SBVAL(blob.data, 0, info.info6.driver_version);
    5238           0 :                 test_binary("DriverVersion",  blob);
    5239             :         } else {
    5240           0 :                 test_sz("DriverDate",         driver_date);
    5241           0 :                 test_sz("DriverVersion",      driver_version);
    5242             :         }
    5243           0 :         test_sz("HardwareID",                 info.info6.hardware_id);
    5244           0 :         test_sz("Help File",                  help_file);
    5245           0 :         test_sz("Manufacturer",                       info.info6.manufacturer_name);
    5246           0 :         test_sz("Monitor",                    info.info6.monitor_name);
    5247           0 :         test_sz("OEM URL",                    info.info6.manufacturer_url);
    5248           0 :         test_sz("Provider",                   info.info6.provider);
    5249           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5250           0 :         test_multi_sz("Previous Names",               info.info6.previous_names);
    5251             : /*      test_dword("Attributes",              ?); */
    5252           0 :         test_dword("Version",                 info.info6.version);
    5253             : /*      test_dword("TempDir",                 ?); */
    5254             : 
    5255           0 :         if (handle) {
    5256           0 :                 torture_assert(tctx,
    5257             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
    5258             :                         "failed to get driver info level 3");
    5259             :         } else {
    5260           0 :                 torture_assert(tctx,
    5261             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
    5262             :                         "failed to get driver info level 3");
    5263             :         }
    5264             : 
    5265           0 :         driver_path     = strip_path(info.info3.driver_path);
    5266           0 :         data_file       = strip_path(info.info3.data_file);
    5267           0 :         config_file     = strip_path(info.info3.config_file);
    5268           0 :         help_file       = strip_path(info.info3.help_file);
    5269           0 :         dependent_files = strip_paths(info.info3.dependent_files);
    5270             : 
    5271           0 :         test_sz("Configuration File",         config_file);
    5272           0 :         test_sz("Data File",                  data_file);
    5273           0 :         test_sz("Datatype",                   info.info3.default_datatype);
    5274           0 :         test_sz("Driver",                     driver_path);
    5275           0 :         test_sz("Help File",                  help_file);
    5276           0 :         test_sz("Monitor",                    info.info3.monitor_name);
    5277           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5278             : /*      test_dword("Attributes",              ?); */
    5279           0 :         test_dword("Version",                 info.info3.version);
    5280             : /*      test_dword("TempDir",                 ?); */
    5281             : 
    5282             : 
    5283           0 :         torture_assert(tctx,
    5284             :                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    5285             : 
    5286           0 :         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
    5287             : 
    5288           0 :         return true;
    5289             : }
    5290             : 
    5291             : #undef test_sz
    5292             : #undef test_dword
    5293             : 
    5294         168 : static bool test_SetPrinterData(struct torture_context *tctx,
    5295             :                                 struct dcerpc_binding_handle *b,
    5296             :                                 struct policy_handle *handle,
    5297             :                                 const char *value_name,
    5298             :                                 enum winreg_Type type,
    5299             :                                 uint8_t *data,
    5300             :                                 uint32_t offered)
    5301             : {
    5302             :         struct spoolss_SetPrinterData r;
    5303             : 
    5304         168 :         r.in.handle = handle;
    5305         168 :         r.in.value_name = value_name;
    5306         168 :         r.in.type = type;
    5307         168 :         r.in.data = data;
    5308         168 :         r.in.offered = offered;
    5309             : 
    5310         168 :         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
    5311             :                 r.in.value_name);
    5312             : 
    5313         168 :         torture_assert_ntstatus_ok(tctx,
    5314             :                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
    5315             :                 "SetPrinterData failed");
    5316         168 :         torture_assert_werr_ok(tctx, r.out.result,
    5317             :                 "SetPrinterData failed");
    5318             : 
    5319         168 :         return true;
    5320             : }
    5321             : 
    5322          28 : static bool test_SetPrinterData_matrix(struct torture_context *tctx,
    5323             :                                        struct dcerpc_binding_handle *b,
    5324             :                                        struct policy_handle *handle,
    5325             :                                        const char *printer_name,
    5326             :                                        struct dcerpc_binding_handle *winreg_handle,
    5327             :                                        struct policy_handle *hive_handle)
    5328             : {
    5329          28 :         const char *values[] = {
    5330             :                 "spootyfoot",
    5331             :                 "spooty\\foot",
    5332             : #if 0
    5333             :         /* FIXME: not working with s3 atm. */
    5334             :                 "spooty,foot",
    5335             :                 "spooty,fo,ot",
    5336             : #endif
    5337             :                 "spooty foot",
    5338             : #if 0
    5339             :         /* FIXME: not working with s3 atm. */
    5340             :                 "spooty\\fo,ot",
    5341             :                 "spooty,fo\\ot"
    5342             : #endif
    5343             :         };
    5344             :         int i;
    5345             : 
    5346         196 :         for (i=0; i < ARRAY_SIZE(values); i++) {
    5347             : 
    5348          84 :                 enum winreg_Type type, expected_type = REG_SZ;
    5349             :                 DATA_BLOB blob;
    5350             :                 uint8_t *data;
    5351             :                 uint32_t needed;
    5352             : 
    5353          84 :                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
    5354          84 :                 type = REG_SZ;
    5355             : 
    5356          84 :                 torture_assert(tctx,
    5357             :                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
    5358             :                         "SetPrinterData failed");
    5359             : 
    5360          84 :                 torture_assert(tctx,
    5361             :                         test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
    5362             :                         "GetPrinterData failed");
    5363             : 
    5364          84 :                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
    5365          84 :                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
    5366          84 :                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
    5367             : 
    5368          84 :                 if (winreg_handle && hive_handle) {
    5369             : 
    5370             :                         enum winreg_Type w_type;
    5371             :                         uint32_t w_size;
    5372             :                         uint32_t w_length;
    5373             :                         uint8_t *w_data;
    5374             : 
    5375          24 :                         torture_assert(tctx,
    5376             :                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
    5377             :                                         printer_name, "PrinterDriverData", values[i],
    5378             :                                         &w_type, &w_size, &w_length, &w_data), "");
    5379             : 
    5380          24 :                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
    5381          24 :                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
    5382          24 :                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
    5383          24 :                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
    5384             :                 }
    5385             : 
    5386          84 :                 torture_assert(tctx,
    5387             :                         test_DeletePrinterData(tctx, b, handle, values[i]),
    5388             :                         "DeletePrinterData failed");
    5389             :         }
    5390             : 
    5391          28 :         return true;
    5392             : }
    5393             : 
    5394             : 
    5395             : static bool test_EnumPrinterKey(struct torture_context *tctx,
    5396             :                                 struct dcerpc_binding_handle *b,
    5397             :                                 struct policy_handle *handle,
    5398             :                                 const char *key_name,
    5399             :                                 const char ***array);
    5400             : 
    5401        1200 : static bool test_SetPrinterDataEx(struct torture_context *tctx,
    5402             :                                   struct dcerpc_binding_handle *b,
    5403             :                                   struct policy_handle *handle,
    5404             :                                   const char *key_name,
    5405             :                                   const char *value_name,
    5406             :                                   enum winreg_Type type,
    5407             :                                   uint8_t *data,
    5408             :                                   uint32_t offered)
    5409             : {
    5410             :         NTSTATUS status;
    5411             :         struct spoolss_SetPrinterDataEx r;
    5412             : 
    5413        1200 :         r.in.handle = handle;
    5414        1200 :         r.in.key_name = key_name;
    5415        1200 :         r.in.value_name = value_name;
    5416        1200 :         r.in.type = type;
    5417        1200 :         r.in.data = data;
    5418        1200 :         r.in.offered = offered;
    5419             : 
    5420        2100 :         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
    5421        1200 :                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
    5422             : 
    5423        1200 :         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
    5424             : 
    5425        1200 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
    5426        1200 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
    5427             : 
    5428        1200 :         return true;
    5429             : }
    5430             : 
    5431           8 : static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
    5432             :                                        struct dcerpc_pipe *p,
    5433             :                                        struct policy_handle *handle)
    5434             : {
    5435           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5436           8 :         const char *value_name = "dog";
    5437           8 :         const char *keys[] = {
    5438             :                 "torturedataex",
    5439             :                 "torture data ex",
    5440             :                 "torturedataex_with_subkey\\subkey",
    5441             :                 "torturedataex_with_subkey\\subkey:0",
    5442             :                 "torturedataex_with_subkey\\subkey:1",
    5443             :                 "torturedataex_with_subkey\\subkey\\subsubkey",
    5444             :                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
    5445             :                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
    5446             :                 "torture,data",
    5447             :                 "torture,data,ex",
    5448             :                 "torture,data\\ex",
    5449             :                 "torture\\data,ex",
    5450             :                 "torture/data",
    5451             :                 "torture/data ex",
    5452             :                 "torture/data ex/sub",
    5453             :                 "torture//data",
    5454             :                 "torture//data ex",
    5455             :                 "torture//data ex/sub",
    5456             :                 "torture//data ex//sub",
    5457             :         };
    5458             :         int i;
    5459             : 
    5460         280 :         for (i=0; i < ARRAY_SIZE(keys); i++) {
    5461             : 
    5462             :                 char *c;
    5463             :                 const char *key;
    5464             :                 enum winreg_Type type;
    5465             :                 DATA_BLOB blob_in, blob_out;
    5466             :                 const char **subkeys;
    5467             :                 uint32_t ecount;
    5468             :                 struct spoolss_PrinterEnumValues *einfo;
    5469             :                 uint32_t needed;
    5470             : 
    5471         152 :                 blob_in = data_blob_talloc(tctx, NULL, 42);
    5472             : 
    5473         152 :                 generate_random_buffer(blob_in.data, blob_in.length);
    5474             : 
    5475         152 :                 torture_assert(tctx,
    5476             :                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
    5477             :                         "failed to call SetPrinterDataEx");
    5478             : 
    5479         152 :                 torture_assert(tctx,
    5480             :                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
    5481             :                         "failed to call GetPrinterDataEx");
    5482             : 
    5483         152 :                 blob_out.length = needed;
    5484         152 :                 torture_assert(tctx,
    5485             :                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
    5486             :                         "failed to call EnumPrinterDataEx");
    5487             : 
    5488         152 :                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
    5489         152 :                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
    5490         152 :                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
    5491             : 
    5492         152 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5493         152 :                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
    5494         152 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
    5495         152 :                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
    5496         152 :                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
    5497         152 :                 if (einfo[0].data_length > 0) {
    5498         152 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
    5499             :                 }
    5500             : 
    5501         152 :                 key = talloc_strdup(tctx, keys[i]);
    5502             : 
    5503         152 :                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
    5504           0 :                         return false;
    5505             :                 }
    5506             : 
    5507         152 :                 c = strchr(key, '\\');
    5508         152 :                 if (c) {
    5509             :                         int k;
    5510             : 
    5511             :                         /* we have subkeys */
    5512             : 
    5513          64 :                         *c = 0;
    5514             : 
    5515          64 :                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
    5516           0 :                                 return false;
    5517             :                         }
    5518             : 
    5519         128 :                         for (k=0; subkeys && subkeys[k]; k++) {
    5520             : 
    5521          64 :                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
    5522             : 
    5523          64 :                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
    5524           0 :                                         return false;
    5525             :                                 }
    5526             :                         }
    5527             : 
    5528          64 :                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
    5529           0 :                                 return false;
    5530             :                         }
    5531             : 
    5532             :                 } else {
    5533          88 :                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
    5534           0 :                                 return false;
    5535             :                         }
    5536             :                 }
    5537             :         }
    5538             : 
    5539           8 :         return true;
    5540             : }
    5541             : 
    5542           8 : static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
    5543             :                                          struct dcerpc_pipe *p,
    5544             :                                          struct policy_handle *handle)
    5545             : {
    5546           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5547           8 :         const char *key = "torturedataex";
    5548           8 :         const char *values[] = {
    5549             :                 "torture_value",
    5550             :                 "torture value",
    5551             :                 "torture,value",
    5552             :                 "torture/value",
    5553             :                 "torture\\value",
    5554             :                 "torture\\\\value"
    5555             :         };
    5556             :         int i;
    5557             : 
    5558          56 :         for (i=0; i < ARRAY_SIZE(values); i++) {
    5559             : 
    5560          48 :                 enum winreg_Type type = REG_NONE;
    5561          48 :                 DATA_BLOB blob_in = data_blob_null;
    5562          48 :                 DATA_BLOB blob_out = data_blob_null;
    5563             :                 uint32_t ecount;
    5564             :                 struct spoolss_PrinterEnumValues *einfo;
    5565          48 :                 uint32_t needed = 0;
    5566             : 
    5567          48 :                 if (torture_setting_bool(tctx, "samba3", false)) {
    5568             :                         char *q;
    5569          48 :                         q = strrchr(values[i], ',');
    5570          48 :                         if (q) {
    5571           8 :                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
    5572             :                                                 values[i]);
    5573           8 :                                 continue;
    5574             :                         }
    5575             :                 }
    5576             : 
    5577          40 :                 blob_in = data_blob_talloc(tctx, NULL, 42);
    5578             : 
    5579          40 :                 generate_random_buffer(blob_in.data, blob_in.length);
    5580             : 
    5581          40 :                 torture_assert(tctx,
    5582             :                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
    5583             :                         "failed to call SetPrinterDataEx");
    5584             : 
    5585          40 :                 torture_assert(tctx,
    5586             :                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
    5587             :                         "failed to call GetPrinterDataEx");
    5588             : 
    5589          40 :                 blob_out.length = needed;
    5590          40 :                 torture_assert(tctx,
    5591             :                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
    5592             :                         "failed to call EnumPrinterDataEx");
    5593             : 
    5594          40 :                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
    5595          40 :                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
    5596          40 :                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
    5597             : 
    5598          40 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5599          40 :                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
    5600          40 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
    5601          40 :                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
    5602          40 :                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
    5603          40 :                 if (einfo[0].data_length > 0) {
    5604          40 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
    5605             :                 }
    5606             : 
    5607          40 :                 torture_assert(tctx,
    5608             :                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
    5609             :                         "failed to call DeletePrinterDataEx");
    5610             :         }
    5611             : 
    5612           8 :         return true;
    5613             : }
    5614             : 
    5615             : 
    5616          36 : static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
    5617             :                                          struct dcerpc_pipe *p,
    5618             :                                          struct policy_handle *handle,
    5619             :                                          const char *printername,
    5620             :                                          struct dcerpc_binding_handle *winreg_handle,
    5621             :                                          struct policy_handle *hive_handle)
    5622             : {
    5623          36 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5624          36 :         const char *value_name = "dog";
    5625          36 :         const char *key_name = "torturedataex";
    5626          36 :         enum winreg_Type types[] = {
    5627             :                 REG_SZ,
    5628             :                 REG_MULTI_SZ,
    5629             :                 REG_DWORD,
    5630             :                 REG_BINARY
    5631             :         };
    5632          36 :         const char *str = "abcdefghi";
    5633             :         size_t t, s;
    5634             : 
    5635         180 :         for (t=0; t < ARRAY_SIZE(types); t++) {
    5636        2016 :         for (s=0; s < strlen(str); s++) {
    5637             : 
    5638             :                 enum winreg_Type type;
    5639        1008 :                 const char *string = talloc_strndup(tctx, str, s);
    5640             :                 const char *array[2];
    5641        1008 :                 DATA_BLOB blob = data_blob_string_const(string);
    5642             :                 DATA_BLOB data;
    5643             :                 uint8_t *data_out;
    5644        1008 :                 uint32_t needed, offered = 0;
    5645             :                 uint32_t ecount;
    5646             :                 struct spoolss_PrinterEnumValues *einfo;
    5647             : 
    5648        1008 :                 array[0] = talloc_strdup(tctx, string);
    5649        1008 :                 array[1] = NULL;
    5650             : 
    5651        1008 :                 if (types[t] == REG_DWORD) {
    5652          36 :                         s = 0xffff;
    5653             :                 }
    5654             : 
    5655        1008 :                 switch (types[t]) {
    5656         324 :                 case REG_BINARY:
    5657         324 :                         data = blob;
    5658         324 :                         offered = blob.length;
    5659         324 :                         break;
    5660          36 :                 case REG_DWORD:
    5661          36 :                         data = data_blob_talloc(tctx, NULL, 4);
    5662          36 :                         SIVAL(data.data, 0, 0x12345678);
    5663          36 :                         offered = 4;
    5664          36 :                         break;
    5665         324 :                 case REG_SZ:
    5666         324 :                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
    5667         324 :                         type = REG_SZ;
    5668         324 :                         offered = data.length;
    5669             :                         /*strlen_m_term(data.string)*2;*/
    5670         324 :                         break;
    5671         324 :                 case REG_MULTI_SZ:
    5672         324 :                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
    5673         324 :                         type = REG_MULTI_SZ;
    5674         324 :                         offered = data.length;
    5675         324 :                         break;
    5676           0 :                 default:
    5677           0 :                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
    5678             :                 }
    5679             : 
    5680        1008 :                 torture_assert(tctx,
    5681             :                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
    5682             :                         "failed to call SetPrinterDataEx");
    5683             : 
    5684        1008 :                 torture_assert(tctx,
    5685             :                         test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
    5686             :                         "failed to call GetPrinterDataEx");
    5687             : 
    5688        1008 :                 torture_assert(tctx,
    5689             :                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
    5690             :                         "failed to call EnumPrinterDataEx");
    5691             : 
    5692        1008 :                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
    5693        1008 :                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
    5694        1008 :                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
    5695             : 
    5696        1008 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5697        1008 :                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
    5698        1008 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
    5699        1008 :                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
    5700        1008 :                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
    5701        1008 :                 if (einfo[0].data_length > 0) {
    5702         972 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
    5703             :                 }
    5704             : 
    5705        1008 :                 if (winreg_handle && hive_handle) {
    5706             :                         enum winreg_Type w_type;
    5707             :                         uint32_t w_size;
    5708             :                         uint32_t w_length;
    5709             :                         uint8_t *w_data;
    5710             : 
    5711         224 :                         torture_assert(tctx,
    5712             :                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
    5713             :                                         printername, key_name, value_name,
    5714             :                                         &w_type, &w_size, &w_length, &w_data), "");
    5715             : 
    5716         224 :                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
    5717         224 :                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
    5718         224 :                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
    5719         224 :                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
    5720             :                 }
    5721             : 
    5722        1008 :                 torture_assert(tctx,
    5723             :                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
    5724             :                         "failed to call DeletePrinterDataEx");
    5725             :         }
    5726             :         }
    5727             : 
    5728          36 :         return true;
    5729             : }
    5730             : 
    5731           8 : static bool test_PrinterData_winreg(struct torture_context *tctx,
    5732             :                                     struct dcerpc_pipe *p,
    5733             :                                     struct policy_handle *handle,
    5734             :                                     const char *printer_name)
    5735             : {
    5736           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5737             :         struct dcerpc_pipe *p2;
    5738           8 :         bool ret = true;
    5739             :         struct policy_handle hive_handle;
    5740             :         struct dcerpc_binding_handle *b2;
    5741             : 
    5742           8 :         torture_assert_ntstatus_ok(tctx,
    5743             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5744             :                 "could not open winreg pipe");
    5745           8 :         b2 = p2->binding_handle;
    5746             : 
    5747           8 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5748             : 
    5749           8 :         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
    5750           8 :         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
    5751             : 
    5752           8 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5753             : 
    5754           8 :         talloc_free(p2);
    5755             : 
    5756           8 :         return ret;
    5757             : }
    5758             : 
    5759          24 : static bool test_Forms_winreg(struct torture_context *tctx,
    5760             :                               struct dcerpc_binding_handle *b,
    5761             :                               struct policy_handle *handle,
    5762             :                               bool print_server,
    5763             :                               const char *printer_name)
    5764             : {
    5765             :         struct dcerpc_pipe *p2;
    5766          24 :         bool ret = true;
    5767             :         struct policy_handle hive_handle;
    5768             :         struct dcerpc_binding_handle *b2;
    5769             : 
    5770          24 :         torture_assert_ntstatus_ok(tctx,
    5771             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5772             :                 "could not open winreg pipe");
    5773          24 :         b2 = p2->binding_handle;
    5774             : 
    5775          24 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5776             : 
    5777          24 :         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
    5778             : 
    5779          24 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5780             : 
    5781          24 :         talloc_free(p2);
    5782             : 
    5783          24 :         return ret;
    5784             : }
    5785             : 
    5786           8 : static bool test_PrinterInfo_winreg(struct torture_context *tctx,
    5787             :                                     struct dcerpc_pipe *p,
    5788             :                                     struct policy_handle *handle,
    5789             :                                     const char *printer_name)
    5790             : {
    5791           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5792             :         struct dcerpc_pipe *p2;
    5793           8 :         bool ret = true;
    5794             :         struct policy_handle hive_handle;
    5795             :         struct dcerpc_binding_handle *b2;
    5796             : 
    5797           8 :         torture_assert_ntstatus_ok(tctx,
    5798             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5799             :                 "could not open winreg pipe");
    5800           8 :         b2 = p2->binding_handle;
    5801             : 
    5802           8 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5803             : 
    5804           8 :         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
    5805             : 
    5806           8 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5807             : 
    5808           8 :         talloc_free(p2);
    5809             : 
    5810           8 :         return ret;
    5811             : }
    5812             : 
    5813           4 : static bool test_PrintserverInfo_winreg(struct torture_context *tctx,
    5814             :                                         struct dcerpc_pipe *p,
    5815             :                                         struct policy_handle *handle)
    5816             : {
    5817           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5818             :         struct dcerpc_pipe *p2;
    5819           4 :         bool ret = true;
    5820             :         struct policy_handle hive_handle;
    5821             :         struct dcerpc_binding_handle *b2;
    5822             : 
    5823           4 :         torture_assert_ntstatus_ok(tctx,
    5824             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5825             :                 "could not open winreg pipe");
    5826           4 :         b2 = p2->binding_handle;
    5827             : 
    5828           4 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5829             : 
    5830           4 :         ret = test_GetPrintserverInfo_winreg(tctx, b, handle, b2, &hive_handle);
    5831             : 
    5832           4 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5833             : 
    5834           4 :         talloc_free(p2);
    5835             : 
    5836           4 :         return ret;
    5837             : }
    5838             : 
    5839             : 
    5840           0 : static bool test_DriverInfo_winreg(struct torture_context *tctx,
    5841             :                                    struct dcerpc_pipe *p,
    5842             :                                    struct policy_handle *handle,
    5843             :                                    const char *printer_name,
    5844             :                                    const char *driver_name,
    5845             :                                    const char *environment,
    5846             :                                    enum spoolss_DriverOSVersion version)
    5847             : {
    5848           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5849             :         struct dcerpc_pipe *p2;
    5850           0 :         bool ret = true;
    5851             :         struct policy_handle hive_handle;
    5852             :         struct dcerpc_binding_handle *b2;
    5853             : 
    5854           0 :         torture_assert_ntstatus_ok(tctx,
    5855             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5856             :                 "could not open winreg pipe");
    5857           0 :         b2 = p2->binding_handle;
    5858             : 
    5859           0 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5860             : 
    5861           0 :         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
    5862             : 
    5863           0 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5864             : 
    5865           0 :         talloc_free(p2);
    5866             : 
    5867           0 :         return ret;
    5868             : }
    5869             : 
    5870           4 : static bool test_PrintProcessors_winreg(struct torture_context *tctx,
    5871             :                                         struct dcerpc_binding_handle *b,
    5872             :                                         const char *environment)
    5873             : {
    5874             :         struct dcerpc_pipe *p2;
    5875           4 :         bool ret = true;
    5876             :         struct policy_handle hive_handle;
    5877             :         struct dcerpc_binding_handle *b2;
    5878             : 
    5879           4 :         torture_assert_ntstatus_ok(tctx,
    5880             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5881             :                 "could not open winreg pipe");
    5882           4 :         b2 = p2->binding_handle;
    5883             : 
    5884           4 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5885             : 
    5886           4 :         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
    5887             : 
    5888           4 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5889             : 
    5890           4 :         talloc_free(p2);
    5891             : 
    5892           4 :         return ret;
    5893             : }
    5894             : 
    5895           8 : static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
    5896             :                                        struct dcerpc_pipe *p,
    5897             :                                        struct policy_handle *handle,
    5898             :                                        const char *printer_name)
    5899             : {
    5900             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    5901             :         struct spoolss_DevmodeContainer devmode_ctr;
    5902             :         struct sec_desc_buf secdesc_ctr;
    5903             :         union spoolss_SetPrinterInfo sinfo;
    5904             :         union spoolss_PrinterInfo info;
    5905           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5906             :         const char *pname;
    5907             : 
    5908           8 :         ZERO_STRUCT(info_ctr);
    5909           8 :         ZERO_STRUCT(devmode_ctr);
    5910           8 :         ZERO_STRUCT(secdesc_ctr);
    5911             : 
    5912           8 :         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
    5913             : 
    5914           8 :         torture_assert(tctx,
    5915             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    5916             :                 "failed to query Printer level 2");
    5917             : 
    5918           8 :         torture_assert(tctx,
    5919             :                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
    5920             :                 "failed to convert");
    5921             : 
    5922           8 :         info_ctr.level = 2;
    5923           8 :         info_ctr.info = sinfo;
    5924             : 
    5925             : #define TEST_SZ(wname, iname) \
    5926             : do {\
    5927             :         enum winreg_Type type;\
    5928             :         uint8_t *data;\
    5929             :         uint32_t needed;\
    5930             :         DATA_BLOB blob;\
    5931             :         const char *str;\
    5932             :         torture_assert(tctx,\
    5933             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5934             :                 "failed to query");\
    5935             :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
    5936             :         blob = data_blob_const(data, needed);\
    5937             :         torture_assert(tctx,\
    5938             :                 pull_reg_sz(tctx, &blob, &str),\
    5939             :                 "failed to pull REG_SZ");\
    5940             :         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
    5941             : } while(0);
    5942             : 
    5943             : 
    5944             : #define TEST_SET_SZ(wname, iname, val) \
    5945             : do {\
    5946             :         enum winreg_Type type;\
    5947             :         uint8_t *data;\
    5948             :         uint32_t needed;\
    5949             :         DATA_BLOB blob;\
    5950             :         const char *str;\
    5951             :         sinfo.info2->iname = val;\
    5952             :         torture_assert(tctx,\
    5953             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
    5954             :                 "failed to call SetPrinter");\
    5955             :         torture_assert(tctx,\
    5956             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5957             :                 "failed to query");\
    5958             :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
    5959             :         blob = data_blob_const(data, needed);\
    5960             :         torture_assert(tctx,\
    5961             :                 pull_reg_sz(tctx, &blob, &str),\
    5962             :                 "failed to pull REG_SZ");\
    5963             :         torture_assert_str_equal(tctx, str, val, "unexpected result");\
    5964             : } while(0);
    5965             : 
    5966             : #define TEST_SET_DWORD(wname, iname, val) \
    5967             : do {\
    5968             :         enum winreg_Type type;\
    5969             :         uint8_t *data;\
    5970             :         uint32_t needed;\
    5971             :         uint32_t value;\
    5972             :         sinfo.info2->iname = val;\
    5973             :         torture_assert(tctx,\
    5974             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
    5975             :                 "failed to call SetPrinter");\
    5976             :         torture_assert(tctx,\
    5977             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5978             :                 "failed to query");\
    5979             :         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
    5980             :         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
    5981             :         value = IVAL(data, 0); \
    5982             :         torture_assert_int_equal(tctx, value, val, "unexpected result");\
    5983             : } while(0);
    5984             : 
    5985           8 :         TEST_SET_SZ("description", comment, "newval");
    5986           8 :         TEST_SET_SZ("location", location, "newval");
    5987           8 :         TEST_SET_SZ("driverName", drivername, "newval");
    5988             : /*      TEST_SET_DWORD("priority", priority, 25); */
    5989             : 
    5990           8 :         torture_assert(tctx,
    5991             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    5992             :                 "failed to query Printer level 2");
    5993             : 
    5994           8 :         TEST_SZ("description", info.info2.comment);
    5995           8 :         TEST_SZ("driverName", info.info2.drivername);
    5996           8 :         TEST_SZ("location", info.info2.location);
    5997             : 
    5998           8 :         pname = strrchr(info.info2.printername, '\\');
    5999           8 :         if (pname == NULL) {
    6000           0 :                 pname = info.info2.printername;
    6001             :         } else {
    6002           8 :                 pname++;
    6003             :         }
    6004           8 :         TEST_SZ("printerName", pname);
    6005             :         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
    6006             :         /* TEST_SZ("printShareName", info.info2.sharename); */
    6007             : 
    6008             :         /* FIXME gd: complete the list */
    6009             : 
    6010             : #undef TEST_SZ
    6011             : #undef TEST_SET_SZ
    6012             : #undef TEST_DWORD
    6013             : 
    6014           8 :         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
    6015             : 
    6016           8 :         return true;
    6017             : }
    6018             : 
    6019           4 : static bool test_print_processors_winreg(struct torture_context *tctx,
    6020             :                                          void *private_data)
    6021             : {
    6022           3 :         struct test_spoolss_context *ctx =
    6023           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6024           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6025           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6026             : 
    6027           4 :         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
    6028             : }
    6029             : 
    6030           4 : static bool test_AddPrintProcessor(struct torture_context *tctx,
    6031             :                                    struct dcerpc_binding_handle *b,
    6032             :                                    const char *environment,
    6033             :                                    const char *path_name,
    6034             :                                    const char *print_processor_name,
    6035             :                                    WERROR expected_error)
    6036             : {
    6037             :         struct spoolss_AddPrintProcessor r;
    6038             : 
    6039           4 :         r.in.server = NULL;
    6040           4 :         r.in.architecture = environment;
    6041           4 :         r.in.path_name = path_name;
    6042           4 :         r.in.print_processor_name = print_processor_name;
    6043             : 
    6044           4 :         torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
    6045             :                 print_processor_name);
    6046             : 
    6047           4 :         torture_assert_ntstatus_ok(tctx,
    6048             :                 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
    6049             :                 "spoolss_AddPrintProcessor failed");
    6050           4 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6051             :                 "spoolss_AddPrintProcessor failed");
    6052             : 
    6053           0 :         return true;
    6054             : }
    6055             : 
    6056           0 : static bool test_DeletePrintProcessor(struct torture_context *tctx,
    6057             :                                       struct dcerpc_binding_handle *b,
    6058             :                                       const char *environment,
    6059             :                                       const char *print_processor_name,
    6060             :                                       WERROR expected_error)
    6061             : {
    6062             :         struct spoolss_DeletePrintProcessor r;
    6063             : 
    6064           0 :         r.in.server = NULL;
    6065           0 :         r.in.architecture = environment;
    6066           0 :         r.in.print_processor_name = print_processor_name;
    6067             : 
    6068           0 :         torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
    6069             :                 print_processor_name);
    6070             : 
    6071           0 :         torture_assert_ntstatus_ok(tctx,
    6072             :                 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
    6073             :                 "spoolss_DeletePrintProcessor failed");
    6074           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6075             :                 "spoolss_DeletePrintProcessor failed");
    6076             : 
    6077           0 :         return true;
    6078             : }
    6079             : 
    6080           4 : static bool test_add_print_processor(struct torture_context *tctx,
    6081             :                                      void *private_data)
    6082             : {
    6083           3 :         struct test_spoolss_context *ctx =
    6084           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6085           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6086           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6087             :         int i;
    6088             : 
    6089             :         struct {
    6090             :                 const char *environment;
    6091             :                 const char *path_name;
    6092             :                 const char *print_processor_name;
    6093             :                 WERROR expected_add_result;
    6094             :                 WERROR expected_del_result;
    6095           7 :         } tests[] = {
    6096             :                 {
    6097           4 :                         .environment            = ctx->environment,
    6098             :                         .path_name              = "",
    6099             :                         .print_processor_name   = "winprint",
    6100             :                         .expected_add_result    = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
    6101             :                         .expected_del_result    = WERR_CAN_NOT_COMPLETE
    6102             :                 },{
    6103           4 :                         .environment            = ctx->environment,
    6104             :                         .path_name              = "",
    6105             :                         .print_processor_name   = "unknown",
    6106             :                         .expected_add_result    = WERR_MOD_NOT_FOUND,
    6107             :                         .expected_del_result    = WERR_UNKNOWN_PRINTPROCESSOR
    6108             :                 }
    6109             :         };
    6110             : 
    6111           4 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6112           4 :                 torture_assert(tctx,
    6113             :                         test_AddPrintProcessor(tctx, b,
    6114             :                                                tests[i].environment,
    6115             :                                                tests[i].path_name,
    6116             :                                                tests[i].print_processor_name,
    6117             :                                                tests[i].expected_add_result),
    6118             :                         "add print processor failed");
    6119           0 :                 torture_assert(tctx,
    6120             :                         test_DeletePrintProcessor(tctx, b,
    6121             :                                                   tests[i].environment,
    6122             :                                                   tests[i].print_processor_name,
    6123             :                                                   tests[i].expected_del_result),
    6124             :                         "delete print processor failed");
    6125             :         }
    6126             : 
    6127           0 :         return true;
    6128             : }
    6129             : 
    6130           4 : static bool test_AddPerMachineConnection(struct torture_context *tctx,
    6131             :                                          struct dcerpc_binding_handle *b,
    6132             :                                          const char *servername,
    6133             :                                          const char *printername,
    6134             :                                          const char *printserver,
    6135             :                                          const char *provider,
    6136             :                                          WERROR expected_error)
    6137             : {
    6138             :         struct spoolss_AddPerMachineConnection r;
    6139           4 :         const char *composed_printername = printername;
    6140             : 
    6141           4 :         if (servername != NULL) {
    6142           0 :                 composed_printername = talloc_asprintf(tctx, "%s\\%s",
    6143             :                                                 servername,
    6144             :                                                 printername);
    6145             :         }
    6146           4 :         r.in.server = servername;
    6147           4 :         r.in.printername = composed_printername;
    6148           4 :         r.in.printserver = printserver;
    6149           4 :         r.in.provider = provider;
    6150             : 
    6151           4 :         torture_comment(tctx, "Testing AddPerMachineConnection(%s|%s|%s)\n",
    6152             :                 printername, printserver, provider);
    6153             : 
    6154           4 :         torture_assert_ntstatus_ok(tctx,
    6155             :                 dcerpc_spoolss_AddPerMachineConnection_r(b, tctx, &r),
    6156             :                 "spoolss_AddPerMachineConnection failed");
    6157           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6158             :                 "spoolss_AddPerMachineConnection failed");
    6159             : 
    6160           0 :         return true;
    6161             : }
    6162             : 
    6163           0 : static bool test_DeletePerMachineConnection(struct torture_context *tctx,
    6164             :                                             struct dcerpc_binding_handle *b,
    6165             :                                             const char *servername,
    6166             :                                             const char *printername,
    6167             :                                             WERROR expected_error)
    6168             : {
    6169             :         struct spoolss_DeletePerMachineConnection r;
    6170           0 :         const char *composed_printername = printername;
    6171             : 
    6172           0 :         if (servername != NULL) {
    6173           0 :                 composed_printername = talloc_asprintf(tctx, "%s\\%s",
    6174             :                                                 servername,
    6175             :                                                 printername);
    6176             :         }
    6177             : 
    6178           0 :         r.in.server = servername;
    6179           0 :         r.in.printername = composed_printername;
    6180             : 
    6181           0 :         torture_comment(tctx, "Testing DeletePerMachineConnection(%s)\n",
    6182             :                 printername);
    6183             : 
    6184           0 :         torture_assert_ntstatus_ok(tctx,
    6185             :                 dcerpc_spoolss_DeletePerMachineConnection_r(b, tctx, &r),
    6186             :                 "spoolss_DeletePerMachineConnection failed");
    6187           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6188             :                 "spoolss_DeletePerMachineConnection failed");
    6189             : 
    6190           0 :         return true;
    6191             : }
    6192             : 
    6193           0 : static bool test_EnumPerMachineConnections(struct torture_context *tctx,
    6194             :                                            struct dcerpc_binding_handle *b,
    6195             :                                            const char *servername)
    6196             : {
    6197             :         struct spoolss_EnumPerMachineConnections r;
    6198           0 :         DATA_BLOB blob = data_blob_null;
    6199             :         struct spoolss_PrinterInfo4 *info;
    6200             :         uint32_t needed;
    6201             :         uint32_t count;
    6202             : 
    6203           0 :         r.in.server = servername;
    6204           0 :         r.in.buffer = &blob;
    6205           0 :         r.in.offered = 0;
    6206             : 
    6207           0 :         r.out.info = &info;
    6208           0 :         r.out.needed = &needed;
    6209           0 :         r.out.count = &count;
    6210             : 
    6211           0 :         torture_comment(tctx, "Testing EnumPerMachineConnections(%s)\n",
    6212             :                 servername);
    6213             : 
    6214           0 :         torture_assert_ntstatus_ok(tctx,
    6215             :                 dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
    6216             :                 "spoolss_EnumPerMachineConnections failed");
    6217           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    6218           0 :                 blob = data_blob_talloc_zero(tctx, needed);
    6219           0 :                 r.in.buffer = &blob;
    6220           0 :                 r.in.offered = needed;
    6221             : 
    6222           0 :                 torture_assert_ntstatus_ok(tctx,
    6223             :                         dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
    6224             :                         "spoolss_EnumPerMachineConnections failed");
    6225             :         }
    6226           0 :         torture_assert_werr_ok(tctx, r.out.result,
    6227             :                 "spoolss_EnumPerMachineConnections failed");
    6228             : 
    6229           0 :         return true;
    6230             : }
    6231             : 
    6232           4 : static bool test_addpermachineconnection(struct torture_context *tctx,
    6233             :                                          void *private_data)
    6234             : {
    6235           3 :         struct test_spoolss_context *ctx =
    6236           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6237           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6238           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6239           4 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    6240             :         int i;
    6241             : 
    6242             :         struct {
    6243             :                 const char *servername;
    6244             :                 const char *printername;
    6245             :                 const char *printserver;
    6246             :                 const char *provider;
    6247             :                 WERROR expected_add_result;
    6248             :                 WERROR expected_del_result;
    6249           4 :         } tests[] = {
    6250             :                 {
    6251             :                         .servername             = NULL,
    6252             :                         .printername            = "foo",
    6253             :                         .printserver            = "",
    6254             :                         .provider               = "unknown",
    6255             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6256             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6257             :                 },{
    6258             :                         .servername             = NULL,
    6259             :                         .printername            = "Microsoft Print to PDF",
    6260             :                         .printserver            = "samba.org",
    6261             :                         .provider               = "unknown",
    6262             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6263             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6264             :                 },{
    6265             :                         .servername             = NULL,
    6266             :                         .printername            = "Microsoft Print to PDF",
    6267             :                         .printserver            = "samba.org",
    6268             :                         .provider               = "",
    6269             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6270             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6271             :                 },{
    6272             :                         .servername             = server_name_slash,
    6273             :                         .printername            = "foo",
    6274             :                         .printserver            = "",
    6275             :                         .provider               = "unknown",
    6276             :                         .expected_add_result    = WERR_FILE_NOT_FOUND,
    6277             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6278             :                 },{
    6279             :                         .servername             = server_name_slash,
    6280             :                         .printername            = "foo",
    6281             :                         .printserver            = "",
    6282             :                         .provider               = "",
    6283             :                         .expected_add_result    = WERR_OK,
    6284             :                         .expected_del_result    = WERR_OK
    6285             :                 },{
    6286             :                         .servername             = server_name_slash,
    6287             :                         .printername            = "Microsoft Print to PDF",
    6288             :                         .printserver            = "samba.org",
    6289             :                         .provider               = "unknown",
    6290             :                         .expected_add_result    = WERR_FILE_NOT_FOUND,
    6291             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6292             :                 },{
    6293             :                         .servername             = server_name_slash,
    6294             :                         .printername            = "Microsoft Print to PDF",
    6295             :                         .printserver            = "samba.org",
    6296             :                         .provider               = "",
    6297             :                         .expected_add_result    = WERR_OK,
    6298             :                         .expected_del_result    = WERR_OK
    6299             :                 }
    6300             :         };
    6301             : 
    6302           4 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6303           4 :                 torture_assert(tctx,
    6304             :                         test_AddPerMachineConnection(tctx, b,
    6305             :                                                      tests[i].servername,
    6306             :                                                      tests[i].printername,
    6307             :                                                      tests[i].printserver,
    6308             :                                                      tests[i].provider,
    6309             :                                                      tests[i].expected_add_result),
    6310             :                         "add per machine connection failed");
    6311           0 :                 torture_assert(tctx,
    6312             :                         test_EnumPerMachineConnections(tctx, b,
    6313             :                                                        tests[i].servername),
    6314             :                         "enum per machine connections failed");
    6315           0 :                 torture_assert(tctx,
    6316             :                         test_DeletePerMachineConnection(tctx, b,
    6317             :                                                         tests[i].servername,
    6318             :                                                         tests[i].printername,
    6319             :                                                         tests[i].expected_del_result),
    6320             :                         "delete per machine connection failed");
    6321           0 :                 torture_assert(tctx,
    6322             :                         test_EnumPerMachineConnections(tctx, b,
    6323             :                                                        tests[i].servername),
    6324             :                         "enum per machine connections failed");
    6325             :         }
    6326             : 
    6327           0 :         return true;
    6328             : }
    6329             : 
    6330          32 : static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
    6331             :                                          struct dcerpc_binding_handle *b,
    6332             :                                          struct policy_handle *handle,
    6333             :                                          uint32_t *change_id)
    6334             : {
    6335             :         enum winreg_Type type;
    6336             :         uint8_t *data;
    6337             :         uint32_t needed;
    6338             : 
    6339          32 :         torture_assert(tctx,
    6340             :                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
    6341             :                 "failed to call GetPrinterData");
    6342             : 
    6343          32 :         torture_assert(tctx, type == REG_DWORD, "unexpected type");
    6344          32 :         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
    6345             : 
    6346          32 :         *change_id = IVAL(data, 0);
    6347             : 
    6348          32 :         return true;
    6349             : }
    6350             : 
    6351          32 : static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
    6352             :                                            struct dcerpc_pipe *p,
    6353             :                                            struct policy_handle *handle,
    6354             :                                            uint32_t *change_id)
    6355             : {
    6356          32 :         enum winreg_Type type = REG_NONE;
    6357          32 :         uint8_t *data = NULL;
    6358          32 :         uint32_t needed = 0;
    6359             : 
    6360          32 :         torture_assert(tctx,
    6361             :                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
    6362             :                 "failed to call GetPrinterData");
    6363             : 
    6364          32 :         torture_assert(tctx, type == REG_DWORD, "unexpected type");
    6365          32 :         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
    6366             : 
    6367          32 :         *change_id = IVAL(data, 0);
    6368             : 
    6369          32 :         return true;
    6370             : }
    6371             : 
    6372          32 : static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
    6373             :                                          struct dcerpc_binding_handle *b,
    6374             :                                          struct policy_handle *handle,
    6375             :                                          uint32_t *change_id)
    6376             : {
    6377             :         union spoolss_PrinterInfo info;
    6378             : 
    6379          32 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
    6380             :                 "failed to query Printer level 0");
    6381             : 
    6382          32 :         *change_id = info.info0.change_id;
    6383             : 
    6384          32 :         return true;
    6385             : }
    6386             : 
    6387           8 : static bool test_ChangeID(struct torture_context *tctx,
    6388             :                           struct dcerpc_pipe *p,
    6389             :                           struct policy_handle *handle)
    6390             : {
    6391             :         uint32_t change_id, change_id_ex, change_id_info;
    6392             :         uint32_t change_id2, change_id_ex2, change_id_info2;
    6393             :         union spoolss_PrinterInfo info;
    6394             :         const char *comment;
    6395           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6396             : 
    6397           8 :         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
    6398             : 
    6399           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6400             :                 "failed to query for ChangeID");
    6401           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6402             :                 "failed to query for ChangeID");
    6403           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6404             :                 "failed to query for ChangeID");
    6405             : 
    6406           8 :         torture_assert_int_equal(tctx, change_id, change_id_ex,
    6407             :                 "change_ids should all be equal");
    6408           8 :         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
    6409             :                 "change_ids should all be equal");
    6410             : 
    6411             : 
    6412           8 :         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
    6413             : 
    6414           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6415             :                 "failed to query for ChangeID");
    6416           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    6417             :                 "failed to query Printer level 2");
    6418           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6419             :                 "failed to query for ChangeID");
    6420           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6421             :                 "failed to query for ChangeID");
    6422           8 :         torture_assert_int_equal(tctx, change_id, change_id_ex,
    6423             :                 "change_id should not have changed");
    6424           8 :         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
    6425             :                 "change_id should not have changed");
    6426             : 
    6427             : 
    6428           8 :         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
    6429             : 
    6430           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6431             :                 "failed to query for ChangeID");
    6432           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6433             :                 "failed to query for ChangeID");
    6434           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6435             :                 "failed to query for ChangeID");
    6436           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    6437             :                 "failed to query Printer level 2");
    6438           8 :         comment = talloc_strdup(tctx, info.info2.comment);
    6439             : 
    6440             :         {
    6441             :                 struct spoolss_SetPrinterInfoCtr info_ctr;
    6442             :                 struct spoolss_DevmodeContainer devmode_ctr;
    6443             :                 struct sec_desc_buf secdesc_ctr;
    6444             :                 union spoolss_SetPrinterInfo sinfo;
    6445             : 
    6446           8 :                 ZERO_STRUCT(info_ctr);
    6447           8 :                 ZERO_STRUCT(devmode_ctr);
    6448           8 :                 ZERO_STRUCT(secdesc_ctr);
    6449             : 
    6450             : 
    6451           8 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    6452           8 :                 sinfo.info2->comment = "torture_comment";
    6453             : 
    6454           8 :                 info_ctr.level = 2;
    6455           8 :                 info_ctr.info = sinfo;
    6456             : 
    6457           8 :                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6458             :                         "failed to call SetPrinter");
    6459             : 
    6460           8 :                 sinfo.info2->comment = comment;
    6461             : 
    6462           8 :                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6463             :                         "failed to call SetPrinter");
    6464             : 
    6465             :         }
    6466             : 
    6467           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
    6468             :                 "failed to query for ChangeID");
    6469           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
    6470             :                 "failed to query for ChangeID");
    6471           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
    6472             :                 "failed to query for ChangeID");
    6473             : 
    6474           8 :         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
    6475             :                 "change_ids should all be equal");
    6476           8 :         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
    6477             :                 "change_ids should all be equal");
    6478             : 
    6479           8 :         torture_assert(tctx, (change_id < change_id2),
    6480             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6481             :                 change_id2, change_id));
    6482           8 :         torture_assert(tctx, (change_id_ex < change_id_ex2),
    6483             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6484             :                 change_id_ex2, change_id_ex));
    6485           8 :         torture_assert(tctx, (change_id_info < change_id_info2),
    6486             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6487             :                 change_id_info2, change_id_info));
    6488             : 
    6489           8 :         torture_comment(tctx, "ChangeID tests succeeded\n\n");
    6490             : 
    6491           8 :         return true;
    6492             : }
    6493             : 
    6494           0 : static bool test_SecondaryClosePrinter(struct torture_context *tctx,
    6495             :                                        struct dcerpc_pipe *p,
    6496             :                                        struct policy_handle *handle)
    6497             : {
    6498             :         NTSTATUS status;
    6499             :         struct cli_credentials *anon_creds;
    6500             :         const struct dcerpc_binding *binding2;
    6501             :         struct dcerpc_pipe *p2;
    6502             :         struct spoolss_ClosePrinter cp;
    6503             : 
    6504             :         /* only makes sense on SMB */
    6505           0 :         if (p->conn->transport.transport != NCACN_NP) {
    6506           0 :                 return true;
    6507             :         }
    6508             : 
    6509           0 :         torture_comment(tctx, "Testing close on secondary pipe\n");
    6510             : 
    6511           0 :         anon_creds = cli_credentials_init_anon(tctx);
    6512           0 :         torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
    6513             : 
    6514           0 :         binding2 = p->binding;
    6515           0 :         status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_spoolss,
    6516             :                                                   anon_creds, tctx->lp_ctx,
    6517             :                                                   tctx, &p2);
    6518           0 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
    6519             : 
    6520           0 :         cp.in.handle = handle;
    6521           0 :         cp.out.handle = handle;
    6522             : 
    6523           0 :         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
    6524           0 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
    6525             :                         "ERROR: Allowed close on secondary connection");
    6526             : 
    6527           0 :         talloc_free(p2);
    6528             : 
    6529           0 :         return true;
    6530             : }
    6531             : 
    6532          28 : static bool test_OpenPrinter_badname(struct torture_context *tctx,
    6533             :                                      struct dcerpc_binding_handle *b, const char *name)
    6534             : {
    6535             :         NTSTATUS status;
    6536             :         struct spoolss_OpenPrinter op;
    6537             :         struct spoolss_OpenPrinterEx opEx;
    6538             :         struct policy_handle handle;
    6539          28 :         bool ret = true;
    6540             : 
    6541          28 :         op.in.printername       = name;
    6542          28 :         op.in.datatype          = NULL;
    6543          28 :         op.in.devmode_ctr.devmode= NULL;
    6544          28 :         op.in.access_mask       = 0;
    6545          28 :         op.out.handle           = &handle;
    6546             : 
    6547          28 :         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
    6548             : 
    6549          28 :         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
    6550          28 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
    6551          28 :         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
    6552             :                 "unexpected result");
    6553             : 
    6554          28 :         if (W_ERROR_IS_OK(op.out.result)) {
    6555           0 :                 ret &=test_ClosePrinter(tctx, b, &handle);
    6556             :         }
    6557             : 
    6558          28 :         opEx.in.printername             = name;
    6559          28 :         opEx.in.datatype                = NULL;
    6560          28 :         opEx.in.devmode_ctr.devmode     = NULL;
    6561          28 :         opEx.in.access_mask             = 0;
    6562          28 :         opEx.in.userlevel_ctr.level             = 1;
    6563          28 :         opEx.in.userlevel_ctr.user_info.level1 = NULL;
    6564          28 :         opEx.out.handle                 = &handle;
    6565             : 
    6566          28 :         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
    6567             : 
    6568          28 :         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
    6569          28 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
    6570          28 :         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAMETER,
    6571             :                 "unexpected result");
    6572             : 
    6573          28 :         if (W_ERROR_IS_OK(opEx.out.result)) {
    6574           0 :                 ret &=test_ClosePrinter(tctx, b, &handle);
    6575             :         }
    6576             : 
    6577          28 :         return ret;
    6578             : }
    6579             : 
    6580           4 : static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
    6581             :                                           void *private_data)
    6582             : {
    6583           3 :         struct test_spoolss_context *ctx =
    6584           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6585             : 
    6586           4 :         const char *badnames[] = {
    6587             :                 "__INVALID_PRINTER__",
    6588             :                 "\\\\__INVALID_HOST__",
    6589             :                 "",
    6590             :                 "\\\\\\",
    6591             :                 "\\\\\\__INVALID_PRINTER__"
    6592             :         };
    6593             :         const char *badname;
    6594           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6595           4 :         const char *server_name = dcerpc_server_name(p);
    6596           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6597             :         int i;
    6598             : 
    6599          24 :         for (i=0; i < ARRAY_SIZE(badnames); i++) {
    6600          20 :                 torture_assert(tctx,
    6601             :                         test_OpenPrinter_badname(tctx, b, badnames[i]),
    6602             :                         "");
    6603             :         }
    6604             : 
    6605           4 :         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
    6606           4 :         torture_assert(tctx,
    6607             :                 test_OpenPrinter_badname(tctx, b, badname),
    6608             :                 "");
    6609             : 
    6610           4 :         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
    6611           4 :         torture_assert(tctx,
    6612             :                 test_OpenPrinter_badname(tctx, b, badname),
    6613             :                 "");
    6614             : 
    6615           4 :         return true;
    6616             : }
    6617             : 
    6618          60 : static bool test_OpenPrinter(struct torture_context *tctx,
    6619             :                              struct dcerpc_pipe *p,
    6620             :                              const char *name,
    6621             :                              const char *environment,
    6622             :                              bool open_only)
    6623             : {
    6624             :         NTSTATUS status;
    6625             :         struct spoolss_OpenPrinter r;
    6626             :         struct policy_handle handle;
    6627          60 :         bool ret = true;
    6628          60 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6629             : 
    6630          60 :         r.in.printername        = name;
    6631          60 :         r.in.datatype           = NULL;
    6632          60 :         r.in.devmode_ctr.devmode= NULL;
    6633          60 :         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
    6634          60 :         r.out.handle            = &handle;
    6635             : 
    6636          60 :         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
    6637             : 
    6638          60 :         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
    6639             : 
    6640          60 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
    6641             : 
    6642          60 :         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
    6643             : 
    6644          60 :         if (open_only) {
    6645          40 :                 goto close_printer;
    6646             :         }
    6647             : 
    6648          20 :         if (!test_GetPrinter(tctx, b, &handle, environment)) {
    6649           0 :                 ret = false;
    6650             :         }
    6651             : 
    6652          20 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    6653           0 :                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
    6654           0 :                         ret = false;
    6655             :                 }
    6656             :         }
    6657             : 
    6658          65 :  close_printer:
    6659          60 :         if (!test_ClosePrinter(tctx, b, &handle)) {
    6660           0 :                 ret = false;
    6661             :         }
    6662             : 
    6663          60 :         return ret;
    6664             : }
    6665             : 
    6666         664 : static bool test_OpenPrinterEx(struct torture_context *tctx,
    6667             :                                struct dcerpc_binding_handle *b,
    6668             :                                const char *printername,
    6669             :                                const char *datatype,
    6670             :                                struct spoolss_DeviceMode *devmode,
    6671             :                                uint32_t access_mask,
    6672             :                                struct spoolss_UserLevelCtr *userlevel_ctr,
    6673             :                                struct policy_handle *handle,
    6674             :                                WERROR expected_result)
    6675             : {
    6676             :         struct spoolss_OpenPrinterEx r;
    6677             : 
    6678         664 :         r.in.printername        = printername;
    6679         664 :         r.in.datatype           = datatype;
    6680         664 :         r.in.devmode_ctr.devmode= devmode;
    6681         664 :         r.in.access_mask        = access_mask;
    6682         664 :         r.in.userlevel_ctr      = *userlevel_ctr;
    6683         664 :         r.out.handle            = handle;
    6684             : 
    6685         664 :         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
    6686             : 
    6687         664 :         torture_assert_ntstatus_ok(tctx,
    6688             :                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
    6689             :                 "OpenPrinterEx failed");
    6690             : 
    6691         664 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    6692             :                 "OpenPrinterEx failed");
    6693             : 
    6694         664 :         return true;
    6695             : }
    6696             : 
    6697         104 : static bool call_OpenPrinterEx(struct torture_context *tctx,
    6698             :                                struct dcerpc_pipe *p,
    6699             :                                const char *name,
    6700             :                                struct spoolss_DeviceMode *devmode,
    6701             :                                struct policy_handle *handle)
    6702             : {
    6703             :         struct spoolss_UserLevelCtr userlevel_ctr;
    6704             :         struct spoolss_UserLevel1 userlevel1;
    6705         104 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6706             : 
    6707         104 :         userlevel1.size = 1234;
    6708         104 :         userlevel1.client = "hello";
    6709         104 :         userlevel1.user = "spottyfoot!";
    6710         104 :         userlevel1.build = 1;
    6711         104 :         userlevel1.major = 2;
    6712         104 :         userlevel1.minor = 3;
    6713         104 :         userlevel1.processor = 4;
    6714             : 
    6715         104 :         userlevel_ctr.level = 1;
    6716         104 :         userlevel_ctr.user_info.level1 = &userlevel1;
    6717             : 
    6718         130 :         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
    6719             :                                   SEC_FLAG_MAXIMUM_ALLOWED,
    6720             :                                   &userlevel_ctr,
    6721             :                                   handle,
    6722         104 :                                   WERR_OK);
    6723             : }
    6724             : 
    6725           8 : static bool test_printer_rename(struct torture_context *tctx,
    6726             :                                 void *private_data)
    6727             : {
    6728           6 :         struct torture_printer_context *t =
    6729           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    6730           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    6731             : 
    6732           8 :         bool ret = true;
    6733             :         union spoolss_PrinterInfo info;
    6734             :         union spoolss_SetPrinterInfo sinfo;
    6735             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    6736             :         struct spoolss_DevmodeContainer devmode_ctr;
    6737             :         struct sec_desc_buf secdesc_ctr;
    6738             :         const char *printer_name;
    6739             :         const char *printer_name_orig;
    6740           8 :         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
    6741             :         struct policy_handle new_handle;
    6742             :         const char *q;
    6743           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6744             : 
    6745           8 :         ZERO_STRUCT(devmode_ctr);
    6746           8 :         ZERO_STRUCT(secdesc_ctr);
    6747             : 
    6748           8 :         torture_comment(tctx, "Testing Printer rename operations\n");
    6749             : 
    6750           8 :         torture_assert(tctx,
    6751             :                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
    6752             :                 "failed to call GetPrinter level 2");
    6753             : 
    6754           8 :         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
    6755             : 
    6756           8 :         q = strrchr(info.info2.printername, '\\');
    6757           8 :         if (q) {
    6758           8 :                 torture_warning(tctx,
    6759             :                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
    6760             :         }
    6761             : 
    6762           8 :         torture_assert(tctx,
    6763             :                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    6764             : 
    6765           8 :         sinfo.info2->printername = printer_name_new;
    6766             : 
    6767           8 :         info_ctr.level = 2;
    6768           8 :         info_ctr.info = sinfo;
    6769             : 
    6770           8 :         torture_assert(tctx,
    6771             :                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6772             :                 "failed to call SetPrinter level 2");
    6773             : 
    6774           8 :         torture_assert(tctx,
    6775             :                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
    6776             :                 "failed to call GetPrinter level 2");
    6777             : 
    6778           8 :         printer_name = talloc_strdup(tctx, info.info2.printername);
    6779             : 
    6780           8 :         q = strrchr(info.info2.printername, '\\');
    6781           8 :         if (q) {
    6782           8 :                 torture_warning(tctx,
    6783             :                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
    6784           8 :                 q++;
    6785           8 :                 printer_name = q;
    6786             :         }
    6787             : 
    6788           8 :         torture_assert_str_equal(tctx, printer_name, printer_name_new,
    6789             :                 "new printer name was not set");
    6790             : 
    6791             :         /* samba currently cannot fully rename printers */
    6792           8 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    6793           0 :                 torture_assert(tctx,
    6794             :                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
    6795             :                         "still can open printer with oldname after rename");
    6796             :         } else {
    6797           8 :                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
    6798             :         }
    6799             : 
    6800           8 :         torture_assert(tctx,
    6801             :                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
    6802             :                 "failed to open printer with new name");
    6803             : 
    6804           8 :         torture_assert(tctx,
    6805             :                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
    6806             :                 "failed to call GetPrinter level 2");
    6807             : 
    6808           8 :         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
    6809             :                 "new printer name was not set");
    6810             : 
    6811           8 :         torture_assert(tctx,
    6812             :                 test_ClosePrinter(tctx, b, &new_handle),
    6813             :                 "failed to close printer");
    6814             : 
    6815           8 :         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
    6816             : 
    6817           8 :         return ret;
    6818             : }
    6819             : 
    6820          28 : static bool test_openprinter(struct torture_context *tctx,
    6821             :                              struct dcerpc_binding_handle *b,
    6822             :                              const char *real_printername)
    6823             : {
    6824             :         struct spoolss_UserLevelCtr userlevel_ctr;
    6825             :         struct policy_handle handle;
    6826             :         struct spoolss_UserLevel1 userlevel1;
    6827          28 :         const char *printername = NULL;
    6828             :         int i;
    6829             : 
    6830             :         struct {
    6831             :                 const char *suffix;
    6832             :                 WERROR expected_result;
    6833          28 :         } tests[] = {
    6834             :                 {
    6835             :                         .suffix                 = "rubbish",
    6836             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6837             :                 },{
    6838             :                         .suffix                 = ", LocalOnl",
    6839             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6840             :                 },{
    6841             :                         .suffix                 = ", localOnly",
    6842             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6843             :                 },{
    6844             :                         .suffix                 = ", localonl",
    6845             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6846             :                 },{
    6847             :                         .suffix                 = ",LocalOnl",
    6848             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6849             :                 },{
    6850             :                         .suffix                 = ",localOnl2",
    6851             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6852             :                 },{
    6853             :                         .suffix                 = ", DrvConver2t",
    6854             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6855             :                 },{
    6856             :                         .suffix                 = ", drvconvert",
    6857             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6858             :                 },{
    6859             :                         .suffix                 = ",drvconvert",
    6860             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6861             :                 },{
    6862             :                         .suffix                 = ", DrvConvert",
    6863             :                         .expected_result        = WERR_OK
    6864             :                 },{
    6865             :                         .suffix                 = " , DrvConvert",
    6866             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6867             :                 },{
    6868             :                         .suffix                 = ",DrvConvert",
    6869             :                         .expected_result        = WERR_OK
    6870             :                 },{
    6871             :                         .suffix                 = ", DrvConvertsadfasdf",
    6872             :                         .expected_result        = WERR_OK
    6873             :                 },{
    6874             :                         .suffix                 = ",DrvConvertasdfasd",
    6875             :                         .expected_result        = WERR_OK
    6876             :                 },{
    6877             :                         .suffix                 = ", LocalOnly",
    6878             :                         .expected_result        = WERR_OK
    6879             :                 },{
    6880             :                         .suffix                 = " , LocalOnly",
    6881             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6882             :                 },{
    6883             :                         .suffix                 = ",LocalOnly",
    6884             :                         .expected_result        = WERR_OK
    6885             :                 },{
    6886             :                         .suffix                 = ", LocalOnlysagi4gjfkd",
    6887             :                         .expected_result        = WERR_OK
    6888             :                 },{
    6889             :                         .suffix                 = ",LocalOnlysagi4gjfkd",
    6890             :                         .expected_result        = WERR_OK
    6891             :                 }
    6892             :         };
    6893             : 
    6894          28 :         userlevel1.size = 1234;
    6895          28 :         userlevel1.client = "hello";
    6896          28 :         userlevel1.user = "spottyfoot!";
    6897          28 :         userlevel1.build = 1;
    6898          28 :         userlevel1.major = 2;
    6899          28 :         userlevel1.minor = 3;
    6900          28 :         userlevel1.processor = 4;
    6901             : 
    6902          28 :         userlevel_ctr.level = 1;
    6903          28 :         userlevel_ctr.user_info.level1 = &userlevel1;
    6904             : 
    6905          28 :         torture_comment(tctx, "Testing openprinterex printername pattern\n");
    6906             : 
    6907          28 :         torture_assert(tctx,
    6908             :                 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
    6909             :                                    &userlevel_ctr, &handle,
    6910             :                                    WERR_OK),
    6911             :                 "OpenPrinterEx failed");
    6912          28 :         test_ClosePrinter(tctx, b, &handle);
    6913             : 
    6914         560 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6915             : 
    6916         532 :                 printername = talloc_asprintf(tctx, "%s%s",
    6917             :                                               real_printername,
    6918             :                                               tests[i].suffix);
    6919             : 
    6920         532 :                 torture_assert(tctx,
    6921             :                         test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
    6922             :                                            &userlevel_ctr, &handle,
    6923             :                                            tests[i].expected_result),
    6924             :                         "OpenPrinterEx failed");
    6925         532 :                 if (W_ERROR_IS_OK(tests[i].expected_result)) {
    6926         224 :                         test_ClosePrinter(tctx, b, &handle);
    6927             :                 }
    6928             :         }
    6929             : 
    6930          28 :         return true;
    6931             : }
    6932             : 
    6933             : 
    6934          20 : static bool test_existing_printer_openprinterex(struct torture_context *tctx,
    6935             :                                                 struct dcerpc_pipe *p,
    6936             :                                                 const char *name,
    6937             :                                                 const char *environment)
    6938             : {
    6939             :         struct policy_handle handle;
    6940          20 :         bool ret = true;
    6941          20 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6942             : 
    6943          20 :         if (!test_openprinter(tctx, b, name)) {
    6944           0 :                 return false;
    6945             :         }
    6946             : 
    6947          20 :         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
    6948           0 :                 return false;
    6949             :         }
    6950             : 
    6951          20 :         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
    6952           0 :                 ret = false;
    6953             :         }
    6954             : 
    6955          20 :         if (!test_GetPrinter(tctx, b, &handle, environment)) {
    6956           0 :                 ret = false;
    6957             :         }
    6958             : 
    6959          20 :         if (!test_EnumForms_all(tctx, b, &handle, false)) {
    6960           0 :                 ret = false;
    6961             :         }
    6962             : 
    6963          20 :         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
    6964           0 :                 ret = false;
    6965             :         }
    6966             : 
    6967          20 :         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
    6968           0 :                 ret = false;
    6969             :         }
    6970             : 
    6971          20 :         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
    6972           0 :                 ret = false;
    6973             :         }
    6974             : 
    6975          20 :         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
    6976           0 :                 ret = false;
    6977             :         }
    6978             : 
    6979          20 :         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
    6980           0 :                 ret = false;
    6981             :         }
    6982             : 
    6983          20 :         if (!test_printer_all_keys(tctx, b, &handle)) {
    6984           0 :                 ret = false;
    6985             :         }
    6986             : 
    6987          20 :         if (!test_PausePrinter(tctx, b, &handle)) {
    6988           0 :                 ret = false;
    6989             :         }
    6990             : 
    6991          20 :         if (!test_DoPrintTest(tctx, b, &handle)) {
    6992          10 :                 ret = false;
    6993             :         }
    6994             : 
    6995          20 :         if (!test_ResumePrinter(tctx, b, &handle)) {
    6996           0 :                 ret = false;
    6997             :         }
    6998             : 
    6999          20 :         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
    7000           0 :                 ret = false;
    7001             :         }
    7002             : 
    7003          20 :         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
    7004           0 :                 ret = false;
    7005             :         }
    7006             : 
    7007          20 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    7008           0 :                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
    7009           0 :                         ret = false;
    7010             :                 }
    7011             :         }
    7012             : 
    7013          20 :         if (!test_ClosePrinter(tctx, b, &handle)) {
    7014           0 :                 ret = false;
    7015             :         }
    7016             : 
    7017          20 :         return ret;
    7018             : }
    7019             : 
    7020           4 : static bool test_EnumPrinters_old(struct torture_context *tctx,
    7021             :                                   void *private_data)
    7022             : {
    7023           3 :         struct test_spoolss_context *ctx =
    7024           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7025             :         struct spoolss_EnumPrinters r;
    7026             :         NTSTATUS status;
    7027           4 :         uint16_t levels[] = {1, 2, 4, 5};
    7028             :         int i;
    7029           4 :         bool ret = true;
    7030           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7031           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7032             : 
    7033          20 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7034             :                 union spoolss_PrinterInfo *info;
    7035             :                 int j;
    7036             :                 uint32_t needed;
    7037             :                 uint32_t count;
    7038             : 
    7039          16 :                 r.in.flags      = PRINTER_ENUM_LOCAL;
    7040          16 :                 r.in.server     = "";
    7041          16 :                 r.in.level      = levels[i];
    7042          16 :                 r.in.buffer     = NULL;
    7043          16 :                 r.in.offered    = 0;
    7044          16 :                 r.out.needed    = &needed;
    7045          16 :                 r.out.count     = &count;
    7046          16 :                 r.out.info      = &info;
    7047             : 
    7048          16 :                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
    7049             : 
    7050          16 :                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
    7051          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
    7052             : 
    7053          16 :                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7054          16 :                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7055          16 :                         r.in.buffer = &blob;
    7056          16 :                         r.in.offered = needed;
    7057          16 :                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
    7058             :                 }
    7059             : 
    7060          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
    7061             : 
    7062          16 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
    7063             : 
    7064          16 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
    7065             : 
    7066          16 :                 if (!info) {
    7067           0 :                         torture_comment(tctx, "No printers returned\n");
    7068           0 :                         return true;
    7069             :                 }
    7070             : 
    7071          96 :                 for (j=0;j<count;j++) {
    7072          80 :                         if (r.in.level == 1) {
    7073          20 :                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
    7074             :                                 char *slash, *name, *full_name;
    7075          20 :                                 name = unc;
    7076          20 :                                 if (unc[0] == '\\' && unc[1] == '\\') {
    7077           0 :                                         unc +=2;
    7078             :                                 }
    7079          20 :                                 slash = strchr(unc, '\\');
    7080          20 :                                 if (slash) {
    7081           0 :                                         slash++;
    7082           0 :                                         name = slash;
    7083             :                                 }
    7084          20 :                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
    7085             :                                                             dcerpc_server_name(p), name);
    7086          20 :                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
    7087           0 :                                         ret = false;
    7088             :                                 }
    7089          20 :                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
    7090           0 :                                         ret = false;
    7091             :                                 }
    7092          20 :                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
    7093           0 :                                         ret = false;
    7094             :                                 }
    7095          20 :                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
    7096          10 :                                         ret = false;
    7097             :                                 }
    7098             :                         }
    7099             :                 }
    7100             :         }
    7101             : 
    7102           4 :         return ret;
    7103             : }
    7104             : 
    7105           8 : static bool test_EnumPrinters_level(struct torture_context *tctx,
    7106             :                                     struct dcerpc_binding_handle *b,
    7107             :                                     uint32_t flags,
    7108             :                                     const char *servername,
    7109             :                                     uint32_t level,
    7110             :                                     uint32_t *count_p,
    7111             :                                     union spoolss_PrinterInfo **info_p)
    7112             : {
    7113             :         struct spoolss_EnumPrinters r;
    7114             :         union spoolss_PrinterInfo *info;
    7115             :         uint32_t needed;
    7116             :         uint32_t count;
    7117             : 
    7118           8 :         r.in.flags      = flags;
    7119           8 :         r.in.server     = servername;
    7120           8 :         r.in.level      = level;
    7121           8 :         r.in.buffer     = NULL;
    7122           8 :         r.in.offered    = 0;
    7123           8 :         r.out.needed    = &needed;
    7124           8 :         r.out.count     = &count;
    7125           8 :         r.out.info      = &info;
    7126             : 
    7127           8 :         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
    7128             :                 r.in.server, r.in.level);
    7129             : 
    7130           8 :         torture_assert_ntstatus_ok(tctx,
    7131             :                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
    7132             :                 "EnumPrinters failed");
    7133           8 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7134           8 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7135           8 :                 r.in.buffer = &blob;
    7136           8 :                 r.in.offered = needed;
    7137           8 :                 torture_assert_ntstatus_ok(tctx,
    7138             :                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
    7139             :                         "EnumPrinters failed");
    7140             :         }
    7141             : 
    7142           8 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
    7143             : 
    7144           8 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
    7145             : 
    7146           8 :         if (count_p) {
    7147           8 :                 *count_p = count;
    7148             :         }
    7149           8 :         if (info_p) {
    7150           8 :                 *info_p = info;
    7151             :         }
    7152             : 
    7153           8 :         return true;
    7154             : }
    7155             : 
    7156          40 : static const char *get_short_printername(struct torture_context *tctx,
    7157             :                                          const char *name)
    7158             : {
    7159             :         const char *short_name;
    7160             : 
    7161          40 :         if (name[0] == '\\' && name[1] == '\\') {
    7162          20 :                 name += 2;
    7163          20 :                 short_name = strchr(name, '\\');
    7164          20 :                 if (short_name) {
    7165          20 :                         return talloc_strdup(tctx, short_name+1);
    7166             :                 }
    7167             :         }
    7168             : 
    7169          20 :         return name;
    7170             : }
    7171             : 
    7172          40 : static const char *get_full_printername(struct torture_context *tctx,
    7173             :                                         const char *name)
    7174             : {
    7175          40 :         const char *full_name = talloc_strdup(tctx, name);
    7176             :         char *p;
    7177             : 
    7178          40 :         if (name && name[0] == '\\' && name[1] == '\\') {
    7179          20 :                 name += 2;
    7180          20 :                 p = strchr(name, '\\');
    7181          20 :                 if (p) {
    7182          20 :                         return full_name;
    7183             :                 }
    7184             :         }
    7185             : 
    7186          20 :         return NULL;
    7187             : }
    7188             : 
    7189          40 : static bool test_OnePrinter_servername(struct torture_context *tctx,
    7190             :                                        struct dcerpc_pipe *p,
    7191             :                                        struct dcerpc_binding_handle *b,
    7192             :                                        const char *servername,
    7193             :                                        const char *printername)
    7194             : {
    7195             :         union spoolss_PrinterInfo info;
    7196          40 :         const char *short_name = get_short_printername(tctx, printername);
    7197          40 :         const char *full_name = get_full_printername(tctx, printername);
    7198             : 
    7199          40 :         if (short_name) {
    7200             :                 struct policy_handle handle;
    7201          40 :                 torture_assert(tctx,
    7202             :                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
    7203             :                         "failed to open printer");
    7204             : 
    7205          40 :                 torture_assert(tctx,
    7206             :                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
    7207             :                         "failed to get printer info");
    7208             : 
    7209          40 :                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
    7210             :                         "unexpected servername");
    7211          40 :                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
    7212             :                         "unexpected printername");
    7213             : 
    7214          40 :                 if (info.info2.devmode) {
    7215             :                         const char *expected_devicename;
    7216          36 :                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
    7217          36 :                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
    7218             :                                 "unexpected devicemode devicename");
    7219             :                 }
    7220             : 
    7221          40 :                 torture_assert(tctx,
    7222             :                         test_ClosePrinter(tctx, b, &handle),
    7223             :                         "failed to close printer");
    7224             :         }
    7225             : 
    7226          40 :         if (full_name) {
    7227             :                 struct policy_handle handle;
    7228             : 
    7229          20 :                 torture_assert(tctx,
    7230             :                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
    7231             :                         "failed to open printer");
    7232             : 
    7233          20 :                 torture_assert(tctx,
    7234             :                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
    7235             :                         "failed to get printer info");
    7236             : 
    7237          20 :                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
    7238             :                         "unexpected servername");
    7239          20 :                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
    7240             :                         "unexpected printername");
    7241             : 
    7242          20 :                 if (info.info2.devmode) {
    7243             :                         const char *expected_devicename;
    7244          18 :                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
    7245          18 :                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
    7246             :                                 "unexpected devicemode devicename");
    7247             :                 }
    7248             : 
    7249          20 :                 torture_assert(tctx,
    7250             :                         test_ClosePrinter(tctx, b, &handle),
    7251             :                         "failed to close printer");
    7252             :         }
    7253             : 
    7254          40 :         return true;
    7255             : }
    7256             : 
    7257           4 : static bool test_EnumPrinters_servername(struct torture_context *tctx,
    7258             :                                          void *private_data)
    7259             : {
    7260           3 :         struct test_spoolss_context *ctx =
    7261           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7262             :         int i;
    7263           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7264           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7265             :         uint32_t count;
    7266             :         union spoolss_PrinterInfo *info;
    7267             :         const char *servername;
    7268           4 :         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
    7269             : 
    7270           4 :         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
    7271             : 
    7272           4 :         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    7273             : 
    7274           4 :         torture_assert(tctx,
    7275             :                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
    7276             :                 "failed to enumerate printers");
    7277             : 
    7278          24 :         for (i=0; i < count; i++) {
    7279             : 
    7280          20 :                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
    7281             :                         "unexpected servername");
    7282             : 
    7283          20 :                 torture_assert(tctx,
    7284             :                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
    7285             :                         "failed to check printer");
    7286             :         }
    7287             : 
    7288           4 :         servername = "";
    7289             : 
    7290           4 :         torture_assert(tctx,
    7291             :                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
    7292             :                 "failed to enumerate printers");
    7293             : 
    7294          24 :         for (i=0; i < count; i++) {
    7295             : 
    7296          20 :                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
    7297             :                         "unexpected servername");
    7298             : 
    7299          20 :                 torture_assert(tctx,
    7300             :                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
    7301             :                         "failed to check printer");
    7302             :         }
    7303             : 
    7304             : 
    7305           4 :         return true;
    7306             : }
    7307             : 
    7308             : #if 0
    7309             : static bool test_GetPrinterDriver(struct torture_context *tctx,
    7310             :                                   struct dcerpc_binding_handle *b,
    7311             :                                   struct policy_handle *handle,
    7312             :                                   const char *driver_name)
    7313             : {
    7314             :         struct spoolss_GetPrinterDriver r;
    7315             :         uint32_t needed;
    7316             : 
    7317             :         r.in.handle = handle;
    7318             :         r.in.architecture = "W32X86";
    7319             :         r.in.level = 1;
    7320             :         r.in.buffer = NULL;
    7321             :         r.in.offered = 0;
    7322             :         r.out.needed = &needed;
    7323             : 
    7324             :         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
    7325             : 
    7326             :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
    7327             :                 "failed to call GetPrinterDriver");
    7328             :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7329             :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7330             :                 r.in.buffer = &blob;
    7331             :                 r.in.offered = needed;
    7332             :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
    7333             :                         "failed to call GetPrinterDriver");
    7334             :         }
    7335             : 
    7336             :         torture_assert_werr_ok(tctx, r.out.result,
    7337             :                 "failed to call GetPrinterDriver");
    7338             : 
    7339             :         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
    7340             : 
    7341             :         return true;
    7342             : }
    7343             : #endif
    7344             : 
    7345           0 : static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
    7346             :                                          struct dcerpc_binding_handle *b,
    7347             :                                          struct policy_handle *handle,
    7348             :                                          const char *driver_name,
    7349             :                                          const char *architecture,
    7350             :                                          uint32_t level,
    7351             :                                          uint32_t client_major_version,
    7352             :                                          uint32_t client_minor_version,
    7353             :                                          union spoolss_DriverInfo *info_p,
    7354             :                                          WERROR *result_p)
    7355             : 
    7356             : {
    7357             :         struct spoolss_GetPrinterDriver2 r;
    7358             :         uint32_t needed;
    7359             :         uint32_t server_major_version;
    7360             :         uint32_t server_minor_version;
    7361             : 
    7362           0 :         r.in.handle = handle;
    7363           0 :         r.in.architecture = architecture;
    7364           0 :         r.in.client_major_version = client_major_version;
    7365           0 :         r.in.client_minor_version = client_minor_version;
    7366           0 :         r.in.buffer = NULL;
    7367           0 :         r.in.offered = 0;
    7368           0 :         r.in.level = level;
    7369           0 :         r.out.needed = &needed;
    7370           0 :         r.out.server_major_version = &server_major_version;
    7371           0 :         r.out.server_minor_version = &server_minor_version;
    7372             : 
    7373           0 :         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
    7374             :                 driver_name, r.in.level);
    7375             : 
    7376           0 :         torture_assert_ntstatus_ok(tctx,
    7377             :                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
    7378             :                 "failed to call GetPrinterDriver2");
    7379           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7380           0 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7381           0 :                 r.in.buffer = &blob;
    7382           0 :                 r.in.offered = needed;
    7383           0 :                 torture_assert_ntstatus_ok(tctx,
    7384             :                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
    7385             :                         "failed to call GetPrinterDriver2");
    7386             :         }
    7387             : 
    7388           0 :         if (result_p) {
    7389           0 :                 *result_p = r.out.result;
    7390             :         }
    7391             : 
    7392           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
    7393           0 :                 switch (r.in.level) {
    7394           0 :                 case 101:
    7395             :                 case 8:
    7396           0 :                         torture_comment(tctx,
    7397             :                                 "level %d not implemented, not considering as an error\n",
    7398             :                                 r.in.level);
    7399           0 :                         return true;
    7400           0 :                 default:
    7401           0 :                         break;
    7402             :                 }
    7403           0 :         }
    7404             : 
    7405           0 :         torture_assert_werr_ok(tctx, r.out.result,
    7406             :                 "failed to call GetPrinterDriver2");
    7407             : 
    7408           0 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
    7409             : 
    7410           0 :         if (info_p) {
    7411           0 :                 *info_p = *r.out.info;
    7412             :         }
    7413             : 
    7414           0 :         return true;
    7415             : }
    7416             : 
    7417           0 : static bool test_GetPrinterDriver2(struct torture_context *tctx,
    7418             :                                    struct dcerpc_binding_handle *b,
    7419             :                                    struct policy_handle *handle,
    7420             :                                    const char *driver_name,
    7421             :                                    const char *architecture)
    7422             : {
    7423           0 :         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
    7424             :         int i;
    7425             : 
    7426             : 
    7427           0 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7428             : 
    7429           0 :                 torture_assert(tctx,
    7430             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
    7431             :                         "");
    7432             :         }
    7433             : 
    7434           0 :         return true;
    7435             : }
    7436             : 
    7437           4 : static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
    7438             :                                         void *private_data)
    7439             : {
    7440           3 :         struct test_spoolss_context *ctx =
    7441           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7442           4 :         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
    7443             :         int i;
    7444           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7445           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7446           4 :         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    7447             : 
    7448           4 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7449             : 
    7450             :                 uint32_t count;
    7451             :                 union spoolss_DriverInfo *info;
    7452             : 
    7453           4 :                 torture_assert(tctx,
    7454             :                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
    7455             :                         "failed to enumerate drivers");
    7456             : 
    7457           4 :                 if (!info) {
    7458           4 :                         torture_comment(tctx, "No printer drivers returned\n");
    7459           4 :                         break;
    7460             :                 }
    7461             :         }
    7462             : 
    7463           4 :         return true;
    7464             : }
    7465             : 
    7466          16 : static bool test_DeletePrinter(struct torture_context *tctx,
    7467             :                                struct dcerpc_binding_handle *b,
    7468             :                                struct policy_handle *handle)
    7469             : {
    7470             :         struct spoolss_DeletePrinter r;
    7471             : 
    7472          16 :         torture_comment(tctx, "Testing DeletePrinter\n");
    7473             : 
    7474          16 :         r.in.handle = handle;
    7475             : 
    7476          16 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
    7477             :                 "failed to delete printer");
    7478          16 :         torture_assert_werr_ok(tctx, r.out.result,
    7479             :                 "failed to delete printer");
    7480             : 
    7481          16 :         return true;
    7482             : }
    7483             : 
    7484          24 : static bool test_EnumPrinters_findname(struct torture_context *tctx,
    7485             :                                        struct dcerpc_binding_handle *b,
    7486             :                                        uint32_t flags,
    7487             :                                        uint32_t level,
    7488             :                                        const char *name,
    7489             :                                        bool *found)
    7490             : {
    7491             :         struct spoolss_EnumPrinters e;
    7492             :         uint32_t count;
    7493             :         union spoolss_PrinterInfo *info;
    7494             :         uint32_t needed;
    7495             :         int i;
    7496             : 
    7497          24 :         *found = false;
    7498             : 
    7499          24 :         e.in.flags = flags;
    7500          24 :         e.in.server = NULL;
    7501          24 :         e.in.level = level;
    7502          24 :         e.in.buffer = NULL;
    7503          24 :         e.in.offered = 0;
    7504          24 :         e.out.count = &count;
    7505          24 :         e.out.info = &info;
    7506          24 :         e.out.needed = &needed;
    7507             : 
    7508          24 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
    7509             :                 "failed to enum printers");
    7510             : 
    7511          24 :         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7512          24 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7513          24 :                 e.in.buffer = &blob;
    7514          24 :                 e.in.offered = needed;
    7515             : 
    7516          24 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
    7517             :                         "failed to enum printers");
    7518             :         }
    7519             : 
    7520          24 :         torture_assert_werr_ok(tctx, e.out.result,
    7521             :                 "failed to enum printers");
    7522             : 
    7523         152 :         for (i=0; i < count; i++) {
    7524             : 
    7525         151 :                 const char *current = NULL;
    7526             :                 const char *q;
    7527             : 
    7528         151 :                 switch (level) {
    7529         151 :                 case 1:
    7530         151 :                         current = info[i].info1.name;
    7531         151 :                         break;
    7532             :                 }
    7533             : 
    7534         151 :                 if (strequal(current, name)) {
    7535          23 :                         *found = true;
    7536          23 :                         break;
    7537             :                 }
    7538             : 
    7539         128 :                 q = strrchr(current, '\\');
    7540         128 :                 if (q) {
    7541           0 :                         if (!e.in.server) {
    7542           0 :                                 torture_warning(tctx,
    7543             :                                         "server returns printername %s incl. servername although we did not set servername", current);
    7544             :                         }
    7545           0 :                         q++;
    7546           0 :                         if (strequal(q, name)) {
    7547           0 :                                 *found = true;
    7548           0 :                                 break;
    7549             :                         }
    7550             :                 }
    7551             :         }
    7552             : 
    7553          24 :         return true;
    7554             : }
    7555             : 
    7556           0 : static bool test_AddPrinter_wellknown(struct torture_context *tctx,
    7557             :                                       struct dcerpc_pipe *p,
    7558             :                                       const char *printername,
    7559             :                                       bool ex)
    7560             : {
    7561             :         WERROR result;
    7562             :         struct spoolss_AddPrinter r;
    7563             :         struct spoolss_AddPrinterEx rex;
    7564             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    7565             :         struct spoolss_SetPrinterInfo1 info1;
    7566             :         struct spoolss_DevmodeContainer devmode_ctr;
    7567             :         struct sec_desc_buf secdesc_ctr;
    7568             :         struct spoolss_UserLevelCtr userlevel_ctr;
    7569             :         struct policy_handle handle;
    7570           0 :         bool found = false;
    7571           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7572             : 
    7573           0 :         ZERO_STRUCT(devmode_ctr);
    7574           0 :         ZERO_STRUCT(secdesc_ctr);
    7575           0 :         ZERO_STRUCT(userlevel_ctr);
    7576           0 :         ZERO_STRUCT(info1);
    7577             : 
    7578           0 :         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
    7579             :                         ex ? "Ex":"", printername);
    7580             : 
    7581             :         /* try to add printer to wellknown printer list (level 1) */
    7582             : 
    7583           0 :         userlevel_ctr.level = 1;
    7584             : 
    7585           0 :         info_ctr.info.info1 = &info1;
    7586           0 :         info_ctr.level = 1;
    7587             : 
    7588           0 :         rex.in.server = NULL;
    7589           0 :         rex.in.info_ctr = &info_ctr;
    7590           0 :         rex.in.devmode_ctr = &devmode_ctr;
    7591           0 :         rex.in.secdesc_ctr = &secdesc_ctr;
    7592           0 :         rex.in.userlevel_ctr = &userlevel_ctr;
    7593           0 :         rex.out.handle = &handle;
    7594             : 
    7595           0 :         r.in.server = NULL;
    7596           0 :         r.in.info_ctr = &info_ctr;
    7597           0 :         r.in.devmode_ctr = &devmode_ctr;
    7598           0 :         r.in.secdesc_ctr = &secdesc_ctr;
    7599           0 :         r.out.handle = &handle;
    7600             : 
    7601           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7602             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7603             :                 "failed to add printer");
    7604           0 :         result = ex ? rex.out.result : r.out.result;
    7605           0 :         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
    7606             :                 "unexpected result code");
    7607             : 
    7608           0 :         info1.name = printername;
    7609           0 :         info1.flags = PRINTER_ATTRIBUTE_SHARED;
    7610             : 
    7611           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7612             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7613             :                 "failed to add printer");
    7614           0 :         result = ex ? rex.out.result : r.out.result;
    7615           0 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7616             :                 "unexpected result code");
    7617             : 
    7618             :         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
    7619             :            better do a real check to see the printer is really there */
    7620             : 
    7621           0 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7622             :                                                         PRINTER_ENUM_NETWORK, 1,
    7623             :                                                         printername,
    7624             :                                                         &found),
    7625             :                         "failed to enum printers");
    7626             : 
    7627           0 :         torture_assert(tctx, found, "failed to find newly added printer");
    7628             : 
    7629           0 :         info1.flags = 0;
    7630             : 
    7631           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7632             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7633             :                 "failed to add printer");
    7634           0 :         result = ex ? rex.out.result : r.out.result;
    7635           0 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7636             :                 "unexpected result code");
    7637             : 
    7638             :         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
    7639             :            better do a real check to see the printer has really been removed
    7640             :            from the well known printer list */
    7641             : 
    7642           0 :         found = false;
    7643             : 
    7644           0 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7645             :                                                         PRINTER_ENUM_NETWORK, 1,
    7646             :                                                         printername,
    7647             :                                                         &found),
    7648             :                         "failed to enum printers");
    7649             : #if 0
    7650             :         torture_assert(tctx, !found, "printer still in well known printer list");
    7651             : #endif
    7652           0 :         return true;
    7653             : }
    7654             : 
    7655          16 : static bool test_AddPrinter_normal(struct torture_context *tctx,
    7656             :                                    struct dcerpc_pipe *p,
    7657             :                                    struct policy_handle *handle_p,
    7658             :                                    const char *printername,
    7659             :                                    const char *drivername,
    7660             :                                    const char *portname,
    7661             :                                    struct spoolss_DeviceMode *devmode,
    7662             :                                    bool ex)
    7663             : {
    7664             :         WERROR result;
    7665             :         struct spoolss_AddPrinter r;
    7666             :         struct spoolss_AddPrinterEx rex;
    7667             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    7668             :         struct spoolss_SetPrinterInfo2 info2;
    7669             :         struct spoolss_DevmodeContainer devmode_ctr;
    7670             :         struct sec_desc_buf secdesc_ctr;
    7671             :         struct spoolss_UserLevelCtr userlevel_ctr;
    7672             :         struct policy_handle handle;
    7673          16 :         bool found = false;
    7674          16 :         bool existing_printer_deleted = false;
    7675          16 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7676             : 
    7677          16 :         ZERO_STRUCT(devmode_ctr);
    7678          16 :         ZERO_STRUCT(secdesc_ctr);
    7679          16 :         ZERO_STRUCT(userlevel_ctr);
    7680             : 
    7681          16 :         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
    7682             :                         ex ? "Ex":"", printername);
    7683             : 
    7684          16 :         devmode_ctr.devmode = devmode;
    7685             : 
    7686          16 :         userlevel_ctr.level = 1;
    7687             : 
    7688          16 :         rex.in.server = NULL;
    7689          16 :         rex.in.info_ctr = &info_ctr;
    7690          16 :         rex.in.devmode_ctr = &devmode_ctr;
    7691          16 :         rex.in.secdesc_ctr = &secdesc_ctr;
    7692          16 :         rex.in.userlevel_ctr = &userlevel_ctr;
    7693          16 :         rex.out.handle = &handle;
    7694             : 
    7695          16 :         r.in.server = NULL;
    7696          16 :         r.in.info_ctr = &info_ctr;
    7697          16 :         r.in.devmode_ctr = &devmode_ctr;
    7698          16 :         r.in.secdesc_ctr = &secdesc_ctr;
    7699          16 :         r.out.handle = &handle;
    7700             : 
    7701          16 :  again:
    7702             : 
    7703             :         /* try to add printer to printer list (level 2) */
    7704             : 
    7705          16 :         ZERO_STRUCT(info2);
    7706             : 
    7707          16 :         info_ctr.info.info2 = &info2;
    7708          16 :         info_ctr.level = 2;
    7709             : 
    7710          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7711             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7712             :                 "failed to add printer");
    7713          16 :         result = ex ? rex.out.result : r.out.result;
    7714          16 :         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
    7715             :                 "unexpected result code");
    7716             : 
    7717          16 :         info2.printername = printername;
    7718             : 
    7719          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7720             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7721             :                 "failed to add printer");
    7722          16 :         result = ex ? rex.out.result : r.out.result;
    7723             : 
    7724          16 :         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
    7725             :                 struct policy_handle printer_handle;
    7726             : 
    7727           0 :                 if (existing_printer_deleted) {
    7728           0 :                         torture_fail(tctx, "already deleted printer still existing?");
    7729             :                 }
    7730             : 
    7731           0 :                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
    7732             :                         "failed to open printer handle");
    7733             : 
    7734           0 :                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
    7735             :                         "failed to delete printer");
    7736             : 
    7737           0 :                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
    7738             :                         "failed to close server handle");
    7739             : 
    7740           0 :                 existing_printer_deleted = true;
    7741             : 
    7742           0 :                 goto again;
    7743             :         }
    7744             : 
    7745          16 :         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
    7746             :                 "unexpected result code");
    7747             : 
    7748          16 :         info2.portname = portname;
    7749             : 
    7750          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7751             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7752             :                 "failed to add printer");
    7753          16 :         result = ex ? rex.out.result : r.out.result;
    7754          16 :         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
    7755             :                 "unexpected result code");
    7756             : 
    7757          16 :         info2.drivername = drivername;
    7758             : 
    7759          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7760             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7761             :                 "failed to add printer");
    7762          16 :         result = ex ? rex.out.result : r.out.result;
    7763             : 
    7764             :         /* w2k8r2 allows one to add printer w/o defining printprocessor */
    7765             : 
    7766          16 :         if (!W_ERROR_IS_OK(result)) {
    7767          16 :                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
    7768             :                         "unexpected result code");
    7769             : 
    7770          16 :                 info2.printprocessor = "winprint";
    7771             : 
    7772          16 :                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7773             :                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7774             :                         "failed to add printer");
    7775          16 :                 result = ex ? rex.out.result : r.out.result;
    7776          16 :                 torture_assert_werr_ok(tctx, result,
    7777             :                         "failed to add printer");
    7778             :         }
    7779             : 
    7780          16 :         *handle_p = handle;
    7781             : 
    7782             :         /* we are paranoid, really check if the printer is there now */
    7783             : 
    7784          16 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7785             :                                                         PRINTER_ENUM_LOCAL, 1,
    7786             :                                                         printername,
    7787             :                                                         &found),
    7788             :                         "failed to enum printers");
    7789          16 :         torture_assert(tctx, found, "failed to find newly added printer");
    7790             : 
    7791          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7792             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7793             :                 "failed to add printer");
    7794          16 :         result = ex ? rex.out.result : r.out.result;
    7795          16 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7796             :                 "unexpected result code");
    7797             : 
    7798          16 :         return true;
    7799             : }
    7800             : 
    7801           8 : static bool test_printer_info(struct torture_context *tctx,
    7802             :                               void *private_data)
    7803             : {
    7804           6 :         struct torture_printer_context *t =
    7805           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7806           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7807           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7808             : 
    7809           8 :         bool ret = true;
    7810             : 
    7811           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    7812           8 :                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
    7813             :         }
    7814             : 
    7815           0 :         if (!test_PrinterInfo(tctx, b, &t->handle)) {
    7816           0 :                 ret = false;
    7817             :         }
    7818             : 
    7819           0 :         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
    7820           0 :                 ret = false;
    7821             :         }
    7822             : 
    7823           0 :         return ret;
    7824             : }
    7825             : 
    7826         160 : static bool test_EnumPrinterKey(struct torture_context *tctx,
    7827             :                                 struct dcerpc_binding_handle *b,
    7828             :                                 struct policy_handle *handle,
    7829             :                                 const char *key_name,
    7830             :                                 const char ***array)
    7831             : {
    7832             :         struct spoolss_EnumPrinterKey r;
    7833         160 :         uint32_t needed = 0;
    7834             :         union spoolss_KeyNames key_buffer;
    7835         160 :         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
    7836             :         uint32_t _ndr_size;
    7837             :         int i;
    7838             : 
    7839         160 :         r.in.handle = handle;
    7840         160 :         r.in.key_name = key_name;
    7841         160 :         r.out.key_buffer = &key_buffer;
    7842         160 :         r.out.needed = &needed;
    7843         160 :         r.out._ndr_size = &_ndr_size;
    7844             : 
    7845        2560 :         for (i=0; i < ARRAY_SIZE(offered); i++) {
    7846             : 
    7847        2400 :                 if (offered[i] < 0 && needed) {
    7848         800 :                         if (needed <= 4) {
    7849         340 :                                 continue;
    7850             :                         }
    7851         460 :                         r.in.offered = needed + offered[i];
    7852             :                 } else {
    7853        1600 :                         r.in.offered = offered[i];
    7854             :                 }
    7855             : 
    7856        2060 :                 ZERO_STRUCT(key_buffer);
    7857             : 
    7858        2060 :                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
    7859             : 
    7860        2060 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
    7861             :                         "failed to call EnumPrinterKey");
    7862        2060 :                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    7863             : 
    7864        1284 :                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
    7865             :                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
    7866             :                                         _ndr_size, r.in.offered/2));
    7867             : 
    7868        1284 :                         r.in.offered = needed;
    7869        1284 :                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
    7870             :                                 "failed to call EnumPrinterKey");
    7871             :                 }
    7872             : 
    7873        2060 :                 if (offered[i] > 0) {
    7874        1440 :                         torture_assert_werr_ok(tctx, r.out.result,
    7875             :                                 "failed to call EnumPrinterKey");
    7876             :                 }
    7877             : 
    7878        2060 :                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
    7879             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
    7880             :                                 _ndr_size, r.in.offered/2));
    7881             : 
    7882        2060 :                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
    7883             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
    7884             : 
    7885        2060 :                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
    7886             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
    7887             : 
    7888        2060 :                 if (key_buffer.string_array) {
    7889        2060 :                         uint32_t calc_needed = 0;
    7890             :                         int s;
    7891        4040 :                         for (s=0; key_buffer.string_array[s]; s++) {
    7892        1980 :                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
    7893             :                         }
    7894        2060 :                         if (!key_buffer.string_array[0]) {
    7895         680 :                                 calc_needed += 2;
    7896             :                         }
    7897        2060 :                         calc_needed += 2;
    7898             : 
    7899        2060 :                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
    7900             :                                 "EnumPrinterKey unexpected size");
    7901             :                 }
    7902             :         }
    7903             : 
    7904         160 :         if (array) {
    7905          92 :                 *array = key_buffer.string_array;
    7906             :         }
    7907             : 
    7908         160 :         return true;
    7909             : }
    7910             : 
    7911          28 : bool test_printer_all_keys(struct torture_context *tctx,
    7912             :                            struct dcerpc_binding_handle *b,
    7913             :                            struct policy_handle *handle)
    7914             : {
    7915          28 :         const char **key_array = NULL;
    7916             :         int i;
    7917             : 
    7918          28 :         torture_comment(tctx, "Testing Printer Keys\n");
    7919             : 
    7920          28 :         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
    7921             :                 "failed to call test_EnumPrinterKey");
    7922             : 
    7923          96 :         for (i=0; key_array && key_array[i]; i++) {
    7924          68 :                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
    7925             :                         "failed to call test_EnumPrinterKey");
    7926             :         }
    7927          96 :         for (i=0; key_array && key_array[i]; i++) {
    7928          68 :                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
    7929             :                         "failed to call test_EnumPrinterDataEx");
    7930             :         }
    7931             : 
    7932          28 :         torture_comment(tctx, "Printer Keys test succeeded\n\n");
    7933             : 
    7934          28 :         return true;
    7935             : }
    7936             : 
    7937           8 : static bool test_openprinter_wrap(struct torture_context *tctx,
    7938             :                                   void *private_data)
    7939             : {
    7940           6 :         struct torture_printer_context *t =
    7941           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7942           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7943           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7944           8 :         const char *printername = t->info2.printername;
    7945             : 
    7946           8 :         return test_openprinter(tctx, b, printername);
    7947             : }
    7948             : 
    7949           8 : static bool test_csetprinter(struct torture_context *tctx,
    7950             :                              void *private_data)
    7951             : {
    7952           6 :         struct torture_printer_context *t =
    7953           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7954           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7955             : 
    7956           8 :         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
    7957           8 :         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    7958           8 :         const char *portname = t->info2.portname;
    7959             : 
    7960             :         union spoolss_PrinterInfo info;
    7961             :         struct policy_handle new_handle, new_handle2;
    7962           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7963             : 
    7964           8 :         torture_comment(tctx, "Testing c_setprinter\n");
    7965             : 
    7966           8 :         torture_assert(tctx,
    7967             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    7968             :                 "failed to get level 0 printer info");
    7969           8 :         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
    7970             :                 info.info0.c_setprinter);
    7971             : 
    7972             :         /* check if c_setprinter on 1st handle increases after a printer has
    7973             :          * been added */
    7974             : 
    7975           8 :         torture_assert(tctx,
    7976             :                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
    7977             :                 "failed to add new printer");
    7978           8 :         torture_assert(tctx,
    7979             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    7980             :                 "failed to get level 0 printer info");
    7981           8 :         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
    7982             :                 info.info0.c_setprinter);
    7983             : 
    7984             :         /* check if c_setprinter on new handle increases after a printer has
    7985             :          * been added */
    7986             : 
    7987           8 :         torture_assert(tctx,
    7988             :                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
    7989             :                 "failed to get level 0 printer info");
    7990           8 :         torture_comment(tctx, "csetprinter on created handle: %d\n",
    7991             :                 info.info0.c_setprinter);
    7992             : 
    7993             :         /* open the new printer and check if c_setprinter increases */
    7994             : 
    7995           8 :         torture_assert(tctx,
    7996             :                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
    7997             :                 "failed to open created printer");
    7998           8 :         torture_assert(tctx,
    7999             :                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
    8000             :                 "failed to get level 0 printer info");
    8001           8 :         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
    8002             :                 info.info0.c_setprinter);
    8003             : 
    8004             :         /* cleanup */
    8005             : 
    8006           8 :         torture_assert(tctx,
    8007             :                 test_ClosePrinter(tctx, b, &new_handle2),
    8008             :                 "failed to close printer");
    8009           8 :         torture_assert(tctx,
    8010             :                 test_DeletePrinter(tctx, b, &new_handle),
    8011             :                 "failed to delete new printer");
    8012             : 
    8013           8 :         return true;
    8014             : }
    8015             : 
    8016           8 : static bool compose_local_driver_directory(struct torture_context *tctx,
    8017             :                                            const char *environment,
    8018             :                                            const char *local_dir,
    8019             :                                            const char **path)
    8020             : {
    8021             :         char *p;
    8022             : 
    8023           8 :         p = strrchr(local_dir, '/');
    8024           8 :         if (!p) {
    8025           0 :                 return NULL;
    8026             :         }
    8027           8 :         p++;
    8028             : 
    8029           8 :         if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
    8030           8 :                 if (!strequal(p, "x64")) {
    8031           8 :                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
    8032             :                 }
    8033           0 :         } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
    8034           0 :                 if (!strequal(p, "i386")) {
    8035           0 :                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
    8036             :                 }
    8037             :         } else {
    8038             :                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
    8039             :         }
    8040             : 
    8041           8 :         return true;
    8042             : }
    8043             : 
    8044             : #if 0
    8045             : static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
    8046             :                                                      const char *devicename)
    8047             : {
    8048             :         struct spoolss_DeviceMode *r;
    8049             : 
    8050             :         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
    8051             :         if (r == NULL) {
    8052             :                 return NULL;
    8053             :         }
    8054             : 
    8055             :         r->devicename                = talloc_strdup(r, devicename);
    8056             :         r->specversion               = DMSPEC_NT4_AND_ABOVE;
    8057             :         r->driverversion     = 0x0600;
    8058             :         r->size                      = 0x00dc;
    8059             :         r->__driverextra_length = 0;
    8060             :         r->fields            = DEVMODE_FORMNAME |
    8061             :                                   DEVMODE_TTOPTION |
    8062             :                                   DEVMODE_PRINTQUALITY |
    8063             :                                   DEVMODE_DEFAULTSOURCE |
    8064             :                                   DEVMODE_COPIES |
    8065             :                                   DEVMODE_SCALE |
    8066             :                                   DEVMODE_PAPERSIZE |
    8067             :                                   DEVMODE_ORIENTATION;
    8068             :         r->orientation               = DMORIENT_PORTRAIT;
    8069             :         r->papersize         = DMPAPER_LETTER;
    8070             :         r->paperlength               = 0;
    8071             :         r->paperwidth                = 0;
    8072             :         r->scale             = 100;
    8073             :         r->copies            = 55;
    8074             :         r->defaultsource     = DMBIN_FORMSOURCE;
    8075             :         r->printquality              = DMRES_HIGH;
    8076             :         r->color             = DMRES_MONOCHROME;
    8077             :         r->duplex            = DMDUP_SIMPLEX;
    8078             :         r->yresolution               = 0;
    8079             :         r->ttoption          = DMTT_SUBDEV;
    8080             :         r->collate           = DMCOLLATE_FALSE;
    8081             :         r->formname          = talloc_strdup(r, "Letter");
    8082             : 
    8083             :         return r;
    8084             : }
    8085             : #endif
    8086             : 
    8087           4 : static bool test_architecture_buffer(struct torture_context *tctx,
    8088             :                                      void *private_data)
    8089             : {
    8090           3 :         struct test_spoolss_context *ctx =
    8091           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8092             : 
    8093             :         struct spoolss_OpenPrinterEx r;
    8094             :         struct spoolss_UserLevel1 u1;
    8095             :         struct policy_handle handle;
    8096           4 :         uint32_t architectures[] = {
    8097             :                 PROCESSOR_ARCHITECTURE_INTEL,
    8098             :                 PROCESSOR_ARCHITECTURE_IA64,
    8099             :                 PROCESSOR_ARCHITECTURE_AMD64
    8100             :         };
    8101             :         uint32_t needed[3];
    8102             :         int i;
    8103           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8104           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8105             : 
    8106          16 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8107             : 
    8108          12 :                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
    8109             : 
    8110          12 :                 u1.size = 0;
    8111          12 :                 u1.client = NULL;
    8112          12 :                 u1.user = NULL;
    8113          12 :                 u1.build = 0;
    8114          12 :                 u1.major = 3;
    8115          12 :                 u1.minor = 0;
    8116          12 :                 u1.processor = architectures[i];
    8117             : 
    8118          12 :                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8119          12 :                 r.in.datatype           = NULL;
    8120          12 :                 r.in.devmode_ctr.devmode= NULL;
    8121          12 :                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
    8122          12 :                 r.in.userlevel_ctr.level = 1;
    8123          12 :                 r.in.userlevel_ctr.user_info.level1 = &u1;
    8124          12 :                 r.out.handle            = &handle;
    8125             : 
    8126          12 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
    8127          12 :                 torture_assert_werr_ok(tctx, r.out.result, "");
    8128             : 
    8129             :                 {
    8130             :                         struct spoolss_EnumPrinters e;
    8131             :                         uint32_t count;
    8132             :                         union spoolss_PrinterInfo *info;
    8133             : 
    8134          12 :                         e.in.flags = PRINTER_ENUM_LOCAL;
    8135          12 :                         e.in.server = NULL;
    8136          12 :                         e.in.level = 2;
    8137          12 :                         e.in.buffer = NULL;
    8138          12 :                         e.in.offered = 0;
    8139          12 :                         e.out.count = &count;
    8140          12 :                         e.out.info = &info;
    8141          12 :                         e.out.needed = &needed[i];
    8142             : 
    8143          12 :                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
    8144             : #if 0
    8145             :                         torture_comment(tctx, "needed was %d\n", needed[i]);
    8146             : #endif
    8147             :                 }
    8148             : 
    8149          12 :                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
    8150             :         }
    8151             : 
    8152          12 :         for (i=1; i < ARRAY_SIZE(architectures); i++) {
    8153           8 :                 if (needed[i-1] != needed[i]) {
    8154           0 :                         torture_fail(tctx,
    8155             :                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
    8156             :                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
    8157             :                 }
    8158             :         }
    8159             : 
    8160           4 :         return true;
    8161             : }
    8162             : 
    8163           8 : static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
    8164             :                                                     struct dcerpc_pipe *p,
    8165             :                                                     const char *architecture,
    8166             :                                                     const char *guid_str,
    8167             :                                                     const char **package_id)
    8168             : {
    8169             :         struct spoolss_GetCorePrinterDrivers r;
    8170             :         struct spoolss_CorePrinterDriver core_printer_drivers;
    8171           8 :         DATA_BLOB blob = data_blob_talloc_zero(tctx, 2);
    8172             :         const char **s;
    8173           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8174             :         struct GUID guid;
    8175             : 
    8176           8 :         s = talloc_zero_array(tctx, const char *, 2);
    8177             : 
    8178           8 :         r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8179           8 :         r.in.architecture = "foobar";
    8180           8 :         r.in.core_driver_size = 0;
    8181           8 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8182           8 :         r.in.core_printer_driver_count = 0;
    8183           8 :         r.out.core_printer_drivers = &core_printer_drivers;
    8184             : 
    8185           8 :         torture_assert_ntstatus_ok(tctx,
    8186             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8187             :                 "spoolss_GetCorePrinterDrivers failed");
    8188           0 :         torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
    8189             :                 "spoolss_GetCorePrinterDrivers failed");
    8190             : 
    8191           0 :         guid = GUID_random();
    8192           0 :         s[0] = GUID_string2(tctx, &guid);
    8193             : 
    8194           0 :         torture_assert(tctx,
    8195             :                 push_reg_multi_sz(tctx, &blob, s),
    8196             :                 "push_reg_multi_sz failed");
    8197             : 
    8198           0 :         r.in.core_driver_size = blob.length/2;
    8199           0 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8200           0 :         r.in.core_printer_driver_count = 1;
    8201           0 :         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
    8202             : 
    8203           0 :         torture_assert_ntstatus_ok(tctx,
    8204             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8205             :                 "spoolss_GetCorePrinterDrivers failed");
    8206           0 :         torture_assert_werr_equal(tctx,
    8207             :                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
    8208             :                 "spoolss_GetCorePrinterDrivers failed");
    8209             : 
    8210           0 :         r.in.architecture = architecture;
    8211             : 
    8212           0 :         torture_assert_ntstatus_ok(tctx,
    8213             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8214             :                 "spoolss_GetCorePrinterDrivers failed");
    8215           0 :         torture_assert_werr_equal(tctx,
    8216             :                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
    8217             :                 "spoolss_GetCorePrinterDrivers failed");
    8218             : 
    8219           0 :         s[0] = talloc_strdup(s, guid_str);
    8220             : 
    8221           0 :         torture_assert(tctx,
    8222             :                 push_reg_multi_sz(tctx, &blob, s),
    8223             :                 "push_reg_multi_sz failed");
    8224             : 
    8225           0 :         r.in.core_driver_size = blob.length/2;
    8226           0 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8227           0 :         r.in.core_printer_driver_count = 1;
    8228           0 :         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
    8229             : 
    8230           0 :         torture_assert_ntstatus_ok(tctx,
    8231             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8232             :                 "spoolss_GetCorePrinterDrivers failed");
    8233           0 :         torture_assert_hresult_ok(tctx, r.out.result,
    8234             :                 "spoolss_GetCorePrinterDrivers failed");
    8235             : 
    8236           0 :         if (package_id) {
    8237           0 :                 *package_id = r.out.core_printer_drivers[0].szPackageID;
    8238             :         }
    8239             : 
    8240           0 :         return true;
    8241             : }
    8242             : 
    8243           4 : static bool test_get_core_printer_drivers(struct torture_context *tctx,
    8244             :                                           void *private_data)
    8245             : {
    8246           3 :         struct test_spoolss_context *ctx =
    8247           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8248             : 
    8249           4 :         const char *architectures[] = {
    8250             :                 SPOOLSS_ARCHITECTURE_NT_X86,
    8251             :                 SPOOLSS_ARCHITECTURE_x64
    8252             :         };
    8253             :         int i;
    8254           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8255             : 
    8256           4 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8257             : 
    8258           4 :                 torture_comment(tctx, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
    8259             :                         architectures[i],
    8260             :                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
    8261             : 
    8262           4 :                 torture_assert(tctx,
    8263             :                         test_get_core_printer_drivers_arch_guid(tctx, p,
    8264             :                                 architectures[i],
    8265             :                                 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
    8266             :                                 NULL),
    8267             :                         "");
    8268             :         }
    8269             : 
    8270           0 :         return true;
    8271             : }
    8272             : 
    8273           4 : static bool test_get_printer_driver_package_path(struct torture_context *tctx,
    8274             :                                                  void *private_data)
    8275             : {
    8276           3 :         struct test_spoolss_context *ctx =
    8277           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8278             : 
    8279           4 :         const char *architectures[] = {
    8280             :                 SPOOLSS_ARCHITECTURE_NT_X86,
    8281             :                 SPOOLSS_ARCHITECTURE_x64
    8282             :         };
    8283             :         int i;
    8284           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8285           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8286             : 
    8287           4 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8288             :                 struct spoolss_GetPrinterDriverPackagePath r;
    8289           4 :                 uint32_t required = 0;
    8290           4 :                 const char *package_id = NULL;
    8291             : 
    8292           4 :                 test_get_core_printer_drivers_arch_guid(tctx, p,
    8293             :                         architectures[i],
    8294             :                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
    8295             :                         &package_id),
    8296             : 
    8297           4 :                 torture_comment(tctx, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
    8298             :                         architectures[i], package_id);
    8299             : 
    8300           4 :                 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8301           4 :                 r.in.architecture = "foobar";
    8302           4 :                 r.in.language = NULL;
    8303           4 :                 r.in.package_id = "";
    8304           4 :                 r.in.driver_package_cab_size = 0;
    8305           4 :                 r.in.driver_package_cab = NULL;
    8306             : 
    8307           4 :                 r.out.required = &required;
    8308           4 :                 r.out.driver_package_cab = NULL;
    8309             : 
    8310           4 :                 torture_assert_ntstatus_ok(tctx,
    8311             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8312             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8313           0 :                 torture_assert_werr_equal(tctx,
    8314             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
    8315             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8316             : 
    8317           0 :                 r.in.architecture = architectures[i];
    8318             : 
    8319           0 :                 torture_assert_ntstatus_ok(tctx,
    8320             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8321             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8322           0 :                 torture_assert_werr_equal(tctx,
    8323             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
    8324             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8325             : 
    8326           0 :                 r.in.package_id = package_id;
    8327             : 
    8328           0 :                 torture_assert_ntstatus_ok(tctx,
    8329             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8330             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8331           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8332             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8333             : 
    8334           0 :                 r.in.driver_package_cab_size = required;
    8335           0 :                 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
    8336           0 :                 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
    8337             : 
    8338           0 :                 torture_assert_ntstatus_ok(tctx,
    8339             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8340             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8341           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8342             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8343             : 
    8344           0 :                 r.in.servername = NULL;
    8345             : 
    8346           0 :                 torture_assert_ntstatus_ok(tctx,
    8347             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8348             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8349           0 :                 torture_assert_werr_equal(tctx,
    8350             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INSUFFICIENT_BUFFER,
    8351             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8352             : 
    8353           0 :                 r.in.driver_package_cab_size = required;
    8354           0 :                 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
    8355           0 :                 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
    8356             : 
    8357           0 :                 torture_assert_ntstatus_ok(tctx,
    8358             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8359             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8360           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8361             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8362             : 
    8363             :         }
    8364             : 
    8365           0 :         return true;
    8366             : }
    8367             : 
    8368           4 : static bool test_get_printer_printserverhandle(struct torture_context *tctx,
    8369             :                                                void *private_data)
    8370             : {
    8371           3 :         struct test_spoolss_context *ctx =
    8372           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8373             : 
    8374           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8375           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8376           4 :         uint32_t levels[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
    8377             :         int i;
    8378             : 
    8379          36 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    8380             : 
    8381          32 :                 torture_assert(tctx,
    8382             :                         test_GetPrinter_level_exp(tctx, b, &ctx->server_handle,
    8383             :                                                   levels[i], WERR_INVALID_LEVEL,
    8384             :                                                   NULL),
    8385             :                         "failed to call GetPrinter");
    8386             :         }
    8387             : 
    8388           4 :         torture_assert(tctx,
    8389             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, NULL),
    8390             :                 "failed to call GetPrinter");
    8391             : 
    8392           4 :         return true;
    8393             : }
    8394             : 
    8395             : #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
    8396             : 
    8397           4 : static bool test_set_printer_printserverhandle(struct torture_context *tctx,
    8398             :                                                void *private_data)
    8399             : {
    8400           3 :         struct test_spoolss_context *ctx =
    8401           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8402             : 
    8403           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8404           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8405             :         union spoolss_PrinterInfo info;
    8406             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    8407             :         struct spoolss_SetPrinterInfo3 info3;
    8408             :         struct spoolss_DevmodeContainer devmode_ctr;
    8409             :         struct sec_desc_buf secdesc_ctr;
    8410             :         struct security_descriptor *sd;
    8411             :         struct security_ace *ace;
    8412             :         struct dom_sid sid;
    8413             :         int i;
    8414             : 
    8415           4 :         torture_assert(tctx,
    8416             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8417             :                 "failed to call GetPrinter");
    8418             : 
    8419           4 :         secdesc_ctr.sd = info.info3.secdesc;
    8420           4 :         secdesc_ctr.sd->owner_sid = NULL;
    8421           4 :         secdesc_ctr.sd->group_sid = NULL;
    8422             : 
    8423           4 :         sd = security_descriptor_copy(tctx, secdesc_ctr.sd);
    8424           4 :         if (sd == NULL) {
    8425           0 :                 return false;
    8426             :         }
    8427             : 
    8428           4 :         ace = security_ace_create(tctx,
    8429             :                                   TEST_SID,
    8430             :                                   SEC_ACE_TYPE_ACCESS_ALLOWED,
    8431             :                                   SEC_STD_REQUIRED,
    8432             :                                   SEC_ACE_FLAG_CONTAINER_INHERIT);
    8433           4 :         torture_assert(tctx, ace, "failed to create ace");
    8434             : 
    8435           4 :         torture_assert_ntstatus_ok(tctx,
    8436             :                 security_descriptor_dacl_add(sd, ace),
    8437             :                 "failed to add ace");
    8438             : 
    8439           4 :         secdesc_ctr.sd = sd;
    8440             : 
    8441           4 :         info3.sec_desc_ptr = 0;
    8442             : 
    8443           4 :         info_ctr.level = 3;
    8444           4 :         info_ctr.info.info3 = &info3;
    8445             : 
    8446           4 :         ZERO_STRUCT(devmode_ctr);
    8447             : 
    8448           4 :         torture_assert(tctx,
    8449             :                 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
    8450             :                                 &devmode_ctr, &secdesc_ctr, 0),
    8451             :                 "failed to call SetPrinter");
    8452             : 
    8453           4 :         torture_assert(tctx,
    8454             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8455             :                 "failed to call GetPrinter");
    8456             : 
    8457          32 :         for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
    8458          32 :                 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
    8459           4 :                         break;
    8460             :                 }
    8461             :         }
    8462             : 
    8463           4 :         if (i == info.info3.secdesc->dacl->num_aces) {
    8464           0 :                 torture_fail(tctx, "ace not present");
    8465             :         }
    8466             : 
    8467           4 :         torture_assert(tctx,
    8468             :                 dom_sid_parse(TEST_SID, &sid),
    8469             :                 "failed to parse sid");
    8470             : 
    8471           4 :         torture_assert_ntstatus_ok(tctx,
    8472             :                 security_descriptor_dacl_del(info.info3.secdesc, &sid),
    8473             :                 "failed to remove ace from sd");
    8474             : 
    8475           4 :         secdesc_ctr.sd = info.info3.secdesc;
    8476             : 
    8477           4 :         torture_assert(tctx,
    8478             :                 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
    8479             :                                 &devmode_ctr, &secdesc_ctr, 0),
    8480             :                 "failed to call SetPrinter");
    8481             : 
    8482           4 :         torture_assert(tctx,
    8483             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8484             :                 "failed to call GetPrinter");
    8485             : 
    8486          32 :         for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
    8487          28 :                 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
    8488           0 :                         torture_fail(tctx, "ace still present");
    8489             :                 }
    8490             :         }
    8491             : 
    8492           4 :         return true;
    8493             : }
    8494             : 
    8495             : 
    8496           4 : static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
    8497             :                                           void *private_data)
    8498             : {
    8499           3 :         struct test_spoolss_context *ctx =
    8500           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8501           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8502           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8503             : 
    8504           4 :         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
    8505             : }
    8506             : 
    8507           4 : static bool test_PrintServer_Forms(struct torture_context *tctx,
    8508             :                                    void *private_data)
    8509             : {
    8510           3 :         struct test_spoolss_context *ctx =
    8511           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8512           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8513           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8514             : 
    8515           4 :         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
    8516             : }
    8517             : 
    8518           4 : static bool test_PrintServer_EnumForms(struct torture_context *tctx,
    8519             :                                        void *private_data)
    8520             : {
    8521           3 :         struct test_spoolss_context *ctx =
    8522           1 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8523           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8524           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8525             : 
    8526           4 :         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
    8527             : }
    8528             : 
    8529           4 : static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
    8530             : {
    8531             :         NTSTATUS status;
    8532             : 
    8533           4 :         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
    8534             : 
    8535           4 :         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
    8536             : 
    8537           4 :         torture_assert(tctx,
    8538             :                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
    8539             :                 "failed to open printserver");
    8540           4 :         torture_assert(tctx,
    8541             :                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
    8542             :                 "failed to get environment");
    8543             : 
    8544           4 :         return true;
    8545             : }
    8546             : 
    8547           4 : static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
    8548             : {
    8549             :         struct test_spoolss_context *t;
    8550             : 
    8551           4 :         *data = t = talloc_zero(tctx, struct test_spoolss_context);
    8552             : 
    8553           4 :         return torture_rpc_spoolss_setup_common(tctx, t);
    8554             : }
    8555             : 
    8556           4 : static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
    8557             : {
    8558           4 :         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
    8559             : 
    8560           4 :         return true;
    8561             : }
    8562             : 
    8563           4 : static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
    8564             : {
    8565           4 :         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
    8566             :         bool ret;
    8567             : 
    8568           4 :         ret = torture_rpc_spoolss_teardown_common(tctx, t);
    8569           4 :         talloc_free(t);
    8570             : 
    8571           4 :         return ret;
    8572             : }
    8573             : 
    8574           8 : static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
    8575             : {
    8576             :         struct dcerpc_pipe *p;
    8577             :         struct dcerpc_binding_handle *b;
    8578             :         const char *server_name_slash;
    8579             :         const char *driver_name;
    8580             :         const char *printer_name;
    8581             :         const char *port_name;
    8582             : 
    8583           8 :         torture_assert_ntstatus_ok(tctx,
    8584             :                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
    8585             :                 "Error connecting to server");
    8586             : 
    8587           8 :         p = t->spoolss_pipe;
    8588           8 :         b = p->binding_handle;
    8589           8 :         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8590             : 
    8591           8 :         t->driver.info8.version                      = SPOOLSS_DRIVER_VERSION_200X;
    8592           8 :         t->driver.info8.driver_name          = TORTURE_DRIVER;
    8593           8 :         t->driver.info8.driver_path          = "pscript5.dll";
    8594           8 :         t->driver.info8.data_file            = "cups6.ppd";
    8595           8 :         t->driver.info8.config_file          = "ps5ui.dll";
    8596           8 :         t->driver.info8.help_file            = "pscript.hlp";
    8597           8 :         t->driver.info8.default_datatype     = "RAW";
    8598           8 :         t->driver.info8.dependent_files              = talloc_zero(t, struct spoolss_StringArray);
    8599           8 :         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
    8600           8 :         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
    8601           8 :         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
    8602           8 :         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
    8603           8 :         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
    8604           8 :         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
    8605           8 :         t->driver.info8.dependent_files->string[5] = "cups6.ini";
    8606           8 :         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
    8607           8 :         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
    8608             : 
    8609           8 :         t->driver.local.driver_directory= "/usr/share/cups/drivers";
    8610             : 
    8611           8 :         t->info2.portname            = "LPT1:";
    8612             : 
    8613           8 :         printer_name = t->info2.printername;
    8614           8 :         port_name = t->info2.portname;
    8615             : 
    8616           8 :         torture_assert(tctx,
    8617             :                 fillup_printserver_info(tctx, p, &t->driver),
    8618             :                 "failed to fillup printserver info");
    8619             : 
    8620           8 :         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
    8621             : 
    8622           8 :         torture_assert(tctx,
    8623             :                 compose_local_driver_directory(tctx, t->driver.remote.environment,
    8624             :                                                t->driver.local.driver_directory,
    8625             :                                                &t->driver.local.driver_directory),
    8626             :                 "failed to compose local driver directory");
    8627             : 
    8628           8 :         t->info2.drivername          = "Microsoft XPS Document Writer";
    8629             : 
    8630           8 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
    8631           0 :                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
    8632             :                         t->info2.drivername, t->driver.remote.environment);
    8633           0 :                 t->have_driver = true;
    8634           0 :                 goto try_add;
    8635             :         }
    8636             : 
    8637           8 :         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
    8638             :                 t->info2.drivername, t->driver.remote.environment);
    8639             : 
    8640           8 :         t->info2.drivername          = "Microsoft XPS Document Writer v4";
    8641             : 
    8642           8 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
    8643           0 :                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
    8644             :                         t->info2.drivername, t->driver.remote.environment);
    8645           0 :                 t->have_driver = true;
    8646           0 :                 goto try_add;
    8647             :         }
    8648             : 
    8649           8 :         torture_comment(tctx, "trying to upload own driver\n");
    8650             : 
    8651           8 :         if (!directory_exist(t->driver.local.driver_directory)) {
    8652           8 :                 torture_warning(tctx, "no local driver is available!");
    8653           8 :                 t->have_driver = false;
    8654           8 :                 goto try_add;
    8655             :         }
    8656             : 
    8657           0 :         torture_assert(tctx,
    8658             :                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
    8659             :                 "failed to upload printer driver");
    8660             : 
    8661           0 :         torture_assert(tctx,
    8662             :                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
    8663             :                 "failed to add driver");
    8664             : 
    8665           0 :         t->added_driver = true;
    8666           0 :         t->have_driver = true;
    8667             : 
    8668           8 :  try_add:
    8669           8 :         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    8670             : 
    8671           8 :         if (t->wellknown) {
    8672           0 :                 torture_assert(tctx,
    8673             :                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
    8674             :                         "failed to add wellknown printer");
    8675             :         } else {
    8676           8 :                 torture_assert(tctx,
    8677             :                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
    8678             :                         "failed to add printer");
    8679             :         }
    8680             : 
    8681           8 :         return true;
    8682             : }
    8683             : 
    8684           4 : static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
    8685             : {
    8686             :         struct torture_printer_context *t;
    8687             : 
    8688           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8689             : 
    8690           4 :         t->ex                        = false;
    8691           4 :         t->wellknown         = false;
    8692           4 :         t->info2.printername = TORTURE_PRINTER;
    8693           4 :         t->devmode           = NULL;
    8694             : 
    8695           4 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8696             : }
    8697             : 
    8698           4 : static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
    8699             : {
    8700             :         struct torture_printer_context *t;
    8701             : 
    8702           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8703             : 
    8704           4 :         t->ex                        = true;
    8705           4 :         t->wellknown         = false;
    8706           4 :         t->info2.printername = TORTURE_PRINTER_EX;
    8707           4 :         t->devmode           = NULL;
    8708             : 
    8709           4 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8710             : }
    8711             : 
    8712           4 : static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
    8713             : {
    8714             :         struct torture_printer_context *t;
    8715             : 
    8716           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8717             : 
    8718           4 :         t->ex                        = false;
    8719           4 :         t->wellknown         = true;
    8720           4 :         t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
    8721           4 :         t->devmode           = NULL;
    8722             : 
    8723             :         /* FIXME */
    8724           4 :         if (t->wellknown) {
    8725           4 :                 torture_skip(tctx, "skipping AddPrinter level 1");
    8726             :         }
    8727             : 
    8728           0 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8729             : }
    8730             : 
    8731           4 : static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
    8732             : {
    8733             :         struct torture_printer_context *t;
    8734             : 
    8735           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8736             : 
    8737           4 :         t->ex                        = true;
    8738           4 :         t->wellknown         = true;
    8739           4 :         t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
    8740           4 :         t->devmode           = NULL;
    8741             : 
    8742             :         /* FIXME */
    8743           4 :         if (t->wellknown) {
    8744           4 :                 torture_skip(tctx, "skipping AddPrinterEx level 1");
    8745             :         }
    8746             : 
    8747           0 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8748             : }
    8749             : 
    8750             : #if 0
    8751             : static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
    8752             : {
    8753             :         struct torture_printer_context *t;
    8754             : 
    8755             :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8756             : 
    8757             :         t->ex                        = true;
    8758             :         t->wellknown         = false;
    8759             :         t->info2.printername = TORTURE_PRINTER_EX;
    8760             :         t->devmode           = torture_devicemode(t, TORTURE_PRINTER_EX);
    8761             : 
    8762             :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8763             : }
    8764             : #endif
    8765             : 
    8766             : static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
    8767             :                                            struct dcerpc_binding_handle *b,
    8768             :                                            const char *server,
    8769             :                                            const char *driver,
    8770             :                                            const char *environment,
    8771             :                                            uint32_t delete_flags,
    8772             :                                            uint32_t version,
    8773             :                                            WERROR expected_result);
    8774             : 
    8775          16 : static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
    8776             : {
    8777          16 :         bool found = false;
    8778          16 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8779          16 :         struct dcerpc_binding_handle *b = NULL;
    8780             :         const char *server_name_slash;
    8781          16 :         bool ok = true;
    8782             : 
    8783          16 :         if (p == NULL) {
    8784           8 :                 return true;
    8785             :         }
    8786           8 :         b = p->binding_handle;
    8787             : 
    8788           8 :         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8789             : 
    8790           8 :         if (!t->wellknown) {
    8791           8 :                 const char *printer_name = t->info2.printername;
    8792             : 
    8793           8 :                 torture_assert_goto(tctx,
    8794             :                         test_DeletePrinter(tctx, b, &t->handle),
    8795             :                         ok,
    8796             :                         remove_driver,
    8797             :                         "failed to delete printer");
    8798             : 
    8799           8 :                 torture_assert_goto(tctx,
    8800             :                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
    8801             :                                                    printer_name, &found),
    8802             :                         ok,
    8803             :                         remove_driver,
    8804             :                         "failed to enumerate printers");
    8805             : 
    8806          13 :                 torture_assert_goto(tctx,
    8807             :                         !found,
    8808             :                         ok,
    8809             :                         remove_driver,
    8810             :                         "deleted printer still there");
    8811             :         }
    8812             : 
    8813             : 
    8814           7 : remove_driver:
    8815           8 :         if (t->added_driver) {
    8816           0 :                 ok = remove_printer_driver(tctx,
    8817             :                                            dcerpc_server_name(p),
    8818             :                                            &t->driver);
    8819           0 :                 if (!ok) {
    8820           0 :                         torture_warning(tctx,
    8821             :                                         "failed to remove printer driver\n");
    8822             :                 }
    8823             : 
    8824           0 :                 ok = test_DeletePrinterDriverEx_exp(tctx, b,
    8825             :                                                     server_name_slash,
    8826             :                                                     t->driver.info8.driver_name,
    8827             :                                                     t->driver.info8.architecture,
    8828             :                                                     DPD_DELETE_ALL_FILES,
    8829           0 :                                                     t->driver.info8.version,
    8830           0 :                                                     WERR_OK);
    8831           0 :                 if (!ok) {
    8832           0 :                         torture_warning(tctx,
    8833             :                                         "failed to delete printer driver via "
    8834             :                                         "spoolss\n");
    8835             :                 }
    8836             :         }
    8837             : 
    8838           8 :         return ok;
    8839             : }
    8840             : 
    8841          16 : static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
    8842             : {
    8843          16 :         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
    8844             :         bool ret;
    8845             : 
    8846          16 :         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
    8847          16 :         talloc_free(t);
    8848             : 
    8849          16 :         return ret;
    8850             : }
    8851             : 
    8852           8 : static bool test_print_test(struct torture_context *tctx,
    8853             :                             void *private_data)
    8854             : {
    8855           6 :         struct torture_printer_context *t =
    8856           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8857           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8858           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8859             : 
    8860           8 :         torture_assert(tctx,
    8861             :                 test_PausePrinter(tctx, b, &t->handle),
    8862             :                 "failed to pause printer");
    8863             : 
    8864           8 :         torture_assert(tctx,
    8865             :                 test_DoPrintTest(tctx, b, &t->handle),
    8866             :                 "failed to do print test");
    8867             : 
    8868           4 :         torture_assert(tctx,
    8869             :                 test_ResumePrinter(tctx, b, &t->handle),
    8870             :                 "failed to resume printer");
    8871             : 
    8872           4 :         return true;
    8873             : }
    8874             : 
    8875           8 : static bool test_print_test_extended(struct torture_context *tctx,
    8876             :                                      void *private_data)
    8877             : {
    8878           6 :         struct torture_printer_context *t =
    8879           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8880           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8881           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8882           8 :         bool ret = true;
    8883             : 
    8884           8 :         torture_assert(tctx,
    8885             :                 test_PausePrinter(tctx, b, &t->handle),
    8886             :                 "failed to pause printer");
    8887             : 
    8888           8 :         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
    8889           8 :         if (ret == false) {
    8890           4 :                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
    8891           4 :                 if (torture_setting_bool(tctx, "samba3", false)) {
    8892           4 :                         torture_comment(tctx, "non-critical for samba3\n");
    8893           4 :                         ret = true;
    8894           4 :                         tctx->last_result = TORTURE_SKIP;
    8895             :                 }
    8896             :         }
    8897             : 
    8898           8 :         torture_assert(tctx,
    8899             :                 test_ResumePrinter(tctx, b, &t->handle),
    8900             :                 "failed to resume printer");
    8901             : 
    8902           8 :         return ret;
    8903             : }
    8904             : 
    8905           8 : static bool test_print_test_properties(struct torture_context *tctx,
    8906             :                                        void *private_data)
    8907             : {
    8908           6 :         struct torture_printer_context *t =
    8909           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8910           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8911           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8912             : 
    8913           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    8914           8 :                 torture_skip(tctx, "skip printer job property tests against samba");
    8915             :         }
    8916             : 
    8917           0 :         torture_assert(tctx,
    8918             :                 test_PausePrinter(tctx, b, &t->handle),
    8919             :                 "failed to pause printer");
    8920             : 
    8921           0 :         torture_assert(tctx,
    8922             :                 test_DoPrintTest_properties(tctx, b, &t->handle),
    8923             :                 "failed to test print job properties");
    8924             : 
    8925           0 :         torture_assert(tctx,
    8926             :                 test_ResumePrinter(tctx, b, &t->handle),
    8927             :                 "failed to resume printer");
    8928             : 
    8929           0 :         return true;
    8930             : }
    8931             : 
    8932             : /* use smbd file IO to spool a print job */
    8933           8 : static bool test_print_test_smbd(struct torture_context *tctx,
    8934             :                                  void *private_data)
    8935             : {
    8936           6 :         struct torture_printer_context *t =
    8937           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8938           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8939           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8940             :         NTSTATUS status;
    8941             :         uint32_t count;
    8942           8 :         union spoolss_JobInfo *info = NULL;
    8943             :         int i;
    8944             : 
    8945             :         struct smb2_tree *tree;
    8946             :         struct smb2_handle job_h;
    8947             :         struct smbcli_options options;
    8948           8 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    8949             :         /*
    8950             :          * Do not test against the dynamically added printers, printing via
    8951             :          * smbd means that a different spoolss process may handle the
    8952             :          * OpenPrinter request to the one that handled the AddPrinter request.
    8953             :          * This currently leads to an ugly race condition where one process
    8954             :          * sees the new printer and one doesn't.
    8955             :          */
    8956           8 :         const char *share = TORTURE_PRINTER_STATIC1;
    8957             : 
    8958           8 :         torture_comment(tctx, "Testing smbd job spooling\n");
    8959           8 :         lpcfg_smbcli_options(tctx->lp_ctx, &options);
    8960             : 
    8961           8 :         status = smb2_connect(mem_ctx,
    8962             :                               torture_setting_string(tctx, "host", NULL),
    8963             :                               lpcfg_smb_ports(tctx->lp_ctx),
    8964             :                               share,
    8965             :                               lpcfg_resolve_context(tctx->lp_ctx),
    8966             :                               samba_cmdline_get_creds(),
    8967             :                               &tree,
    8968             :                               tctx->ev,
    8969             :                               &options,
    8970             :                               lpcfg_socket_options(tctx->lp_ctx),
    8971             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
    8972           8 :         if (!NT_STATUS_IS_OK(status)) {
    8973           0 :                 printf("Failed to connect to SMB2 printer %s - %s\n",
    8974             :                        share, nt_errstr(status));
    8975           0 :                 return false;
    8976             :         }
    8977             : 
    8978           8 :         status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
    8979           8 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
    8980             : 
    8981           8 :         status = smb2_util_write(tree, job_h, "exciting print job data", 0,
    8982             :                                  sizeof("exciting print job data"));
    8983           8 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
    8984             : 
    8985             :         /* check back end spoolss job was created */
    8986           8 :         torture_assert(tctx,
    8987             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    8988             :                                    &count, &info),
    8989             :                 "EnumJobs level 1 failed");
    8990             : 
    8991           8 :         for (i = 0; i < count; i++) {
    8992           0 :                 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
    8993           0 :                         break;
    8994             :                 }
    8995             :         }
    8996           8 :         torture_assert(tctx, (i != count), "smbd_spooler_job not found");
    8997             : 
    8998           0 :         status = smb2_util_close(tree, job_h);
    8999           0 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
    9000             : 
    9001             :         /* disconnect from printer share */
    9002           0 :         talloc_free(mem_ctx);
    9003             : 
    9004           0 :         return true;
    9005             : }
    9006             : 
    9007           8 : static bool test_print_test_purge(struct torture_context *tctx,
    9008             :                                   void *private_data)
    9009             : {
    9010           6 :         struct torture_printer_context *t =
    9011           2 :            (struct torture_printer_context *)talloc_get_type_abort(private_data,
    9012             :                                                 struct torture_printer_context);
    9013           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9014           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9015           8 :         uint32_t num_jobs = 8;
    9016             :         uint32_t *job_ids;
    9017             :         int i;
    9018           8 :         bool ret = true;
    9019             :         uint32_t count;
    9020             :         union spoolss_JobInfo *info;
    9021             : 
    9022           8 :         torture_assert(tctx,
    9023             :                 test_PausePrinter(tctx, b, &t->handle),
    9024             :                 "failed to pause printer");
    9025             : 
    9026           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    9027          72 :         for (i=0; i < num_jobs; i++) {
    9028          64 :                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
    9029             :                                                    "TorturePrintJob",
    9030          64 :                                                    &job_ids[i]);
    9031          64 :                 torture_assert(tctx, ret, "failed to add print job");
    9032             :         }
    9033             : 
    9034           8 :         torture_assert(tctx,
    9035             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9036             :                                    &count, &info),
    9037             :                 "EnumJobs level 1 failed");
    9038             : 
    9039           8 :         torture_assert_int_equal(tctx, count, num_jobs,
    9040             :                                  "unexpected number of jobs in queue");
    9041             : 
    9042           4 :         torture_assert(tctx,
    9043             :                 test_printer_purge(tctx, b, &t->handle),
    9044             :                 "failed to purge printer");
    9045             : 
    9046           4 :         torture_assert(tctx,
    9047             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9048             :                                    &count, &info),
    9049             :                 "EnumJobs level 1 failed");
    9050             : 
    9051           4 :         torture_assert_int_equal(tctx, count, 0,
    9052             :                                  "unexpected number of jobs in queue");
    9053             : 
    9054           4 :         torture_assert(tctx,
    9055             :                 test_ResumePrinter(tctx, b, &t->handle),
    9056             :                 "failed to resume printer");
    9057             : 
    9058           4 :         return true;
    9059             : }
    9060             : 
    9061           8 : static bool test_printer_sd(struct torture_context *tctx,
    9062             :                             void *private_data)
    9063             : {
    9064           6 :         struct torture_printer_context *t =
    9065           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9066           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9067           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9068             : 
    9069           8 :         torture_assert(tctx,
    9070             :                 test_PrinterInfo_SD(tctx, b, &t->handle),
    9071             :                 "failed to test security descriptors");
    9072             : 
    9073           8 :         return true;
    9074             : }
    9075             : 
    9076           8 : static bool test_printer_dm(struct torture_context *tctx,
    9077             :                             void *private_data)
    9078             : {
    9079           6 :         struct torture_printer_context *t =
    9080           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9081           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9082             : 
    9083           8 :         torture_assert(tctx,
    9084             :                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
    9085             :                 "failed to test devicemodes");
    9086             : 
    9087           8 :         return true;
    9088             : }
    9089             : 
    9090           8 : static bool test_printer_info_winreg(struct torture_context *tctx,
    9091             :                                      void *private_data)
    9092             : {
    9093           6 :         struct torture_printer_context *t =
    9094           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9095           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9096             : 
    9097           8 :         torture_assert(tctx,
    9098             :                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
    9099             :                 "failed to test printer info winreg");
    9100             : 
    9101           8 :         return true;
    9102             : }
    9103             : 
    9104           4 : static bool test_printserver_info_winreg(struct torture_context *tctx,
    9105             :                                          void *private_data)
    9106             : {
    9107           3 :         struct test_spoolss_context *t =
    9108           1 :                 (struct test_spoolss_context *)talloc_get_type_abort(private_data, struct test_spoolss_context);
    9109           4 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9110             : 
    9111           4 :         torture_assert(tctx,
    9112             :                 test_PrintserverInfo_winreg(tctx, p, &t->server_handle),
    9113             :                 "failed to test printserver info winreg");
    9114             : 
    9115           4 :         return true;
    9116             : }
    9117             : 
    9118             : 
    9119           8 : static bool test_printer_change_id(struct torture_context *tctx,
    9120             :                                    void *private_data)
    9121             : {
    9122           6 :         struct torture_printer_context *t =
    9123           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9124           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9125             : 
    9126           8 :         torture_assert(tctx,
    9127             :                 test_ChangeID(tctx, p, &t->handle),
    9128             :                 "failed to test change id");
    9129             : 
    9130           8 :         return true;
    9131             : }
    9132             : 
    9133           8 : static bool test_printer_keys(struct torture_context *tctx,
    9134             :                               void *private_data)
    9135             : {
    9136           6 :         struct torture_printer_context *t =
    9137           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9138           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9139           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9140             : 
    9141           8 :         torture_assert(tctx,
    9142             :                 test_printer_all_keys(tctx, b, &t->handle),
    9143             :                 "failed to test printer keys");
    9144             : 
    9145           8 :         return true;
    9146             : }
    9147             : 
    9148           8 : static bool test_printer_data_consistency(struct torture_context *tctx,
    9149             :                                           void *private_data)
    9150             : {
    9151           6 :         struct torture_printer_context *t =
    9152           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9153           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9154             : 
    9155           8 :         torture_assert(tctx,
    9156             :                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
    9157             :                 "failed to test printer data consistency");
    9158             : 
    9159           8 :         return true;
    9160             : }
    9161             : 
    9162           8 : static bool test_printer_data_keys(struct torture_context *tctx,
    9163             :                                    void *private_data)
    9164             : {
    9165           6 :         struct torture_printer_context *t =
    9166           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9167           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9168             : 
    9169           8 :         torture_assert(tctx,
    9170             :                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
    9171             :                 "failed to test printer data keys");
    9172             : 
    9173           8 :         return true;
    9174             : }
    9175             : 
    9176           8 : static bool test_printer_data_values(struct torture_context *tctx,
    9177             :                                      void *private_data)
    9178             : {
    9179           6 :         struct torture_printer_context *t =
    9180           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9181           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9182             : 
    9183           8 :         torture_assert(tctx,
    9184             :                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
    9185             :                 "failed to test printer data values");
    9186             : 
    9187           8 :         return true;
    9188             : }
    9189             : 
    9190           8 : static bool test_printer_data_set(struct torture_context *tctx,
    9191             :                                   void *private_data)
    9192             : {
    9193           6 :         struct torture_printer_context *t =
    9194           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9195           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9196             : 
    9197           8 :         torture_assert(tctx,
    9198             :                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
    9199             :                 "failed to test printer data set");
    9200             : 
    9201           8 :         return true;
    9202             : }
    9203             : 
    9204           8 : static bool test_printer_data_winreg(struct torture_context *tctx,
    9205             :                                      void *private_data)
    9206             : {
    9207           6 :         struct torture_printer_context *t =
    9208           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9209           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9210             : 
    9211           8 :         torture_assert(tctx,
    9212             :                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
    9213             :                 "failed to test printer data winreg");
    9214             : 
    9215           8 :         return true;
    9216             : }
    9217             : 
    9218           8 : static bool test_printer_data_dsspooler(struct torture_context *tctx,
    9219             :                                         void *private_data)
    9220             : {
    9221           6 :         struct torture_printer_context *t =
    9222           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9223           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9224             : 
    9225           8 :         torture_assert(tctx,
    9226             :                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
    9227             :                 "failed to test printer data winreg dsspooler");
    9228             : 
    9229           8 :         return true;
    9230             : }
    9231             : 
    9232           8 : static bool test_printer_ic(struct torture_context *tctx,
    9233             :                             void *private_data)
    9234             : {
    9235           6 :         struct torture_printer_context *t =
    9236           2 :                 talloc_get_type_abort(private_data,
    9237             :                                       struct torture_printer_context);
    9238           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9239           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9240             :         struct policy_handle gdi_handle;
    9241             : 
    9242           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    9243           8 :                 torture_skip(tctx, "skip printer information context tests against samba");
    9244             :         }
    9245             : 
    9246             :         {
    9247             :                 struct spoolss_CreatePrinterIC r;
    9248             :                 struct spoolss_DevmodeContainer devmode_ctr;
    9249             : 
    9250           0 :                 ZERO_STRUCT(devmode_ctr);
    9251             : 
    9252           0 :                 r.in.handle = &t->handle;
    9253           0 :                 r.in.devmode_ctr = &devmode_ctr;
    9254           0 :                 r.out.gdi_handle = &gdi_handle;
    9255             : 
    9256           0 :                 torture_assert_ntstatus_ok(tctx,
    9257             :                         dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
    9258             :                         "CreatePrinterIC failed");
    9259           0 :                 torture_assert_werr_ok(tctx, r.out.result,
    9260             :                         "CreatePrinterIC failed");
    9261             :         }
    9262             : 
    9263             :         {
    9264             :                 struct spoolss_PlayGDIScriptOnPrinterIC r;
    9265             :                 DATA_BLOB in,out;
    9266             :                 int i;
    9267           0 :                 uint32_t num_fonts = 0;
    9268             : 
    9269           0 :                 in = data_blob_string_const("");
    9270             : 
    9271           0 :                 r.in.gdi_handle = &gdi_handle;
    9272           0 :                 r.in.pIn = in.data;
    9273           0 :                 r.in.cIn = in.length;
    9274           0 :                 r.in.ul = 0;
    9275             : 
    9276           0 :                 for (i = 0; i < 4; i++) {
    9277             : 
    9278           0 :                         out = data_blob_talloc_zero(tctx, i);
    9279             : 
    9280           0 :                         r.in.cOut = out.length;
    9281           0 :                         r.out.pOut = out.data;
    9282             : 
    9283           0 :                         torture_assert_ntstatus_ok(tctx,
    9284             :                                 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9285             :                                 "PlayGDIScriptOnPrinterIC failed");
    9286           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_ENOUGH_MEMORY,
    9287             :                                 "PlayGDIScriptOnPrinterIC failed");
    9288             :                 }
    9289             : 
    9290           0 :                 out = data_blob_talloc_zero(tctx, 4);
    9291             : 
    9292           0 :                 r.in.cOut = out.length;
    9293           0 :                 r.out.pOut = out.data;
    9294             : 
    9295           0 :                 torture_assert_ntstatus_ok(tctx,
    9296             :                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9297             :                         "PlayGDIScriptOnPrinterIC failed");
    9298           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9299             :                         "PlayGDIScriptOnPrinterIC failed");
    9300             : 
    9301             :                 /* now we should have the required length, so retry with a
    9302             :                  * buffer which is large enough to carry all font ids */
    9303             : 
    9304           0 :                 num_fonts = IVAL(r.out.pOut, 0);
    9305             : 
    9306           0 :                 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
    9307             : 
    9308           0 :                 out = data_blob_talloc_zero(tctx,
    9309           0 :                         num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
    9310             : 
    9311           0 :                 r.in.cOut = out.length;
    9312           0 :                 r.out.pOut = out.data;
    9313             : 
    9314           0 :                 torture_assert_ntstatus_ok(tctx,
    9315             :                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9316             :                         "PlayGDIScriptOnPrinterIC failed");
    9317           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9318             :                         "PlayGDIScriptOnPrinterIC failed");
    9319             : 
    9320             :         }
    9321             : 
    9322             :         {
    9323             :                 struct spoolss_DeletePrinterIC r;
    9324             : 
    9325           0 :                 r.in.gdi_handle = &gdi_handle;
    9326           0 :                 r.out.gdi_handle = &gdi_handle;
    9327             : 
    9328           0 :                 torture_assert_ntstatus_ok(tctx,
    9329             :                         dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
    9330             :                         "DeletePrinterIC failed");
    9331           0 :                 torture_assert_werr_ok(tctx, r.out.result,
    9332             :                         "DeletePrinterIC failed");
    9333             : 
    9334             :         }
    9335             : 
    9336           0 :         return true;
    9337             : }
    9338             : 
    9339           8 : static bool test_printer_bidi(struct torture_context *tctx,
    9340             :                               void *private_data)
    9341             : {
    9342           6 :         struct torture_printer_context *t =
    9343           2 :                 talloc_get_type_abort(private_data,
    9344             :                                       struct torture_printer_context);
    9345           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9346           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9347             :         struct spoolss_SendRecvBidiData r;
    9348             :         struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
    9349           8 :         struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
    9350             : 
    9351           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    9352           8 :                 torture_skip(tctx, "skip printer bidirectional tests against samba");
    9353             :         }
    9354             : 
    9355           0 :         ZERO_STRUCT(bidi_req);
    9356             : 
    9357           0 :         r.in.hPrinter = t->handle;
    9358           0 :         r.in.pAction = "foobar";
    9359           0 :         r.in.pReqData = &bidi_req;
    9360           0 :         r.out.ppRespData = &bidi_rep;
    9361             : 
    9362           0 :         torture_assert_ntstatus_ok(tctx,
    9363             :                 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
    9364             :                 "SendRecvBidiData failed");
    9365           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
    9366             :                 "SendRecvBidiData failed");
    9367             : 
    9368           0 :         if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
    9369           0 :                 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
    9370             :         }
    9371             : 
    9372           0 :         r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
    9373             : 
    9374           0 :         torture_assert_ntstatus_ok(tctx,
    9375             :                 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
    9376             :                 "SendRecvBidiData failed");
    9377           0 :         torture_assert_werr_ok(tctx, r.out.result,
    9378             :                 "SendRecvBidiData failed");
    9379             : 
    9380           0 :         return true;
    9381             : }
    9382             : 
    9383           8 : static bool test_printer_set_publish(struct torture_context *tctx,
    9384             :                                        struct dcerpc_binding_handle *b,
    9385             :                                        struct policy_handle *handle)
    9386             : {
    9387             :         union spoolss_PrinterInfo info;
    9388             :         struct spoolss_SetPrinterInfo7 info7;
    9389             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    9390             :         struct spoolss_DevmodeContainer devmode_ctr;
    9391             :         struct sec_desc_buf secdesc_ctr;
    9392             : 
    9393           8 :         info7.guid = "";
    9394           8 :         info7.action = DSPRINT_PUBLISH;
    9395             : 
    9396           8 :         ZERO_STRUCT(info_ctr);
    9397           8 :         ZERO_STRUCT(devmode_ctr);
    9398           8 :         ZERO_STRUCT(secdesc_ctr);
    9399           8 :         info_ctr.level = 7;
    9400           8 :         info_ctr.info.info7 = &info7;
    9401             : 
    9402           8 :         torture_assert(tctx,
    9403             :                        test_SetPrinter(tctx, b, handle, &info_ctr,
    9404             :                                        &devmode_ctr, &secdesc_ctr, 0), "");
    9405             : 
    9406           0 :         torture_assert(tctx,
    9407             :                        test_GetPrinter_level(tctx, b, handle, 2, &info),
    9408             :                        "");
    9409           0 :         torture_assert(tctx,
    9410             :                        (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
    9411             :                        "info2 publish flag not set");
    9412           0 :         torture_assert(tctx,
    9413             :                        test_GetPrinter_level(tctx, b, handle, 7, &info),
    9414             :                        "");
    9415           0 :         if (info.info7.action & DSPRINT_PENDING) {
    9416           0 :                 torture_comment(tctx, "publish is pending\n");
    9417           0 :                 torture_assert_int_equal(tctx,
    9418             :                                          info.info7.action,
    9419             :                                          (DSPRINT_PENDING | DSPRINT_PUBLISH),
    9420             :                                          "info7 publish flag not set");
    9421             :         } else {
    9422             :                 struct GUID guid;
    9423             :                 char *ref_guid;
    9424           0 :                 torture_assert_int_equal(tctx,
    9425             :                                          info.info7.action,
    9426             :                                          DSPRINT_PUBLISH,
    9427             :                                          "info7 publish flag not set");
    9428             : 
    9429             :                 /* GUID_from_string is able to parse both plain and
    9430             :                  * curly-braced guids */
    9431           0 :                 torture_assert_ntstatus_ok(tctx,
    9432             :                                            GUID_from_string(info.info7.guid,
    9433             :                                            &guid),
    9434             :                                            "invalid published printer GUID");
    9435             : 
    9436             :                 /* Build reference GUID string */
    9437           0 :                 ref_guid = GUID_string2(tctx, &guid);
    9438           0 :                 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
    9439           0 :                 ref_guid = talloc_strdup_upper(tctx, ref_guid);
    9440           0 :                 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
    9441           0 :                 torture_assert_str_equal(tctx, info.info7.guid, ref_guid,
    9442             :                         "invalid GUID format");
    9443             :         }
    9444             : 
    9445           0 :         return true;
    9446             : }
    9447             : 
    9448           0 : static bool test_printer_set_unpublish(struct torture_context *tctx,
    9449             :                                        struct dcerpc_binding_handle *b,
    9450             :                                        struct policy_handle *handle)
    9451             : {
    9452             :         union spoolss_PrinterInfo info;
    9453             :         struct spoolss_SetPrinterInfo7 info7;
    9454             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    9455             :         struct spoolss_DevmodeContainer devmode_ctr;
    9456             :         struct sec_desc_buf secdesc_ctr;
    9457             : 
    9458           0 :         info7.action = DSPRINT_UNPUBLISH;
    9459           0 :         info7.guid = "";
    9460             : 
    9461           0 :         ZERO_STRUCT(info_ctr);
    9462           0 :         ZERO_STRUCT(devmode_ctr);
    9463           0 :         ZERO_STRUCT(secdesc_ctr);
    9464           0 :         info_ctr.level = 7;
    9465           0 :         info_ctr.info.info7 = &info7;
    9466             : 
    9467           0 :         torture_assert(tctx,
    9468             :                        test_SetPrinter(tctx, b, handle, &info_ctr,
    9469             :                                        &devmode_ctr, &secdesc_ctr, 0), "");
    9470             : 
    9471           0 :         torture_assert(tctx,
    9472             :                        test_GetPrinter_level(tctx, b, handle, 2, &info),
    9473             :                        "");
    9474           0 :         torture_assert(tctx,
    9475             :                        !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
    9476             :                        "info2 publish flag still set");
    9477           0 :         torture_assert(tctx,
    9478             :                        test_GetPrinter_level(tctx, b, handle, 7, &info),
    9479             :                        "");
    9480             : 
    9481           0 :         if (info.info7.action & DSPRINT_PENDING) {
    9482             :                 struct GUID guid;
    9483           0 :                 torture_comment(tctx, "unpublish is pending\n");
    9484           0 :                 torture_assert_int_equal(tctx,
    9485             :                                          info.info7.action,
    9486             :                                          (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
    9487             :                                          "info7 unpublish flag not set");
    9488           0 :                 torture_assert_ntstatus_ok(tctx,
    9489             :                                            GUID_from_string(info.info7.guid,
    9490             :                                            &guid),
    9491             :                                            "invalid printer GUID");
    9492             :         } else {
    9493           0 :                 torture_assert_int_equal(tctx,
    9494             :                                          info.info7.action, DSPRINT_UNPUBLISH,
    9495             :                                          "info7 unpublish flag not set");
    9496             :         }
    9497             : 
    9498           0 :         return true;
    9499             : }
    9500             : 
    9501           8 : static bool test_printer_publish_toggle(struct torture_context *tctx,
    9502             :                                            void *private_data)
    9503             : {
    9504           6 :         struct torture_printer_context *t =
    9505           2 :                 talloc_get_type_abort(private_data,
    9506             :                                       struct torture_printer_context);
    9507           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9508           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9509           8 :         struct policy_handle *handle = &t->handle;
    9510             :         union spoolss_PrinterInfo info7;
    9511             :         union spoolss_PrinterInfo info2;
    9512             : 
    9513             :         /* check publish status via level 7 and level 2 */
    9514           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
    9515             :                        "");
    9516           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
    9517             :                        "");
    9518             : 
    9519           8 :         if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
    9520           0 :                 torture_assert_int_equal(tctx,
    9521             :                                          info7.info7.action, DSPRINT_PUBLISH,
    9522             :                                          "info7 publish flag not set");
    9523           0 :                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
    9524           0 :                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
    9525             :         } else {
    9526           8 :                 torture_assert_int_equal(tctx,
    9527             :                                          info7.info7.action, DSPRINT_UNPUBLISH,
    9528             :                                          "info7 unpublish flag not set");
    9529           8 :                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
    9530           0 :                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
    9531             :         }
    9532             : 
    9533           0 :         return true;
    9534             : }
    9535             : 
    9536           8 : static bool test_driver_info_winreg(struct torture_context *tctx,
    9537             :                                     void *private_data)
    9538             : {
    9539           6 :         struct torture_printer_context *t =
    9540           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9541           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9542           8 :         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    9543             : 
    9544           8 :         if (!t->have_driver) {
    9545           8 :                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
    9546             :         }
    9547             : 
    9548           0 :         torture_assert(tctx,
    9549             :                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
    9550             :                 "failed to test driver info winreg");
    9551             : 
    9552           0 :         return true;
    9553             : }
    9554             : 
    9555           8 : static bool test_print_job_enum(struct torture_context *tctx,
    9556             :                                 void *private_data)
    9557             : {
    9558           6 :         struct torture_printer_context *t =
    9559           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9560           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9561           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9562           8 :         bool ret = true;
    9563           8 :         uint32_t num_jobs = 8;
    9564             :         uint32_t *job_ids;
    9565             :         int i;
    9566           8 :         union spoolss_JobInfo *info = NULL;
    9567             :         uint32_t count;
    9568             : 
    9569           8 :         torture_assert(tctx,
    9570             :                 test_PausePrinter(tctx, b, &t->handle),
    9571             :                 "failed to pause printer");
    9572             : 
    9573             :         /* purge in case of any jobs from previous tests */
    9574           8 :         torture_assert(tctx,
    9575             :                 test_printer_purge(tctx, b, &t->handle),
    9576             :                 "failed to purge printer");
    9577             : 
    9578             :         /* enum before jobs, valid level */
    9579           8 :         torture_assert(tctx,
    9580             :                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9581             :                                           &count, &info),
    9582             :                        "EnumJobs with valid level");
    9583           8 :         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
    9584           8 :         torture_assert(tctx,
    9585             :                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
    9586             :                                           &count, &info),
    9587             :                        "EnumJobs with valid level");
    9588           8 :         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
    9589             :         /* enum before jobs, invalid level - expect failure */
    9590           8 :         torture_assert(tctx,
    9591             :                        test_EnumJobs_args(tctx, b, &t->handle, 100,
    9592             :                                           WERR_INVALID_LEVEL,
    9593             :                                           &count, &info),
    9594             :                        "EnumJobs with invalid level");
    9595             : 
    9596           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    9597             : 
    9598          72 :         for (i = 0; i < num_jobs; i++) {
    9599          64 :                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
    9600             :                                                     "TorturePrintJob",
    9601          64 :                                                     &job_ids[i]);
    9602          64 :                 torture_assert(tctx, ret, "failed to add print job");
    9603             :         }
    9604             : 
    9605             :         /* enum after jobs, valid level */
    9606           8 :         torture_assert(tctx,
    9607             :                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9608             :                                           &count, &info),
    9609             :                        "EnumJobs with valid level");
    9610           8 :         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
    9611           4 :         torture_assert(tctx,
    9612             :                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
    9613             :                                           &count, &info),
    9614             :                        "EnumJobs with valid level");
    9615           4 :         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
    9616             :         /* enum after jobs, invalid level - expect failure */
    9617           4 :         torture_assert(tctx,
    9618             :                        test_EnumJobs_args(tctx, b, &t->handle, 100,
    9619             :                                           WERR_INVALID_LEVEL,
    9620             :                                           &count, &info),
    9621             :                        "EnumJobs with invalid level");
    9622             : 
    9623          36 :         for (i = 0; i < num_jobs; i++) {
    9624          32 :                 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
    9625             :                             SPOOLSS_JOB_CONTROL_DELETE);
    9626             :         }
    9627             : 
    9628           4 :         torture_assert(tctx,
    9629             :                 test_ResumePrinter(tctx, b, &t->handle),
    9630             :                 "failed to resume printer");
    9631             : 
    9632           4 :         return true;
    9633             : }
    9634             : 
    9635           8 : static bool test_printer_log_jobinfo(struct torture_context *tctx,
    9636             :                                      void *private_data)
    9637             : {
    9638           6 :         struct torture_printer_context *t =
    9639           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9640           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9641           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9642             :         struct spoolss_BranchOfficeJobDataContainer info;
    9643             :         int i;
    9644             : 
    9645             :         struct spoolss_LogJobInfoForBranchOffice r;
    9646             : 
    9647           8 :         torture_comment(tctx, "Testing LogJobInfoForBranchOffice\n");
    9648             : 
    9649           8 :         info.cJobDataEntries = 0;
    9650           8 :         info.JobData = NULL;
    9651             : 
    9652           8 :         r.in.hPrinter = &t->handle;
    9653           8 :         r.in.pBranchOfficeJobDataContainer = &info;
    9654             : 
    9655           8 :         torture_assert_ntstatus_ok(tctx,
    9656             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9657             :                 "LogJobInfoForBranchOffice failed");
    9658           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    9659             :                 "LogJobInfoForBranchOffice failed");
    9660             : 
    9661           0 :         info.cJobDataEntries = 1;
    9662           0 :         info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
    9663             : 
    9664           0 :         info.JobData[0].eEventType = kLogOfflineFileFull;
    9665           0 :         info.JobData[0].JobId = 42;
    9666           0 :         info.JobData[0].JobInfo.LogOfflineFileFull.pMachineName = talloc_strdup(tctx, "mthelena");
    9667             : 
    9668           0 :         torture_assert_ntstatus_ok(tctx,
    9669             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9670             :                 "LogJobInfoForBranchOffice failed");
    9671           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9672             :                 "LogJobInfoForBranchOffice failed");
    9673             : 
    9674           0 :         info.cJobDataEntries = 42;
    9675           0 :         info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
    9676             : 
    9677           0 :         for (i=0; i < info.cJobDataEntries; i++) {
    9678           0 :                 info.JobData[i].eEventType = kLogOfflineFileFull;
    9679           0 :                 info.JobData[i].JobId = i;
    9680           0 :                 info.JobData[i].JobInfo.LogOfflineFileFull.pMachineName = talloc_asprintf(tctx, "torture_%d", i);
    9681             :         }
    9682             : 
    9683           0 :         torture_assert_ntstatus_ok(tctx,
    9684             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9685             :                 "LogJobInfoForBranchOffice failed");
    9686           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9687             :                 "LogJobInfoForBranchOffice failed");
    9688             : 
    9689           0 :         return true;
    9690             : }
    9691             : 
    9692           8 : static bool test_printer_os_versions(struct torture_context *tctx,
    9693             :                                      void *private_data)
    9694             : {
    9695           6 :         struct torture_printer_context *t =
    9696           2 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9697           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9698           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9699             :         union spoolss_PrinterInfo info;
    9700             :         DATA_BLOB blob;
    9701             :         uint8_t *data;
    9702             :         uint32_t length;
    9703             :         struct spoolss_OSVersion osversion;
    9704             :         uint8_t os_major, os_minor;
    9705             :         uint16_t os_build;
    9706             :         struct policy_handle server_handle;
    9707             : 
    9708           8 :         torture_comment(tctx, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
    9709             : 
    9710           8 :         torture_assert(tctx,
    9711             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    9712             :                 "failed to get level 0 printer info");
    9713             : 
    9714           8 :         torture_assert(tctx,
    9715             :                 test_OpenPrinter_server(tctx, p, &server_handle),
    9716             :                 "failed to open printserver");
    9717             : 
    9718           8 :         torture_assert(tctx,
    9719             :                 test_GetPrinterData_checktype(tctx, b, &server_handle, "OSVersion",
    9720             :                                               NULL, NULL, &data, &length),
    9721             :                 "failed to fetch OSVersion printer data");
    9722             : 
    9723           8 :         test_ClosePrinter(tctx, b, &server_handle);
    9724             : 
    9725           8 :         blob = data_blob_const(data, length);
    9726             : 
    9727           8 :         torture_assert_ndr_success(tctx,
    9728             :                 ndr_pull_struct_blob(&blob, tctx, &osversion,
    9729             :                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion),
    9730             :                 "failed to pull OSVersion");
    9731             : 
    9732           8 :         os_major = CVAL(&info.info0.version, 0);
    9733           8 :         os_minor = CVAL(&info.info0.version, 1);
    9734           8 :         os_build = SVAL(&info.info0.version, 2);
    9735             : 
    9736           8 :         torture_assert_int_equal(tctx, os_major, osversion.major, "major");
    9737           8 :         torture_assert_int_equal(tctx, os_minor, osversion.minor, "minor");
    9738           8 :         torture_assert_int_equal(tctx, os_build, osversion.build, "build");
    9739             : 
    9740           8 :         return true;
    9741             : }
    9742             : 
    9743             : 
    9744        4710 : void torture_tcase_printer(struct torture_tcase *tcase)
    9745             : {
    9746        4710 :         torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
    9747        4710 :         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
    9748        4710 :         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
    9749        4710 :         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
    9750        4710 :         torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
    9751        4710 :         torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
    9752        4710 :         torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
    9753        4710 :         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
    9754        4710 :         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
    9755        4710 :         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
    9756        4710 :         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
    9757        4710 :         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
    9758        4710 :         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
    9759        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
    9760        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
    9761        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
    9762        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
    9763        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
    9764        4710 :         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
    9765        4710 :         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
    9766        4710 :         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
    9767        4710 :         torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
    9768        4710 :         torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
    9769        4710 :         torture_tcase_add_simple_test(tcase, "publish_toggle",
    9770             :                                       test_printer_publish_toggle);
    9771        4710 :         torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
    9772        4710 :         torture_tcase_add_simple_test(tcase, "log_jobinfo", test_printer_log_jobinfo);
    9773        4710 :         torture_tcase_add_simple_test(tcase, "os_versions", test_printer_os_versions);
    9774        4710 : }
    9775             : 
    9776        2355 : struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
    9777             : {
    9778        2355 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
    9779             :         struct torture_tcase *tcase;
    9780             : 
    9781        2355 :         tcase = torture_suite_add_tcase(suite, "addprinter");
    9782             : 
    9783        2355 :         torture_tcase_set_fixture(tcase,
    9784             :                                   torture_rpc_spoolss_printer_setup,
    9785             :                                   torture_rpc_spoolss_printer_teardown);
    9786             : 
    9787        2355 :         torture_tcase_printer(tcase);
    9788             : 
    9789        2355 :         tcase = torture_suite_add_tcase(suite, "addprinterex");
    9790             : 
    9791        2355 :         torture_tcase_set_fixture(tcase,
    9792             :                                   torture_rpc_spoolss_printerex_setup,
    9793             :                                   torture_rpc_spoolss_printer_teardown);
    9794             : 
    9795        2355 :         torture_tcase_printer(tcase);
    9796             : 
    9797        2355 :         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
    9798             : 
    9799        2355 :         torture_tcase_set_fixture(tcase,
    9800             :                                   torture_rpc_spoolss_printerwkn_setup,
    9801             :                                   torture_rpc_spoolss_printer_teardown);
    9802             : 
    9803        2355 :         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
    9804             : 
    9805        2355 :         torture_tcase_set_fixture(tcase,
    9806             :                                   torture_rpc_spoolss_printerexwkn_setup,
    9807             :                                   torture_rpc_spoolss_printer_teardown);
    9808             : 
    9809             : #if 0
    9810             :         /* test is not correct */
    9811             :         tcase = torture_suite_add_tcase(suite, "addprinterdm");
    9812             : 
    9813             :         torture_tcase_set_fixture(tcase,
    9814             :                                   torture_rpc_spoolss_printerdm_setup,
    9815             :                                   torture_rpc_spoolss_printer_teardown);
    9816             : 
    9817             :         torture_tcase_printer(tcase);
    9818             : #endif
    9819        2355 :         return suite;
    9820             : }
    9821             : 
    9822        2355 : struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
    9823             : {
    9824        2355 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
    9825        2355 :         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
    9826             : 
    9827        2355 :         to