LCOV - code coverage report
Current view: top level - source4/torture/rpc - spoolss.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 3060 5199 58.9 %
Date: 2024-04-21 15:09:00 Functions: 191 239 79.9 %

          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           0 :         NTSTATUS status;
     284           0 :         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           0 :         struct test_spoolss_context *ctx =
     306           4 :                 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           0 :         NTSTATUS status;
     310           0 :         struct spoolss_EnumPorts r;
     311           4 :         uint16_t levels[] = { 1, 2 };
     312           0 :         int i, j;
     313             : 
     314          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     315           8 :                 int level = levels[i];
     316           0 :                 DATA_BLOB blob;
     317           0 :                 uint32_t needed;
     318           0 :                 uint32_t count;
     319           0 :                 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           0 :         struct test_spoolss_context *ctx =
     388           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     389             : 
     390           0 :         NTSTATUS status;
     391           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     392           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     393           0 :         struct spoolss_GetPrintProcessorDirectory r;
     394           0 :         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           0 :         int i;
     415           0 :         uint32_t needed;
     416             : 
     417          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     418          20 :                 int level = levels[i].level;
     419           0 :                 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           0 :         struct test_spoolss_context *ctx =
     456           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
     457             : 
     458           0 :         NTSTATUS status;
     459           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
     460           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
     461           0 :         struct spoolss_GetPrinterDriverDirectory r;
     462           0 :         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           0 :         int i;
     483           0 :         uint32_t needed;
     484             : 
     485          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     486          20 :                 int level = levels[i].level;
     487           0 :                 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           0 :         struct spoolss_EnumPrinterDrivers r;
     529           0 :         uint32_t needed;
     530           0 :         uint32_t count;
     531           0 :         union spoolss_DriverInfo *info;
     532           0 :         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           0 :         uint32_t count;
     602           0 :         union spoolss_DriverInfo *info;
     603           0 :         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           0 :         struct test_spoolss_context *ctx =
     664           4 :                 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           0 :         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           0 :         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           0 :                 uint32_t count;
     694           0 :                 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           0 :         struct test_spoolss_context *ctx =
     801           4 :                 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           0 :         NTSTATUS status;
     805           0 :         struct spoolss_EnumMonitors r;
     806           4 :         uint16_t levels[] = { 1, 2 };
     807           0 :         int i, j;
     808             : 
     809          12 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
     810           8 :                 int level = levels[i];
     811           0 :                 DATA_BLOB blob;
     812           0 :                 uint32_t needed;
     813           0 :                 uint32_t count;
     814           0 :                 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           0 :         struct spoolss_EnumPrintProcessors r;
     886           0 :         DATA_BLOB blob;
     887           0 :         uint32_t needed;
     888           0 :         uint32_t count;
     889           0 :         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           0 :         struct test_spoolss_context *ctx =
     933           4 :                 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           0 :         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           0 :                 union spoolss_PrintProcessorInfo *info;
     947           0 :                 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           0 :         struct spoolss_EnumPrintProcessorDataTypes r;
     967           0 :         DATA_BLOB blob;
     968           0 :         uint32_t needed;
     969           0 :         uint32_t count;
     970           0 :         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           0 :         struct test_spoolss_context *ctx =
    1014           4 :                 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           0 :         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           0 :                 uint32_t count;
    1033           0 :                 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           0 :                 union spoolss_PrintProcessorInfo *info;
    1043           0 :                 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           0 :         struct test_spoolss_context *ctx =
    1064           4 :                 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           0 :         struct spoolss_EnumPrinters r;
    1068           0 :         NTSTATUS status;
    1069           4 :         uint16_t levels[] = { 0, 1, 2, 4, 5 };
    1070           0 :         int i, j;
    1071             : 
    1072          24 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1073          20 :                 int level = levels[i];
    1074           0 :                 DATA_BLOB blob;
    1075           0 :                 uint32_t needed;
    1076           0 :                 uint32_t count;
    1077           0 :                 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           0 :         struct spoolss_GetPrinter r;
    1204           0 :         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           0 :         int i;
    1255             : 
    1256         400 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    1257             : 
    1258           0 :                 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           0 :         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           0 :         struct spoolss_SetPrinter r;
    1307           0 :         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    1308           0 :         int i;
    1309             : 
    1310           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1311           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    1312           0 :         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           0 :                 struct spoolss_SetPrinterInfo0 info0;
    1337           0 :                 struct spoolss_SetPrinterInfo1 info1;
    1338           0 :                 struct spoolss_SetPrinterInfo2 info2;
    1339           0 :                 struct spoolss_SetPrinterInfo3 info3;
    1340           0 :                 struct spoolss_SetPrinterInfo4 info4;
    1341           0 :                 struct spoolss_SetPrinterInfo5 info5;
    1342           0 :                 struct spoolss_SetPrinterInfo6 info6;
    1343           0 :                 struct spoolss_SetPrinterInfo7 info7;
    1344           0 :                 struct spoolss_SetPrinterInfo8 info8;
    1345           0 :                 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           0 :                         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           0 :         NTSTATUS status;
    1478           0 :         struct spoolss_SetPrinter s;
    1479           0 :         struct spoolss_GetPrinter q;
    1480           0 :         struct spoolss_GetPrinter q0;
    1481           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1482           0 :         union spoolss_PrinterInfo info;
    1483           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    1484           0 :         struct sec_desc_buf secdesc_ctr;
    1485           0 :         uint32_t needed = 0;
    1486           0 :         DATA_BLOB blob = data_blob_null;
    1487           0 :         bool ret = true;
    1488           0 :         int i;
    1489             : 
    1490           0 :         uint32_t status_list[] = {
    1491             :                 /* these do not stick
    1492             :                 PRINTER_STATUS_PAUSED,
    1493             :                 PRINTER_STATUS_ERROR,
    1494             :                 PRINTER_STATUS_PENDING_DELETION, */
    1495             :                 PRINTER_STATUS_PAPER_JAM,
    1496             :                 PRINTER_STATUS_PAPER_OUT,
    1497             :                 PRINTER_STATUS_MANUAL_FEED,
    1498             :                 PRINTER_STATUS_PAPER_PROBLEM,
    1499             :                 PRINTER_STATUS_OFFLINE,
    1500             :                 PRINTER_STATUS_IO_ACTIVE,
    1501             :                 PRINTER_STATUS_BUSY,
    1502             :                 PRINTER_STATUS_PRINTING,
    1503             :                 PRINTER_STATUS_OUTPUT_BIN_FULL,
    1504             :                 PRINTER_STATUS_NOT_AVAILABLE,
    1505             :                 PRINTER_STATUS_WAITING,
    1506             :                 PRINTER_STATUS_PROCESSING,
    1507             :                 PRINTER_STATUS_INITIALIZING,
    1508             :                 PRINTER_STATUS_WARMING_UP,
    1509             :                 PRINTER_STATUS_TONER_LOW,
    1510             :                 PRINTER_STATUS_NO_TONER,
    1511             :                 PRINTER_STATUS_PAGE_PUNT,
    1512             :                 PRINTER_STATUS_USER_INTERVENTION,
    1513             :                 PRINTER_STATUS_OUT_OF_MEMORY,
    1514             :                 PRINTER_STATUS_DOOR_OPEN,
    1515             :                 PRINTER_STATUS_SERVER_UNKNOWN,
    1516             :                 PRINTER_STATUS_POWER_SAVE,
    1517             :                 /* these do not stick
    1518             :                 0x02000000,
    1519             :                 0x04000000,
    1520             :                 0x08000000,
    1521             :                 0x10000000,
    1522             :                 0x20000000,
    1523             :                 0x40000000,
    1524             :                 0x80000000 */
    1525             :         };
    1526           0 :         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
    1527           0 :         uint32_t attribute_list[] = {
    1528             :                 PRINTER_ATTRIBUTE_QUEUED,
    1529             :                 /* fails with WERR_INVALID_DATATYPE:
    1530             :                 PRINTER_ATTRIBUTE_DIRECT, */
    1531             :                 /* does not stick
    1532             :                 PRINTER_ATTRIBUTE_DEFAULT, */
    1533             :                 PRINTER_ATTRIBUTE_SHARED,
    1534             :                 /* does not stick
    1535             :                 PRINTER_ATTRIBUTE_NETWORK, */
    1536             :                 PRINTER_ATTRIBUTE_HIDDEN,
    1537             :                 PRINTER_ATTRIBUTE_LOCAL,
    1538             :                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
    1539             :                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
    1540             :                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
    1541             :                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
    1542             :                 /* does not stick
    1543             :                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
    1544             :                 /* fails with WERR_INVALID_DATATYPE:
    1545             :                 PRINTER_ATTRIBUTE_RAW_ONLY, */
    1546             :                 /* these do not stick
    1547             :                 PRINTER_ATTRIBUTE_PUBLISHED,
    1548             :                 PRINTER_ATTRIBUTE_FAX,
    1549             :                 PRINTER_ATTRIBUTE_TS,
    1550             :                 0x00010000,
    1551             :                 0x00020000,
    1552             :                 0x00040000,
    1553             :                 0x00080000,
    1554             :                 0x00100000,
    1555             :                 0x00200000,
    1556             :                 0x00400000,
    1557             :                 0x00800000,
    1558             :                 0x01000000,
    1559             :                 0x02000000,
    1560             :                 0x04000000,
    1561             :                 0x08000000,
    1562             :                 0x10000000,
    1563             :                 0x20000000,
    1564             :                 0x40000000,
    1565             :                 0x80000000 */
    1566             :         };
    1567             : 
    1568           0 :         torture_skip(tctx, "Printer Info test is currently broken, skipping");
    1569             : 
    1570             : 
    1571             :         ZERO_STRUCT(devmode_ctr);
    1572             :         ZERO_STRUCT(secdesc_ctr);
    1573             : 
    1574             :         s.in.handle = handle;
    1575             :         s.in.command = 0;
    1576             :         s.in.info_ctr = &info_ctr;
    1577             :         s.in.devmode_ctr = &devmode_ctr;
    1578             :         s.in.secdesc_ctr = &secdesc_ctr;
    1579             : 
    1580             :         q.in.handle = handle;
    1581             :         q.out.info = &info;
    1582             :         q0 = q;
    1583             : 
    1584             : #define TESTGETCALL(call, r, needed, blob) \
    1585             :                 r.in.buffer = NULL; \
    1586             :                 r.in.offered = 0;\
    1587             :                 r.out.needed = &needed; \
    1588             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1589             :                 if (!NT_STATUS_IS_OK(status)) { \
    1590             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1591             :                                r.in.level, nt_errstr(status), __location__); \
    1592             :                         ret = false; \
    1593             :                         break; \
    1594             :                 }\
    1595             :                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
    1596             :                         blob = data_blob_talloc_zero(tctx, needed); \
    1597             :                         r.in.buffer = &blob; \
    1598             :                         r.in.offered = needed; \
    1599             :                 }\
    1600             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1601             :                 if (!NT_STATUS_IS_OK(status)) { \
    1602             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1603             :                                r.in.level, nt_errstr(status), __location__); \
    1604             :                         ret = false; \
    1605             :                         break; \
    1606             :                 } \
    1607             :                 if (!W_ERROR_IS_OK(r.out.result)) { \
    1608             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1609             :                                r.in.level, win_errstr(r.out.result), __location__); \
    1610             :                         ret = false; \
    1611             :                         break; \
    1612             :                 }
    1613             : 
    1614             : 
    1615             : #define TESTSETCALL_EXP(call, r, err) \
    1616             :                 clear_info2(&info_ctr);\
    1617             :                 status = dcerpc_spoolss_ ##call## _r(b, tctx, &r); \
    1618             :                 if (!NT_STATUS_IS_OK(status)) { \
    1619             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1620             :                                r.in.info_ctr->level, nt_errstr(status), __location__); \
    1621             :                         ret = false; \
    1622             :                         break; \
    1623             :                 } \
    1624             :                 if (!W_ERROR_IS_OK(err)) { \
    1625             :                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
    1626             :                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
    1627             :                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
    1628             :                                 ret = false; \
    1629             :                         } \
    1630             :                         break; \
    1631             :                 } \
    1632             :                 if (!W_ERROR_IS_OK(r.out.result)) { \
    1633             :                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
    1634             :                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
    1635             :                         ret = false; \
    1636             :                         break; \
    1637             :                 }
    1638             : 
    1639             : #define TESTSETCALL(call, r) \
    1640             :         TESTSETCALL_EXP(call, r, WERR_OK)
    1641             : 
    1642             : #define STRING_EQUAL(s1, s2, field) \
    1643             :                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
    1644             :                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
    1645             :                                #field, s2, __location__); \
    1646             :                         ret = false; \
    1647             :                         break; \
    1648             :                 }
    1649             : 
    1650             : #define MEM_EQUAL(s1, s2, length, field) \
    1651             :                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
    1652             :                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
    1653             :                                #field, (const char *)s2, __location__); \
    1654             :                         ret = false; \
    1655             :                         break; \
    1656             :                 }
    1657             : 
    1658             : #define INT_EQUAL(i1, i2, field) \
    1659             :                 if (i1 != i2) { \
    1660             :                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
    1661             :                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
    1662             :                         ret = false; \
    1663             :                         break; \
    1664             :                 }
    1665             : 
    1666             : #define SD_EQUAL(sd1, sd2, field) \
    1667             :                 if (!security_descriptor_equal(sd1, sd2)) { \
    1668             :                         torture_comment(tctx, "Failed to set %s (%s)\n", \
    1669             :                                #field, __location__); \
    1670             :                         ret = false; \
    1671             :                         break; \
    1672             :                 }
    1673             : 
    1674             : #define TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, err) do { \
    1675             :                 void *p; \
    1676             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    1677             :                 q.in.level = lvl1; \
    1678             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1679             :                 info_ctr.level = lvl1; \
    1680             :                 p = (void *)&q.out.info->info ## lvl1; \
    1681             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1682             :                 info_ctr.info.info ## lvl1->field1 = value;\
    1683             :                 TESTSETCALL_EXP(SetPrinter, s, err) \
    1684             :                 info_ctr.info.info ## lvl1->field1 = ""; \
    1685             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1686             :                 info_ctr.info.info ## lvl1->field1 = value; \
    1687             :                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
    1688             :                 q.in.level = lvl2; \
    1689             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1690             :                 p = (void *)&q.out.info->info ## lvl2; \
    1691             :                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
    1692             :                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
    1693             :         } while (0)
    1694             : 
    1695             : #define TEST_PRINTERINFO_STRING(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
    1696             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, lvl1, field1, lvl2, field2, value, WERR_OK); \
    1697             :         } while (0);
    1698             : 
    1699             : #define TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value) do { \
    1700             :                 void *p; \
    1701             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    1702             :                 q.in.level = lvl1; \
    1703             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1704             :                 info_ctr.level = lvl1; \
    1705             :                 p = (void *)&q.out.info->info ## lvl1; \
    1706             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1707             :                 info_ctr.info.info ## lvl1->field1 = value; \
    1708             :                 TESTSETCALL(SetPrinter, s) \
    1709             :                 info_ctr.info.info ## lvl1->field1 = 0; \
    1710             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1711             :                 p = (void *)&q.out.info->info ## lvl1; \
    1712             :                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    1713             :                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
    1714             :                 q.in.level = lvl2; \
    1715             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    1716             :                 p = (void *)&q.out.info->info ## lvl2; \
    1717             :                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)p; \
    1718             :                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
    1719             :         } while (0)
    1720             : 
    1721             : #define TEST_PRINTERINFO_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
    1722             :         TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value); \
    1723             :         } while (0)
    1724             : 
    1725             :         q0.in.level = 0;
    1726             :         do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
    1727             : 
    1728             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, comment,  1, comment, "xx2-1 comment");
    1729             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, comment,  2, comment, "xx2-2 comment");
    1730             : 
    1731             :         /* level 0 printername does not stick */
    1732             : /*      TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername,  0, printername, "xx2-0 printer"); */
    1733             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername,  1, name,    "xx2-1 printer");
    1734             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername,  2, printername, "xx2-2 printer");
    1735             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername,  4, printername, "xx2-4 printer");
    1736             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, printername,  5, printername, "xx2-5 printer");
    1737             : /*      TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername,  0, printername, "xx4-0 printer"); */
    1738             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername,  1, name,    "xx4-1 printer");
    1739             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername,  2, printername, "xx4-2 printer");
    1740             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername,  4, printername, "xx4-4 printer");
    1741             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 4, printername,  5, printername, "xx4-5 printer");
    1742             : /*      TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername,  0, printername, "xx5-0 printer"); */
    1743             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername,  1, name,    "xx5-1 printer");
    1744             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername,  2, printername, "xx5-2 printer");
    1745             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername,  4, printername, "xx5-4 printer");
    1746             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 5, printername,  5, printername, "xx5-5 printer");
    1747             : 
    1748             :         /* servername can be set but does not stick
    1749             :         TEST_PRINTERINFO_STRING(q, 2, servername,  0, servername, "xx2-0 servername");
    1750             :         TEST_PRINTERINFO_STRING(q, 2, servername,  2, servername, "xx2-2 servername");
    1751             :         TEST_PRINTERINFO_STRING(q, 2, servername,  4, servername, "xx2-4 servername");
    1752             :         */
    1753             : 
    1754             :         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
    1755             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
    1756             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
    1757             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
    1758             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
    1759             : 
    1760             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, sharename,       2, sharename,   "xx2-2 sharename");
    1761             :         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
    1762             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, drivername,      2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
    1763             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, location,        2, location,    "xx2-2 location");
    1764             :         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
    1765             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, sepfile, 2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
    1766             :         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
    1767             :         TEST_PRINTERINFO_STRING_EXP_ERR(q, s, needed, blob, 2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
    1768             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, datatype,        2, datatype,    "xx2-2 datatype");
    1769             :         TEST_PRINTERINFO_STRING(q, s, needed, blob, 2, parameters,      2, parameters,  "xx2-2 parameters");
    1770             : 
    1771             :         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
    1772             : /*              TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 1, flags,
    1773             :                         attribute_list[i],
    1774             :                         (attribute_list[i] | default_attribute)
    1775             :                         ); */
    1776             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 2, attributes,
    1777             :                         attribute_list[i],
    1778             :                         (attribute_list[i] | default_attribute)
    1779             :                         );
    1780             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 4, attributes,
    1781             :                         attribute_list[i],
    1782             :                         (attribute_list[i] | default_attribute)
    1783             :                         );
    1784             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 2, attributes, 5, attributes,
    1785             :                         attribute_list[i],
    1786             :                         (attribute_list[i] | default_attribute)
    1787             :                         );
    1788             : /*              TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 1, flags,
    1789             :                         attribute_list[i],
    1790             :                         (attribute_list[i] | default_attribute)
    1791             :                         ); */
    1792             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 2, attributes,
    1793             :                         attribute_list[i],
    1794             :                         (attribute_list[i] | default_attribute)
    1795             :                         );
    1796             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 4, attributes,
    1797             :                         attribute_list[i],
    1798             :                         (attribute_list[i] | default_attribute)
    1799             :                         );
    1800             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 4, attributes, 5, attributes,
    1801             :                         attribute_list[i],
    1802             :                         (attribute_list[i] | default_attribute)
    1803             :                         );
    1804             : /*              TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 1, flags,
    1805             :                         attribute_list[i],
    1806             :                         (attribute_list[i] | default_attribute)
    1807             :                         ); */
    1808             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 2, attributes,
    1809             :                         attribute_list[i],
    1810             :                         (attribute_list[i] | default_attribute)
    1811             :                         );
    1812             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 4, attributes,
    1813             :                         attribute_list[i],
    1814             :                         (attribute_list[i] | default_attribute)
    1815             :                         );
    1816             :                 TEST_PRINTERINFO_INT_EXP(q, s, needed, blob, 5, attributes, 5, attributes,
    1817             :                         attribute_list[i],
    1818             :                         (attribute_list[i] | default_attribute)
    1819             :                         );
    1820             :         }
    1821             : 
    1822             :         for (i=0; i < ARRAY_SIZE(status_list); i++) {
    1823             :                 /* level 2 sets do not stick
    1824             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status,     0, status, status_list[i]);
    1825             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status,     2, status, status_list[i]);
    1826             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 2, status,     6, status, status_list[i]); */
    1827             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status,     0, status, status_list[i]);
    1828             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status,     2, status, status_list[i]);
    1829             :                 TEST_PRINTERINFO_INT(q, s, needed, blob, 6, status,     6, status, status_list[i]);
    1830             :         }
    1831             : 
    1832             :         /* priorities need to be between 0 and 99
    1833             :            passing an invalid priority will result in WERR_INVALID_PRIORITY */
    1834             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority,   2, priority, 0);
    1835             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority,   2, priority, 1);
    1836             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority,   2, priority, 99);
    1837             :         /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, priority,        2, priority, 100); */
    1838             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 0);
    1839             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 1);
    1840             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 99);
    1841             :         /* TEST_PRINTERINFO_INT(q, s, needed, blob, 2, defaultpriority,2, defaultpriority, 100); */
    1842             : 
    1843             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, starttime,  2, starttime, __LINE__);
    1844             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, untiltime,  2, untiltime, __LINE__);
    1845             : 
    1846             :         /* does not stick
    1847             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, cjobs,              2, cjobs, __LINE__);
    1848             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 2, averageppm, 2, averageppm, __LINE__); */
    1849             : 
    1850             :         /* does not stick
    1851             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
    1852             :         TEST_PRINTERINFO_INT(q, s, needed, blob, 5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
    1853             : 
    1854             :         /* FIXME: gd also test devmode and secdesc behavior */
    1855             : 
    1856             :         {
    1857             :                 /* verify composition of level 1 description field */
    1858             :                 const char *description;
    1859             :                 const char *tmp;
    1860             : 
    1861             :                 q0.in.level = 1;
    1862             :                 do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
    1863             : 
    1864             :                 description = talloc_strdup(tctx, q0.out.info->info1.description);
    1865             : 
    1866             :                 q0.in.level = 2;
    1867             :                 do { TESTGETCALL(GetPrinter, q0, needed, blob) } while (0);
    1868             : 
    1869             :                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
    1870             :                         q0.out.info->info2.printername,
    1871             :                         q0.out.info->info2.drivername,
    1872             :                         q0.out.info->info2.location);
    1873             : 
    1874             :                 do { STRING_EQUAL(description, tmp, "description")} while (0);
    1875             :         }
    1876             : 
    1877             :         return ret;
    1878             : }
    1879             : 
    1880         132 : static bool test_security_descriptor_equal(struct torture_context *tctx,
    1881             :                                            const struct security_descriptor *sd1,
    1882             :                                            const struct security_descriptor *sd2)
    1883             : {
    1884         132 :         if (sd1 == sd2) {
    1885           0 :                 return true;
    1886             :         }
    1887             : 
    1888         132 :         if (!sd1 || !sd2) {
    1889           0 :                 torture_comment(tctx, "%s\n", __location__);
    1890           0 :                 return false;
    1891             :         }
    1892             : 
    1893         132 :         torture_assert_int_equal(tctx, sd1->revision, sd2->revision, "revision mismatch");
    1894         132 :         torture_assert_int_equal(tctx, sd1->type, sd2->type, "type mismatch");
    1895             : 
    1896         132 :         torture_assert_sid_equal(tctx, sd1->owner_sid, sd2->owner_sid, "owner mismatch");
    1897         132 :         torture_assert_sid_equal(tctx, sd1->group_sid, sd2->group_sid, "group mismatch");
    1898             : 
    1899         132 :         if (!security_acl_equal(sd1->sacl, sd2->sacl)) {
    1900           0 :                 torture_comment(tctx, "%s: sacl mismatch\n", __location__);
    1901           0 :                 NDR_PRINT_DEBUG(security_acl, sd1->sacl);
    1902           0 :                 NDR_PRINT_DEBUG(security_acl, sd2->sacl);
    1903           0 :                 return false;
    1904             :         }
    1905         132 :         if (!security_acl_equal(sd1->dacl, sd2->dacl)) {
    1906           0 :                 torture_comment(tctx, "%s: dacl mismatch\n", __location__);
    1907           0 :                 NDR_PRINT_DEBUG(security_acl, sd1->dacl);
    1908           0 :                 NDR_PRINT_DEBUG(security_acl, sd2->dacl);
    1909           0 :                 return false;
    1910             :         }
    1911             : 
    1912         132 :         return true;
    1913             : }
    1914             : 
    1915         112 : static bool test_sd_set_level(struct torture_context *tctx,
    1916             :                               struct dcerpc_binding_handle *b,
    1917             :                               struct policy_handle *handle,
    1918             :                               uint32_t level,
    1919             :                               struct security_descriptor *sd)
    1920             : {
    1921           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1922           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    1923           0 :         struct sec_desc_buf secdesc_ctr;
    1924           0 :         union spoolss_SetPrinterInfo sinfo;
    1925           0 :         union spoolss_PrinterInfo info;
    1926           0 :         struct spoolss_SetPrinterInfo3 info3;
    1927             : 
    1928         112 :         ZERO_STRUCT(devmode_ctr);
    1929         112 :         ZERO_STRUCT(secdesc_ctr);
    1930             : 
    1931         112 :         switch (level) {
    1932          28 :         case 2: {
    1933          28 :                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1934          28 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    1935             : 
    1936          28 :                 info_ctr.level = 2;
    1937          28 :                 info_ctr.info = sinfo;
    1938             : 
    1939          28 :                 break;
    1940             :         }
    1941          84 :         case 3: {
    1942             : 
    1943          84 :                 info3.sec_desc_ptr = 0;
    1944             : 
    1945          84 :                 info_ctr.level = 3;
    1946          84 :                 info_ctr.info.info3 = &info3;
    1947             : 
    1948          84 :                 break;
    1949             :         }
    1950           0 :         default:
    1951           0 :                 return false;
    1952             :         }
    1953             : 
    1954         112 :         secdesc_ctr.sd = sd;
    1955             : 
    1956         112 :         torture_assert(tctx,
    1957             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0), "");
    1958             : 
    1959         112 :         return true;
    1960             : }
    1961             : 
    1962          28 : static bool test_PrinterInfo_SDs(struct torture_context *tctx,
    1963             :                                  struct dcerpc_binding_handle *b,
    1964             :                                  struct policy_handle *handle)
    1965             : {
    1966           0 :         union spoolss_PrinterInfo info;
    1967           0 :         struct security_descriptor *sd1, *sd2;
    1968           0 :         int i;
    1969             : 
    1970             :         /* just compare level 2 and level 3 */
    1971             : 
    1972          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1973             : 
    1974          28 :         sd1 = info.info2.secdesc;
    1975             : 
    1976          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 3, &info), "");
    1977             : 
    1978          28 :         sd2 = info.info3.secdesc;
    1979             : 
    1980          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    1981             :                 "SD level 2 != SD level 3");
    1982             : 
    1983             : 
    1984             :         /* query level 2, set level 2, query level 2 */
    1985             : 
    1986          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1987             : 
    1988          28 :         sd1 = info.info2.secdesc;
    1989             : 
    1990          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 2, sd1), "");
    1991             : 
    1992          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    1993             : 
    1994          28 :         sd2 = info.info2.secdesc;
    1995          28 :         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
    1996           0 :                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
    1997           0 :                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
    1998             :         }
    1999             : 
    2000          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2001             :                 "SD level 2 != SD level 2 after SD has been set via level 2");
    2002             : 
    2003             : 
    2004             :         /* query level 2, set level 3, query level 2 */
    2005             : 
    2006          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2007             : 
    2008          28 :         sd1 = info.info2.secdesc;
    2009             : 
    2010          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
    2011             : 
    2012          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2013             : 
    2014          28 :         sd2 = info.info2.secdesc;
    2015             : 
    2016          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2017             :                 "SD level 2 != SD level 2 after SD has been set via level 3");
    2018             : 
    2019             :         /* set modified sd level 3, query level 2 */
    2020             : 
    2021        2632 :         for (i=0; i < 93; i++) {
    2022        2604 :                 struct security_ace a = {};
    2023        2604 :                 const char *sid_string = talloc_asprintf(tctx, "S-1-5-32-9999%i", i);
    2024        2604 :                 a.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
    2025        2604 :                 a.flags = 0;
    2026        2604 :                 a.size = 0; /* autogenerated */
    2027        2604 :                 a.access_mask = 0;
    2028        2604 :                 a.trustee = *dom_sid_parse_talloc(tctx, sid_string);
    2029        2604 :                 torture_assert_ntstatus_ok(tctx, security_descriptor_dacl_add(sd1, &a), "");
    2030             :         }
    2031             : 
    2032          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd1), "");
    2033             : 
    2034          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2035          28 :         sd2 = info.info2.secdesc;
    2036             : 
    2037          28 :         if (sd1->type & SEC_DESC_DACL_DEFAULTED) {
    2038           0 :                 torture_comment(tctx, "removing SEC_DESC_DACL_DEFAULTED\n");
    2039           0 :                 sd1->type &= ~SEC_DESC_DACL_DEFAULTED;
    2040             :         }
    2041             : 
    2042          28 :         torture_assert(tctx, test_security_descriptor_equal(tctx, sd1, sd2),
    2043             :                 "modified SD level 2 != SD level 2 after SD has been set via level 3");
    2044             : 
    2045             : 
    2046          28 :         return true;
    2047             : }
    2048             : 
    2049             : /*
    2050             :  * wrapper call that saves original sd, runs tests, and restores sd
    2051             :  */
    2052             : 
    2053          28 : static bool test_PrinterInfo_SD(struct torture_context *tctx,
    2054             :                                 struct dcerpc_binding_handle *b,
    2055             :                                 struct policy_handle *handle)
    2056             : {
    2057           0 :         union spoolss_PrinterInfo info;
    2058           0 :         struct security_descriptor *sd;
    2059          28 :         bool ret = true;
    2060             : 
    2061          28 :         torture_comment(tctx, "Testing Printer Security Descriptors\n");
    2062             : 
    2063             :         /* save original sd */
    2064             : 
    2065          28 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    2066             :                 "failed to get initial security descriptor");
    2067             : 
    2068          28 :         sd = security_descriptor_copy(tctx, info.info2.secdesc);
    2069             : 
    2070             :         /* run tests */
    2071             : 
    2072          28 :         ret = test_PrinterInfo_SDs(tctx, b, handle);
    2073             : 
    2074             :         /* restore original sd */
    2075             : 
    2076          28 :         torture_assert(tctx, test_sd_set_level(tctx, b, handle, 3, sd),
    2077             :                 "failed to restore initial security descriptor");
    2078             : 
    2079          28 :         torture_comment(tctx, "Printer Security Descriptors test %s\n\n",
    2080             :                 ret ? "succeeded" : "failed");
    2081             : 
    2082             : 
    2083          28 :         return ret;
    2084             : }
    2085             : 
    2086          32 : static bool test_devmode_set_level(struct torture_context *tctx,
    2087             :                                    struct dcerpc_binding_handle *b,
    2088             :                                    struct policy_handle *handle,
    2089             :                                    uint32_t level,
    2090             :                                    struct spoolss_DeviceMode *devmode)
    2091             : {
    2092           0 :         struct spoolss_SetPrinterInfo8 info8;
    2093           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    2094           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    2095           0 :         struct sec_desc_buf secdesc_ctr;
    2096           0 :         union spoolss_SetPrinterInfo sinfo;
    2097             : 
    2098          32 :         ZERO_STRUCT(devmode_ctr);
    2099          32 :         ZERO_STRUCT(secdesc_ctr);
    2100             : 
    2101          32 :         switch (level) {
    2102           8 :         case 2: {
    2103           0 :                 union spoolss_PrinterInfo info;
    2104           8 :                 torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2105           8 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    2106             : 
    2107           8 :                 info_ctr.level = 2;
    2108           8 :                 info_ctr.info = sinfo;
    2109             : 
    2110           8 :                 break;
    2111             :         }
    2112          24 :         case 8: {
    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           0 :         struct spoolss_SetPrinter s;
    2189           0 :         struct spoolss_GetPrinter q;
    2190           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    2191           0 :         struct spoolss_SetPrinterInfo8 info8;
    2192           0 :         union spoolss_PrinterInfo info;
    2193           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    2194           0 :         struct sec_desc_buf secdesc_ctr;
    2195           8 :         uint32_t needed = 0;
    2196           8 :         DATA_BLOB blob = data_blob_null;
    2197           8 :         bool ret = true;
    2198           0 :         NTSTATUS status;
    2199             : 
    2200             : #define TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, exp_value, expected_result) do { \
    2201             :                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
    2202             :                 q.in.level = lvl1; \
    2203             :                 TESTGETCALL(GetPrinter, q, needed, blob) \
    2204             :                 info_ctr.level = lvl1; \
    2205             :                 if (lvl1 == 2) {\
    2206             :                         void *p = (void *)&q.out.info->info ## lvl1; \
    2207             :                         info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)p; \
    2208             :                 } else if (lvl1 == 8) {\
    2209             :                         info_ctr.info.info ## lvl1 = &info8; \
    2210             :                 }\
    2211             :                 devmode_ctr.devmode = q.out.info->info ## lvl1.devmode; \
    2212             :                 devmode_ctr.devmode->field1 = value; \
    2213             :                 TESTSETCALL_EXP(SetPrinter, s, expected_result) \
    2214             :                 if (W_ERROR_IS_OK(expected_result)) { \
    2215             :                         TESTGETCALL(GetPrinter, q, needed, blob) \
    2216             :                         INT_EQUAL(q.out.info->info ## lvl1.devmode->field1, exp_value, field1); \
    2217             :                         q.in.level = lvl2; \
    2218             :                         TESTGETCALL(GetPrinter, q, needed, blob) \
    2219             :                         INT_EQUAL(q.out.info->info ## lvl2.devmode->field2, exp_value, field1); \
    2220             :                 }\
    2221             :         } while (0)
    2222             : 
    2223             : #define TEST_DEVMODE_INT_EXP(q, s, needed, blob, lvl1, field1, lvl2, field2, value, expected_result) do { \
    2224             :         TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, expected_result); \
    2225             :         } while (0)
    2226             : 
    2227             : #define TEST_DEVMODE_INT(q, s, needed, blob, lvl1, field1, lvl2, field2, value) do { \
    2228             :         TEST_DEVMODE_INT_EXP_RESULT(q, s, needed, blob, lvl1, field1, lvl2, field2, value, value, WERR_OK); \
    2229             :         } while (0)
    2230             : 
    2231           8 :         ZERO_STRUCT(devmode_ctr);
    2232           8 :         ZERO_STRUCT(secdesc_ctr);
    2233           8 :         ZERO_STRUCT(info8);
    2234             : 
    2235           8 :         s.in.handle = handle;
    2236           8 :         s.in.command = 0;
    2237           8 :         s.in.info_ctr = &info_ctr;
    2238           8 :         s.in.devmode_ctr = &devmode_ctr;
    2239           8 :         s.in.secdesc_ctr = &secdesc_ctr;
    2240             : 
    2241           8 :         q.in.handle = handle;
    2242           8 :         q.out.info = &info;
    2243             : 
    2244             : #if 0
    2245             :         const char *devicename;/* [charset(UTF16)] */
    2246             :         enum spoolss_DeviceModeSpecVersion specversion;
    2247             :         uint16_t driverversion;
    2248             :         uint16_t __driverextra_length;/* [value(r->driverextra_data.length)] */
    2249             :         uint32_t fields;
    2250             : #endif
    2251           8 :         TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size,               8, size, __LINE__, WERR_INVALID_PARAMETER);
    2252           8 :         TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size,               8, size, 0, WERR_INVALID_PARAMETER);
    2253           8 :         TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size,               8, size, 0xffff, WERR_INVALID_PARAMETER);
    2254           8 :         TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size,               8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
    2255           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, size,           8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
    2256             : 
    2257           8 :         devmode_ctr.devmode->driverextra_data = data_blob_string_const("foobar");
    2258           8 :         torture_assert(tctx,
    2259             :                 test_devmode_set_level(tctx, b, handle, 8, devmode_ctr.devmode),
    2260             :                 "failed to set devmode");
    2261             : 
    2262           8 :         TEST_DEVMODE_INT_EXP(q, s, needed, blob, 8, size,               8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0), (devmode_ctr.devmode->__driverextra_length > 0 ) ? WERR_INVALID_PARAMETER : WERR_OK);
    2263           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, size,           8, size, ndr_size_spoolss_DeviceMode(devmode_ctr.devmode, 0) - devmode_ctr.devmode->__driverextra_length);
    2264             : 
    2265           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, orientation,    8, orientation, __LINE__);
    2266           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, papersize,              8, papersize, __LINE__);
    2267           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, paperlength,    8, paperlength, __LINE__);
    2268           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, paperwidth,             8, paperwidth, __LINE__);
    2269           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, scale,          8, scale, __LINE__);
    2270           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, copies,         8, copies, __LINE__);
    2271           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, defaultsource,  8, defaultsource, __LINE__);
    2272           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, printquality,   8, printquality, __LINE__);
    2273           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, color,          8, color, __LINE__);
    2274           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, duplex,         8, duplex, __LINE__);
    2275           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, yresolution,    8, yresolution, __LINE__);
    2276           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, ttoption,               8, ttoption, __LINE__);
    2277           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, collate,                8, collate, __LINE__);
    2278             : #if 0
    2279             :         const char *formname;/* [charset(UTF16)] */
    2280             : #endif
    2281           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, logpixels,              8, logpixels, __LINE__);
    2282           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, bitsperpel,             8, bitsperpel, __LINE__);
    2283           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, pelswidth,              8, pelswidth, __LINE__);
    2284           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, pelsheight,             8, pelsheight, __LINE__);
    2285           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, displayflags,   8, displayflags, __LINE__);
    2286           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, displayfrequency,       8, displayfrequency, __LINE__);
    2287           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, icmmethod,              8, icmmethod, __LINE__);
    2288           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, icmintent,              8, icmintent, __LINE__);
    2289           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, mediatype,              8, mediatype, __LINE__);
    2290           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, dithertype,             8, dithertype, __LINE__);
    2291           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, reserved1,              8, reserved1, __LINE__);
    2292           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, reserved2,              8, reserved2, __LINE__);
    2293           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, panningwidth,   8, panningwidth, __LINE__);
    2294           8 :         TEST_DEVMODE_INT(q, s, needed, blob, 8, panningheight,  8, panningheight, __LINE__);
    2295             : 
    2296           8 :         return ret;
    2297             : }
    2298             : 
    2299             : static bool call_OpenPrinterEx(struct torture_context *tctx,
    2300             :                                struct dcerpc_pipe *p,
    2301             :                                const char *name,
    2302             :                                struct spoolss_DeviceMode *devmode,
    2303             :                                struct policy_handle *handle);
    2304             : 
    2305           8 : static bool test_PrinterInfo_DevModes(struct torture_context *tctx,
    2306             :                                       struct dcerpc_pipe *p,
    2307             :                                       struct policy_handle *handle,
    2308             :                                       const char *name)
    2309             : {
    2310           0 :         union spoolss_PrinterInfo info;
    2311           0 :         struct spoolss_DeviceMode *devmode;
    2312           0 :         struct spoolss_DeviceMode *devmode2;
    2313           0 :         struct policy_handle handle_devmode;
    2314           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    2315             : 
    2316             :         /* simply compare level8 and level2 devmode */
    2317             : 
    2318           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2319             : 
    2320           8 :         devmode = info.info8.devmode;
    2321             : 
    2322           8 :         if (devmode && devmode->size == 0) {
    2323           0 :                 torture_fail(tctx,
    2324             :                         "devmode of zero size!");
    2325             :         }
    2326             : 
    2327           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2328             : 
    2329           8 :         devmode2 = info.info2.devmode;
    2330             : 
    2331           8 :         if (devmode2 && devmode2->size == 0) {
    2332           0 :                 torture_fail(tctx,
    2333             :                         "devmode of zero size!");
    2334             :         }
    2335             : 
    2336           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2337             :                 "DM level 8 != DM level 2");
    2338             : 
    2339             : 
    2340             :         /* set devicemode level 8 and see if it persists */
    2341             : 
    2342           8 :         devmode->copies = 93;
    2343           8 :         devmode->formname = talloc_strdup(tctx, "Legal");
    2344             : 
    2345           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode), "");
    2346             : 
    2347           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2348             : 
    2349           8 :         devmode2 = info.info8.devmode;
    2350             : 
    2351           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2352             :                 "modified DM level 8 != DM level 8 after DM has been set via level 8");
    2353             : 
    2354           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2355             : 
    2356           8 :         devmode2 = info.info2.devmode;
    2357             : 
    2358           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2359             :                 "modified DM level 8 != DM level 2");
    2360             : 
    2361             : 
    2362             :         /* set devicemode level 2 and see if it persists */
    2363             : 
    2364           8 :         devmode->copies = 39;
    2365           8 :         devmode->formname = talloc_strdup(tctx, "Executive");
    2366             : 
    2367           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 2, devmode), "");
    2368             : 
    2369           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info), "");
    2370             : 
    2371           8 :         devmode2 = info.info8.devmode;
    2372             : 
    2373           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2374             :                 "modified DM level 8 != DM level 8 after DM has been set via level 2");
    2375             : 
    2376           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info), "");
    2377             : 
    2378           8 :         devmode2 = info.info2.devmode;
    2379             : 
    2380           8 :         torture_assert(tctx, test_devicemode_equal(tctx, devmode, devmode2),
    2381             :                 "modified DM level 8 != DM level 2");
    2382             : 
    2383             : 
    2384             :         /* check every single bit in public part of devicemode */
    2385             : 
    2386           8 :         torture_assert(tctx, test_devicemode_full(tctx, b, handle),
    2387             :                 "failed to set every single devicemode component");
    2388             : 
    2389             : 
    2390             :         /* change formname upon open and see if it persists in getprinter calls */
    2391             : 
    2392           8 :         devmode->formname = talloc_strdup(tctx, "A4");
    2393           8 :         devmode->copies = 42;
    2394             : 
    2395           8 :         torture_assert(tctx, call_OpenPrinterEx(tctx, p, name, devmode, &handle_devmode),
    2396             :                 "failed to open printer handle");
    2397             : 
    2398           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 8, &info), "");
    2399             : 
    2400           8 :         devmode2 = info.info8.devmode;
    2401             : 
    2402           8 :         if (strequal(devmode->devicename, devmode2->devicename)) {
    2403           0 :                 torture_warning(tctx, "devicenames are the same\n");
    2404             :         } else {
    2405           8 :                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
    2406           8 :                 torture_comment(tctx, "devicename after level 8 get: %s\n", devmode2->devicename);
    2407             :         }
    2408             : 
    2409           8 :         if (strequal(devmode->formname, devmode2->formname)) {
    2410           0 :                 torture_warning(tctx, "formname are the same\n");
    2411             :         } else {
    2412           8 :                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
    2413           8 :                 torture_comment(tctx, "formname after level 8 get: %s\n", devmode2->formname);
    2414             :         }
    2415             : 
    2416           8 :         if (devmode->copies == devmode2->copies) {
    2417           0 :                 torture_warning(tctx, "copies are the same\n");
    2418             :         } else {
    2419           8 :                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
    2420           8 :                 torture_comment(tctx, "copies after level 8 get: %d\n", devmode2->copies);
    2421             :         }
    2422             : 
    2423           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, &handle_devmode, 2, &info), "");
    2424             : 
    2425           8 :         devmode2 = info.info2.devmode;
    2426             : 
    2427           8 :         if (strequal(devmode->devicename, devmode2->devicename)) {
    2428           0 :                 torture_warning(tctx, "devicenames are the same\n");
    2429             :         } else {
    2430           8 :                 torture_comment(tctx, "devicename passed in for open: %s\n", devmode->devicename);
    2431           8 :                 torture_comment(tctx, "devicename after level 2 get: %s\n", devmode2->devicename);
    2432             :         }
    2433             : 
    2434           8 :         if (strequal(devmode->formname, devmode2->formname)) {
    2435           0 :                 torture_warning(tctx, "formname is the same\n");
    2436             :         } else {
    2437           8 :                 torture_comment(tctx, "formname passed in for open: %s\n", devmode->formname);
    2438           8 :                 torture_comment(tctx, "formname after level 2 get: %s\n", devmode2->formname);
    2439             :         }
    2440             : 
    2441           8 :         if (devmode->copies == devmode2->copies) {
    2442           0 :                 torture_warning(tctx, "copies are the same\n");
    2443             :         } else {
    2444           8 :                 torture_comment(tctx, "copies passed in for open: %d\n", devmode->copies);
    2445           8 :                 torture_comment(tctx, "copies after level 2 get: %d\n", devmode2->copies);
    2446             :         }
    2447             : 
    2448           8 :         test_ClosePrinter(tctx, b, &handle_devmode);
    2449             : 
    2450           8 :         return true;
    2451             : }
    2452             : 
    2453             : /*
    2454             :  * wrapper call that saves original devmode, runs tests, and restores devmode
    2455             :  */
    2456             : 
    2457           8 : static bool test_PrinterInfo_DevMode(struct torture_context *tctx,
    2458             :                                      struct dcerpc_pipe *p,
    2459             :                                      struct policy_handle *handle,
    2460             :                                      const char *name,
    2461             :                                      struct spoolss_DeviceMode *addprinter_devmode)
    2462             : {
    2463           0 :         union spoolss_PrinterInfo info;
    2464           0 :         struct spoolss_DeviceMode *devmode;
    2465           8 :         bool ret = true;
    2466           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    2467             : 
    2468           8 :         torture_comment(tctx, "Testing Printer Devicemodes\n");
    2469             : 
    2470             :         /* save original devmode */
    2471             : 
    2472           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 8, &info),
    2473             :                 "failed to get initial global devicemode");
    2474             : 
    2475           8 :         devmode = info.info8.devmode;
    2476             : 
    2477           8 :         if (devmode && devmode->size == 0) {
    2478           0 :                 torture_fail(tctx,
    2479             :                         "devmode of zero size!");
    2480             :         }
    2481             : 
    2482           8 :         if (addprinter_devmode) {
    2483           0 :                 if (!test_devicemode_equal(tctx, devmode, addprinter_devmode)) {
    2484           0 :                         torture_warning(tctx, "current global DM is != DM provided in addprinter");
    2485             :                 }
    2486             :         }
    2487             : 
    2488             :         /* run tests */
    2489             : 
    2490           8 :         ret = test_PrinterInfo_DevModes(tctx, p, handle, name);
    2491             : 
    2492             :         /* restore original devmode */
    2493             : 
    2494           8 :         torture_assert(tctx, test_devmode_set_level(tctx, b, handle, 8, devmode),
    2495             :                 "failed to restore initial global device mode");
    2496             : 
    2497           8 :         torture_comment(tctx, "Printer Devicemodes test %s\n\n",
    2498             :                 ret ? "succeeded" : "failed");
    2499             : 
    2500             : 
    2501           8 :         return ret;
    2502             : }
    2503             : 
    2504         574 : bool test_ClosePrinter(struct torture_context *tctx,
    2505             :                        struct dcerpc_binding_handle *b,
    2506             :                        struct policy_handle *handle)
    2507             : {
    2508           0 :         NTSTATUS status;
    2509           0 :         struct spoolss_ClosePrinter r;
    2510             : 
    2511         574 :         r.in.handle = handle;
    2512         574 :         r.out.handle = handle;
    2513             : 
    2514         574 :         torture_comment(tctx, "Testing ClosePrinter\n");
    2515             : 
    2516         574 :         status = dcerpc_spoolss_ClosePrinter_r(b, tctx, &r);
    2517         574 :         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
    2518         574 :         torture_assert_werr_ok(tctx, r.out.result, "ClosePrinter failed");
    2519             : 
    2520         574 :         return true;
    2521             : }
    2522             : 
    2523        2520 : static bool test_GetForm_args(struct torture_context *tctx,
    2524             :                               struct dcerpc_binding_handle *b,
    2525             :                               struct policy_handle *handle,
    2526             :                               const char *form_name,
    2527             :                               uint32_t level,
    2528             :                               union spoolss_FormInfo *info_p)
    2529             : {
    2530           0 :         NTSTATUS status;
    2531           0 :         struct spoolss_GetForm r;
    2532           0 :         uint32_t needed;
    2533             : 
    2534        2520 :         r.in.handle = handle;
    2535        2520 :         r.in.form_name = form_name;
    2536        2520 :         r.in.level = level;
    2537        2520 :         r.in.buffer = NULL;
    2538        2520 :         r.in.offered = 0;
    2539        2520 :         r.out.needed = &needed;
    2540             : 
    2541        2520 :         torture_comment(tctx, "Testing GetForm(%s) level %d\n", form_name, r.in.level);
    2542             : 
    2543        2520 :         status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
    2544        2520 :         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
    2545             : 
    2546        2520 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    2547        2520 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    2548        2520 :                 r.in.buffer = &blob;
    2549        2520 :                 r.in.offered = needed;
    2550        2520 :                 status = dcerpc_spoolss_GetForm_r(b, tctx, &r);
    2551        2520 :                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
    2552             : 
    2553        2520 :                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
    2554             : 
    2555        2520 :                 torture_assert(tctx, r.out.info, "No form info returned");
    2556             :         }
    2557             : 
    2558        2520 :         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
    2559             : 
    2560        2520 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_FormInfo, r.out.info, r.in.level, needed, 4);
    2561             : 
    2562        2520 :         if (info_p) {
    2563         160 :                 *info_p = *r.out.info;
    2564             :         }
    2565             : 
    2566        2520 :         return true;
    2567             : }
    2568             : 
    2569        2360 : static bool test_GetForm(struct torture_context *tctx,
    2570             :                          struct dcerpc_binding_handle *b,
    2571             :                          struct policy_handle *handle,
    2572             :                          const char *form_name,
    2573             :                          uint32_t level)
    2574             : {
    2575        2360 :         return test_GetForm_args(tctx, b, handle, form_name, level, NULL);
    2576             : }
    2577             : 
    2578         288 : static bool test_EnumForms(struct torture_context *tctx,
    2579             :                            struct dcerpc_binding_handle *b,
    2580             :                            struct policy_handle *handle,
    2581             :                            bool print_server,
    2582             :                            uint32_t level,
    2583             :                            uint32_t *count_p,
    2584             :                            union spoolss_FormInfo **info_p)
    2585             : {
    2586           0 :         struct spoolss_EnumForms r;
    2587           0 :         uint32_t needed;
    2588           0 :         uint32_t count;
    2589           0 :         union spoolss_FormInfo *info;
    2590             : 
    2591         288 :         r.in.handle = handle;
    2592         288 :         r.in.level = level;
    2593         288 :         r.in.buffer = NULL;
    2594         288 :         r.in.offered = 0;
    2595         288 :         r.out.needed = &needed;
    2596         288 :         r.out.count = &count;
    2597         288 :         r.out.info = &info;
    2598             : 
    2599         288 :         torture_comment(tctx, "Testing EnumForms level %d\n", r.in.level);
    2600             : 
    2601         288 :         torture_assert_ntstatus_ok(tctx,
    2602             :                 dcerpc_spoolss_EnumForms_r(b, tctx, &r),
    2603             :                 "EnumForms failed");
    2604             : 
    2605         288 :         if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL))) {
    2606          24 :                 torture_skip(tctx, "EnumForms level 2 not supported");
    2607             :         }
    2608             : 
    2609         264 :         if (print_server && W_ERROR_EQUAL(r.out.result, WERR_INVALID_HANDLE)) {
    2610           0 :                 torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
    2611             :         }
    2612             : 
    2613         264 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    2614         264 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    2615         264 :                 r.in.buffer = &blob;
    2616         264 :                 r.in.offered = needed;
    2617             : 
    2618         264 :                 torture_assert_ntstatus_ok(tctx,
    2619             :                         dcerpc_spoolss_EnumForms_r(b, tctx, &r),
    2620             :                         "EnumForms failed");
    2621             : 
    2622         264 :                 torture_assert(tctx, info, "No forms returned");
    2623             :         }
    2624             : 
    2625         264 :         torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
    2626             : 
    2627         264 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumForms, info, r.in.level, count, needed, 4);
    2628             : 
    2629         264 :         if (info_p) {
    2630         264 :                 *info_p = info;
    2631             :         }
    2632         264 :         if (count_p) {
    2633         264 :                 *count_p = count;
    2634             :         }
    2635             : 
    2636         264 :         return true;
    2637             : }
    2638             : 
    2639          24 : static bool test_EnumForms_all(struct torture_context *tctx,
    2640             :                                struct dcerpc_binding_handle *b,
    2641             :                                struct policy_handle *handle,
    2642             :                                bool print_server)
    2643             : {
    2644          24 :         uint32_t levels[] = { 1, 2 };
    2645           0 :         int i, j;
    2646             : 
    2647          72 :         for (i=0; i<ARRAY_SIZE(levels); i++) {
    2648             : 
    2649          48 :                 uint32_t count = 0;
    2650          48 :                 union spoolss_FormInfo *info = NULL;
    2651             : 
    2652          48 :                 torture_assert(tctx,
    2653             :                         test_EnumForms(tctx, b, handle, print_server, levels[i], &count, &info),
    2654             :                         "failed to enum forms");
    2655             : 
    2656        2880 :                 for (j = 0; j < count; j++) {
    2657        2832 :                         if (!print_server) {
    2658        2360 :                                 torture_assert(tctx,
    2659             :                                         test_GetForm(tctx, b, handle, info[j].info1.form_name, levels[i]),
    2660             :                                         "failed to get form");
    2661             :                         }
    2662             :                 }
    2663             :         }
    2664             : 
    2665          24 :         return true;
    2666             : }
    2667             : 
    2668         240 : static bool test_EnumForms_find_one(struct torture_context *tctx,
    2669             :                                     struct dcerpc_binding_handle *b,
    2670             :                                     struct policy_handle *handle,
    2671             :                                     bool print_server,
    2672             :                                     const char *form_name)
    2673             : {
    2674         240 :         union spoolss_FormInfo *info = NULL;
    2675         240 :         uint32_t count = 0;
    2676         240 :         bool found = false;
    2677           0 :         int i;
    2678             : 
    2679         240 :         torture_assert(tctx,
    2680             :                 test_EnumForms(tctx, b, handle, print_server, 1, &count, &info),
    2681             :                 "failed to enumerate forms");
    2682             : 
    2683       11568 :         for (i=0; i<count; i++) {
    2684       11568 :                 if (strequal(form_name, info[i].info1.form_name)) {
    2685         240 :                         found = true;
    2686         240 :                         break;
    2687             :                 }
    2688             :         }
    2689             : 
    2690         240 :         return found;
    2691             : }
    2692             : 
    2693         288 : static bool test_DeleteForm(struct torture_context *tctx,
    2694             :                             struct dcerpc_binding_handle *b,
    2695             :                             struct policy_handle *handle,
    2696             :                             const char *form_name,
    2697             :                             WERROR expected_result)
    2698             : {
    2699           0 :         struct spoolss_DeleteForm r;
    2700             : 
    2701         288 :         r.in.handle = handle;
    2702         288 :         r.in.form_name = form_name;
    2703             : 
    2704         288 :         torture_comment(tctx, "Testing DeleteForm(%s)\n", form_name);
    2705             : 
    2706         288 :         torture_assert_ntstatus_ok(tctx,
    2707             :                 dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
    2708             :                 "DeleteForm failed");
    2709         288 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    2710             :                 "DeleteForm gave unexpected result");
    2711         288 :         if (W_ERROR_IS_OK(r.out.result)) {
    2712          96 :                 torture_assert_ntstatus_ok(tctx,
    2713             :                         dcerpc_spoolss_DeleteForm_r(b, tctx, &r),
    2714             :                         "2nd DeleteForm failed");
    2715          96 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_FORM_NAME,
    2716             :                         "2nd DeleteForm failed");
    2717             :         }
    2718             : 
    2719         288 :         return true;
    2720             : }
    2721             : 
    2722         288 : static bool test_AddForm(struct torture_context *tctx,
    2723             :                          struct dcerpc_binding_handle *b,
    2724             :                          struct policy_handle *handle,
    2725             :                          uint32_t level,
    2726             :                          union spoolss_AddFormInfo *info,
    2727             :                          WERROR expected_result)
    2728             : {
    2729           0 :         struct spoolss_AddForm r;
    2730           0 :         struct spoolss_AddFormInfoCtr info_ctr;
    2731             : 
    2732         288 :         info_ctr.level = level;
    2733         288 :         info_ctr.info = *info;
    2734             : 
    2735         288 :         if (level != 1) {
    2736           0 :                 torture_skip(tctx, "only level 1 supported");
    2737             :         }
    2738             : 
    2739         288 :         r.in.handle     = handle;
    2740         288 :         r.in.info_ctr   = &info_ctr;
    2741             : 
    2742         288 :         torture_comment(tctx, "Testing AddForm(%s) level %d, type %d\n",
    2743         288 :                 r.in.info_ctr->info.info1->form_name, level,
    2744         288 :                 r.in.info_ctr->info.info1->flags);
    2745             : 
    2746         288 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
    2747             :                 "AddForm failed");
    2748         288 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    2749             :                 "AddForm gave unexpected result");
    2750             : 
    2751         288 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_AddForm_r(b, tctx, &r),
    2752             :                 "2nd AddForm failed");
    2753         288 :         if (W_ERROR_EQUAL(expected_result, WERR_INVALID_PARAMETER)) {
    2754          48 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    2755             :                         "2nd AddForm gave unexpected result");
    2756             :         } else {
    2757         240 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_FILE_EXISTS,
    2758             :                         "2nd AddForm gave unexpected result");
    2759             :         }
    2760             : 
    2761         288 :         return true;
    2762             : }
    2763             : 
    2764          80 : static bool test_SetForm(struct torture_context *tctx,
    2765             :                          struct dcerpc_binding_handle *b,
    2766             :                          struct policy_handle *handle,
    2767             :                          const char *form_name,
    2768             :                          uint32_t level,
    2769             :                          union spoolss_AddFormInfo *info)
    2770             : {
    2771           0 :         struct spoolss_SetForm r;
    2772           0 :         struct spoolss_AddFormInfoCtr info_ctr;
    2773             : 
    2774          80 :         info_ctr.level  = level;
    2775          80 :         info_ctr.info   = *info;
    2776             : 
    2777          80 :         r.in.handle     = handle;
    2778          80 :         r.in.form_name  = form_name;
    2779          80 :         r.in.info_ctr   = &info_ctr;
    2780             : 
    2781          80 :         torture_comment(tctx, "Testing SetForm(%s) level %d\n",
    2782             :                 form_name, level);
    2783             : 
    2784          80 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetForm_r(b, tctx, &r),
    2785             :                 "SetForm failed");
    2786             : 
    2787          80 :         torture_assert_werr_ok(tctx, r.out.result,
    2788             :                 "SetForm failed");
    2789             : 
    2790          80 :         return true;
    2791             : }
    2792             : 
    2793             : static bool test_GetForm_winreg(struct torture_context *tctx,
    2794             :                                 struct dcerpc_binding_handle *b,
    2795             :                                 struct policy_handle *handle,
    2796             :                                 const char *key_name,
    2797             :                                 const char *form_name,
    2798             :                                 enum winreg_Type *w_type,
    2799             :                                 uint32_t *w_size,
    2800             :                                 uint32_t *w_length,
    2801             :                                 uint8_t **w_data);
    2802             : 
    2803         288 : static bool test_Forms_args(struct torture_context *tctx,
    2804             :                             struct dcerpc_binding_handle *b,
    2805             :                             struct policy_handle *handle,
    2806             :                             bool print_server,
    2807             :                             const char *printer_name,
    2808             :                             struct dcerpc_binding_handle *winreg_handle,
    2809             :                             struct policy_handle *hive_handle,
    2810             :                             const char *form_name,
    2811             :                             struct spoolss_AddFormInfo1 *info1,
    2812             :                             WERROR expected_add_result,
    2813             :                             WERROR expected_delete_result)
    2814             : {
    2815           0 :         union spoolss_FormInfo info;
    2816           0 :         union spoolss_AddFormInfo add_info;
    2817             : 
    2818           0 :         enum winreg_Type w_type;
    2819           0 :         uint32_t w_size;
    2820           0 :         uint32_t w_length;
    2821           0 :         uint8_t *w_data;
    2822             : 
    2823         288 :         add_info.info1 = info1;
    2824             : 
    2825         288 :         torture_assert(tctx,
    2826             :                 test_AddForm(tctx, b, handle, 1, &add_info, expected_add_result),
    2827             :                 "failed to add form");
    2828             : 
    2829         288 :         if (winreg_handle && hive_handle && W_ERROR_IS_OK(expected_add_result)) {
    2830             : 
    2831           0 :                 struct spoolss_FormInfo1 i1;
    2832             : 
    2833          48 :                 torture_assert(tctx,
    2834             :                         test_GetForm_winreg(tctx, winreg_handle, hive_handle, TOP_LEVEL_CONTROL_FORMS_KEY, form_name, &w_type, &w_size, &w_length, &w_data),
    2835             :                         "failed to get form via winreg");
    2836             : 
    2837          48 :                 i1.size.width   = IVAL(w_data, 0);
    2838          48 :                 i1.size.height  = IVAL(w_data, 4);
    2839          48 :                 i1.area.left    = IVAL(w_data, 8);
    2840          48 :                 i1.area.top     = IVAL(w_data, 12);
    2841          48 :                 i1.area.right   = IVAL(w_data, 16);
    2842          48 :                 i1.area.bottom  = IVAL(w_data, 20);
    2843             :                 /* skip index here */
    2844          48 :                 i1.flags        = IVAL(w_data, 28);
    2845             : 
    2846          48 :                 torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");
    2847          48 :                 torture_assert_int_equal(tctx, w_size, 0x20, "unexpected size");
    2848          48 :                 torture_assert_int_equal(tctx, w_length, 0x20, "unexpected length");
    2849          48 :                 torture_assert_int_equal(tctx, i1.size.width, add_info.info1->size.width, "width mismatch");
    2850          48 :                 torture_assert_int_equal(tctx, i1.size.height, add_info.info1->size.height, "height mismatch");
    2851          48 :                 torture_assert_int_equal(tctx, i1.area.left, add_info.info1->area.left, "left mismatch");
    2852          48 :                 torture_assert_int_equal(tctx, i1.area.top, add_info.info1->area.top, "top mismatch");
    2853          48 :                 torture_assert_int_equal(tctx, i1.area.right, add_info.info1->area.right, "right mismatch");
    2854          48 :                 torture_assert_int_equal(tctx, i1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
    2855          48 :                 torture_assert_int_equal(tctx, i1.flags, add_info.info1->flags, "flags mismatch");
    2856             :         }
    2857             : 
    2858         288 :         if (!print_server && W_ERROR_IS_OK(expected_add_result)) {
    2859          80 :                 torture_assert(tctx,
    2860             :                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
    2861             :                         "failed to get added form");
    2862             : 
    2863          80 :                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
    2864          80 :                 torture_assert_int_equal(tctx, info.info1.size.height, add_info.info1->size.height, "height mismatch");
    2865          80 :                 torture_assert_int_equal(tctx, info.info1.area.left, add_info.info1->area.left, "left mismatch");
    2866          80 :                 torture_assert_int_equal(tctx, info.info1.area.top, add_info.info1->area.top, "top mismatch");
    2867          80 :                 torture_assert_int_equal(tctx, info.info1.area.right, add_info.info1->area.right, "right mismatch");
    2868          80 :                 torture_assert_int_equal(tctx, info.info1.area.bottom, add_info.info1->area.bottom, "bottom mismatch");
    2869          80 :                 torture_assert_int_equal(tctx, info.info1.flags, add_info.info1->flags, "flags mismatch");
    2870             : 
    2871          80 :                 if (winreg_handle && hive_handle) {
    2872             : 
    2873           0 :                         struct spoolss_FormInfo1 i1;
    2874             : 
    2875          40 :                         i1.size.width   = IVAL(w_data, 0);
    2876          40 :                         i1.size.height  = IVAL(w_data, 4);
    2877          40 :                         i1.area.left    = IVAL(w_data, 8);
    2878          40 :                         i1.area.top     = IVAL(w_data, 12);
    2879          40 :                         i1.area.right   = IVAL(w_data, 16);
    2880          40 :                         i1.area.bottom  = IVAL(w_data, 20);
    2881             :                         /* skip index here */
    2882          40 :                         i1.flags        = IVAL(w_data, 28);
    2883             : 
    2884          40 :                         torture_assert_int_equal(tctx, i1.size.width, info.info1.size.width, "width mismatch");
    2885          40 :                         torture_assert_int_equal(tctx, i1.size.height, info.info1.size.height, "height mismatch");
    2886          40 :                         torture_assert_int_equal(tctx, i1.area.left, info.info1.area.left, "left mismatch");
    2887          40 :                         torture_assert_int_equal(tctx, i1.area.top, info.info1.area.top, "top mismatch");
    2888          40 :                         torture_assert_int_equal(tctx, i1.area.right, info.info1.area.right, "right mismatch");
    2889          40 :                         torture_assert_int_equal(tctx, i1.area.bottom, info.info1.area.bottom, "bottom mismatch");
    2890          40 :                         torture_assert_int_equal(tctx, i1.flags, info.info1.flags, "flags mismatch");
    2891             :                 }
    2892             : 
    2893          80 :                 add_info.info1->size.width = 1234;
    2894             : 
    2895          80 :                 torture_assert(tctx,
    2896             :                         test_SetForm(tctx, b, handle, form_name, 1, &add_info),
    2897             :                         "failed to set form");
    2898          80 :                 torture_assert(tctx,
    2899             :                         test_GetForm_args(tctx, b, handle, form_name, 1, &info),
    2900             :                         "failed to get set form");
    2901             : 
    2902          80 :                 torture_assert_int_equal(tctx, info.info1.size.width, add_info.info1->size.width, "width mismatch");
    2903             :         }
    2904             : 
    2905         288 :         if (!W_ERROR_EQUAL(expected_add_result, WERR_INVALID_PARAMETER)) {
    2906         240 :                 torture_assert(tctx,
    2907             :                         test_EnumForms_find_one(tctx, b, handle, print_server, form_name),
    2908             :                         "Newly added form not found in enum call");
    2909             :         }
    2910             : 
    2911         288 :         torture_assert(tctx,
    2912             :                 test_DeleteForm(tctx, b, handle, form_name, expected_delete_result),
    2913             :                 "failed to delete form");
    2914             : 
    2915         288 :         return true;
    2916             : }
    2917             : 
    2918          48 : static bool test_Forms(struct torture_context *tctx,
    2919             :                        struct dcerpc_binding_handle *b,
    2920             :                        struct policy_handle *handle,
    2921             :                        bool print_server,
    2922             :                        const char *printer_name,
    2923             :                        struct dcerpc_binding_handle *winreg_handle,
    2924             :                        struct policy_handle *hive_handle)
    2925             : {
    2926           0 :         const struct spoolss_FormSize size = {
    2927             :                 .width  = 50,
    2928             :                 .height = 25
    2929             :         };
    2930           0 :         const struct spoolss_FormArea area = {
    2931             :                 .left   = 5,
    2932             :                 .top    = 10,
    2933             :                 .right  = 45,
    2934             :                 .bottom = 15
    2935             :         };
    2936           0 :         int i;
    2937             : 
    2938           0 :         struct {
    2939             :                 struct spoolss_AddFormInfo1 info1;
    2940             :                 WERROR expected_add_result;
    2941             :                 WERROR expected_delete_result;
    2942          48 :         } forms[] = {
    2943             :                 {
    2944             :                         .info1 = {
    2945             :                                 .flags          = SPOOLSS_FORM_USER,
    2946             :                                 .form_name      = "testform_user",
    2947             :                                 .size           = size,
    2948             :                                 .area           = area,
    2949             :                         },
    2950             :                         .expected_add_result    = WERR_OK,
    2951             :                         .expected_delete_result = WERR_OK
    2952             :                 },
    2953             : /*
    2954             :                 weird, we can add a builtin form but we can never remove it
    2955             :                 again - gd
    2956             : 
    2957             :                 {
    2958             :                         .info1 = {
    2959             :                                 .flags          = SPOOLSS_FORM_BUILTIN,
    2960             :                                 .form_name      = "testform_builtin",
    2961             :                                 .size           = size,
    2962             :                                 .area           = area,
    2963             :                         },
    2964             :                         .expected_add_result    = WERR_OK,
    2965             :                         .expected_delete_result = WERR_INVALID_PARAMETER,
    2966             :                 },
    2967             : */
    2968             :                 {
    2969             :                         .info1 = {
    2970             :                                 .flags          = SPOOLSS_FORM_PRINTER,
    2971             :                                 .form_name      = "testform_printer",
    2972             :                                 .size           = size,
    2973             :                                 .area           = area,
    2974             :                         },
    2975             :                         .expected_add_result    = WERR_OK,
    2976             :                         .expected_delete_result = WERR_OK
    2977             :                 },
    2978             :                 {
    2979             :                         .info1 = {
    2980             :                                 .flags          = SPOOLSS_FORM_USER,
    2981             :                                 .form_name      = "Letter",
    2982             :                                 .size           = size,
    2983             :                                 .area           = area,
    2984             :                         },
    2985             :                         .expected_add_result    = WERR_FILE_EXISTS,
    2986             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    2987             :                 },
    2988             :                 {
    2989             :                         .info1 = {
    2990             :                                 .flags          = SPOOLSS_FORM_BUILTIN,
    2991             :                                 .form_name      = "Letter",
    2992             :                                 .size           = size,
    2993             :                                 .area           = area,
    2994             :                         },
    2995             :                         .expected_add_result    = WERR_FILE_EXISTS,
    2996             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    2997             :                 },
    2998             :                 {
    2999             :                         .info1 = {
    3000             :                                 .flags          = SPOOLSS_FORM_PRINTER,
    3001             :                                 .form_name      = "Letter",
    3002             :                                 .size           = size,
    3003             :                                 .area           = area,
    3004             :                         },
    3005             :                         .expected_add_result    = WERR_FILE_EXISTS,
    3006             :                         .expected_delete_result = WERR_INVALID_PARAMETER
    3007             :                 },
    3008             :                 {
    3009             :                         .info1 = {
    3010             :                                 .flags          = 12345,
    3011             :                                 .form_name      = "invalid_flags",
    3012             :                                 .size           = size,
    3013             :                                 .area           = area,
    3014             :                         },
    3015             :                         .expected_add_result    = WERR_INVALID_PARAMETER,
    3016             :                         .expected_delete_result = WERR_INVALID_FORM_NAME
    3017             :                 }
    3018             : 
    3019             :         };
    3020             : 
    3021         336 :         for (i=0; i < ARRAY_SIZE(forms); i++) {
    3022         288 :                 torture_assert(tctx,
    3023             :                         test_Forms_args(tctx, b, handle, print_server, printer_name,
    3024             :                                         winreg_handle, hive_handle,
    3025             :                                         forms[i].info1.form_name,
    3026             :                                         &forms[i].info1,
    3027             :                                         forms[i].expected_add_result,
    3028             :                                         forms[i].expected_delete_result),
    3029             :                         talloc_asprintf(tctx, "failed to test form '%s'", forms[i].info1.form_name));
    3030             :         }
    3031             : 
    3032          48 :         return true;
    3033             : }
    3034             : 
    3035           4 : static bool test_EnumPorts_old(struct torture_context *tctx,
    3036             :                                void *private_data)
    3037             : {
    3038           0 :         struct test_spoolss_context *ctx =
    3039           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    3040             : 
    3041           0 :         NTSTATUS status;
    3042           0 :         struct spoolss_EnumPorts r;
    3043           0 :         uint32_t needed;
    3044           0 :         uint32_t count;
    3045           0 :         union spoolss_PortInfo *info;
    3046           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    3047           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    3048             : 
    3049           4 :         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
    3050             :                                           dcerpc_server_name(p));
    3051           4 :         r.in.level = 2;
    3052           4 :         r.in.buffer = NULL;
    3053           4 :         r.in.offered = 0;
    3054           4 :         r.out.needed = &needed;
    3055           4 :         r.out.count = &count;
    3056           4 :         r.out.info = &info;
    3057             : 
    3058           4 :         torture_comment(tctx, "Testing EnumPorts\n");
    3059             : 
    3060           4 :         status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
    3061             : 
    3062           4 :         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
    3063             : 
    3064           4 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3065           4 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3066           4 :                 r.in.buffer = &blob;
    3067           4 :                 r.in.offered = needed;
    3068             : 
    3069           4 :                 status = dcerpc_spoolss_EnumPorts_r(b, tctx, &r);
    3070           4 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
    3071           4 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
    3072             : 
    3073           4 :                 torture_assert(tctx, info, "No ports returned");
    3074             :         }
    3075             : 
    3076           4 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
    3077             : 
    3078           4 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPorts, info, 2, count, needed, 4);
    3079             : 
    3080           4 :         return true;
    3081             : }
    3082             : 
    3083           4 : static bool test_AddPort(struct torture_context *tctx,
    3084             :                          void *private_data)
    3085             : {
    3086           0 :         struct test_spoolss_context *ctx =
    3087           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    3088             : 
    3089           0 :         NTSTATUS status;
    3090           0 :         struct spoolss_AddPort r;
    3091           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    3092           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    3093             : 
    3094           4 :         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
    3095             :                                            dcerpc_server_name(p));
    3096           4 :         r.in.unknown = 0;
    3097           4 :         r.in.monitor_name = "foo";
    3098             : 
    3099           4 :         torture_comment(tctx, "Testing AddPort\n");
    3100             : 
    3101           4 :         status = dcerpc_spoolss_AddPort_r(b, tctx, &r);
    3102             : 
    3103           4 :         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
    3104             : 
    3105             :         /* win2k3 returns WERR_NOT_SUPPORTED */
    3106             : 
    3107             : #if 0
    3108             : 
    3109             :         if (!W_ERROR_IS_OK(r.out.result)) {
    3110             :                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
    3111             :                 return false;
    3112             :         }
    3113             : 
    3114             : #endif
    3115             : 
    3116           4 :         return true;
    3117             : }
    3118             : 
    3119        1984 : static bool test_GetJob_args(struct torture_context *tctx,
    3120             :                              struct dcerpc_binding_handle *b,
    3121             :                              struct policy_handle *handle,
    3122             :                              uint32_t job_id,
    3123             :                              uint32_t level,
    3124             :                              union spoolss_JobInfo *info_p)
    3125             : {
    3126           0 :         NTSTATUS status;
    3127           0 :         struct spoolss_GetJob r;
    3128           0 :         union spoolss_JobInfo info;
    3129           0 :         uint32_t needed;
    3130             : 
    3131        1984 :         r.in.handle = handle;
    3132        1984 :         r.in.job_id = job_id;
    3133        1984 :         r.in.level = level;
    3134        1984 :         r.in.buffer = NULL;
    3135        1984 :         r.in.offered = 0;
    3136        1984 :         r.out.needed = &needed;
    3137        1984 :         r.out.info = &info;
    3138             : 
    3139        1984 :         torture_comment(tctx, "Testing GetJob(%d), level %d\n", job_id, r.in.level);
    3140             : 
    3141        1984 :         status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
    3142        1984 :         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
    3143        1984 :         if (level == 0) {
    3144           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "Unexpected return code");
    3145             :         }
    3146             : 
    3147        1984 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3148          64 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3149          64 :                 r.in.buffer = &blob;
    3150          64 :                 r.in.offered = needed;
    3151             : 
    3152          64 :                 status = dcerpc_spoolss_GetJob_r(b, tctx, &r);
    3153          64 :                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
    3154             :         }
    3155             : 
    3156        1984 :         torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
    3157          64 :         torture_assert(tctx, r.out.info, "No job info returned");
    3158             : 
    3159          64 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_JobInfo, r.out.info, r.in.level, needed, 4);
    3160             : 
    3161          64 :         if (info_p) {
    3162          64 :                 *info_p = *r.out.info;
    3163             :         }
    3164             : 
    3165          64 :         return true;
    3166             : }
    3167             : 
    3168             : #if 0
    3169             : static bool test_GetJob(struct torture_context *tctx,
    3170             :                         struct dcerpc_binding_handle *b,
    3171             :                         struct policy_handle *handle,
    3172             :                         uint32_t job_id)
    3173             : {
    3174             :         uint32_t levels[] = {0, 1, 2 /* 3, 4 */};
    3175             :         uint32_t i;
    3176             : 
    3177             :         for (i=0; i < ARRAY_SIZE(levels); i++) {
    3178             :                 torture_assert(tctx,
    3179             :                         test_GetJob_args(tctx, b, handle, job_id, levels[i], NULL),
    3180             :                         "GetJob failed");
    3181             :         }
    3182             : 
    3183             :         return true;
    3184             : }
    3185             : #endif
    3186             : 
    3187         640 : static bool test_SetJob(struct torture_context *tctx,
    3188             :                         struct dcerpc_binding_handle *b,
    3189             :                         struct policy_handle *handle,
    3190             :                         uint32_t job_id,
    3191             :                         struct spoolss_JobInfoContainer *ctr,
    3192             :                         enum spoolss_JobControl command)
    3193             : {
    3194           0 :         NTSTATUS status;
    3195           0 :         struct spoolss_SetJob r;
    3196             : 
    3197         640 :         r.in.handle     = handle;
    3198         640 :         r.in.job_id     = job_id;
    3199         640 :         r.in.ctr        = ctr;
    3200         640 :         r.in.command    = command;
    3201             : 
    3202         640 :         switch (command) {
    3203          32 :         case SPOOLSS_JOB_CONTROL_PAUSE:
    3204          32 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_PAUSE\n", job_id);
    3205          32 :                 break;
    3206          32 :         case SPOOLSS_JOB_CONTROL_RESUME:
    3207          32 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESUME\n", job_id);
    3208          32 :                 break;
    3209           0 :         case SPOOLSS_JOB_CONTROL_CANCEL:
    3210           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_CANCEL\n", job_id);
    3211           0 :                 break;
    3212           0 :         case SPOOLSS_JOB_CONTROL_RESTART:
    3213           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RESTART\n", job_id);
    3214           0 :                 break;
    3215         544 :         case SPOOLSS_JOB_CONTROL_DELETE:
    3216         544 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_DELETE\n", job_id);
    3217         544 :                 break;
    3218           0 :         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
    3219           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n", job_id);
    3220           0 :                 break;
    3221           0 :         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
    3222           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n", job_id);
    3223           0 :                 break;
    3224           0 :         case SPOOLSS_JOB_CONTROL_RETAIN:
    3225           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RETAIN\n", job_id);
    3226           0 :                 break;
    3227           0 :         case SPOOLSS_JOB_CONTROL_RELEASE:
    3228           0 :                 torture_comment(tctx, "Testing SetJob(%d), SPOOLSS_JOB_CONTROL_RELEASE\n", job_id);
    3229           0 :                 break;
    3230          32 :         default:
    3231          32 :                 torture_comment(tctx, "Testing SetJob(%d)\n", job_id);
    3232          32 :                 break;
    3233             :         }
    3234             : 
    3235         640 :         status = dcerpc_spoolss_SetJob_r(b, tctx, &r);
    3236         640 :         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
    3237         640 :         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
    3238             : 
    3239         402 :         return true;
    3240             : }
    3241             : 
    3242           8 : static bool test_AddJob(struct torture_context *tctx,
    3243             :                         struct dcerpc_binding_handle *b,
    3244             :                         struct policy_handle *handle)
    3245             : {
    3246           0 :         NTSTATUS status;
    3247           0 :         struct spoolss_AddJob r;
    3248           0 :         uint32_t needed;
    3249             : 
    3250           8 :         r.in.level = 0;
    3251           8 :         r.in.handle = handle;
    3252           8 :         r.in.offered = 0;
    3253           8 :         r.out.needed = &needed;
    3254           8 :         r.in.buffer = r.out.buffer = NULL;
    3255             : 
    3256           8 :         torture_comment(tctx, "Testing AddJob\n");
    3257             : 
    3258           8 :         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
    3259           8 :         torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
    3260           8 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_LEVEL, "AddJob failed");
    3261             : 
    3262           8 :         r.in.level = 1;
    3263             : 
    3264           8 :         status = dcerpc_spoolss_AddJob_r(b, tctx, &r);
    3265           8 :         torture_assert_ntstatus_ok(tctx, status, "AddJob failed");
    3266           8 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER, "AddJob failed");
    3267             : 
    3268           8 :         return true;
    3269             : }
    3270             : 
    3271             : 
    3272          68 : static bool test_EnumJobs_args(struct torture_context *tctx,
    3273             :                                struct dcerpc_binding_handle *b,
    3274             :                                struct policy_handle *handle,
    3275             :                                uint32_t level,
    3276             :                                WERROR werr_expected,
    3277             :                                uint32_t *count_p,
    3278             :                                union spoolss_JobInfo **info_p)
    3279             : {
    3280           0 :         NTSTATUS status;
    3281           0 :         struct spoolss_EnumJobs r;
    3282           0 :         uint32_t needed;
    3283           0 :         uint32_t count;
    3284           0 :         union spoolss_JobInfo *info;
    3285             : 
    3286          68 :         r.in.handle = handle;
    3287          68 :         r.in.firstjob = 0;
    3288          68 :         r.in.numjobs = 0xffffffff;
    3289          68 :         r.in.level = level;
    3290          68 :         r.in.buffer = NULL;
    3291          68 :         r.in.offered = 0;
    3292          68 :         r.out.needed = &needed;
    3293          68 :         r.out.count = &count;
    3294          68 :         r.out.info = &info;
    3295             : 
    3296          68 :         torture_comment(tctx, "Testing EnumJobs level %d\n", level);
    3297             : 
    3298          68 :         status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
    3299             : 
    3300          68 :         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
    3301             : 
    3302          68 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    3303          16 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    3304          16 :                 r.in.buffer = &blob;
    3305          16 :                 r.in.offered = needed;
    3306             : 
    3307          16 :                 status = dcerpc_spoolss_EnumJobs_r(b, tctx, &r);
    3308             : 
    3309          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
    3310          16 :                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
    3311             :                                           "EnumJobs failed");
    3312          16 :                 torture_assert(tctx, info, "No jobs returned");
    3313             : 
    3314          16 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumJobs, *r.out.info, r.in.level, count, needed, 4);
    3315             : 
    3316             :         } else {
    3317          52 :                 torture_assert_werr_equal(tctx, r.out.result, werr_expected,
    3318             :                                           "EnumJobs failed");
    3319             :         }
    3320             : 
    3321          68 :         if (count_p) {
    3322          68 :                 *count_p = count;
    3323             :         }
    3324          68 :         if (info_p) {
    3325          68 :                 *info_p = info;
    3326             :         }
    3327             : 
    3328          68 :         return true;
    3329             : }
    3330             : 
    3331           0 : static bool test_JobPropertiesEnum(struct torture_context *tctx,
    3332             :                                    struct dcerpc_binding_handle *b,
    3333             :                                    struct policy_handle *handle,
    3334             :                                    uint32_t job_id)
    3335             : {
    3336           0 :         struct spoolss_EnumJobNamedProperties r;
    3337           0 :         uint32_t pcProperties = 0;
    3338           0 :         struct spoolss_PrintNamedProperty *ppProperties = NULL;
    3339             : 
    3340           0 :         r.in.hPrinter = handle;
    3341           0 :         r.in.JobId = job_id;
    3342           0 :         r.out.pcProperties = &pcProperties;
    3343           0 :         r.out.ppProperties = &ppProperties;
    3344             : 
    3345           0 :         torture_comment(tctx, "Testing EnumJobNamedProperties(%d)\n", job_id);
    3346             : 
    3347           0 :         torture_assert_ntstatus_ok(tctx,
    3348             :                 dcerpc_spoolss_EnumJobNamedProperties_r(b, tctx, &r),
    3349             :                 "spoolss_EnumJobNamedProperties failed");
    3350           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3351             :                 "spoolss_EnumJobNamedProperties failed");
    3352             : 
    3353           0 :         return true;
    3354             : }
    3355             : 
    3356           0 : static bool test_JobPropertySet(struct torture_context *tctx,
    3357             :                                 struct dcerpc_binding_handle *b,
    3358             :                                 struct policy_handle *handle,
    3359             :                                 uint32_t job_id,
    3360             :                                 struct spoolss_PrintNamedProperty *property)
    3361             : {
    3362           0 :         struct spoolss_SetJobNamedProperty r;
    3363             : 
    3364           0 :         r.in.hPrinter = handle;
    3365           0 :         r.in.JobId = job_id;
    3366           0 :         r.in.pProperty = property;
    3367             : 
    3368           0 :         torture_comment(tctx, "Testing SetJobNamedProperty(%d) %s - %d\n",
    3369             :                 job_id, property->propertyName,
    3370           0 :                 property->propertyValue.ePropertyType);
    3371             : 
    3372           0 :         torture_assert_ntstatus_ok(tctx,
    3373             :                 dcerpc_spoolss_SetJobNamedProperty_r(b, tctx, &r),
    3374             :                 "spoolss_SetJobNamedProperty failed");
    3375           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3376             :                 "spoolss_SetJobNamedProperty failed");
    3377             : 
    3378           0 :         return true;
    3379             : }
    3380             : 
    3381           0 : static bool test_JobPropertyGetValue(struct torture_context *tctx,
    3382             :                                      struct dcerpc_binding_handle *b,
    3383             :                                      struct policy_handle *handle,
    3384             :                                      uint32_t job_id,
    3385             :                                      const char *property_name,
    3386             :                                      struct spoolss_PrintPropertyValue *value)
    3387             : {
    3388           0 :         struct spoolss_GetJobNamedPropertyValue r;
    3389             : 
    3390           0 :         r.in.hPrinter = handle;
    3391           0 :         r.in.JobId = job_id;
    3392           0 :         r.in.pszName = property_name;
    3393           0 :         r.out.pValue = value;
    3394             : 
    3395           0 :         torture_comment(tctx, "Testing GetJobNamedPropertyValue(%d) %s\n",
    3396             :                 job_id, property_name);
    3397             : 
    3398           0 :         torture_assert_ntstatus_ok(tctx,
    3399             :                 dcerpc_spoolss_GetJobNamedPropertyValue_r(b, tctx, &r),
    3400             :                 "spoolss_GetJobNamedPropertyValue failed");
    3401           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3402             :                 "spoolss_GetJobNamedPropertyValue failed");
    3403             : 
    3404           0 :         return true;
    3405             : }
    3406             : 
    3407           0 : static bool test_JobPropertyDelete(struct torture_context *tctx,
    3408             :                                    struct dcerpc_binding_handle *b,
    3409             :                                    struct policy_handle *handle,
    3410             :                                    uint32_t job_id,
    3411             :                                    const char *property_name)
    3412             : {
    3413           0 :         struct spoolss_DeleteJobNamedProperty r;
    3414             : 
    3415           0 :         r.in.hPrinter = handle;
    3416           0 :         r.in.JobId = job_id;
    3417           0 :         r.in.pszName = property_name;
    3418             : 
    3419           0 :         torture_comment(tctx, "Testing DeleteJobNamedProperty(%d) %s\n",
    3420             :                 job_id, property_name);
    3421             : 
    3422           0 :         torture_assert_ntstatus_ok(tctx,
    3423             :                 dcerpc_spoolss_DeleteJobNamedProperty_r(b, tctx, &r),
    3424             :                 "spoolss_DeleteJobNamedProperty failed");
    3425           0 :         torture_assert_werr_ok(tctx, r.out.result,
    3426             :                 "spoolss_DeleteJobNamedProperty failed");
    3427             : 
    3428           0 :         return true;
    3429             : }
    3430             : 
    3431         640 : static bool test_DoPrintTest_add_one_job_common(struct torture_context *tctx,
    3432             :                                          struct dcerpc_binding_handle *b,
    3433             :                                          struct policy_handle *handle,
    3434             :                                          const char *document_name,
    3435             :                                          const char *datatype,
    3436             :                                          uint32_t *job_id)
    3437             : {
    3438           0 :         NTSTATUS status;
    3439           0 :         struct spoolss_StartDocPrinter s;
    3440           0 :         struct spoolss_DocumentInfoCtr info_ctr;
    3441           0 :         struct spoolss_DocumentInfo1 info1;
    3442           0 :         struct spoolss_StartPagePrinter sp;
    3443           0 :         struct spoolss_WritePrinter w;
    3444           0 :         struct spoolss_EndPagePrinter ep;
    3445           0 :         struct spoolss_EndDocPrinter e;
    3446           0 :         int i;
    3447           0 :         uint32_t num_written;
    3448             : 
    3449         640 :         torture_comment(tctx, "Testing StartDocPrinter\n");
    3450             : 
    3451         640 :         s.in.handle             = handle;
    3452         640 :         s.in.info_ctr           = &info_ctr;
    3453         640 :         s.out.job_id            = job_id;
    3454             : 
    3455         640 :         info1.document_name     = document_name;
    3456         640 :         info1.output_file       = NULL;
    3457         640 :         info1.datatype          = datatype;
    3458             : 
    3459         640 :         info_ctr.level          = 1;
    3460         640 :         info_ctr.info.info1     = &info1;
    3461             : 
    3462         640 :         status = dcerpc_spoolss_StartDocPrinter_r(b, tctx, &s);
    3463         640 :         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
    3464         640 :         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
    3465             : 
    3466        2560 :         for (i=1; i < 4; i++) {
    3467           0 :                 union spoolss_JobInfo ginfo;
    3468           0 :                 bool ok;
    3469             : 
    3470        1920 :                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3471             : 
    3472        1920 :                 sp.in.handle            = handle;
    3473             : 
    3474        1920 :                 status = dcerpc_spoolss_StartPagePrinter_r(b, tctx, &sp);
    3475        1920 :                 torture_assert_ntstatus_ok(tctx, status,
    3476             :                                            "dcerpc_spoolss_StartPagePrinter failed");
    3477        1920 :                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
    3478             : 
    3479        1920 :                 ok = test_GetJob_args(tctx, b, handle, *job_id, 1, &ginfo);
    3480        1920 :                 if (!ok) {
    3481        1920 :                         torture_comment(tctx, "test_GetJob failed for JobId[%d]\n", *job_id);
    3482             :                 }
    3483             : 
    3484        1920 :                 torture_comment(tctx, "Testing WritePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3485             : 
    3486        1920 :                 w.in.handle             = handle;
    3487        1920 :                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
    3488        1920 :                 w.out.num_written       = &num_written;
    3489             : 
    3490        1920 :                 status = dcerpc_spoolss_WritePrinter_r(b, tctx, &w);
    3491        1920 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
    3492        1920 :                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
    3493             : 
    3494        1920 :                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d], JobId[%d]\n", i, *job_id);
    3495             : 
    3496        1920 :                 ep.in.handle            = handle;
    3497             : 
    3498        1920 :                 status = dcerpc_spoolss_EndPagePrinter_r(b, tctx, &ep);
    3499        1920 :                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
    3500        1920 :                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
    3501             :         }
    3502             : 
    3503         640 :         torture_comment(tctx, "Testing EndDocPrinter: JobId[%d]\n", *job_id);
    3504             : 
    3505         640 :         e.in.handle = handle;
    3506             : 
    3507         640 :         status = dcerpc_spoolss_EndDocPrinter_r(b, tctx, &e);
    3508         640 :         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
    3509         640 :         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
    3510             : 
    3511         352 :         return true;
    3512             : }
    3513             : 
    3514         416 : static bool test_DoPrintTest_add_one_job(struct torture_context *tctx,
    3515             :                                          struct dcerpc_binding_handle *b,
    3516             :                                          struct policy_handle *handle,
    3517             :                                          const char *document_name,
    3518             :                                          uint32_t *job_id)
    3519             : {
    3520         416 :         test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "RAW", job_id);
    3521             : 
    3522         416 :         return true;
    3523             : }
    3524             : 
    3525         224 : static bool test_DoPrintTest_add_one_job_v4(struct torture_context *tctx,
    3526             :                                          struct dcerpc_binding_handle *b,
    3527             :                                          struct policy_handle *handle,
    3528             :                                          const char *document_name,
    3529             :                                          uint32_t *job_id)
    3530             : {
    3531         224 :         test_DoPrintTest_add_one_job_common(tctx, b, handle, document_name, "XPS_PASS", job_id);
    3532             : 
    3533         224 :         return true;
    3534             : }
    3535             : 
    3536             : 
    3537           8 : static bool test_DoPrintTest_check_jobs(struct torture_context *tctx,
    3538             :                                         struct dcerpc_binding_handle *b,
    3539             :                                         struct policy_handle *handle,
    3540             :                                         uint32_t num_jobs,
    3541             :                                         uint32_t *job_ids)
    3542             : {
    3543           0 :         uint32_t count;
    3544           8 :         union spoolss_JobInfo *info = NULL;
    3545           0 :         int i;
    3546             : 
    3547           8 :         torture_assert(tctx,
    3548             :                 test_AddJob(tctx, b, handle),
    3549             :                 "AddJob failed");
    3550             : 
    3551           8 :         torture_assert(tctx,
    3552             :                 test_EnumJobs_args(tctx, b, handle, 1, WERR_OK, &count, &info),
    3553             :                 "EnumJobs level 1 failed");
    3554             : 
    3555           8 :         torture_assert_int_equal(tctx, count, num_jobs, "unexpected number of jobs in queue");
    3556             : 
    3557          36 :         for (i=0; i < num_jobs; i++) {
    3558           0 :                 union spoolss_JobInfo ginfo;
    3559           0 :                 const char *document_name;
    3560          32 :                 const char *new_document_name = "any_other_docname";
    3561           0 :                 struct spoolss_JobInfoContainer ctr;
    3562           0 :                 struct spoolss_SetJobInfo1 info1;
    3563             : 
    3564          32 :                 torture_assert_int_equal(tctx, info[i].info1.job_id, job_ids[i], "job id mismatch");
    3565             : 
    3566          32 :                 torture_assert(tctx,
    3567             :                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
    3568             :                         "failed to call test_GetJob");
    3569             : 
    3570          32 :                 torture_assert_int_equal(tctx, ginfo.info1.job_id, info[i].info1.job_id, "job id mismatch");
    3571             : 
    3572          32 :                 document_name = ginfo.info1.document_name;
    3573             : 
    3574          32 :                 info1.job_id            = ginfo.info1.job_id;
    3575          32 :                 info1.printer_name      = ginfo.info1.printer_name;
    3576          32 :                 info1.server_name       = ginfo.info1.server_name;
    3577          32 :                 info1.user_name         = ginfo.info1.user_name;
    3578          32 :                 info1.document_name     = new_document_name;
    3579          32 :                 info1.data_type         = ginfo.info1.data_type;
    3580          32 :                 info1.text_status       = ginfo.info1.text_status;
    3581          32 :                 info1.status            = ginfo.info1.status;
    3582          32 :                 info1.priority          = ginfo.info1.priority;
    3583          32 :                 info1.position          = ginfo.info1.position;
    3584          32 :                 info1.total_pages       = ginfo.info1.total_pages;
    3585          32 :                 info1.pages_printed     = ginfo.info1.pages_printed;
    3586          32 :                 info1.submitted         = ginfo.info1.submitted;
    3587             : 
    3588          32 :                 ctr.level = 1;
    3589          32 :                 ctr.info.info1 = &info1;
    3590             : 
    3591          32 :                 torture_assert(tctx,
    3592             :                         test_SetJob(tctx, b, handle, info[i].info1.job_id, &ctr, 0),
    3593             :                         "failed to call test_SetJob level 1");
    3594             : 
    3595          32 :                 torture_assert(tctx,
    3596             :                         test_GetJob_args(tctx, b, handle, info[i].info1.job_id, 1, &ginfo),
    3597             :                         "failed to call test_GetJob");
    3598             : 
    3599          32 :                 if (strequal(ginfo.info1.document_name, document_name)) {
    3600          22 :                         torture_warning(tctx,
    3601             :                                         "document_name did *NOT* change from '%s' to '%s'\n",
    3602             :                                         document_name, new_document_name);
    3603             :                 }
    3604             :         }
    3605             : 
    3606          36 :         for (i=0; i < num_jobs; i++) {
    3607          32 :                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_PAUSE)) {
    3608           0 :                         torture_warning(tctx, "failed to pause printjob\n");
    3609             :                 }
    3610          32 :                 if (!test_SetJob(tctx, b, handle, info[i].info1.job_id, NULL, SPOOLSS_JOB_CONTROL_RESUME)) {
    3611           0 :                         torture_warning(tctx, "failed to resume printjob\n");
    3612             :                 }
    3613             :         }
    3614             : 
    3615           4 :         return true;
    3616             : }
    3617             : 
    3618          28 : static bool test_DoPrintTest(struct torture_context *tctx,
    3619             :                              struct dcerpc_binding_handle *b,
    3620             :                              struct policy_handle *handle)
    3621             : {
    3622          28 :         bool ret = true;
    3623          28 :         uint32_t num_jobs = 8;
    3624           0 :         uint32_t *job_ids;
    3625           0 :         int i;
    3626             : 
    3627          28 :         torture_comment(tctx, "Testing real print operations\n");
    3628             : 
    3629          28 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3630             : 
    3631         252 :         for (i=0; i < num_jobs; i++) {
    3632         224 :                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
    3633             :         }
    3634             : 
    3635         252 :         for (i=0; i < num_jobs; i++) {
    3636         224 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3637             :         }
    3638             : 
    3639         252 :         for (i=0; i < num_jobs; i++) {
    3640         224 :                 ret &= test_DoPrintTest_add_one_job_v4(tctx, b, handle, "TorturePrintJob v4", &job_ids[i]);
    3641             :         }
    3642             : 
    3643         252 :         for (i=0; i < num_jobs; i++) {
    3644         224 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3645             :         }
    3646             : 
    3647          28 :         if (ret == true) {
    3648          14 :                 torture_comment(tctx, "real print operations test succeeded\n\n");
    3649             :         }
    3650             : 
    3651          28 :         return ret;
    3652             : }
    3653             : 
    3654           8 : static bool test_DoPrintTest_extended(struct torture_context *tctx,
    3655             :                                       struct dcerpc_binding_handle *b,
    3656             :                                       struct policy_handle *handle)
    3657             : {
    3658           8 :         bool ret = true;
    3659           8 :         uint32_t num_jobs = 8;
    3660           0 :         uint32_t *job_ids;
    3661           0 :         int i;
    3662           8 :         torture_comment(tctx, "Testing real print operations (extended)\n");
    3663             : 
    3664           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3665             : 
    3666          72 :         for (i=0; i < num_jobs; i++) {
    3667          64 :                 ret &= test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]);
    3668             :         }
    3669             : 
    3670           8 :         ret &= test_DoPrintTest_check_jobs(tctx, b, handle, num_jobs, job_ids);
    3671             : 
    3672          72 :         for (i=0; i < num_jobs; i++) {
    3673          64 :                 ret &= test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE);
    3674             :         }
    3675             : 
    3676           8 :         if (ret == true) {
    3677           4 :                 torture_comment(tctx, "real print operations (extended) test succeeded\n\n");
    3678             :         }
    3679             : 
    3680           8 :         return ret;
    3681             : }
    3682             : 
    3683           0 : static bool test_JobPrintProperties_equal(struct torture_context *tctx,
    3684             :                                           struct spoolss_PrintPropertyValue *got,
    3685             :                                           struct spoolss_PrintNamedProperty *exp)
    3686             : {
    3687           0 :         torture_assert_int_equal(tctx,
    3688             :                                  got->ePropertyType,
    3689             :                                  exp->propertyValue.ePropertyType,
    3690             :                                  "ePropertyType");
    3691             : 
    3692           0 :         switch (exp->propertyValue.ePropertyType) {
    3693           0 :         case kRpcPropertyTypeString:
    3694           0 :                 torture_assert_str_equal(tctx,
    3695             :                                          got->value.propertyString,
    3696             :                                          exp->propertyValue.value.propertyString,
    3697             :                                          "propertyString");
    3698           0 :                 break;
    3699           0 :         case kRpcPropertyTypeInt32:
    3700           0 :                 torture_assert_int_equal(tctx,
    3701             :                                          got->value.propertyInt32,
    3702             :                                          exp->propertyValue.value.propertyInt32,
    3703             :                                          "propertyInt32");
    3704           0 :                 break;
    3705           0 :         case kRpcPropertyTypeInt64:
    3706           0 :                 torture_assert_u64_equal(tctx,
    3707             :                                          got->value.propertyInt64,
    3708             :                                          exp->propertyValue.value.propertyInt64,
    3709             :                                          "propertyInt64");
    3710           0 :                 break;
    3711           0 :         case kRpcPropertyTypeByte:
    3712           0 :                 torture_assert_int_equal(tctx,
    3713             :                                          got->value.propertyByte,
    3714             :                                          exp->propertyValue.value.propertyByte,
    3715             :                                          "propertyByte");
    3716           0 :                 break;
    3717           0 :         case kRpcPropertyTypeBuffer:
    3718           0 :                 torture_assert_int_equal(tctx,
    3719             :                                          got->value.propertyBlob.cbBuf,
    3720             :                                          exp->propertyValue.value.propertyBlob.cbBuf,
    3721             :                                          "propertyBlob.cbBuf");
    3722           0 :                 torture_assert_mem_equal(tctx,
    3723             :                                          got->value.propertyBlob.pBuf,
    3724             :                                          exp->propertyValue.value.propertyBlob.pBuf,
    3725             :                                          exp->propertyValue.value.propertyBlob.cbBuf,
    3726             :                                          "propertyBlob.pBuf");
    3727             : 
    3728           0 :                 break;
    3729             : 
    3730             :         }
    3731             : 
    3732           0 :         return true;
    3733             : }
    3734             : 
    3735           0 : static bool test_JobPrintProperties(struct torture_context *tctx,
    3736             :                                     struct dcerpc_binding_handle *b,
    3737             :                                     struct policy_handle *handle,
    3738             :                                     uint32_t job_id)
    3739             : {
    3740           0 :         struct spoolss_PrintNamedProperty in;
    3741           0 :         struct spoolss_PrintPropertyValue out;
    3742           0 :         int i;
    3743           0 :         DATA_BLOB blob = data_blob_string_const("blob");
    3744           0 :         struct {
    3745             :                 const char *property_name;
    3746             :                 enum spoolss_EPrintPropertyType type;
    3747             :                 union spoolss_PrintPropertyValueUnion value;
    3748             :                 WERROR expected_result;
    3749           0 :         } tests[] = {
    3750             :                 {
    3751             :                         .property_name                  = "torture_property_string",
    3752             :                         .type                           = kRpcPropertyTypeString,
    3753             :                         .value.propertyString           = "torture_property_value_string",
    3754             :                 },{
    3755             :                         .property_name                  = "torture_property_int32",
    3756             :                         .type                           = kRpcPropertyTypeInt32,
    3757             :                         .value.propertyInt32            = 42,
    3758             :                 },{
    3759             :                         .property_name                  = "torture_property_int64",
    3760             :                         .type                           = kRpcPropertyTypeInt64,
    3761             :                         .value.propertyInt64            = 0xaffe,
    3762             :                 },{
    3763             :                         .property_name                  = "torture_property_byte",
    3764             :                         .type                           = kRpcPropertyTypeByte,
    3765             :                         .value.propertyByte             = 0xab,
    3766             :                 },{
    3767             :                         .property_name                  = "torture_property_buffer",
    3768             :                         .type                           = kRpcPropertyTypeBuffer,
    3769           0 :                         .value.propertyBlob.cbBuf       = blob.length,
    3770           0 :                         .value.propertyBlob.pBuf        = blob.data,
    3771             :                 }
    3772             :         };
    3773             : 
    3774           0 :         torture_assert(tctx,
    3775             :                 test_JobPropertiesEnum(tctx, b, handle, job_id),
    3776             :                 "failed to enum properties");
    3777             : 
    3778           0 :         for (i=0; i <ARRAY_SIZE(tests); i++) {
    3779             : 
    3780           0 :                 in.propertyName                 = tests[i].property_name;
    3781           0 :                 in.propertyValue.ePropertyType  = tests[i].type;
    3782           0 :                 in.propertyValue.value          = tests[i].value;
    3783             : 
    3784           0 :                 torture_assert(tctx,
    3785             :                         test_JobPropertySet(tctx, b, handle, job_id, &in),
    3786             :                         "failed to set property");
    3787             : 
    3788           0 :                 torture_assert(tctx,
    3789             :                         test_JobPropertyGetValue(tctx, b, handle, job_id, in.propertyName, &out),
    3790             :                         "failed to get property");
    3791             : 
    3792           0 :                 torture_assert(tctx,
    3793             :                         test_JobPrintProperties_equal(tctx, &out, &in),
    3794             :                         "property unequal");
    3795             : 
    3796           0 :                 torture_assert(tctx,
    3797             :                         test_JobPropertiesEnum(tctx, b, handle, job_id),
    3798             :                         "failed to enum properties");
    3799             : 
    3800           0 :                 torture_assert(tctx,
    3801             :                         test_JobPropertyDelete(tctx, b, handle, job_id, in.propertyName),
    3802             :                         "failed to delete job property");
    3803             :         }
    3804             : 
    3805           0 :         torture_assert(tctx,
    3806             :                 test_JobPropertiesEnum(tctx, b, handle, job_id),
    3807             :                 "failed to enum properties");
    3808             : 
    3809           0 :         return true;
    3810             : }
    3811             : 
    3812           0 : static bool test_DoPrintTest_properties(struct torture_context *tctx,
    3813             :                                         struct dcerpc_binding_handle *b,
    3814             :                                         struct policy_handle *handle)
    3815             : {
    3816           0 :         uint32_t num_jobs = 8;
    3817           0 :         uint32_t *job_ids;
    3818           0 :         int i;
    3819           0 :         torture_comment(tctx, "Testing real print operations (properties)\n");
    3820             : 
    3821           0 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    3822             : 
    3823           0 :         for (i=0; i < num_jobs; i++) {
    3824           0 :                 torture_assert(tctx,
    3825             :                         test_DoPrintTest_add_one_job(tctx, b, handle, "TorturePrintJob", &job_ids[i]),
    3826             :                         "failed to create print job");
    3827             :         }
    3828             : 
    3829           0 :         for (i=0; i < num_jobs; i++) {
    3830           0 :                 torture_assert(tctx,
    3831             :                         test_JobPrintProperties(tctx, b, handle, job_ids[i]),
    3832             :                         "failed to test job properties");
    3833             :         }
    3834             : 
    3835             : 
    3836           0 :         for (i=0; i < num_jobs; i++) {
    3837           0 :                 torture_assert(tctx,
    3838             :                         test_SetJob(tctx, b, handle, job_ids[i], NULL, SPOOLSS_JOB_CONTROL_DELETE),
    3839             :                         "failed to delete printjob");
    3840             :         }
    3841             : 
    3842           0 :         torture_comment(tctx, "real print operations (properties) test succeeded\n\n");
    3843             : 
    3844           0 :         return true;
    3845             : }
    3846             : 
    3847          52 : static bool test_PausePrinter(struct torture_context *tctx,
    3848             :                               struct dcerpc_binding_handle *b,
    3849             :                               struct policy_handle *handle)
    3850             : {
    3851           0 :         NTSTATUS status;
    3852           0 :         struct spoolss_SetPrinter r;
    3853           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3854           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    3855           0 :         struct sec_desc_buf secdesc_ctr;
    3856             : 
    3857          52 :         info_ctr.level = 0;
    3858          52 :         info_ctr.info.info0 = NULL;
    3859             : 
    3860          52 :         ZERO_STRUCT(devmode_ctr);
    3861          52 :         ZERO_STRUCT(secdesc_ctr);
    3862             : 
    3863          52 :         r.in.handle             = handle;
    3864          52 :         r.in.info_ctr           = &info_ctr;
    3865          52 :         r.in.devmode_ctr        = &devmode_ctr;
    3866          52 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3867          52 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
    3868             : 
    3869          52 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
    3870             : 
    3871          52 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3872             : 
    3873          52 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3874             : 
    3875          52 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3876             : 
    3877          52 :         return true;
    3878             : }
    3879             : 
    3880          40 : static bool test_ResumePrinter(struct torture_context *tctx,
    3881             :                                struct dcerpc_binding_handle *b,
    3882             :                                struct policy_handle *handle)
    3883             : {
    3884           0 :         NTSTATUS status;
    3885           0 :         struct spoolss_SetPrinter r;
    3886           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3887           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    3888           0 :         struct sec_desc_buf secdesc_ctr;
    3889             : 
    3890          40 :         info_ctr.level = 0;
    3891          40 :         info_ctr.info.info0 = NULL;
    3892             : 
    3893          40 :         ZERO_STRUCT(devmode_ctr);
    3894          40 :         ZERO_STRUCT(secdesc_ctr);
    3895             : 
    3896          40 :         r.in.handle             = handle;
    3897          40 :         r.in.info_ctr           = &info_ctr;
    3898          40 :         r.in.devmode_ctr        = &devmode_ctr;
    3899          40 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3900          40 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
    3901             : 
    3902          40 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
    3903             : 
    3904          40 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3905             : 
    3906          40 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3907             : 
    3908          40 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3909             : 
    3910          40 :         return true;
    3911             : }
    3912             : 
    3913          12 : static bool test_printer_purge(struct torture_context *tctx,
    3914             :                                struct dcerpc_binding_handle *b,
    3915             :                                struct policy_handle *handle)
    3916             : {
    3917           0 :         NTSTATUS status;
    3918           0 :         struct spoolss_SetPrinter r;
    3919           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3920           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    3921           0 :         struct sec_desc_buf secdesc_ctr;
    3922             : 
    3923          12 :         info_ctr.level = 0;
    3924          12 :         info_ctr.info.info0 = NULL;
    3925             : 
    3926          12 :         ZERO_STRUCT(devmode_ctr);
    3927          12 :         ZERO_STRUCT(secdesc_ctr);
    3928             : 
    3929          12 :         r.in.handle             = handle;
    3930          12 :         r.in.info_ctr           = &info_ctr;
    3931          12 :         r.in.devmode_ctr        = &devmode_ctr;
    3932          12 :         r.in.secdesc_ctr        = &secdesc_ctr;
    3933          12 :         r.in.command            = SPOOLSS_PRINTER_CONTROL_PURGE;
    3934             : 
    3935          12 :         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PURGE\n");
    3936             : 
    3937          12 :         status = dcerpc_spoolss_SetPrinter_r(b, tctx, &r);
    3938          12 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
    3939          12 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
    3940             : 
    3941          12 :         return true;
    3942             : }
    3943             : 
    3944         232 : static bool test_GetPrinterData_checktype(struct torture_context *tctx,
    3945             :                                           struct dcerpc_binding_handle *b,
    3946             :                                           struct policy_handle *handle,
    3947             :                                           const char *value_name,
    3948             :                                           enum winreg_Type *expected_type,
    3949             :                                           enum winreg_Type *type_p,
    3950             :                                           uint8_t **data_p,
    3951             :                                           uint32_t *needed_p)
    3952             : {
    3953           0 :         NTSTATUS status;
    3954           0 :         struct spoolss_GetPrinterData r;
    3955           0 :         uint32_t needed;
    3956           0 :         enum winreg_Type type;
    3957           0 :         union spoolss_PrinterData data;
    3958             : 
    3959         232 :         r.in.handle = handle;
    3960         232 :         r.in.value_name = value_name;
    3961         232 :         r.in.offered = 0;
    3962         232 :         r.out.needed = &needed;
    3963         232 :         r.out.type = &type;
    3964         232 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    3965             : 
    3966         232 :         torture_comment(tctx, "Testing GetPrinterData(%s)\n", r.in.value_name);
    3967             : 
    3968         232 :         status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
    3969         232 :         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
    3970             : 
    3971         232 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    3972         232 :                 if (expected_type) {
    3973          84 :                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
    3974             :                 }
    3975         232 :                 r.in.offered = needed;
    3976         232 :                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    3977         232 :                 status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &r);
    3978         232 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
    3979             :         }
    3980             : 
    3981         232 :         torture_assert_werr_ok(tctx, r.out.result,
    3982             :                 talloc_asprintf(tctx, "GetPrinterData(%s) failed", r.in.value_name));
    3983             : 
    3984         232 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
    3985             : 
    3986         232 :         if (type_p) {
    3987         224 :                 *type_p = type;
    3988             :         }
    3989             : 
    3990         232 :         if (data_p) {
    3991         232 :                 *data_p = r.out.data;
    3992             :         }
    3993             : 
    3994         232 :         if (needed_p) {
    3995         232 :                 *needed_p = needed;
    3996             :         }
    3997             : 
    3998         232 :         return true;
    3999             : }
    4000             : 
    4001         140 : static bool test_GetPrinterData(struct torture_context *tctx,
    4002             :                                 struct dcerpc_binding_handle *b,
    4003             :                                 struct policy_handle *handle,
    4004             :                                 const char *value_name,
    4005             :                                 enum winreg_Type *type_p,
    4006             :                                 uint8_t **data_p,
    4007             :                                 uint32_t *needed_p)
    4008             : {
    4009         140 :         return test_GetPrinterData_checktype(tctx, b, handle, value_name,
    4010             :                                              NULL, type_p, data_p, needed_p);
    4011             : }
    4012             : 
    4013        1368 : static bool test_GetPrinterDataEx_checktype(struct torture_context *tctx,
    4014             :                                             struct dcerpc_pipe *p,
    4015             :                                             struct policy_handle *handle,
    4016             :                                             const char *key_name,
    4017             :                                             const char *value_name,
    4018             :                                             enum winreg_Type *expected_type,
    4019             :                                             enum winreg_Type *type_p,
    4020             :                                             uint8_t **data_p,
    4021             :                                             uint32_t *needed_p)
    4022             : {
    4023           0 :         NTSTATUS status;
    4024           0 :         struct spoolss_GetPrinterDataEx r;
    4025           0 :         enum winreg_Type type;
    4026           0 :         uint32_t needed;
    4027           0 :         union spoolss_PrinterData data;
    4028        1368 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4029             : 
    4030        1368 :         r.in.handle = handle;
    4031        1368 :         r.in.key_name = key_name;
    4032        1368 :         r.in.value_name = value_name;
    4033        1368 :         r.in.offered = 0;
    4034        1368 :         r.out.type = &type;
    4035        1368 :         r.out.needed = &needed;
    4036        1368 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    4037             : 
    4038        1368 :         torture_comment(tctx, "Testing GetPrinterDataEx(%s - %s)\n",
    4039             :                 r.in.key_name, r.in.value_name);
    4040             : 
    4041        1368 :         status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
    4042        1368 :         if (!NT_STATUS_IS_OK(status)) {
    4043           0 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
    4044           0 :                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
    4045             :                 }
    4046           0 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
    4047             :         }
    4048             : 
    4049        1368 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4050        1332 :                 if (expected_type) {
    4051         972 :                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
    4052             :                 }
    4053        1332 :                 r.in.offered = needed;
    4054        1332 :                 r.out.data = talloc_zero_array(tctx, uint8_t, r.in.offered);
    4055        1332 :                 status = dcerpc_spoolss_GetPrinterDataEx_r(b, tctx, &r);
    4056        1332 :                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
    4057             :         }
    4058             : 
    4059        1368 :         torture_assert_werr_ok(tctx, r.out.result,
    4060             :                 talloc_asprintf(tctx, "GetPrinterDataEx(%s - %s) failed", r.in.key_name, r.in.value_name));
    4061             : 
    4062        1368 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_PrinterData, &data, type, needed, 1);
    4063             : 
    4064        1368 :         if (type_p) {
    4065        1368 :                 *type_p = type;
    4066             :         }
    4067             : 
    4068        1368 :         if (data_p) {
    4069        1368 :                 *data_p = r.out.data;
    4070             :         }
    4071             : 
    4072        1368 :         if (needed_p) {
    4073        1368 :                 *needed_p = needed;
    4074             :         }
    4075             : 
    4076        1368 :         return true;
    4077             : }
    4078             : 
    4079         360 : static bool test_GetPrinterDataEx(struct torture_context *tctx,
    4080             :                                   struct dcerpc_pipe *p,
    4081             :                                   struct policy_handle *handle,
    4082             :                                   const char *key_name,
    4083             :                                   const char *value_name,
    4084             :                                   enum winreg_Type *type_p,
    4085             :                                   uint8_t **data_p,
    4086             :                                   uint32_t *needed_p)
    4087             : {
    4088         360 :         return test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name,
    4089             :                                                NULL, type_p, data_p, needed_p);
    4090             : }
    4091             : 
    4092          68 : static bool test_get_environment(struct torture_context *tctx,
    4093             :                                  struct dcerpc_binding_handle *b,
    4094             :                                  struct policy_handle *handle,
    4095             :                                  const char **architecture)
    4096             : {
    4097           0 :         DATA_BLOB blob;
    4098           0 :         enum winreg_Type type;
    4099           0 :         uint8_t *data;
    4100           0 :         uint32_t needed;
    4101             : 
    4102          68 :         torture_assert(tctx,
    4103             :                 test_GetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
    4104             :                 "failed to get Architecture");
    4105             : 
    4106          68 :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
    4107             : 
    4108          68 :         blob = data_blob_const(data, needed);
    4109          68 :         *architecture = reg_val_data_string(tctx, REG_SZ, blob);
    4110             : 
    4111          68 :         return true;
    4112             : }
    4113             : 
    4114           4 : static bool test_GetPrinterData_list(struct torture_context *tctx,
    4115             :                                      void *private_data)
    4116             : {
    4117           0 :         struct test_spoolss_context *ctx =
    4118           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    4119           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    4120           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4121           4 :         const char *list[] = {
    4122             :                 "W3SvcInstalled",
    4123             :                 "BeepEnabled",
    4124             :                 "EventLog",
    4125             :                 /* "NetPopup", not on w2k8 */
    4126             :                 /* "NetPopupToComputer", not on w2k8 */
    4127             :                 "MajorVersion",
    4128             :                 "MinorVersion",
    4129             :                 "DefaultSpoolDirectory",
    4130             :                 "Architecture",
    4131             :                 "DsPresent",
    4132             :                 "OSVersion",
    4133             :                 /* "OSVersionEx", not on s3 */
    4134             :                 "DNSMachineName"
    4135             :         };
    4136           0 :         int i;
    4137             : 
    4138          44 :         for (i=0; i < ARRAY_SIZE(list); i++) {
    4139          40 :                 enum winreg_Type type = REG_NONE;
    4140          40 :                 enum winreg_Type type_ex1 = REG_NONE;
    4141          40 :                 enum winreg_Type type_ex2 = REG_NONE;
    4142           0 :                 uint8_t *data;
    4143          40 :                 uint8_t *data_ex1 = NULL;
    4144          40 :                 uint8_t *data_ex2 = NULL;
    4145           0 :                 uint32_t needed;
    4146          40 :                 uint32_t needed_ex1 = 0;
    4147          40 :                 uint32_t needed_ex2 = 0;
    4148             : 
    4149          40 :                 torture_assert(tctx, test_GetPrinterData(tctx, b, &ctx->server_handle, list[i], &type, &data, &needed),
    4150             :                         talloc_asprintf(tctx, "GetPrinterData failed on %s\n", list[i]));
    4151          40 :                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "random_string", list[i], &type_ex1, &data_ex1, &needed_ex1),
    4152             :                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
    4153          40 :                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, &ctx->server_handle, "", list[i], &type_ex2, &data_ex2, &needed_ex2),
    4154             :                         talloc_asprintf(tctx, "GetPrinterDataEx failed on %s\n", list[i]));
    4155          40 :                 torture_assert_int_equal(tctx, type, type_ex1, "type mismatch");
    4156          40 :                 torture_assert_int_equal(tctx, type, type_ex2, "type mismatch");
    4157          40 :                 torture_assert_int_equal(tctx, needed, needed_ex1, "needed mismatch");
    4158          40 :                 torture_assert_int_equal(tctx, needed, needed_ex2, "needed mismatch");
    4159          40 :                 torture_assert_mem_equal(tctx, data, data_ex1, needed, "data mismatch");
    4160          40 :                 torture_assert_mem_equal(tctx, data, data_ex2, needed, "data mismatch");
    4161             :         }
    4162             : 
    4163           4 :         return true;
    4164             : }
    4165             : 
    4166         152 : static bool test_EnumPrinterData(struct torture_context *tctx,
    4167             :                                  struct dcerpc_pipe *p,
    4168             :                                  struct policy_handle *handle,
    4169             :                                  uint32_t enum_index,
    4170             :                                  uint32_t value_offered,
    4171             :                                  uint32_t data_offered,
    4172             :                                  enum winreg_Type *type_p,
    4173             :                                  uint32_t *value_needed_p,
    4174             :                                  uint32_t *data_needed_p,
    4175             :                                  const char **value_name_p,
    4176             :                                  uint8_t **data_p,
    4177             :                                  WERROR *result_p)
    4178             : {
    4179           0 :         struct spoolss_EnumPrinterData r;
    4180           0 :         uint32_t data_needed;
    4181           0 :         uint32_t value_needed;
    4182           0 :         enum winreg_Type type;
    4183         152 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4184             : 
    4185         152 :         r.in.handle = handle;
    4186         152 :         r.in.enum_index = enum_index;
    4187         152 :         r.in.value_offered = value_offered;
    4188         152 :         r.in.data_offered = data_offered;
    4189         152 :         r.out.data_needed = &data_needed;
    4190         152 :         r.out.value_needed = &value_needed;
    4191         152 :         r.out.type = &type;
    4192         152 :         r.out.data = talloc_zero_array(tctx, uint8_t, r.in.data_offered);
    4193         152 :         r.out.value_name = talloc_zero_array(tctx, const char, r.in.value_offered);
    4194             : 
    4195         152 :         torture_comment(tctx, "Testing EnumPrinterData(%d)\n", enum_index);
    4196             : 
    4197         152 :         torture_assert_ntstatus_ok(tctx,
    4198             :                 dcerpc_spoolss_EnumPrinterData_r(b, tctx, &r),
    4199             :                 "EnumPrinterData failed");
    4200             : 
    4201         152 :         if (type_p) {
    4202         124 :                 *type_p = type;
    4203             :         }
    4204         152 :         if (value_needed_p) {
    4205         152 :                 *value_needed_p = value_needed;
    4206             :         }
    4207         152 :         if (data_needed_p) {
    4208         152 :                 *data_needed_p = data_needed;
    4209             :         }
    4210         152 :         if (value_name_p) {
    4211         124 :                 *value_name_p = r.out.value_name;
    4212             :         }
    4213         152 :         if (data_p) {
    4214         124 :                 *data_p = r.out.data;
    4215             :         }
    4216         152 :         if (result_p) {
    4217         152 :                 *result_p = r.out.result;
    4218             :         }
    4219             : 
    4220         152 :         return true;
    4221             : }
    4222             : 
    4223             : 
    4224          20 : static bool test_EnumPrinterData_all(struct torture_context *tctx,
    4225             :                                      struct dcerpc_pipe *p,
    4226             :                                      struct policy_handle *handle)
    4227             : {
    4228          20 :         uint32_t enum_index = 0;
    4229           0 :         enum winreg_Type type;
    4230           0 :         uint32_t value_needed;
    4231           0 :         uint32_t data_needed;
    4232           0 :         uint8_t *data;
    4233           0 :         const char *value_name;
    4234           0 :         WERROR result;
    4235             : 
    4236          20 :         torture_comment(tctx, "Testing EnumPrinterData\n");
    4237             : 
    4238           0 :         do {
    4239          20 :                 torture_assert(tctx,
    4240             :                         test_EnumPrinterData(tctx, p, handle, enum_index, 0, 0,
    4241             :                                              &type, &value_needed, &data_needed,
    4242             :                                              &value_name, &data, &result),
    4243             :                         "EnumPrinterData failed");
    4244             : 
    4245          20 :                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
    4246           0 :                         break;
    4247             :                 }
    4248             : 
    4249          20 :                 torture_assert(tctx,
    4250             :                         test_EnumPrinterData(tctx, p, handle, enum_index, value_needed, data_needed,
    4251             :                                              &type, &value_needed, &data_needed,
    4252             :                                              &value_name, &data, &result),
    4253             :                         "EnumPrinterData failed");
    4254             : 
    4255          20 :                 if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS)) {
    4256          20 :                         break;
    4257             :                 }
    4258             : 
    4259           0 :                 enum_index++;
    4260             : 
    4261           0 :         } while (W_ERROR_IS_OK(result));
    4262             : 
    4263          20 :         torture_comment(tctx, "EnumPrinterData test succeeded\n");
    4264             : 
    4265          20 :         return true;
    4266             : }
    4267             : 
    4268        1316 : static bool test_EnumPrinterDataEx(struct torture_context *tctx,
    4269             :                                    struct dcerpc_binding_handle *b,
    4270             :                                    struct policy_handle *handle,
    4271             :                                    const char *key_name,
    4272             :                                    uint32_t *count_p,
    4273             :                                    struct spoolss_PrinterEnumValues **info_p)
    4274             : {
    4275           0 :         struct spoolss_EnumPrinterDataEx r;
    4276           0 :         struct spoolss_PrinterEnumValues *info;
    4277           0 :         uint32_t needed;
    4278           0 :         uint32_t count;
    4279             : 
    4280        1316 :         r.in.handle = handle;
    4281        1316 :         r.in.key_name = key_name;
    4282        1316 :         r.in.offered = 0;
    4283        1316 :         r.out.needed = &needed;
    4284        1316 :         r.out.count = &count;
    4285        1316 :         r.out.info = &info;
    4286             : 
    4287        1316 :         torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key_name);
    4288             : 
    4289        1316 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
    4290             :                 "EnumPrinterDataEx failed");
    4291        1316 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4292        1256 :                 r.in.offered = needed;
    4293        1256 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx_r(b, tctx, &r),
    4294             :                         "EnumPrinterDataEx failed");
    4295             :         }
    4296             : 
    4297        1316 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDataEx failed");
    4298             : 
    4299        1316 :         CHECK_NEEDED_SIZE_ENUM(spoolss_EnumPrinterDataEx, info, count, needed, 1);
    4300             : 
    4301        1316 :         if (count_p) {
    4302        1228 :                 *count_p = count;
    4303             :         }
    4304        1316 :         if (info_p) {
    4305        1228 :                 *info_p = info;
    4306             :         }
    4307             : 
    4308        1316 :         return true;
    4309             : }
    4310             : 
    4311             : static bool test_SetPrinterData(struct torture_context *tctx,
    4312             :                                 struct dcerpc_binding_handle *b,
    4313             :                                 struct policy_handle *handle,
    4314             :                                 const char *value_name,
    4315             :                                 enum winreg_Type type,
    4316             :                                 uint8_t *data,
    4317             :                                 uint32_t offered);
    4318             : static bool test_DeletePrinterData(struct torture_context *tctx,
    4319             :                                    struct dcerpc_binding_handle *b,
    4320             :                                    struct policy_handle *handle,
    4321             :                                    const char *value_name);
    4322             : 
    4323          28 : static bool test_EnumPrinterData_consistency(struct torture_context *tctx,
    4324             :                                              struct dcerpc_pipe *p,
    4325             :                                              struct policy_handle *handle)
    4326             : {
    4327           0 :         uint32_t count;
    4328           0 :         struct spoolss_PrinterEnumValues *info;
    4329           0 :         int i;
    4330           0 :         uint32_t value_needed, data_needed;
    4331           0 :         uint32_t value_offered, data_offered;
    4332           0 :         WERROR result;
    4333          28 :         struct dcerpc_binding_handle *b = p->binding_handle;
    4334             : 
    4335           0 :         enum winreg_Type type;
    4336           0 :         DATA_BLOB blob;
    4337             : 
    4338          28 :         torture_comment(tctx, "Testing EnumPrinterData vs EnumPrinterDataEx consistency\n");
    4339             : 
    4340          28 :         torture_assert(tctx, push_reg_sz(tctx, &blob, "torture_data1"), "");
    4341          28 :         type = REG_SZ;
    4342             : 
    4343          28 :         torture_assert(tctx,
    4344             :                 test_SetPrinterData(tctx, b, handle, "torture_value1", type, blob.data, blob.length),
    4345             :                 "SetPrinterData failed");
    4346             : 
    4347          28 :         blob = data_blob_string_const("torture_data2");
    4348             : 
    4349          28 :         torture_assert(tctx,
    4350             :                 test_SetPrinterData(tctx, b, handle, "torture_value2", REG_BINARY, blob.data, blob.length),
    4351             :                 "SetPrinterData failed");
    4352             : 
    4353          28 :         blob = data_blob_talloc(tctx, NULL, 4);
    4354          28 :         SIVAL(blob.data, 0, 0x11223344);
    4355             : 
    4356          28 :         torture_assert(tctx,
    4357             :                 test_SetPrinterData(tctx, b, handle, "torture_value3", type, blob.data, blob.length),
    4358             :                 "SetPrinterData failed");
    4359             : 
    4360          28 :         torture_assert(tctx,
    4361             :                 test_EnumPrinterDataEx(tctx, b, handle, "PrinterDriverData", &count, &info),
    4362             :                 "failed to call EnumPrinterDataEx");
    4363             : 
    4364             :         /* get the max sizes for value and data */
    4365             : 
    4366          28 :         torture_assert(tctx,
    4367             :                 test_EnumPrinterData(tctx, p, handle, 0, 0, 0,
    4368             :                                      NULL, &value_needed, &data_needed,
    4369             :                                      NULL, NULL, &result),
    4370             :                 "EnumPrinterData failed");
    4371          28 :         torture_assert_werr_ok(tctx, result, "unexpected result");
    4372             : 
    4373             :         /* check if the reply from the EnumPrinterData really matches max values */
    4374             : 
    4375         112 :         for (i=0; i < count; i++) {
    4376          84 :                 if (info[i].value_name_len > value_needed) {
    4377           0 :                         torture_fail(tctx,
    4378             :                                 talloc_asprintf(tctx,
    4379             :                                 "EnumPrinterDataEx gave a reply with value length %d which is larger then expected max value length %d from EnumPrinterData",
    4380             :                                 info[i].value_name_len, value_needed));
    4381             :                 }
    4382          84 :                 if (info[i].data_length > data_needed) {
    4383           0 :                         torture_fail(tctx,
    4384             :                                 talloc_asprintf(tctx,
    4385             :                                 "EnumPrinterDataEx gave a reply with data length %d which is larger then expected max data length %d from EnumPrinterData",
    4386             :                                 info[i].data_length, data_needed));
    4387             :                 }
    4388             :         }
    4389             : 
    4390             :         /* assuming that both EnumPrinterData and EnumPrinterDataEx do either
    4391             :          * sort or not sort the replies by value name, we should be able to do
    4392             :          * the following entry comparison */
    4393             : 
    4394          28 :         data_offered = data_needed;
    4395          28 :         value_offered = value_needed;
    4396             : 
    4397         112 :         for (i=0; i < count; i++) {
    4398             : 
    4399           0 :                 const char *value_name;
    4400           0 :                 uint8_t *data;
    4401             : 
    4402          84 :                 torture_assert(tctx,
    4403             :                         test_EnumPrinterData(tctx, p, handle, i, value_offered, data_offered,
    4404             :                                              &type, &value_needed, &data_needed,
    4405             :                                              &value_name, &data, &result),
    4406             :                         "EnumPrinterData failed");
    4407             : 
    4408          84 :                 if (i -1 == count) {
    4409           0 :                         torture_assert_werr_equal(tctx, result, WERR_NO_MORE_ITEMS,
    4410             :                                 "unexpected result");
    4411           0 :                         break;
    4412             :                 } else {
    4413          84 :                         torture_assert_werr_ok(tctx, result, "unexpected result");
    4414             :                 }
    4415             : 
    4416          84 :                 torture_assert_int_equal(tctx, type, info[i].type, "type mismatch");
    4417          84 :                 torture_assert_int_equal(tctx, value_needed, info[i].value_name_len, "value name length mismatch");
    4418          84 :                 torture_assert_str_equal(tctx, value_name, info[i].value_name, "value name mismatch");
    4419          84 :                 torture_assert_int_equal(tctx, data_needed, info[i].data_length, "data length mismatch");
    4420          84 :                 torture_assert_mem_equal(tctx, data, info[i].data->data, info[i].data_length, "data mismatch");
    4421             :         }
    4422             : 
    4423          28 :         torture_assert(tctx,
    4424             :                 test_DeletePrinterData(tctx, b, handle, "torture_value1"),
    4425             :                 "DeletePrinterData failed");
    4426          28 :         torture_assert(tctx,
    4427             :                 test_DeletePrinterData(tctx, b, handle, "torture_value2"),
    4428             :                 "DeletePrinterData failed");
    4429          28 :         torture_assert(tctx,
    4430             :                 test_DeletePrinterData(tctx, b, handle, "torture_value3"),
    4431             :                 "DeletePrinterData failed");
    4432             : 
    4433          28 :         torture_comment(tctx, "EnumPrinterData vs EnumPrinterDataEx consistency test succeeded\n\n");
    4434             : 
    4435          28 :         return true;
    4436             : }
    4437             : 
    4438         168 : static bool test_DeletePrinterData(struct torture_context *tctx,
    4439             :                                    struct dcerpc_binding_handle *b,
    4440             :                                    struct policy_handle *handle,
    4441             :                                    const char *value_name)
    4442             : {
    4443           0 :         NTSTATUS status;
    4444           0 :         struct spoolss_DeletePrinterData r;
    4445             : 
    4446         168 :         r.in.handle = handle;
    4447         168 :         r.in.value_name = value_name;
    4448             : 
    4449         168 :         torture_comment(tctx, "Testing DeletePrinterData(%s)\n",
    4450             :                 r.in.value_name);
    4451             : 
    4452         168 :         status = dcerpc_spoolss_DeletePrinterData_r(b, tctx, &r);
    4453             : 
    4454         168 :         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
    4455         168 :         torture_assert_werr_ok(tctx, r.out.result, "DeletePrinterData failed");
    4456             : 
    4457         168 :         return true;
    4458             : }
    4459             : 
    4460        1200 : static bool test_DeletePrinterDataEx(struct torture_context *tctx,
    4461             :                                      struct dcerpc_binding_handle *b,
    4462             :                                      struct policy_handle *handle,
    4463             :                                      const char *key_name,
    4464             :                                      const char *value_name)
    4465             : {
    4466           0 :         struct spoolss_DeletePrinterDataEx r;
    4467             : 
    4468        1200 :         r.in.handle = handle;
    4469        1200 :         r.in.key_name = key_name;
    4470        1200 :         r.in.value_name = value_name;
    4471             : 
    4472        1200 :         torture_comment(tctx, "Testing DeletePrinterDataEx(%s - %s)\n",
    4473             :                 r.in.key_name, r.in.value_name);
    4474             : 
    4475        1200 :         torture_assert_ntstatus_ok(tctx,
    4476             :                 dcerpc_spoolss_DeletePrinterDataEx_r(b, tctx, &r),
    4477             :                 "DeletePrinterDataEx failed");
    4478        1200 :         torture_assert_werr_ok(tctx, r.out.result,
    4479             :                 "DeletePrinterDataEx failed");
    4480             : 
    4481        1200 :         return true;
    4482             : }
    4483             : 
    4484         216 : static bool test_DeletePrinterKey(struct torture_context *tctx,
    4485             :                                   struct dcerpc_binding_handle *b,
    4486             :                                   struct policy_handle *handle,
    4487             :                                   const char *key_name)
    4488             : {
    4489           0 :         struct spoolss_DeletePrinterKey r;
    4490             : 
    4491         216 :         r.in.handle = handle;
    4492         216 :         r.in.key_name = key_name;
    4493             : 
    4494         216 :         torture_comment(tctx, "Testing DeletePrinterKey(%s)\n", r.in.key_name);
    4495             : 
    4496         216 :         if (strequal(key_name, "") && !torture_setting_bool(tctx, "dangerous", false)) {
    4497           0 :                 torture_skip(tctx, "not wiping out printer registry - enable dangerous tests to use\n");
    4498             :                 return true;
    4499             :         }
    4500             : 
    4501         216 :         torture_assert_ntstatus_ok(tctx,
    4502             :                 dcerpc_spoolss_DeletePrinterKey_r(b, tctx, &r),
    4503             :                 "DeletePrinterKey failed");
    4504         216 :         torture_assert_werr_ok(tctx, r.out.result,
    4505             :                 "DeletePrinterKey failed");
    4506             : 
    4507         216 :         return true;
    4508             : }
    4509             : 
    4510          48 : static bool test_winreg_OpenHKLM(struct torture_context *tctx,
    4511             :                                  struct dcerpc_binding_handle *b,
    4512             :                                  struct policy_handle *handle)
    4513             : {
    4514           0 :         struct winreg_OpenHKLM r;
    4515             : 
    4516          48 :         r.in.system_name = NULL;
    4517          48 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    4518          48 :         r.out.handle = handle;
    4519             : 
    4520          48 :         torture_comment(tctx, "Testing winreg_OpenHKLM\n");
    4521             : 
    4522          48 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenHKLM_r(b, tctx, &r), "OpenHKLM failed");
    4523          48 :         torture_assert_werr_ok(tctx, r.out.result, "OpenHKLM failed");
    4524             : 
    4525          48 :         return true;
    4526             : }
    4527             : 
    4528        3626 : static void init_winreg_String(struct winreg_String *name, const char *s)
    4529             : {
    4530        3626 :         name->name = s;
    4531        3626 :         if (s) {
    4532        3626 :                 name->name_len = 2 * (strlen_m(s) + 1);
    4533        3626 :                 name->name_size = name->name_len;
    4534             :         } else {
    4535           0 :                 name->name_len = 0;
    4536           0 :                 name->name_size = 0;
    4537             :         }
    4538        3626 : }
    4539             : 
    4540         320 : static bool test_winreg_OpenKey_opts(struct torture_context *tctx,
    4541             :                                      struct dcerpc_binding_handle *b,
    4542             :                                      struct policy_handle *hive_handle,
    4543             :                                      const char *keyname,
    4544             :                                      uint32_t options,
    4545             :                                      struct policy_handle *key_handle)
    4546             : {
    4547           0 :         struct winreg_OpenKey r;
    4548             : 
    4549         320 :         r.in.parent_handle = hive_handle;
    4550         320 :         init_winreg_String(&r.in.keyname, keyname);
    4551         320 :         r.in.options = options;
    4552         320 :         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
    4553         320 :         r.out.handle = key_handle;
    4554             : 
    4555         320 :         torture_comment(tctx, "Testing winreg_OpenKey(%s)\n", keyname);
    4556             : 
    4557         320 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_OpenKey_r(b, tctx, &r), "OpenKey failed");
    4558         320 :         torture_assert_werr_ok(tctx, r.out.result, "OpenKey failed");
    4559             : 
    4560         320 :         return true;
    4561             : }
    4562             : 
    4563         320 : static bool test_winreg_OpenKey(struct torture_context *tctx,
    4564             :                                 struct dcerpc_binding_handle *b,
    4565             :                                 struct policy_handle *hive_handle,
    4566             :                                 const char *keyname,
    4567             :                                 struct policy_handle *key_handle)
    4568             : {
    4569         320 :         return test_winreg_OpenKey_opts(tctx, b, hive_handle, keyname,
    4570             :                                         REG_OPTION_NON_VOLATILE, key_handle);
    4571             : }
    4572             : 
    4573         368 : static bool test_winreg_CloseKey(struct torture_context *tctx,
    4574             :                                  struct dcerpc_binding_handle *b,
    4575             :                                  struct policy_handle *handle)
    4576             : {
    4577           0 :         struct winreg_CloseKey r;
    4578             : 
    4579         368 :         r.in.handle = handle;
    4580         368 :         r.out.handle = handle;
    4581             : 
    4582         368 :         torture_comment(tctx, "Testing winreg_CloseKey\n");
    4583             : 
    4584         368 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey_r(b, tctx, &r), "CloseKey failed");
    4585         368 :         torture_assert_werr_ok(tctx, r.out.result, "CloseKey failed");
    4586             : 
    4587         368 :         return true;
    4588             : }
    4589             : 
    4590        3306 : bool test_winreg_QueryValue(struct torture_context *tctx,
    4591             :                             struct dcerpc_binding_handle *b,
    4592             :                             struct policy_handle *handle,
    4593             :                             const char *value_name,
    4594             :                             enum winreg_Type *type_p,
    4595             :                             uint32_t *data_size_p,
    4596             :                             uint32_t *data_length_p,
    4597             :                             uint8_t **data_p)
    4598             : {
    4599           0 :         struct winreg_QueryValue r;
    4600        3306 :         enum winreg_Type type = REG_NONE;
    4601        3306 :         uint32_t data_size = 0;
    4602        3306 :         uint32_t data_length = 0;
    4603           0 :         struct winreg_String valuename;
    4604        3306 :         uint8_t *data = NULL;
    4605             : 
    4606        3306 :         init_winreg_String(&valuename, value_name);
    4607             : 
    4608        3306 :         data = talloc_zero_array(tctx, uint8_t, 0);
    4609             : 
    4610        3306 :         r.in.handle = handle;
    4611        3306 :         r.in.value_name = &valuename;
    4612        3306 :         r.in.type = &type;
    4613        3306 :         r.in.data_size = &data_size;
    4614        3306 :         r.in.data_length = &data_length;
    4615        3306 :         r.in.data = data;
    4616        3306 :         r.out.type = &type;
    4617        3306 :         r.out.data = data;
    4618        3306 :         r.out.data_size = &data_size;
    4619        3306 :         r.out.data_length = &data_length;
    4620             : 
    4621        3306 :         torture_comment(tctx, "Testing winreg_QueryValue(%s)\n", value_name);
    4622             : 
    4623        3306 :         torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
    4624        3306 :         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    4625        3222 :                 *r.in.data_size = *r.out.data_size;
    4626        3222 :                 data = talloc_zero_array(tctx, uint8_t, *r.in.data_size);
    4627        3222 :                 r.in.data = data;
    4628        3222 :                 r.out.data = data;
    4629        3222 :                 torture_assert_ntstatus_ok(tctx, dcerpc_winreg_QueryValue_r(b, tctx, &r), "QueryValue failed");
    4630             :         }
    4631        3306 :         torture_assert_werr_ok(tctx, r.out.result, "QueryValue failed");
    4632             : 
    4633        3306 :         if (type_p) {
    4634        3306 :                 *type_p = *r.out.type;
    4635             :         }
    4636        3306 :         if (data_size_p) {
    4637        3306 :                 *data_size_p = *r.out.data_size;
    4638             :         }
    4639        3306 :         if (data_length_p) {
    4640        3306 :                 *data_length_p = *r.out.data_length;
    4641             :         }
    4642        3306 :         if (data_p) {
    4643        3306 :                 *data_p = r.out.data;
    4644             :         }
    4645             : 
    4646        3306 :         return true;
    4647             : }
    4648             : 
    4649         248 : static bool test_winreg_query_printerdata(struct torture_context *tctx,
    4650             :                                           struct dcerpc_binding_handle *b,
    4651             :                                           struct policy_handle *handle,
    4652             :                                           const char *printer_name,
    4653             :                                           const char *key_name,
    4654             :                                           const char *value_name,
    4655             :                                           enum winreg_Type *w_type,
    4656             :                                           uint32_t *w_size,
    4657             :                                           uint32_t *w_length,
    4658             :                                           uint8_t **w_data)
    4659             : {
    4660           0 :         const char *printer_key;
    4661           0 :         struct policy_handle key_handle;
    4662             : 
    4663         248 :         printer_key = talloc_asprintf(tctx, "%s\\%s\\%s",
    4664             :                 TOP_LEVEL_PRINT_PRINTERS_KEY, printer_name, key_name);
    4665             : 
    4666         248 :         torture_assert(tctx,
    4667             :                 test_winreg_OpenKey(tctx, b, handle, printer_key, &key_handle), "");
    4668             : 
    4669         248 :         torture_assert(tctx,
    4670             :                 test_winreg_QueryValue(tctx, b, &key_handle, value_name, w_type, w_size, w_length, w_data), "");
    4671             : 
    4672         248 :         torture_assert(tctx,
    4673             :                 test_winreg_CloseKey(tctx, b, &key_handle), "");
    4674             : 
    4675         248 :         return true;
    4676             : }
    4677             : 
    4678          48 : static bool test_GetForm_winreg(struct torture_context *tctx,
    4679             :                                 struct dcerpc_binding_handle *b,
    4680             :                                 struct policy_handle *handle,
    4681             :                                 const char *key_name,
    4682             :                                 const char *form_name,
    4683             :                                 enum winreg_Type *w_type,
    4684             :                                 uint32_t *w_size,
    4685             :                                 uint32_t *w_length,
    4686             :                                 uint8_t **w_data)
    4687             : {
    4688           0 :         struct policy_handle key_handle;
    4689             : 
    4690          48 :         torture_assert(tctx,
    4691             :                 test_winreg_OpenKey(tctx, b, handle, key_name, &key_handle), "");
    4692             : 
    4693          48 :         torture_assert(tctx,
    4694             :                 test_winreg_QueryValue(tctx, b, &key_handle, form_name, w_type, w_size, w_length, w_data), "");
    4695             : 
    4696          48 :         torture_assert(tctx,
    4697             :                 test_winreg_CloseKey(tctx, b, &key_handle), "");
    4698             : 
    4699          48 :         return true;
    4700             : }
    4701             : 
    4702           8 : static bool test_winreg_symbolic_link(struct torture_context *tctx,
    4703             :                                       struct dcerpc_binding_handle *b,
    4704             :                                       struct policy_handle *handle,
    4705             :                                       const char *symlink_keyname,
    4706             :                                       const char *symlink_destination)
    4707             : {
    4708             :         /* check if the first key is a symlink to the second key */
    4709             : 
    4710           0 :         enum winreg_Type w_type;
    4711           0 :         uint32_t w_size;
    4712           0 :         uint32_t w_length;
    4713           0 :         uint8_t *w_data;
    4714           0 :         struct policy_handle key_handle;
    4715           0 :         DATA_BLOB blob;
    4716           0 :         const char *str;
    4717             : 
    4718           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    4719           8 :                 torture_skip(tctx, "skip winreg symlink test against samba");
    4720             :         }
    4721             : 
    4722           0 :         torture_assert(tctx,
    4723             :                 test_winreg_OpenKey_opts(tctx, b, handle, symlink_keyname, REG_OPTION_OPEN_LINK, &key_handle),
    4724             :                         "failed to open key link");
    4725             : 
    4726           0 :         torture_assert(tctx,
    4727             :                 test_winreg_QueryValue(tctx, b, &key_handle,
    4728             :                                        "SymbolicLinkValue",
    4729             :                                        &w_type, &w_size, &w_length, &w_data),
    4730             :                 "failed to query for 'SymbolicLinkValue' attribute");
    4731             : 
    4732           0 :         torture_assert_int_equal(tctx, w_type, REG_LINK, "unexpected type");
    4733             : 
    4734           0 :         blob = data_blob(w_data, w_size);
    4735           0 :         str = reg_val_data_string(tctx, REG_SZ, blob);
    4736             : 
    4737           0 :         torture_assert_str_equal(tctx, str, symlink_destination, "unexpected symlink target string");
    4738             : 
    4739           0 :         torture_assert(tctx,
    4740             :                 test_winreg_CloseKey(tctx, b, &key_handle),
    4741             :                 "failed to close key link");
    4742             : 
    4743           0 :         return true;
    4744             : }
    4745             : 
    4746          16 : static const char *strip_unc(const char *unc)
    4747             : {
    4748           0 :         char *name;
    4749             : 
    4750          16 :         if (!unc) {
    4751           0 :                 return NULL;
    4752             :         }
    4753             : 
    4754          16 :         if (unc[0] == '\\' && unc[1] == '\\') {
    4755           8 :                 unc +=2;
    4756             :         }
    4757             : 
    4758          16 :         name = strchr(unc, '\\');
    4759          16 :         if (name) {
    4760           8 :                 return name+1;
    4761             :         }
    4762             : 
    4763           8 :         return unc;
    4764             : }
    4765             : 
    4766           8 : static bool test_GetPrinterInfo_winreg(struct torture_context *tctx,
    4767             :                                        struct dcerpc_binding_handle *b,
    4768             :                                        struct policy_handle *handle,
    4769             :                                        const char *printer_name,
    4770             :                                        struct dcerpc_binding_handle *winreg_handle,
    4771             :                                        struct policy_handle *hive_handle)
    4772             : {
    4773           0 :         union spoolss_PrinterInfo info;
    4774           8 :         const char *keys[] = {
    4775             :                 TOP_LEVEL_CONTROL_PRINTERS_KEY,
    4776             :                 TOP_LEVEL_PRINT_PRINTERS_KEY
    4777             :         };
    4778           0 :         int i;
    4779           0 :         const char *printername, *sharename;
    4780             : 
    4781           8 :         torture_comment(tctx, "Testing Printer Info and winreg consistency\n");
    4782             : 
    4783           8 :         torture_assert(tctx,
    4784             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    4785             :                 "failed to get printer info level 2");
    4786             : 
    4787           8 :         printername = strip_unc(info.info2.printername);
    4788           8 :         sharename = strip_unc(info.info2.sharename);
    4789             : 
    4790             : #define test_sz(wname, iname) \
    4791             : do {\
    4792             :         DATA_BLOB blob;\
    4793             :         const char *str;\
    4794             :         enum winreg_Type w_type;\
    4795             :         uint32_t w_size;\
    4796             :         uint32_t w_length;\
    4797             :         uint8_t *w_data;\
    4798             :         torture_assert(tctx,\
    4799             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4800             :                                        &w_type, &w_size, &w_length, &w_data),\
    4801             :                 "failed to query winreg");\
    4802             :         torture_assert_int_equal(tctx, w_type, REG_SZ, "unexpected type");\
    4803             :         blob = data_blob(w_data, w_size);\
    4804             :         str = reg_val_data_string(tctx, REG_SZ, blob);\
    4805             :         if (w_size == 2 && iname == NULL) {\
    4806             :                 /*torture_comment(tctx, "%s: \"\", %s: (null)\n", #wname, #iname);\ */\
    4807             :         } else {\
    4808             :                 torture_assert_str_equal(tctx, str, iname,\
    4809             :                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
    4810             :         }\
    4811             : } while(0);
    4812             : 
    4813             : #define test_dword(wname, iname) \
    4814             : do {\
    4815             :         uint32_t value;\
    4816             :         enum winreg_Type w_type;\
    4817             :         uint32_t w_size;\
    4818             :         uint32_t w_length;\
    4819             :         uint8_t *w_data;\
    4820             :         torture_assert(tctx,\
    4821             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4822             :                                        &w_type, &w_size, &w_length, &w_data),\
    4823             :                 "failed to query winreg");\
    4824             :         torture_assert_int_equal(tctx, w_type, REG_DWORD, "unexpected type");\
    4825             :         torture_assert_int_equal(tctx, w_size, 4, "unexpected size");\
    4826             :         torture_assert_int_equal(tctx, w_length, 4, "unexpected length");\
    4827             :         value = IVAL(w_data, 0);\
    4828             :         torture_assert_int_equal(tctx, value, iname,\
    4829             :                 talloc_asprintf(tctx, "%s - %s mismatch", #wname, #iname));\
    4830             : } while(0);
    4831             : 
    4832             : #define test_binary(wname, iname) \
    4833             : do {\
    4834             :         enum winreg_Type w_type;\
    4835             :         uint32_t w_size;\
    4836             :         uint32_t w_length;\
    4837             :         uint8_t *w_data;\
    4838             :         torture_assert(tctx,\
    4839             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4840             :                                        &w_type, &w_size, &w_length, &w_data),\
    4841             :                 "failed to query winreg");\
    4842             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4843             :         torture_assert_int_equal(tctx, w_size, iname.length, "unexpected length");\
    4844             :         torture_assert_mem_equal(tctx, w_data, iname.data, w_size, \
    4845             :                 "binary unequal");\
    4846             : } while(0);
    4847             : 
    4848             : 
    4849             : #define test_dm(wname, iname) \
    4850             : do {\
    4851             :         DATA_BLOB blob;\
    4852             :         struct spoolss_DeviceMode dm;\
    4853             :         enum ndr_err_code ndr_err;\
    4854             :         enum winreg_Type w_type;\
    4855             :         uint32_t w_size;\
    4856             :         uint32_t w_length;\
    4857             :         uint8_t *w_data;\
    4858             :         torture_assert(tctx,\
    4859             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4860             :                                        &w_type, &w_size, &w_length, &w_data),\
    4861             :                 "failed to query winreg");\
    4862             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4863             :         blob = data_blob(w_data, w_size);\
    4864             :         ndr_err = ndr_pull_struct_blob(&blob, tctx, &dm,\
    4865             :                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);\
    4866             :         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall dm");\
    4867             :         torture_assert(tctx, test_devicemode_equal(tctx, &dm, iname),\
    4868             :                 "dm unequal");\
    4869             : } while(0);
    4870             : 
    4871             : #define test_sd(wname, iname) \
    4872             : do {\
    4873             :         DATA_BLOB blob;\
    4874             :         struct security_descriptor sd;\
    4875             :         enum ndr_err_code ndr_err;\
    4876             :         enum winreg_Type w_type;\
    4877             :         uint32_t w_size;\
    4878             :         uint32_t w_length;\
    4879             :         uint8_t *w_data;\
    4880             :         torture_assert(tctx,\
    4881             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4882             :                                        &w_type, &w_size, &w_length, &w_data),\
    4883             :                 "failed to query winreg");\
    4884             :         torture_assert_int_equal(tctx, w_type, REG_BINARY, "unexpected type");\
    4885             :         blob = data_blob(w_data, w_size);\
    4886             :         ndr_err = ndr_pull_struct_blob(&blob, tctx, &sd,\
    4887             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);\
    4888             :         torture_assert_ndr_success(tctx, ndr_err, "failed to unmarshall sd");\
    4889             :         torture_assert(tctx, test_security_descriptor_equal(tctx, &sd, iname),\
    4890             :                 "sd unequal");\
    4891             : } while(0);
    4892             : 
    4893             : #define test_multi_sz(wname, iname) \
    4894             : do {\
    4895             :         DATA_BLOB blob;\
    4896             :         const char **array;\
    4897             :         enum winreg_Type w_type;\
    4898             :         uint32_t w_size;\
    4899             :         uint32_t w_length;\
    4900             :         uint8_t *w_data;\
    4901             :         int i;\
    4902             :         torture_assert(tctx,\
    4903             :                 test_winreg_QueryValue(tctx, winreg_handle, &key_handle, wname,\
    4904             :                                        &w_type, &w_size, &w_length, &w_data),\
    4905             :                 "failed to query winreg");\
    4906             :         torture_assert_int_equal(tctx, w_type, REG_MULTI_SZ, "unexpected type");\
    4907             :         blob = data_blob(w_data, w_size);\
    4908             :         torture_assert(tctx, \
    4909             :                 pull_reg_multi_sz(tctx, &blob, &array),\
    4910             :                 "failed to pull multi sz");\
    4911             :         for (i=0; array[i] != NULL; i++) {\
    4912             :                 torture_assert_str_equal(tctx, array[i], iname[i],\
    4913             :                         talloc_asprintf(tctx, "%s - %s mismatch", #wname, iname[i]));\
    4914             :         }\
    4915             : } while(0);
    4916             : 
    4917           8 :         if (!test_winreg_symbolic_link(tctx, winreg_handle, hive_handle,
    4918             :                                        TOP_LEVEL_CONTROL_PRINTERS_KEY,
    4919             :                                        "\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"))
    4920             :         {
    4921           0 :                 torture_warning(tctx, "failed to check for winreg symlink");
    4922             :         }
    4923             : 
    4924          24 :         for (i=0; i < ARRAY_SIZE(keys); i++) {
    4925             : 
    4926           0 :                 const char *printer_key;
    4927           0 :                 struct policy_handle key_handle;
    4928             : 
    4929          16 :                 printer_key = talloc_asprintf(tctx, "%s\\%s",
    4930             :                         keys[i], printer_name);
    4931             : 
    4932          16 :                 torture_assert(tctx,
    4933             :                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, printer_key, &key_handle), "");
    4934             : 
    4935          16 :                 test_sz("Name", printername);
    4936          16 :                 test_sz("Share Name", sharename);
    4937          16 :                 test_sz("Port", info.info2.portname);
    4938          16 :                 test_sz("Printer Driver", info.info2.drivername);
    4939          16 :                 test_sz("Description", info.info2.comment);
    4940          16 :                 test_sz("Location", info.info2.location);
    4941          16 :                 test_sz("Separator File", info.info2.sepfile);
    4942          16 :                 test_sz("Print Processor", info.info2.printprocessor);
    4943          16 :                 test_sz("Datatype", info.info2.datatype);
    4944          16 :                 test_sz("Parameters", info.info2.parameters);
    4945             :                 /* winreg: 0, spoolss not */
    4946             : /*              test_dword("Attributes", info.info2.attributes); */
    4947          16 :                 test_dword("Priority", info.info2.priority);
    4948          16 :                 test_dword("Default Priority", info.info2.defaultpriority);
    4949             :                 /* winreg: 60, spoolss: 0 */
    4950             : /*              test_dword("StartTime", info.info2.starttime); */
    4951             : /*              test_dword("UntilTime", info.info2.untiltime); */
    4952             :                 /* winreg != spoolss */
    4953             : /*              test_dword("Status", info.info2.status); */
    4954          16 :                 test_dm("Default DevMode", info.info2.devmode);
    4955          16 :                 test_sd("Security", info.info2.secdesc);
    4956             : 
    4957          16 :                 torture_assert(tctx,
    4958             :                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    4959             :         }
    4960             : 
    4961             : #undef test_dm
    4962             : 
    4963           8 :         torture_comment(tctx, "Printer Info and winreg consistency test succeeded\n\n");
    4964             : 
    4965           8 :         return true;
    4966             : }
    4967             : 
    4968           4 : static bool test_GetPrintserverInfo_winreg(struct torture_context *tctx,
    4969             :                                            struct dcerpc_binding_handle *b,
    4970             :                                            struct policy_handle *handle,
    4971             :                                            struct dcerpc_binding_handle *winreg_handle,
    4972             :                                            struct policy_handle *hive_handle)
    4973             : {
    4974           0 :         union spoolss_PrinterInfo info;
    4975           0 :         struct policy_handle key_handle;
    4976             : 
    4977           4 :         torture_comment(tctx,
    4978             :                 "Testing Printserver Info and winreg consistency\n");
    4979             : 
    4980           4 :         torture_assert(tctx,
    4981             :                 test_GetPrinter_level(tctx, b, handle, 3, &info),
    4982             :                 "failed to get printer info level 2");
    4983             : 
    4984           4 :         torture_assert(tctx,
    4985             :                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle,
    4986             :                                     TOP_LEVEL_CONTROL_KEY, &key_handle), "");
    4987             : 
    4988           4 :         test_sd("ServerSecurityDescriptor", info.info3.secdesc);
    4989             : 
    4990           4 :         torture_assert(tctx,
    4991             :                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    4992             : 
    4993             : #undef test_sd
    4994             : 
    4995           4 :         torture_comment(tctx,
    4996             :                 "Printserver Info and winreg consistency test succeeded\n\n");
    4997             : 
    4998           4 :         return true;
    4999             : }
    5000             : 
    5001             : 
    5002           4 : static bool test_PrintProcessors(struct torture_context *tctx,
    5003             :                                  struct dcerpc_binding_handle *b,
    5004             :                                  const char *environment,
    5005             :                                  struct dcerpc_binding_handle *winreg_handle,
    5006             :                                  struct policy_handle *hive_handle)
    5007             : {
    5008           0 :         union spoolss_PrintProcessorInfo *info;
    5009           0 :         uint32_t count;
    5010           0 :         int i;
    5011             : 
    5012           4 :         torture_comment(tctx, "Testing Print Processor Info and winreg consistency\n");
    5013             : 
    5014           4 :         torture_assert(tctx,
    5015             :                 test_EnumPrintProcessors_level(tctx, b, environment, 1, &count, &info, WERR_OK),
    5016             :                 "failed to enum print processors level 1");
    5017             : 
    5018           8 :         for (i=0; i < count; i++) {
    5019             : 
    5020           0 :                 const char *processor_key;
    5021           0 :                 struct policy_handle key_handle;
    5022             : 
    5023           4 :                 processor_key = talloc_asprintf(tctx, "%s\\%s\\Print Processors\\%s",
    5024             :                                                 TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
    5025             :                                                 environment,
    5026           4 :                                                 info[i].info1.print_processor_name);
    5027             : 
    5028           4 :                 torture_assert(tctx,
    5029             :                         test_winreg_OpenKey(tctx, winreg_handle, hive_handle, processor_key, &key_handle), "");
    5030             : 
    5031             :                 /* nothing to check in there so far */
    5032             : 
    5033           4 :                 torture_assert(tctx,
    5034             :                         test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    5035             :         }
    5036             : 
    5037           4 :         torture_comment(tctx, "Print Processor Info and winreg consistency test succeeded\n\n");
    5038             : 
    5039           4 :         return true;
    5040             : }
    5041             : 
    5042             : static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
    5043             :                                          struct dcerpc_binding_handle *b,
    5044             :                                          struct policy_handle *handle,
    5045             :                                          const char *driver_name,
    5046             :                                          const char *architecture,
    5047             :                                          uint32_t level,
    5048             :                                          uint32_t client_major_version,
    5049             :                                          uint32_t client_minor_version,
    5050             :                                          union spoolss_DriverInfo *info_p,
    5051             :                                          WERROR *result);
    5052             : 
    5053           0 : static const char *strip_path(const char *path)
    5054             : {
    5055           0 :         char *p;
    5056             : 
    5057           0 :         if (path == NULL) {
    5058           0 :                 return NULL;
    5059             :         }
    5060             : 
    5061           0 :         p = strrchr(path, '\\');
    5062           0 :         if (p) {
    5063           0 :                 return p+1;
    5064             :         }
    5065             : 
    5066           0 :         return path;
    5067             : }
    5068             : 
    5069           0 : static const char **strip_paths(const char **path_array)
    5070             : {
    5071           0 :         int i;
    5072             : 
    5073           0 :         if (path_array == NULL) {
    5074           0 :                 return NULL;
    5075             :         }
    5076             : 
    5077           0 :         for (i=0; path_array[i] != NULL; i++) {
    5078           0 :                 path_array[i] = strip_path(path_array[i]);
    5079             :         }
    5080             : 
    5081           0 :         return path_array;
    5082             : }
    5083             : 
    5084           0 : static const char *driver_winreg_date(TALLOC_CTX *mem_ctx, NTTIME nt)
    5085             : {
    5086           0 :         time_t t;
    5087           0 :         struct tm *tm;
    5088             : 
    5089           0 :         if (nt == 0) {
    5090           0 :                 return talloc_strdup(mem_ctx, "01/01/1601");
    5091             :         }
    5092             : 
    5093           0 :         t = nt_time_to_unix(nt);
    5094           0 :         tm = localtime(&t);
    5095             : 
    5096           0 :         return talloc_asprintf(mem_ctx, "%02d/%02d/%04d",
    5097           0 :                 tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900);
    5098             : }
    5099             : 
    5100           0 : static const char *driver_winreg_version(TALLOC_CTX *mem_ctx, uint64_t v)
    5101             : {
    5102           0 :         return talloc_asprintf(mem_ctx, "%u.%u.%u.%u",
    5103           0 :                 (unsigned)((v >> 48) & 0xFFFF),
    5104           0 :                 (unsigned)((v >> 32) & 0xFFFF),
    5105           0 :                 (unsigned)((v >> 16) & 0xFFFF),
    5106             :                 (unsigned)(v & 0xFFFF));
    5107             : }
    5108             : 
    5109           0 : static bool test_GetDriverInfo_winreg(struct torture_context *tctx,
    5110             :                                       struct dcerpc_binding_handle *b,
    5111             :                                       struct policy_handle *handle,
    5112             :                                       const char *printer_name,
    5113             :                                       const char *driver_name,
    5114             :                                       const char *environment,
    5115             :                                       enum spoolss_DriverOSVersion version,
    5116             :                                       struct dcerpc_binding_handle *winreg_handle,
    5117             :                                       struct policy_handle *hive_handle,
    5118             :                                       const char *server_name_slash)
    5119             : {
    5120           0 :         WERROR result = WERR_OK;
    5121           0 :         union spoolss_DriverInfo info;
    5122           0 :         const char *driver_key;
    5123           0 :         struct policy_handle key_handle;
    5124             : 
    5125           0 :         const char *driver_path;
    5126           0 :         const char *data_file;
    5127           0 :         const char *config_file;
    5128           0 :         const char *help_file;
    5129           0 :         const char **dependent_files;
    5130             : 
    5131           0 :         const char *driver_date;
    5132           0 :         const char *inbox_driver_date;
    5133             : 
    5134           0 :         const char *driver_version;
    5135           0 :         const char *inbox_driver_version;
    5136             : 
    5137           0 :         ZERO_STRUCT(key_handle);
    5138             : 
    5139           0 :         torture_comment(tctx, "Testing Driver Info and winreg consistency\n");
    5140             : 
    5141           0 :         driver_key = talloc_asprintf(tctx, "%s\\%s\\Drivers\\Version-%d\\%s",
    5142             :                                      TOP_LEVEL_CONTROL_ENVIRONMENTS_KEY,
    5143             :                                      environment,
    5144             :                                      version,
    5145             :                                      driver_name);
    5146             : 
    5147           0 :         torture_assert(tctx,
    5148             :                 test_winreg_OpenKey(tctx, winreg_handle, hive_handle, driver_key, &key_handle),
    5149             :                 "failed to open driver key");
    5150             : 
    5151           0 :         if (torture_setting_bool(tctx, "samba3", false) ||
    5152           0 :             torture_setting_bool(tctx, "w2k3", false)) {
    5153           0 :                 goto try_level6;
    5154             :         }
    5155             : 
    5156           0 :         if (handle) {
    5157           0 :                 torture_assert(tctx,
    5158             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 8, version, 0, &info, &result),
    5159             :                         "failed to get driver info level 8");
    5160             :         } else {
    5161           0 :                 torture_assert(tctx,
    5162             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 8, driver_name, &info),
    5163             :                         "failed to get driver info level 8");
    5164             :         }
    5165             : 
    5166           0 :         if (W_ERROR_EQUAL(result, WERR_INVALID_LEVEL)) {
    5167           0 :                 goto try_level6;
    5168             :         }
    5169             : 
    5170           0 :         driver_path     = strip_path(info.info8.driver_path);
    5171           0 :         data_file       = strip_path(info.info8.data_file);
    5172           0 :         config_file     = strip_path(info.info8.config_file);
    5173           0 :         help_file       = strip_path(info.info8.help_file);
    5174           0 :         dependent_files = strip_paths(info.info8.dependent_files);
    5175             : 
    5176           0 :         driver_date             = driver_winreg_date(tctx, info.info8.driver_date);
    5177           0 :         inbox_driver_date       = driver_winreg_date(tctx, info.info8.min_inbox_driver_ver_date);
    5178             : 
    5179           0 :         driver_version          = driver_winreg_version(tctx, info.info8.driver_version);
    5180           0 :         inbox_driver_version    = driver_winreg_version(tctx, info.info8.min_inbox_driver_ver_version);
    5181             : 
    5182           0 :         test_sz("Configuration File",         config_file);
    5183           0 :         test_sz("Data File",                  data_file);
    5184           0 :         test_sz("Datatype",                   info.info8.default_datatype);
    5185           0 :         test_sz("Driver",                     driver_path);
    5186           0 :         test_sz("DriverDate",                 driver_date);
    5187           0 :         test_sz("DriverVersion",              driver_version);
    5188           0 :         test_sz("HardwareID",                 info.info8.hardware_id);
    5189           0 :         test_sz("Help File",                  help_file);
    5190           0 :         test_sz("InfPath",                    info.info8.inf_path);
    5191           0 :         test_sz("Manufacturer",                       info.info8.manufacturer_name);
    5192           0 :         test_sz("MinInboxDriverVerDate",      inbox_driver_date);
    5193           0 :         test_sz("MinInboxDriverVerVersion",   inbox_driver_version);
    5194           0 :         test_sz("Monitor",                    info.info8.monitor_name);
    5195           0 :         test_sz("OEM URL",                    info.info8.manufacturer_url);
    5196           0 :         test_sz("Print Processor",            info.info8.print_processor);
    5197           0 :         test_sz("Provider",                   info.info8.provider);
    5198           0 :         test_sz("VendorSetup",                        info.info8.vendor_setup);
    5199           0 :         test_multi_sz("ColorProfiles",                info.info8.color_profiles);
    5200           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5201           0 :         test_multi_sz("CoreDependencies",     info.info8.core_driver_dependencies);
    5202           0 :         test_multi_sz("Previous Names",               info.info8.previous_names);
    5203             : /*      test_dword("Attributes",              ?); */
    5204           0 :         test_dword("PrinterDriverAttributes", info.info8.printer_driver_attributes);
    5205           0 :         test_dword("Version",                 info.info8.version);
    5206             : /*      test_dword("TempDir",                 ?); */
    5207             : 
    5208           0 :  try_level6:
    5209             : 
    5210           0 :         if (handle) {
    5211           0 :                 torture_assert(tctx,
    5212             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 6, version, 0, &info, &result),
    5213             :                         "failed to get driver info level 6");
    5214             :         } else {
    5215           0 :                 torture_assert(tctx,
    5216             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 6, driver_name, &info),
    5217             :                         "failed to get driver info level 6");
    5218             :         }
    5219             : 
    5220           0 :         driver_path     = strip_path(info.info6.driver_path);
    5221           0 :         data_file       = strip_path(info.info6.data_file);
    5222           0 :         config_file     = strip_path(info.info6.config_file);
    5223           0 :         help_file       = strip_path(info.info6.help_file);
    5224           0 :         dependent_files = strip_paths(info.info6.dependent_files);
    5225             : 
    5226           0 :         driver_date             = driver_winreg_date(tctx, info.info6.driver_date);
    5227             : 
    5228           0 :         driver_version          = driver_winreg_version(tctx, info.info6.driver_version);
    5229             : 
    5230           0 :         test_sz("Configuration File",         config_file);
    5231           0 :         test_sz("Data File",                  data_file);
    5232           0 :         test_sz("Datatype",                   info.info6.default_datatype);
    5233           0 :         test_sz("Driver",                     driver_path);
    5234           0 :         if (torture_setting_bool(tctx, "w2k3", false)) {
    5235           0 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, 8);
    5236           0 :                 push_nttime(blob.data, 0, info.info6.driver_date);
    5237           0 :                 test_binary("DriverDate",     blob);
    5238           0 :                 SBVAL(blob.data, 0, info.info6.driver_version);
    5239           0 :                 test_binary("DriverVersion",  blob);
    5240             :         } else {
    5241           0 :                 test_sz("DriverDate",         driver_date);
    5242           0 :                 test_sz("DriverVersion",      driver_version);
    5243             :         }
    5244           0 :         test_sz("HardwareID",                 info.info6.hardware_id);
    5245           0 :         test_sz("Help File",                  help_file);
    5246           0 :         test_sz("Manufacturer",                       info.info6.manufacturer_name);
    5247           0 :         test_sz("Monitor",                    info.info6.monitor_name);
    5248           0 :         test_sz("OEM URL",                    info.info6.manufacturer_url);
    5249           0 :         test_sz("Provider",                   info.info6.provider);
    5250           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5251           0 :         test_multi_sz("Previous Names",               info.info6.previous_names);
    5252             : /*      test_dword("Attributes",              ?); */
    5253           0 :         test_dword("Version",                 info.info6.version);
    5254             : /*      test_dword("TempDir",                 ?); */
    5255             : 
    5256           0 :         if (handle) {
    5257           0 :                 torture_assert(tctx,
    5258             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, environment, 3, version, 0, &info, &result),
    5259             :                         "failed to get driver info level 3");
    5260             :         } else {
    5261           0 :                 torture_assert(tctx,
    5262             :                         test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, environment, 3, driver_name, &info),
    5263             :                         "failed to get driver info level 3");
    5264             :         }
    5265             : 
    5266           0 :         driver_path     = strip_path(info.info3.driver_path);
    5267           0 :         data_file       = strip_path(info.info3.data_file);
    5268           0 :         config_file     = strip_path(info.info3.config_file);
    5269           0 :         help_file       = strip_path(info.info3.help_file);
    5270           0 :         dependent_files = strip_paths(info.info3.dependent_files);
    5271             : 
    5272           0 :         test_sz("Configuration File",         config_file);
    5273           0 :         test_sz("Data File",                  data_file);
    5274           0 :         test_sz("Datatype",                   info.info3.default_datatype);
    5275           0 :         test_sz("Driver",                     driver_path);
    5276           0 :         test_sz("Help File",                  help_file);
    5277           0 :         test_sz("Monitor",                    info.info3.monitor_name);
    5278           0 :         test_multi_sz("Dependent Files",      dependent_files);
    5279             : /*      test_dword("Attributes",              ?); */
    5280           0 :         test_dword("Version",                 info.info3.version);
    5281             : /*      test_dword("TempDir",                 ?); */
    5282             : 
    5283             : 
    5284           0 :         torture_assert(tctx,
    5285             :                 test_winreg_CloseKey(tctx, winreg_handle, &key_handle), "");
    5286             : 
    5287           0 :         torture_comment(tctx, "Driver Info and winreg consistency test succeeded\n\n");
    5288             : 
    5289           0 :         return true;
    5290             : }
    5291             : 
    5292             : #undef test_sz
    5293             : #undef test_dword
    5294             : 
    5295         168 : static bool test_SetPrinterData(struct torture_context *tctx,
    5296             :                                 struct dcerpc_binding_handle *b,
    5297             :                                 struct policy_handle *handle,
    5298             :                                 const char *value_name,
    5299             :                                 enum winreg_Type type,
    5300             :                                 uint8_t *data,
    5301             :                                 uint32_t offered)
    5302             : {
    5303           0 :         struct spoolss_SetPrinterData r;
    5304             : 
    5305         168 :         r.in.handle = handle;
    5306         168 :         r.in.value_name = value_name;
    5307         168 :         r.in.type = type;
    5308         168 :         r.in.data = data;
    5309         168 :         r.in.offered = offered;
    5310             : 
    5311         168 :         torture_comment(tctx, "Testing SetPrinterData(%s)\n",
    5312             :                 r.in.value_name);
    5313             : 
    5314         168 :         torture_assert_ntstatus_ok(tctx,
    5315             :                 dcerpc_spoolss_SetPrinterData_r(b, tctx, &r),
    5316             :                 "SetPrinterData failed");
    5317         168 :         torture_assert_werr_ok(tctx, r.out.result,
    5318             :                 "SetPrinterData failed");
    5319             : 
    5320         168 :         return true;
    5321             : }
    5322             : 
    5323          28 : static bool test_SetPrinterData_matrix(struct torture_context *tctx,
    5324             :                                        struct dcerpc_binding_handle *b,
    5325             :                                        struct policy_handle *handle,
    5326             :                                        const char *printer_name,
    5327             :                                        struct dcerpc_binding_handle *winreg_handle,
    5328             :                                        struct policy_handle *hive_handle)
    5329             : {
    5330          28 :         const char *values[] = {
    5331             :                 "spootyfoot",
    5332             :                 "spooty\\foot",
    5333             : #if 0
    5334             :         /* FIXME: not working with s3 atm. */
    5335             :                 "spooty,foot",
    5336             :                 "spooty,fo,ot",
    5337             : #endif
    5338             :                 "spooty foot",
    5339             : #if 0
    5340             :         /* FIXME: not working with s3 atm. */
    5341             :                 "spooty\\fo,ot",
    5342             :                 "spooty,fo\\ot"
    5343             : #endif
    5344             :         };
    5345           0 :         int i;
    5346             : 
    5347         112 :         for (i=0; i < ARRAY_SIZE(values); i++) {
    5348             : 
    5349          84 :                 enum winreg_Type type, expected_type = REG_SZ;
    5350           0 :                 DATA_BLOB blob;
    5351           0 :                 uint8_t *data;
    5352           0 :                 uint32_t needed;
    5353             : 
    5354          84 :                 torture_assert(tctx, push_reg_sz(tctx, &blob, "dog"), "");
    5355          84 :                 type = REG_SZ;
    5356             : 
    5357          84 :                 torture_assert(tctx,
    5358             :                         test_SetPrinterData(tctx, b, handle, values[i], REG_SZ, blob.data, blob.length),
    5359             :                         "SetPrinterData failed");
    5360             : 
    5361          84 :                 torture_assert(tctx,
    5362             :                         test_GetPrinterData_checktype(tctx, b, handle, values[i], &expected_type, &type, &data, &needed),
    5363             :                         "GetPrinterData failed");
    5364             : 
    5365          84 :                 torture_assert_int_equal(tctx, type, REG_SZ, "type mismatch");
    5366          84 :                 torture_assert_int_equal(tctx, needed, blob.length, "size mismatch");
    5367          84 :                 torture_assert_mem_equal(tctx, data, blob.data, blob.length, "buffer mismatch");
    5368             : 
    5369          84 :                 if (winreg_handle && hive_handle) {
    5370             : 
    5371           0 :                         enum winreg_Type w_type;
    5372           0 :                         uint32_t w_size;
    5373           0 :                         uint32_t w_length;
    5374           0 :                         uint8_t *w_data;
    5375             : 
    5376          24 :                         torture_assert(tctx,
    5377             :                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
    5378             :                                         printer_name, "PrinterDriverData", values[i],
    5379             :                                         &w_type, &w_size, &w_length, &w_data), "");
    5380             : 
    5381          24 :                         torture_assert_int_equal(tctx, w_type, REG_SZ, "winreg type mismatch");
    5382          24 :                         torture_assert_int_equal(tctx, w_size, blob.length, "winreg size mismatch");
    5383          24 :                         torture_assert_int_equal(tctx, w_length, blob.length, "winreg length mismatch");
    5384          24 :                         torture_assert_mem_equal(tctx, w_data, blob.data, blob.length, "winreg buffer mismatch");
    5385             :                 }
    5386             : 
    5387          84 :                 torture_assert(tctx,
    5388             :                         test_DeletePrinterData(tctx, b, handle, values[i]),
    5389             :                         "DeletePrinterData failed");
    5390             :         }
    5391             : 
    5392          28 :         return true;
    5393             : }
    5394             : 
    5395             : 
    5396             : static bool test_EnumPrinterKey(struct torture_context *tctx,
    5397             :                                 struct dcerpc_binding_handle *b,
    5398             :                                 struct policy_handle *handle,
    5399             :                                 const char *key_name,
    5400             :                                 const char ***array);
    5401             : 
    5402        1200 : static bool test_SetPrinterDataEx(struct torture_context *tctx,
    5403             :                                   struct dcerpc_binding_handle *b,
    5404             :                                   struct policy_handle *handle,
    5405             :                                   const char *key_name,
    5406             :                                   const char *value_name,
    5407             :                                   enum winreg_Type type,
    5408             :                                   uint8_t *data,
    5409             :                                   uint32_t offered)
    5410             : {
    5411           0 :         NTSTATUS status;
    5412           0 :         struct spoolss_SetPrinterDataEx r;
    5413             : 
    5414        1200 :         r.in.handle = handle;
    5415        1200 :         r.in.key_name = key_name;
    5416        1200 :         r.in.value_name = value_name;
    5417        1200 :         r.in.type = type;
    5418        1200 :         r.in.data = data;
    5419        1200 :         r.in.offered = offered;
    5420             : 
    5421        1200 :         torture_comment(tctx, "Testing SetPrinterDataEx(%s - %s) type: %s, offered: 0x%08x\n",
    5422        1200 :                 r.in.key_name, r.in.value_name, str_regtype(r.in.type), r.in.offered);
    5423             : 
    5424        1200 :         status = dcerpc_spoolss_SetPrinterDataEx_r(b, tctx, &r);
    5425             : 
    5426        1200 :         torture_assert_ntstatus_ok(tctx, status, "SetPrinterDataEx failed");
    5427        1200 :         torture_assert_werr_ok(tctx, r.out.result, "SetPrinterDataEx failed");
    5428             : 
    5429        1200 :         return true;
    5430             : }
    5431             : 
    5432           8 : static bool test_SetPrinterDataEx_keys(struct torture_context *tctx,
    5433             :                                        struct dcerpc_pipe *p,
    5434             :                                        struct policy_handle *handle)
    5435             : {
    5436           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5437           8 :         const char *value_name = "dog";
    5438           8 :         const char *keys[] = {
    5439             :                 "torturedataex",
    5440             :                 "torture data ex",
    5441             :                 "torturedataex_with_subkey\\subkey",
    5442             :                 "torturedataex_with_subkey\\subkey:0",
    5443             :                 "torturedataex_with_subkey\\subkey:1",
    5444             :                 "torturedataex_with_subkey\\subkey\\subsubkey",
    5445             :                 "torturedataex_with_subkey\\subkey\\subsubkey:0",
    5446             :                 "torturedataex_with_subkey\\subkey\\subsubkey:1",
    5447             :                 "torture,data",
    5448             :                 "torture,data,ex",
    5449             :                 "torture,data\\ex",
    5450             :                 "torture\\data,ex",
    5451             :                 "torture/data",
    5452             :                 "torture/data ex",
    5453             :                 "torture/data ex/sub",
    5454             :                 "torture//data",
    5455             :                 "torture//data ex",
    5456             :                 "torture//data ex/sub",
    5457             :                 "torture//data ex//sub",
    5458             :         };
    5459           0 :         int i;
    5460             : 
    5461         160 :         for (i=0; i < ARRAY_SIZE(keys); i++) {
    5462             : 
    5463           0 :                 char *c;
    5464           0 :                 const char *key;
    5465           0 :                 enum winreg_Type type;
    5466           0 :                 DATA_BLOB blob_in, blob_out;
    5467           0 :                 const char **subkeys;
    5468           0 :                 uint32_t ecount;
    5469           0 :                 struct spoolss_PrinterEnumValues *einfo;
    5470           0 :                 uint32_t needed;
    5471             : 
    5472         152 :                 blob_in = data_blob_talloc(tctx, NULL, 42);
    5473             : 
    5474         152 :                 generate_random_buffer(blob_in.data, blob_in.length);
    5475             : 
    5476         152 :                 torture_assert(tctx,
    5477             :                         test_SetPrinterDataEx(tctx, b, handle, keys[i], value_name, REG_BINARY, blob_in.data, blob_in.length),
    5478             :                         "failed to call SetPrinterDataEx");
    5479             : 
    5480         152 :                 torture_assert(tctx,
    5481             :                         test_GetPrinterDataEx(tctx, p, handle, keys[i], value_name, &type, &blob_out.data, &needed),
    5482             :                         "failed to call GetPrinterDataEx");
    5483             : 
    5484         152 :                 blob_out.length = needed;
    5485         152 :                 torture_assert(tctx,
    5486             :                         test_EnumPrinterDataEx(tctx, b, handle, keys[i], &ecount, &einfo),
    5487             :                         "failed to call EnumPrinterDataEx");
    5488             : 
    5489         152 :                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
    5490         152 :                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
    5491         152 :                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
    5492             : 
    5493         152 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5494         152 :                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
    5495         152 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
    5496         152 :                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
    5497         152 :                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
    5498         152 :                 if (einfo[0].data_length > 0) {
    5499         152 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
    5500             :                 }
    5501             : 
    5502         152 :                 key = talloc_strdup(tctx, keys[i]);
    5503             : 
    5504         152 :                 if (!test_DeletePrinterDataEx(tctx, b, handle, keys[i], value_name)) {
    5505           0 :                         return false;
    5506             :                 }
    5507             : 
    5508         152 :                 c = strchr(key, '\\');
    5509         152 :                 if (c) {
    5510           0 :                         int k;
    5511             : 
    5512             :                         /* we have subkeys */
    5513             : 
    5514          64 :                         *c = 0;
    5515             : 
    5516          64 :                         if (!test_EnumPrinterKey(tctx, b, handle, key, &subkeys)) {
    5517           0 :                                 return false;
    5518             :                         }
    5519             : 
    5520         128 :                         for (k=0; subkeys && subkeys[k]; k++) {
    5521             : 
    5522          64 :                                 const char *current_key = talloc_asprintf(tctx, "%s\\%s", key, subkeys[k]);
    5523             : 
    5524          64 :                                 if (!test_DeletePrinterKey(tctx, b, handle, current_key)) {
    5525           0 :                                         return false;
    5526             :                                 }
    5527             :                         }
    5528             : 
    5529          64 :                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
    5530           0 :                                 return false;
    5531             :                         }
    5532             : 
    5533             :                 } else {
    5534          88 :                         if (!test_DeletePrinterKey(tctx, b, handle, key)) {
    5535           0 :                                 return false;
    5536             :                         }
    5537             :                 }
    5538             :         }
    5539             : 
    5540           8 :         return true;
    5541             : }
    5542             : 
    5543           8 : static bool test_SetPrinterDataEx_values(struct torture_context *tctx,
    5544             :                                          struct dcerpc_pipe *p,
    5545             :                                          struct policy_handle *handle)
    5546             : {
    5547           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5548           8 :         const char *key = "torturedataex";
    5549           8 :         const char *values[] = {
    5550             :                 "torture_value",
    5551             :                 "torture value",
    5552             :                 "torture,value",
    5553             :                 "torture/value",
    5554             :                 "torture\\value",
    5555             :                 "torture\\\\value"
    5556             :         };
    5557           0 :         int i;
    5558             : 
    5559          56 :         for (i=0; i < ARRAY_SIZE(values); i++) {
    5560             : 
    5561          48 :                 enum winreg_Type type = REG_NONE;
    5562          48 :                 DATA_BLOB blob_in = data_blob_null;
    5563          48 :                 DATA_BLOB blob_out = data_blob_null;
    5564           0 :                 uint32_t ecount;
    5565           0 :                 struct spoolss_PrinterEnumValues *einfo;
    5566          48 :                 uint32_t needed = 0;
    5567             : 
    5568          48 :                 if (torture_setting_bool(tctx, "samba3", false)) {
    5569           0 :                         char *q;
    5570          48 :                         q = strrchr(values[i], ',');
    5571          48 :                         if (q) {
    5572           8 :                                 torture_comment(tctx, "skipping valuename '%s' including ',' character against Samba3\n",
    5573             :                                                 values[i]);
    5574           8 :                                 continue;
    5575             :                         }
    5576             :                 }
    5577             : 
    5578          40 :                 blob_in = data_blob_talloc(tctx, NULL, 42);
    5579             : 
    5580          40 :                 generate_random_buffer(blob_in.data, blob_in.length);
    5581             : 
    5582          40 :                 torture_assert(tctx,
    5583             :                         test_SetPrinterDataEx(tctx, b, handle, key, values[i], REG_BINARY, blob_in.data, blob_in.length),
    5584             :                         "failed to call SetPrinterDataEx");
    5585             : 
    5586          40 :                 torture_assert(tctx,
    5587             :                         test_GetPrinterDataEx(tctx, p, handle, key, values[i], &type, &blob_out.data, &needed),
    5588             :                         "failed to call GetPrinterDataEx");
    5589             : 
    5590          40 :                 blob_out.length = needed;
    5591          40 :                 torture_assert(tctx,
    5592             :                         test_EnumPrinterDataEx(tctx, b, handle, key, &ecount, &einfo),
    5593             :                         "failed to call EnumPrinterDataEx");
    5594             : 
    5595          40 :                 torture_assert_int_equal(tctx, type, REG_BINARY, "type mismatch");
    5596          40 :                 torture_assert_int_equal(tctx, blob_out.length, blob_in.length, "size mismatch");
    5597          40 :                 torture_assert_mem_equal(tctx, blob_out.data, blob_in.data, blob_in.length, "buffer mismatch");
    5598             : 
    5599          40 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5600          40 :                 torture_assert_str_equal(tctx, einfo[0].value_name, values[i], "value_name mismatch");
    5601          40 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(values[i])*2, "unexpected value_name_len");
    5602          40 :                 torture_assert_int_equal(tctx, einfo[0].type, REG_BINARY, "type mismatch");
    5603          40 :                 torture_assert_int_equal(tctx, einfo[0].data_length, blob_in.length, "size mismatch");
    5604          40 :                 if (einfo[0].data_length > 0) {
    5605          40 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, blob_in.data, blob_in.length, "buffer mismatch");
    5606             :                 }
    5607             : 
    5608          40 :                 torture_assert(tctx,
    5609             :                         test_DeletePrinterDataEx(tctx, b, handle, key, values[i]),
    5610             :                         "failed to call DeletePrinterDataEx");
    5611             :         }
    5612             : 
    5613           8 :         return true;
    5614             : }
    5615             : 
    5616             : 
    5617          36 : static bool test_SetPrinterDataEx_matrix(struct torture_context *tctx,
    5618             :                                          struct dcerpc_pipe *p,
    5619             :                                          struct policy_handle *handle,
    5620             :                                          const char *printername,
    5621             :                                          struct dcerpc_binding_handle *winreg_handle,
    5622             :                                          struct policy_handle *hive_handle)
    5623             : {
    5624          36 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5625          36 :         const char *value_name = "dog";
    5626          36 :         const char *key_name = "torturedataex";
    5627          36 :         enum winreg_Type types[] = {
    5628             :                 REG_SZ,
    5629             :                 REG_MULTI_SZ,
    5630             :                 REG_DWORD,
    5631             :                 REG_BINARY
    5632             :         };
    5633          36 :         const char *str = "abcdefghi";
    5634           0 :         size_t t, s;
    5635             : 
    5636         180 :         for (t=0; t < ARRAY_SIZE(types); t++) {
    5637        1152 :         for (s=0; s < strlen(str); s++) {
    5638             : 
    5639           0 :                 enum winreg_Type type;
    5640        1008 :                 const char *string = talloc_strndup(tctx, str, s);
    5641           0 :                 const char *array[2];
    5642        1008 :                 DATA_BLOB blob = data_blob_string_const(string);
    5643           0 :                 DATA_BLOB data;
    5644           0 :                 uint8_t *data_out;
    5645        1008 :                 uint32_t needed, offered = 0;
    5646           0 :                 uint32_t ecount;
    5647           0 :                 struct spoolss_PrinterEnumValues *einfo;
    5648             : 
    5649        1008 :                 array[0] = talloc_strdup(tctx, string);
    5650        1008 :                 array[1] = NULL;
    5651             : 
    5652        1008 :                 if (types[t] == REG_DWORD) {
    5653          36 :                         s = 0xffff;
    5654             :                 }
    5655             : 
    5656        1008 :                 switch (types[t]) {
    5657         324 :                 case REG_BINARY:
    5658         324 :                         data = blob;
    5659         324 :                         offered = blob.length;
    5660         324 :                         break;
    5661          36 :                 case REG_DWORD:
    5662          36 :                         data = data_blob_talloc(tctx, NULL, 4);
    5663          36 :                         SIVAL(data.data, 0, 0x12345678);
    5664          36 :                         offered = 4;
    5665          36 :                         break;
    5666         324 :                 case REG_SZ:
    5667         324 :                         torture_assert(tctx, push_reg_sz(tctx, &data, string), "");
    5668         324 :                         type = REG_SZ;
    5669         324 :                         offered = data.length;
    5670             :                         /*strlen_m_term(data.string)*2;*/
    5671         324 :                         break;
    5672         324 :                 case REG_MULTI_SZ:
    5673         324 :                         torture_assert(tctx, push_reg_multi_sz(tctx, &data, array), "");
    5674         324 :                         type = REG_MULTI_SZ;
    5675         324 :                         offered = data.length;
    5676         324 :                         break;
    5677           0 :                 default:
    5678           0 :                         torture_fail(tctx, talloc_asprintf(tctx, "type %d untested\n", types[t]));
    5679             :                 }
    5680             : 
    5681        1008 :                 torture_assert(tctx,
    5682             :                         test_SetPrinterDataEx(tctx, b, handle, key_name, value_name, types[t], data.data, offered),
    5683             :                         "failed to call SetPrinterDataEx");
    5684             : 
    5685        1008 :                 torture_assert(tctx,
    5686             :                         test_GetPrinterDataEx_checktype(tctx, p, handle, key_name, value_name, &types[t], &type, &data_out, &needed),
    5687             :                         "failed to call GetPrinterDataEx");
    5688             : 
    5689        1008 :                 torture_assert(tctx,
    5690             :                         test_EnumPrinterDataEx(tctx, b, handle, key_name, &ecount, &einfo),
    5691             :                         "failed to call EnumPrinterDataEx");
    5692             : 
    5693        1008 :                 torture_assert_int_equal(tctx, types[t], type, "type mismatch");
    5694        1008 :                 torture_assert_int_equal(tctx, needed, offered, "size mismatch");
    5695        1008 :                 torture_assert_mem_equal(tctx, data_out, data.data, offered, "buffer mismatch");
    5696             : 
    5697        1008 :                 torture_assert_int_equal(tctx, ecount, 1, "unexpected enum count");
    5698        1008 :                 torture_assert_str_equal(tctx, einfo[0].value_name, value_name, "value_name mismatch");
    5699        1008 :                 torture_assert_int_equal(tctx, einfo[0].value_name_len, strlen_m_term(value_name)*2, "unexpected value_name_len");
    5700        1008 :                 torture_assert_int_equal(tctx, einfo[0].type, types[t], "type mismatch");
    5701        1008 :                 torture_assert_int_equal(tctx, einfo[0].data_length, offered, "size mismatch");
    5702        1008 :                 if (einfo[0].data_length > 0) {
    5703         972 :                         torture_assert_mem_equal(tctx, einfo[0].data->data, data.data, offered, "buffer mismatch");
    5704             :                 }
    5705             : 
    5706        1008 :                 if (winreg_handle && hive_handle) {
    5707           0 :                         enum winreg_Type w_type;
    5708           0 :                         uint32_t w_size;
    5709           0 :                         uint32_t w_length;
    5710           0 :                         uint8_t *w_data;
    5711             : 
    5712         224 :                         torture_assert(tctx,
    5713             :                                 test_winreg_query_printerdata(tctx, winreg_handle, hive_handle,
    5714             :                                         printername, key_name, value_name,
    5715             :                                         &w_type, &w_size, &w_length, &w_data), "");
    5716             : 
    5717         224 :                         torture_assert_int_equal(tctx, w_type, types[t], "winreg type mismatch");
    5718         224 :                         torture_assert_int_equal(tctx, w_size, offered, "winreg size mismatch");
    5719         224 :                         torture_assert_int_equal(tctx, w_length, offered, "winreg length mismatch");
    5720         224 :                         torture_assert_mem_equal(tctx, w_data, data.data, offered, "winreg buffer mismatch");
    5721             :                 }
    5722             : 
    5723        1008 :                 torture_assert(tctx,
    5724             :                         test_DeletePrinterDataEx(tctx, b, handle, key_name, value_name),
    5725             :                         "failed to call DeletePrinterDataEx");
    5726             :         }
    5727             :         }
    5728             : 
    5729          36 :         return true;
    5730             : }
    5731             : 
    5732           8 : static bool test_PrinterData_winreg(struct torture_context *tctx,
    5733             :                                     struct dcerpc_pipe *p,
    5734             :                                     struct policy_handle *handle,
    5735             :                                     const char *printer_name)
    5736             : {
    5737           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5738           0 :         struct dcerpc_pipe *p2;
    5739           8 :         bool ret = true;
    5740           0 :         struct policy_handle hive_handle;
    5741           0 :         struct dcerpc_binding_handle *b2;
    5742             : 
    5743           8 :         torture_assert_ntstatus_ok(tctx,
    5744             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5745             :                 "could not open winreg pipe");
    5746           8 :         b2 = p2->binding_handle;
    5747             : 
    5748           8 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5749             : 
    5750           8 :         ret &= test_SetPrinterData_matrix(tctx, b, handle, printer_name, b2, &hive_handle);
    5751           8 :         ret &= test_SetPrinterDataEx_matrix(tctx, p, handle, printer_name, b2, &hive_handle);
    5752             : 
    5753           8 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5754             : 
    5755           8 :         talloc_free(p2);
    5756             : 
    5757           8 :         return ret;
    5758             : }
    5759             : 
    5760          24 : static bool test_Forms_winreg(struct torture_context *tctx,
    5761             :                               struct dcerpc_binding_handle *b,
    5762             :                               struct policy_handle *handle,
    5763             :                               bool print_server,
    5764             :                               const char *printer_name)
    5765             : {
    5766           0 :         struct dcerpc_pipe *p2;
    5767          24 :         bool ret = true;
    5768           0 :         struct policy_handle hive_handle;
    5769           0 :         struct dcerpc_binding_handle *b2;
    5770             : 
    5771          24 :         torture_assert_ntstatus_ok(tctx,
    5772             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5773             :                 "could not open winreg pipe");
    5774          24 :         b2 = p2->binding_handle;
    5775             : 
    5776          24 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5777             : 
    5778          24 :         ret = test_Forms(tctx, b, handle, print_server, printer_name, b2, &hive_handle);
    5779             : 
    5780          24 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5781             : 
    5782          24 :         talloc_free(p2);
    5783             : 
    5784          24 :         return ret;
    5785             : }
    5786             : 
    5787           8 : static bool test_PrinterInfo_winreg(struct torture_context *tctx,
    5788             :                                     struct dcerpc_pipe *p,
    5789             :                                     struct policy_handle *handle,
    5790             :                                     const char *printer_name)
    5791             : {
    5792           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5793           0 :         struct dcerpc_pipe *p2;
    5794           8 :         bool ret = true;
    5795           0 :         struct policy_handle hive_handle;
    5796           0 :         struct dcerpc_binding_handle *b2;
    5797             : 
    5798           8 :         torture_assert_ntstatus_ok(tctx,
    5799             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5800             :                 "could not open winreg pipe");
    5801           8 :         b2 = p2->binding_handle;
    5802             : 
    5803           8 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5804             : 
    5805           8 :         ret = test_GetPrinterInfo_winreg(tctx, b, handle, printer_name, b2, &hive_handle);
    5806             : 
    5807           8 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5808             : 
    5809           8 :         talloc_free(p2);
    5810             : 
    5811           8 :         return ret;
    5812             : }
    5813             : 
    5814           4 : static bool test_PrintserverInfo_winreg(struct torture_context *tctx,
    5815             :                                         struct dcerpc_pipe *p,
    5816             :                                         struct policy_handle *handle)
    5817             : {
    5818           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5819           0 :         struct dcerpc_pipe *p2;
    5820           4 :         bool ret = true;
    5821           0 :         struct policy_handle hive_handle;
    5822           0 :         struct dcerpc_binding_handle *b2;
    5823             : 
    5824           4 :         torture_assert_ntstatus_ok(tctx,
    5825             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5826             :                 "could not open winreg pipe");
    5827           4 :         b2 = p2->binding_handle;
    5828             : 
    5829           4 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5830             : 
    5831           4 :         ret = test_GetPrintserverInfo_winreg(tctx, b, handle, b2, &hive_handle);
    5832             : 
    5833           4 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5834             : 
    5835           4 :         talloc_free(p2);
    5836             : 
    5837           4 :         return ret;
    5838             : }
    5839             : 
    5840             : 
    5841           0 : static bool test_DriverInfo_winreg(struct torture_context *tctx,
    5842             :                                    struct dcerpc_pipe *p,
    5843             :                                    struct policy_handle *handle,
    5844             :                                    const char *printer_name,
    5845             :                                    const char *driver_name,
    5846             :                                    const char *environment,
    5847             :                                    enum spoolss_DriverOSVersion version)
    5848             : {
    5849           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5850           0 :         struct dcerpc_pipe *p2;
    5851           0 :         bool ret = true;
    5852           0 :         struct policy_handle hive_handle;
    5853           0 :         struct dcerpc_binding_handle *b2;
    5854             : 
    5855           0 :         torture_assert_ntstatus_ok(tctx,
    5856             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5857             :                 "could not open winreg pipe");
    5858           0 :         b2 = p2->binding_handle;
    5859             : 
    5860           0 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5861             : 
    5862           0 :         ret = test_GetDriverInfo_winreg(tctx, b, handle, printer_name, driver_name, environment, version, b2, &hive_handle, NULL);
    5863             : 
    5864           0 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5865             : 
    5866           0 :         talloc_free(p2);
    5867             : 
    5868           0 :         return ret;
    5869             : }
    5870             : 
    5871           4 : static bool test_PrintProcessors_winreg(struct torture_context *tctx,
    5872             :                                         struct dcerpc_binding_handle *b,
    5873             :                                         const char *environment)
    5874             : {
    5875           0 :         struct dcerpc_pipe *p2;
    5876           4 :         bool ret = true;
    5877           0 :         struct policy_handle hive_handle;
    5878           0 :         struct dcerpc_binding_handle *b2;
    5879             : 
    5880           4 :         torture_assert_ntstatus_ok(tctx,
    5881             :                 torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
    5882             :                 "could not open winreg pipe");
    5883           4 :         b2 = p2->binding_handle;
    5884             : 
    5885           4 :         torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
    5886             : 
    5887           4 :         ret = test_PrintProcessors(tctx, b, environment, b2, &hive_handle);
    5888             : 
    5889           4 :         test_winreg_CloseKey(tctx, b2, &hive_handle);
    5890             : 
    5891           4 :         talloc_free(p2);
    5892             : 
    5893           4 :         return ret;
    5894             : }
    5895             : 
    5896           8 : static bool test_PrinterData_DsSpooler(struct torture_context *tctx,
    5897             :                                        struct dcerpc_pipe *p,
    5898             :                                        struct policy_handle *handle,
    5899             :                                        const char *printer_name)
    5900             : {
    5901           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    5902           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    5903           0 :         struct sec_desc_buf secdesc_ctr;
    5904           0 :         union spoolss_SetPrinterInfo sinfo;
    5905           0 :         union spoolss_PrinterInfo info;
    5906           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    5907           0 :         const char *pname;
    5908             : 
    5909           8 :         ZERO_STRUCT(info_ctr);
    5910           8 :         ZERO_STRUCT(devmode_ctr);
    5911           8 :         ZERO_STRUCT(secdesc_ctr);
    5912             : 
    5913           8 :         torture_comment(tctx, "Testing DsSpooler <-> SetPrinter relations\n");
    5914             : 
    5915           8 :         torture_assert(tctx,
    5916             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    5917             :                 "failed to query Printer level 2");
    5918             : 
    5919           8 :         torture_assert(tctx,
    5920             :                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo),
    5921             :                 "failed to convert");
    5922             : 
    5923           8 :         info_ctr.level = 2;
    5924           8 :         info_ctr.info = sinfo;
    5925             : 
    5926             : #define TEST_SZ(wname, iname) \
    5927             : do {\
    5928             :         enum winreg_Type type;\
    5929             :         uint8_t *data;\
    5930             :         uint32_t needed;\
    5931             :         DATA_BLOB blob;\
    5932             :         const char *str;\
    5933             :         torture_assert(tctx,\
    5934             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5935             :                 "failed to query");\
    5936             :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
    5937             :         blob = data_blob_const(data, needed);\
    5938             :         torture_assert(tctx,\
    5939             :                 pull_reg_sz(tctx, &blob, &str),\
    5940             :                 "failed to pull REG_SZ");\
    5941             :         torture_assert_str_equal(tctx, str, iname, "unexpected result");\
    5942             : } while(0);
    5943             : 
    5944             : 
    5945             : #define TEST_SET_SZ(wname, iname, val) \
    5946             : do {\
    5947             :         enum winreg_Type type;\
    5948             :         uint8_t *data;\
    5949             :         uint32_t needed;\
    5950             :         DATA_BLOB blob;\
    5951             :         const char *str;\
    5952             :         sinfo.info2->iname = val;\
    5953             :         torture_assert(tctx,\
    5954             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
    5955             :                 "failed to call SetPrinter");\
    5956             :         torture_assert(tctx,\
    5957             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5958             :                 "failed to query");\
    5959             :         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");\
    5960             :         blob = data_blob_const(data, needed);\
    5961             :         torture_assert(tctx,\
    5962             :                 pull_reg_sz(tctx, &blob, &str),\
    5963             :                 "failed to pull REG_SZ");\
    5964             :         torture_assert_str_equal(tctx, str, val, "unexpected result");\
    5965             : } while(0);
    5966             : 
    5967             : #define TEST_SET_DWORD(wname, iname, val) \
    5968             : do {\
    5969             :         enum winreg_Type type;\
    5970             :         uint8_t *data;\
    5971             :         uint32_t needed;\
    5972             :         uint32_t value;\
    5973             :         sinfo.info2->iname = val;\
    5974             :         torture_assert(tctx,\
    5975             :                 test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),\
    5976             :                 "failed to call SetPrinter");\
    5977             :         torture_assert(tctx,\
    5978             :                 test_GetPrinterDataEx(tctx, p, handle, "DsSpooler", wname, &type, &data, &needed),\
    5979             :                 "failed to query");\
    5980             :         torture_assert_int_equal(tctx, type, REG_DWORD, "unexpected type");\
    5981             :         torture_assert_int_equal(tctx, needed, 4, "unexpected length");\
    5982             :         value = IVAL(data, 0); \
    5983             :         torture_assert_int_equal(tctx, value, val, "unexpected result");\
    5984             : } while(0);
    5985             : 
    5986           8 :         TEST_SET_SZ("description", comment, "newval");
    5987           8 :         TEST_SET_SZ("location", location, "newval");
    5988           8 :         TEST_SET_SZ("driverName", drivername, "newval");
    5989             : /*      TEST_SET_DWORD("priority", priority, 25); */
    5990             : 
    5991           8 :         torture_assert(tctx,
    5992             :                 test_GetPrinter_level(tctx, b, handle, 2, &info),
    5993             :                 "failed to query Printer level 2");
    5994             : 
    5995           8 :         TEST_SZ("description", info.info2.comment);
    5996           8 :         TEST_SZ("driverName", info.info2.drivername);
    5997           8 :         TEST_SZ("location", info.info2.location);
    5998             : 
    5999           8 :         pname = strrchr(info.info2.printername, '\\');
    6000           8 :         if (pname == NULL) {
    6001           0 :                 pname = info.info2.printername;
    6002             :         } else {
    6003           8 :                 pname++;
    6004             :         }
    6005           8 :         TEST_SZ("printerName", pname);
    6006             :         /* TEST_SZ("printSeparatorFile", info.info2.sepfile); */
    6007             :         /* TEST_SZ("printShareName", info.info2.sharename); */
    6008             : 
    6009             :         /* FIXME gd: complete the list */
    6010             : 
    6011             : #undef TEST_SZ
    6012             : #undef TEST_SET_SZ
    6013             : #undef TEST_DWORD
    6014             : 
    6015           8 :         torture_comment(tctx, "DsSpooler <-> SetPrinter relations test succeeded\n\n");
    6016             : 
    6017           8 :         return true;
    6018             : }
    6019             : 
    6020           4 : static bool test_print_processors_winreg(struct torture_context *tctx,
    6021             :                                          void *private_data)
    6022             : {
    6023           0 :         struct test_spoolss_context *ctx =
    6024           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6025           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6026           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6027             : 
    6028           4 :         return test_PrintProcessors_winreg(tctx, b, ctx->environment);
    6029             : }
    6030             : 
    6031           4 : static bool test_AddPrintProcessor(struct torture_context *tctx,
    6032             :                                    struct dcerpc_binding_handle *b,
    6033             :                                    const char *environment,
    6034             :                                    const char *path_name,
    6035             :                                    const char *print_processor_name,
    6036             :                                    WERROR expected_error)
    6037             : {
    6038           0 :         struct spoolss_AddPrintProcessor r;
    6039             : 
    6040           4 :         r.in.server = NULL;
    6041           4 :         r.in.architecture = environment;
    6042           4 :         r.in.path_name = path_name;
    6043           4 :         r.in.print_processor_name = print_processor_name;
    6044             : 
    6045           4 :         torture_comment(tctx, "Testing AddPrintProcessor(%s)\n",
    6046             :                 print_processor_name);
    6047             : 
    6048           4 :         torture_assert_ntstatus_ok(tctx,
    6049             :                 dcerpc_spoolss_AddPrintProcessor_r(b, tctx, &r),
    6050             :                 "spoolss_AddPrintProcessor failed");
    6051           4 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6052             :                 "spoolss_AddPrintProcessor failed");
    6053             : 
    6054           0 :         return true;
    6055             : }
    6056             : 
    6057           0 : static bool test_DeletePrintProcessor(struct torture_context *tctx,
    6058             :                                       struct dcerpc_binding_handle *b,
    6059             :                                       const char *environment,
    6060             :                                       const char *print_processor_name,
    6061             :                                       WERROR expected_error)
    6062             : {
    6063           0 :         struct spoolss_DeletePrintProcessor r;
    6064             : 
    6065           0 :         r.in.server = NULL;
    6066           0 :         r.in.architecture = environment;
    6067           0 :         r.in.print_processor_name = print_processor_name;
    6068             : 
    6069           0 :         torture_comment(tctx, "Testing DeletePrintProcessor(%s)\n",
    6070             :                 print_processor_name);
    6071             : 
    6072           0 :         torture_assert_ntstatus_ok(tctx,
    6073             :                 dcerpc_spoolss_DeletePrintProcessor_r(b, tctx, &r),
    6074             :                 "spoolss_DeletePrintProcessor failed");
    6075           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6076             :                 "spoolss_DeletePrintProcessor failed");
    6077             : 
    6078           0 :         return true;
    6079             : }
    6080             : 
    6081           4 : static bool test_add_print_processor(struct torture_context *tctx,
    6082             :                                      void *private_data)
    6083             : {
    6084           0 :         struct test_spoolss_context *ctx =
    6085           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6086           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6087           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6088           0 :         int i;
    6089             : 
    6090           0 :         struct {
    6091             :                 const char *environment;
    6092             :                 const char *path_name;
    6093             :                 const char *print_processor_name;
    6094             :                 WERROR expected_add_result;
    6095             :                 WERROR expected_del_result;
    6096           4 :         } tests[] = {
    6097             :                 {
    6098           4 :                         .environment            = ctx->environment,
    6099             :                         .path_name              = "",
    6100             :                         .print_processor_name   = "winprint",
    6101             :                         .expected_add_result    = WERR_PRINT_PROCESSOR_ALREADY_INSTALLED,
    6102             :                         .expected_del_result    = WERR_CAN_NOT_COMPLETE
    6103             :                 },{
    6104           4 :                         .environment            = ctx->environment,
    6105             :                         .path_name              = "",
    6106             :                         .print_processor_name   = "unknown",
    6107             :                         .expected_add_result    = WERR_MOD_NOT_FOUND,
    6108             :                         .expected_del_result    = WERR_UNKNOWN_PRINTPROCESSOR
    6109             :                 }
    6110             :         };
    6111             : 
    6112           4 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6113           4 :                 torture_assert(tctx,
    6114             :                         test_AddPrintProcessor(tctx, b,
    6115             :                                                tests[i].environment,
    6116             :                                                tests[i].path_name,
    6117             :                                                tests[i].print_processor_name,
    6118             :                                                tests[i].expected_add_result),
    6119             :                         "add print processor failed");
    6120           0 :                 torture_assert(tctx,
    6121             :                         test_DeletePrintProcessor(tctx, b,
    6122             :                                                   tests[i].environment,
    6123             :                                                   tests[i].print_processor_name,
    6124             :                                                   tests[i].expected_del_result),
    6125             :                         "delete print processor failed");
    6126             :         }
    6127             : 
    6128           0 :         return true;
    6129             : }
    6130             : 
    6131           4 : static bool test_AddPerMachineConnection(struct torture_context *tctx,
    6132             :                                          struct dcerpc_binding_handle *b,
    6133             :                                          const char *servername,
    6134             :                                          const char *printername,
    6135             :                                          const char *printserver,
    6136             :                                          const char *provider,
    6137             :                                          WERROR expected_error)
    6138             : {
    6139           0 :         struct spoolss_AddPerMachineConnection r;
    6140           4 :         const char *composed_printername = printername;
    6141             : 
    6142           4 :         if (servername != NULL) {
    6143           0 :                 composed_printername = talloc_asprintf(tctx, "%s\\%s",
    6144             :                                                 servername,
    6145             :                                                 printername);
    6146             :         }
    6147           4 :         r.in.server = servername;
    6148           4 :         r.in.printername = composed_printername;
    6149           4 :         r.in.printserver = printserver;
    6150           4 :         r.in.provider = provider;
    6151             : 
    6152           4 :         torture_comment(tctx, "Testing AddPerMachineConnection(%s|%s|%s)\n",
    6153             :                 printername, printserver, provider);
    6154             : 
    6155           4 :         torture_assert_ntstatus_ok(tctx,
    6156             :                 dcerpc_spoolss_AddPerMachineConnection_r(b, tctx, &r),
    6157             :                 "spoolss_AddPerMachineConnection failed");
    6158           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6159             :                 "spoolss_AddPerMachineConnection failed");
    6160             : 
    6161           0 :         return true;
    6162             : }
    6163             : 
    6164           0 : static bool test_DeletePerMachineConnection(struct torture_context *tctx,
    6165             :                                             struct dcerpc_binding_handle *b,
    6166             :                                             const char *servername,
    6167             :                                             const char *printername,
    6168             :                                             WERROR expected_error)
    6169             : {
    6170           0 :         struct spoolss_DeletePerMachineConnection r;
    6171           0 :         const char *composed_printername = printername;
    6172             : 
    6173           0 :         if (servername != NULL) {
    6174           0 :                 composed_printername = talloc_asprintf(tctx, "%s\\%s",
    6175             :                                                 servername,
    6176             :                                                 printername);
    6177             :         }
    6178             : 
    6179           0 :         r.in.server = servername;
    6180           0 :         r.in.printername = composed_printername;
    6181             : 
    6182           0 :         torture_comment(tctx, "Testing DeletePerMachineConnection(%s)\n",
    6183             :                 printername);
    6184             : 
    6185           0 :         torture_assert_ntstatus_ok(tctx,
    6186             :                 dcerpc_spoolss_DeletePerMachineConnection_r(b, tctx, &r),
    6187             :                 "spoolss_DeletePerMachineConnection failed");
    6188           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_error,
    6189             :                 "spoolss_DeletePerMachineConnection failed");
    6190             : 
    6191           0 :         return true;
    6192             : }
    6193             : 
    6194           0 : static bool test_EnumPerMachineConnections(struct torture_context *tctx,
    6195             :                                            struct dcerpc_binding_handle *b,
    6196             :                                            const char *servername)
    6197             : {
    6198           0 :         struct spoolss_EnumPerMachineConnections r;
    6199           0 :         DATA_BLOB blob = data_blob_null;
    6200           0 :         struct spoolss_PrinterInfo4 *info;
    6201           0 :         uint32_t needed;
    6202           0 :         uint32_t count;
    6203             : 
    6204           0 :         r.in.server = servername;
    6205           0 :         r.in.buffer = &blob;
    6206           0 :         r.in.offered = 0;
    6207             : 
    6208           0 :         r.out.info = &info;
    6209           0 :         r.out.needed = &needed;
    6210           0 :         r.out.count = &count;
    6211             : 
    6212           0 :         torture_comment(tctx, "Testing EnumPerMachineConnections(%s)\n",
    6213             :                 servername);
    6214             : 
    6215           0 :         torture_assert_ntstatus_ok(tctx,
    6216             :                 dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
    6217             :                 "spoolss_EnumPerMachineConnections failed");
    6218           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    6219           0 :                 blob = data_blob_talloc_zero(tctx, needed);
    6220           0 :                 r.in.buffer = &blob;
    6221           0 :                 r.in.offered = needed;
    6222             : 
    6223           0 :                 torture_assert_ntstatus_ok(tctx,
    6224             :                         dcerpc_spoolss_EnumPerMachineConnections_r(b, tctx, &r),
    6225             :                         "spoolss_EnumPerMachineConnections failed");
    6226             :         }
    6227           0 :         torture_assert_werr_ok(tctx, r.out.result,
    6228             :                 "spoolss_EnumPerMachineConnections failed");
    6229             : 
    6230           0 :         return true;
    6231             : }
    6232             : 
    6233           4 : static bool test_addpermachineconnection(struct torture_context *tctx,
    6234             :                                          void *private_data)
    6235             : {
    6236           0 :         struct test_spoolss_context *ctx =
    6237           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6238           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6239           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6240           4 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    6241           0 :         int i;
    6242             : 
    6243           0 :         struct {
    6244             :                 const char *servername;
    6245             :                 const char *printername;
    6246             :                 const char *printserver;
    6247             :                 const char *provider;
    6248             :                 WERROR expected_add_result;
    6249             :                 WERROR expected_del_result;
    6250           4 :         } tests[] = {
    6251             :                 {
    6252             :                         .servername             = NULL,
    6253             :                         .printername            = "foo",
    6254             :                         .printserver            = "",
    6255             :                         .provider               = "unknown",
    6256             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6257             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6258             :                 },{
    6259             :                         .servername             = NULL,
    6260             :                         .printername            = "Microsoft Print to PDF",
    6261             :                         .printserver            = "samba.org",
    6262             :                         .provider               = "unknown",
    6263             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6264             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6265             :                 },{
    6266             :                         .servername             = NULL,
    6267             :                         .printername            = "Microsoft Print to PDF",
    6268             :                         .printserver            = "samba.org",
    6269             :                         .provider               = "",
    6270             :                         .expected_add_result    = WERR_INVALID_PRINTER_NAME,
    6271             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6272             :                 },{
    6273             :                         .servername             = server_name_slash,
    6274             :                         .printername            = "foo",
    6275             :                         .printserver            = "",
    6276             :                         .provider               = "unknown",
    6277             :                         .expected_add_result    = WERR_FILE_NOT_FOUND,
    6278             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6279             :                 },{
    6280             :                         .servername             = server_name_slash,
    6281             :                         .printername            = "foo",
    6282             :                         .printserver            = "",
    6283             :                         .provider               = "",
    6284             :                         .expected_add_result    = WERR_OK,
    6285             :                         .expected_del_result    = WERR_OK
    6286             :                 },{
    6287             :                         .servername             = server_name_slash,
    6288             :                         .printername            = "Microsoft Print to PDF",
    6289             :                         .printserver            = "samba.org",
    6290             :                         .provider               = "unknown",
    6291             :                         .expected_add_result    = WERR_FILE_NOT_FOUND,
    6292             :                         .expected_del_result    = WERR_INVALID_PRINTER_NAME
    6293             :                 },{
    6294             :                         .servername             = server_name_slash,
    6295             :                         .printername            = "Microsoft Print to PDF",
    6296             :                         .printserver            = "samba.org",
    6297             :                         .provider               = "",
    6298             :                         .expected_add_result    = WERR_OK,
    6299             :                         .expected_del_result    = WERR_OK
    6300             :                 }
    6301             :         };
    6302             : 
    6303           4 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6304           4 :                 torture_assert(tctx,
    6305             :                         test_AddPerMachineConnection(tctx, b,
    6306             :                                                      tests[i].servername,
    6307             :                                                      tests[i].printername,
    6308             :                                                      tests[i].printserver,
    6309             :                                                      tests[i].provider,
    6310             :                                                      tests[i].expected_add_result),
    6311             :                         "add per machine connection failed");
    6312           0 :                 torture_assert(tctx,
    6313             :                         test_EnumPerMachineConnections(tctx, b,
    6314             :                                                        tests[i].servername),
    6315             :                         "enum per machine connections failed");
    6316           0 :                 torture_assert(tctx,
    6317             :                         test_DeletePerMachineConnection(tctx, b,
    6318             :                                                         tests[i].servername,
    6319             :                                                         tests[i].printername,
    6320             :                                                         tests[i].expected_del_result),
    6321             :                         "delete per machine connection failed");
    6322           0 :                 torture_assert(tctx,
    6323             :                         test_EnumPerMachineConnections(tctx, b,
    6324             :                                                        tests[i].servername),
    6325             :                         "enum per machine connections failed");
    6326             :         }
    6327             : 
    6328           0 :         return true;
    6329             : }
    6330             : 
    6331          32 : static bool test_GetChangeID_PrinterData(struct torture_context *tctx,
    6332             :                                          struct dcerpc_binding_handle *b,
    6333             :                                          struct policy_handle *handle,
    6334             :                                          uint32_t *change_id)
    6335             : {
    6336           0 :         enum winreg_Type type;
    6337           0 :         uint8_t *data;
    6338           0 :         uint32_t needed;
    6339             : 
    6340          32 :         torture_assert(tctx,
    6341             :                 test_GetPrinterData(tctx, b, handle, "ChangeID", &type, &data, &needed),
    6342             :                 "failed to call GetPrinterData");
    6343             : 
    6344          32 :         torture_assert(tctx, type == REG_DWORD, "unexpected type");
    6345          32 :         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
    6346             : 
    6347          32 :         *change_id = IVAL(data, 0);
    6348             : 
    6349          32 :         return true;
    6350             : }
    6351             : 
    6352          32 : static bool test_GetChangeID_PrinterDataEx(struct torture_context *tctx,
    6353             :                                            struct dcerpc_pipe *p,
    6354             :                                            struct policy_handle *handle,
    6355             :                                            uint32_t *change_id)
    6356             : {
    6357          32 :         enum winreg_Type type = REG_NONE;
    6358          32 :         uint8_t *data = NULL;
    6359          32 :         uint32_t needed = 0;
    6360             : 
    6361          32 :         torture_assert(tctx,
    6362             :                 test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", "ChangeID", &type, &data, &needed),
    6363             :                 "failed to call GetPrinterData");
    6364             : 
    6365          32 :         torture_assert(tctx, type == REG_DWORD, "unexpected type");
    6366          32 :         torture_assert_int_equal(tctx, needed, 4, "unexpected size");
    6367             : 
    6368          32 :         *change_id = IVAL(data, 0);
    6369             : 
    6370          32 :         return true;
    6371             : }
    6372             : 
    6373          32 : static bool test_GetChangeID_PrinterInfo(struct torture_context *tctx,
    6374             :                                          struct dcerpc_binding_handle *b,
    6375             :                                          struct policy_handle *handle,
    6376             :                                          uint32_t *change_id)
    6377             : {
    6378           0 :         union spoolss_PrinterInfo info;
    6379             : 
    6380          32 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 0, &info),
    6381             :                 "failed to query Printer level 0");
    6382             : 
    6383          32 :         *change_id = info.info0.change_id;
    6384             : 
    6385          32 :         return true;
    6386             : }
    6387             : 
    6388           8 : static bool test_ChangeID(struct torture_context *tctx,
    6389             :                           struct dcerpc_pipe *p,
    6390             :                           struct policy_handle *handle)
    6391             : {
    6392           0 :         uint32_t change_id, change_id_ex, change_id_info;
    6393           0 :         uint32_t change_id2, change_id_ex2, change_id_info2;
    6394           0 :         union spoolss_PrinterInfo info;
    6395           0 :         const char *comment;
    6396           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6397             : 
    6398           8 :         torture_comment(tctx, "Testing ChangeID: id change test #1\n");
    6399             : 
    6400           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6401             :                 "failed to query for ChangeID");
    6402           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6403             :                 "failed to query for ChangeID");
    6404           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6405             :                 "failed to query for ChangeID");
    6406             : 
    6407           8 :         torture_assert_int_equal(tctx, change_id, change_id_ex,
    6408             :                 "change_ids should all be equal");
    6409           8 :         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
    6410             :                 "change_ids should all be equal");
    6411             : 
    6412             : 
    6413           8 :         torture_comment(tctx, "Testing ChangeID: id change test #2\n");
    6414             : 
    6415           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6416             :                 "failed to query for ChangeID");
    6417           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    6418             :                 "failed to query Printer level 2");
    6419           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6420             :                 "failed to query for ChangeID");
    6421           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6422             :                 "failed to query for ChangeID");
    6423           8 :         torture_assert_int_equal(tctx, change_id, change_id_ex,
    6424             :                 "change_id should not have changed");
    6425           8 :         torture_assert_int_equal(tctx, change_id_ex, change_id_info,
    6426             :                 "change_id should not have changed");
    6427             : 
    6428             : 
    6429           8 :         torture_comment(tctx, "Testing ChangeID: id change test #3\n");
    6430             : 
    6431           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id),
    6432             :                 "failed to query for ChangeID");
    6433           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex),
    6434             :                 "failed to query for ChangeID");
    6435           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info),
    6436             :                 "failed to query for ChangeID");
    6437           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info),
    6438             :                 "failed to query Printer level 2");
    6439           8 :         comment = talloc_strdup(tctx, info.info2.comment);
    6440             : 
    6441             :         {
    6442           0 :                 struct spoolss_SetPrinterInfoCtr info_ctr;
    6443           0 :                 struct spoolss_DevmodeContainer devmode_ctr;
    6444           0 :                 struct sec_desc_buf secdesc_ctr;
    6445           0 :                 union spoolss_SetPrinterInfo sinfo;
    6446             : 
    6447           8 :                 ZERO_STRUCT(info_ctr);
    6448           8 :                 ZERO_STRUCT(devmode_ctr);
    6449           8 :                 ZERO_STRUCT(secdesc_ctr);
    6450             : 
    6451             : 
    6452           8 :                 torture_assert(tctx, PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    6453           8 :                 sinfo.info2->comment = "torture_comment";
    6454             : 
    6455           8 :                 info_ctr.level = 2;
    6456           8 :                 info_ctr.info = sinfo;
    6457             : 
    6458           8 :                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6459             :                         "failed to call SetPrinter");
    6460             : 
    6461           8 :                 sinfo.info2->comment = comment;
    6462             : 
    6463           8 :                 torture_assert(tctx, test_SetPrinter(tctx, b, handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6464             :                         "failed to call SetPrinter");
    6465             : 
    6466             :         }
    6467             : 
    6468           8 :         torture_assert(tctx, test_GetChangeID_PrinterData(tctx, b, handle, &change_id2),
    6469             :                 "failed to query for ChangeID");
    6470           8 :         torture_assert(tctx, test_GetChangeID_PrinterDataEx(tctx, p, handle, &change_id_ex2),
    6471             :                 "failed to query for ChangeID");
    6472           8 :         torture_assert(tctx, test_GetChangeID_PrinterInfo(tctx, b, handle, &change_id_info2),
    6473             :                 "failed to query for ChangeID");
    6474             : 
    6475           8 :         torture_assert_int_equal(tctx, change_id2, change_id_ex2,
    6476             :                 "change_ids should all be equal");
    6477           8 :         torture_assert_int_equal(tctx, change_id_ex2, change_id_info2,
    6478             :                 "change_ids should all be equal");
    6479             : 
    6480           8 :         torture_assert(tctx, (change_id < change_id2),
    6481             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6482             :                 change_id2, change_id));
    6483           8 :         torture_assert(tctx, (change_id_ex < change_id_ex2),
    6484             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6485             :                 change_id_ex2, change_id_ex));
    6486           8 :         torture_assert(tctx, (change_id_info < change_id_info2),
    6487             :                 talloc_asprintf(tctx, "change_id %d needs to be larger than change_id %d",
    6488             :                 change_id_info2, change_id_info));
    6489             : 
    6490           8 :         torture_comment(tctx, "ChangeID tests succeeded\n\n");
    6491             : 
    6492           8 :         return true;
    6493             : }
    6494             : 
    6495           0 : static bool test_SecondaryClosePrinter(struct torture_context *tctx,
    6496             :                                        struct dcerpc_pipe *p,
    6497             :                                        struct policy_handle *handle)
    6498             : {
    6499           0 :         NTSTATUS status;
    6500           0 :         struct cli_credentials *anon_creds;
    6501           0 :         const struct dcerpc_binding *binding2;
    6502           0 :         struct dcerpc_pipe *p2;
    6503           0 :         struct spoolss_ClosePrinter cp;
    6504             : 
    6505             :         /* only makes sense on SMB */
    6506           0 :         if (p->conn->transport.transport != NCACN_NP) {
    6507           0 :                 return true;
    6508             :         }
    6509             : 
    6510           0 :         torture_comment(tctx, "Testing close on secondary pipe\n");
    6511             : 
    6512           0 :         anon_creds = cli_credentials_init_anon(tctx);
    6513           0 :         torture_assert(tctx, anon_creds != NULL, "cli_credentials_init_anon failed");
    6514             : 
    6515           0 :         binding2 = p->binding;
    6516           0 :         status = dcerpc_secondary_auth_connection(p, binding2, &ndr_table_spoolss,
    6517             :                                                   anon_creds, tctx->lp_ctx,
    6518             :                                                   tctx, &p2);
    6519           0 :         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
    6520             : 
    6521           0 :         cp.in.handle = handle;
    6522           0 :         cp.out.handle = handle;
    6523             : 
    6524           0 :         status = dcerpc_spoolss_ClosePrinter_r(p2->binding_handle, tctx, &cp);
    6525           0 :         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
    6526             :                         "ERROR: Allowed close on secondary connection");
    6527             : 
    6528           0 :         talloc_free(p2);
    6529             : 
    6530           0 :         return true;
    6531             : }
    6532             : 
    6533          28 : static bool test_OpenPrinter_badname(struct torture_context *tctx,
    6534             :                                      struct dcerpc_binding_handle *b, const char *name)
    6535             : {
    6536           0 :         NTSTATUS status;
    6537           0 :         struct spoolss_OpenPrinter op;
    6538           0 :         struct spoolss_OpenPrinterEx opEx;
    6539           0 :         struct policy_handle handle;
    6540          28 :         bool ret = true;
    6541             : 
    6542          28 :         op.in.printername       = name;
    6543          28 :         op.in.datatype          = NULL;
    6544          28 :         op.in.devmode_ctr.devmode= NULL;
    6545          28 :         op.in.access_mask       = 0;
    6546          28 :         op.out.handle           = &handle;
    6547             : 
    6548          28 :         torture_comment(tctx, "Testing OpenPrinter(%s) with bad name\n", op.in.printername);
    6549             : 
    6550          28 :         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &op);
    6551          28 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
    6552          28 :         torture_assert_werr_equal(tctx, op.out.result, WERR_INVALID_PRINTER_NAME,
    6553             :                 "unexpected result");
    6554             : 
    6555          28 :         if (W_ERROR_IS_OK(op.out.result)) {
    6556           0 :                 ret &=test_ClosePrinter(tctx, b, &handle);
    6557             :         }
    6558             : 
    6559          28 :         opEx.in.printername             = name;
    6560          28 :         opEx.in.datatype                = NULL;
    6561          28 :         opEx.in.devmode_ctr.devmode     = NULL;
    6562          28 :         opEx.in.access_mask             = 0;
    6563          28 :         opEx.in.userlevel_ctr.level             = 1;
    6564          28 :         opEx.in.userlevel_ctr.user_info.level1 = NULL;
    6565          28 :         opEx.out.handle                 = &handle;
    6566             : 
    6567          28 :         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
    6568             : 
    6569          28 :         status = dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &opEx);
    6570          28 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
    6571          28 :         torture_assert_werr_equal(tctx, opEx.out.result, WERR_INVALID_PARAMETER,
    6572             :                 "unexpected result");
    6573             : 
    6574          28 :         if (W_ERROR_IS_OK(opEx.out.result)) {
    6575           0 :                 ret &=test_ClosePrinter(tctx, b, &handle);
    6576             :         }
    6577             : 
    6578          28 :         return ret;
    6579             : }
    6580             : 
    6581           4 : static bool test_OpenPrinter_badname_list(struct torture_context *tctx,
    6582             :                                           void *private_data)
    6583             : {
    6584           0 :         struct test_spoolss_context *ctx =
    6585           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    6586             : 
    6587           4 :         const char *badnames[] = {
    6588             :                 "__INVALID_PRINTER__",
    6589             :                 "\\\\__INVALID_HOST__",
    6590             :                 "",
    6591             :                 "\\\\\\",
    6592             :                 "\\\\\\__INVALID_PRINTER__"
    6593             :         };
    6594           0 :         const char *badname;
    6595           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    6596           4 :         const char *server_name = dcerpc_server_name(p);
    6597           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6598           0 :         int i;
    6599             : 
    6600          24 :         for (i=0; i < ARRAY_SIZE(badnames); i++) {
    6601          20 :                 torture_assert(tctx,
    6602             :                         test_OpenPrinter_badname(tctx, b, badnames[i]),
    6603             :                         "");
    6604             :         }
    6605             : 
    6606           4 :         badname = talloc_asprintf(tctx, "\\\\%s\\", server_name);
    6607           4 :         torture_assert(tctx,
    6608             :                 test_OpenPrinter_badname(tctx, b, badname),
    6609             :                 "");
    6610             : 
    6611           4 :         badname = talloc_asprintf(tctx, "\\\\%s\\__INVALID_PRINTER__", server_name);
    6612           4 :         torture_assert(tctx,
    6613             :                 test_OpenPrinter_badname(tctx, b, badname),
    6614             :                 "");
    6615             : 
    6616           4 :         return true;
    6617             : }
    6618             : 
    6619          60 : static bool test_OpenPrinter(struct torture_context *tctx,
    6620             :                              struct dcerpc_pipe *p,
    6621             :                              const char *name,
    6622             :                              const char *environment,
    6623             :                              bool open_only)
    6624             : {
    6625           0 :         NTSTATUS status;
    6626           0 :         struct spoolss_OpenPrinter r;
    6627           0 :         struct policy_handle handle;
    6628          60 :         bool ret = true;
    6629          60 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6630             : 
    6631          60 :         r.in.printername        = name;
    6632          60 :         r.in.datatype           = NULL;
    6633          60 :         r.in.devmode_ctr.devmode= NULL;
    6634          60 :         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
    6635          60 :         r.out.handle            = &handle;
    6636             : 
    6637          60 :         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
    6638             : 
    6639          60 :         status = dcerpc_spoolss_OpenPrinter_r(b, tctx, &r);
    6640             : 
    6641          60 :         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
    6642             : 
    6643          60 :         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
    6644             : 
    6645          60 :         if (open_only) {
    6646          40 :                 goto close_printer;
    6647             :         }
    6648             : 
    6649          20 :         if (!test_GetPrinter(tctx, b, &handle, environment)) {
    6650           0 :                 ret = false;
    6651             :         }
    6652             : 
    6653          20 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    6654           0 :                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
    6655           0 :                         ret = false;
    6656             :                 }
    6657             :         }
    6658             : 
    6659          20 :  close_printer:
    6660          60 :         if (!test_ClosePrinter(tctx, b, &handle)) {
    6661           0 :                 ret = false;
    6662             :         }
    6663             : 
    6664          60 :         return ret;
    6665             : }
    6666             : 
    6667         664 : static bool test_OpenPrinterEx(struct torture_context *tctx,
    6668             :                                struct dcerpc_binding_handle *b,
    6669             :                                const char *printername,
    6670             :                                const char *datatype,
    6671             :                                struct spoolss_DeviceMode *devmode,
    6672             :                                uint32_t access_mask,
    6673             :                                struct spoolss_UserLevelCtr *userlevel_ctr,
    6674             :                                struct policy_handle *handle,
    6675             :                                WERROR expected_result)
    6676             : {
    6677           0 :         struct spoolss_OpenPrinterEx r;
    6678             : 
    6679         664 :         r.in.printername        = printername;
    6680         664 :         r.in.datatype           = datatype;
    6681         664 :         r.in.devmode_ctr.devmode= devmode;
    6682         664 :         r.in.access_mask        = access_mask;
    6683         664 :         r.in.userlevel_ctr      = *userlevel_ctr;
    6684         664 :         r.out.handle            = handle;
    6685             : 
    6686         664 :         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
    6687             : 
    6688         664 :         torture_assert_ntstatus_ok(tctx,
    6689             :                 dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r),
    6690             :                 "OpenPrinterEx failed");
    6691             : 
    6692         664 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    6693             :                 "OpenPrinterEx failed");
    6694             : 
    6695         664 :         return true;
    6696             : }
    6697             : 
    6698         104 : static bool call_OpenPrinterEx(struct torture_context *tctx,
    6699             :                                struct dcerpc_pipe *p,
    6700             :                                const char *name,
    6701             :                                struct spoolss_DeviceMode *devmode,
    6702             :                                struct policy_handle *handle)
    6703             : {
    6704           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    6705           0 :         struct spoolss_UserLevel1 userlevel1;
    6706         104 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6707             : 
    6708         104 :         userlevel1.size = 1234;
    6709         104 :         userlevel1.client = "hello";
    6710         104 :         userlevel1.user = "spottyfoot!";
    6711         104 :         userlevel1.build = 1;
    6712         104 :         userlevel1.major = 2;
    6713         104 :         userlevel1.minor = 3;
    6714         104 :         userlevel1.processor = 4;
    6715             : 
    6716         104 :         userlevel_ctr.level = 1;
    6717         104 :         userlevel_ctr.user_info.level1 = &userlevel1;
    6718             : 
    6719         208 :         return test_OpenPrinterEx(tctx, b, name, NULL, devmode,
    6720             :                                   SEC_FLAG_MAXIMUM_ALLOWED,
    6721             :                                   &userlevel_ctr,
    6722             :                                   handle,
    6723         104 :                                   WERR_OK);
    6724             : }
    6725             : 
    6726           8 : static bool test_printer_rename(struct torture_context *tctx,
    6727             :                                 void *private_data)
    6728             : {
    6729           0 :         struct torture_printer_context *t =
    6730           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    6731           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    6732             : 
    6733           8 :         bool ret = true;
    6734           0 :         union spoolss_PrinterInfo info;
    6735           0 :         union spoolss_SetPrinterInfo sinfo;
    6736           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    6737           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    6738           0 :         struct sec_desc_buf secdesc_ctr;
    6739           0 :         const char *printer_name;
    6740           0 :         const char *printer_name_orig;
    6741           8 :         const char *printer_name_new = "SAMBA smbtorture Test Printer (Copy 2)";
    6742           0 :         struct policy_handle new_handle;
    6743           0 :         const char *q;
    6744           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6745             : 
    6746           8 :         ZERO_STRUCT(devmode_ctr);
    6747           8 :         ZERO_STRUCT(secdesc_ctr);
    6748             : 
    6749           8 :         torture_comment(tctx, "Testing Printer rename operations\n");
    6750             : 
    6751           8 :         torture_assert(tctx,
    6752             :                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
    6753             :                 "failed to call GetPrinter level 2");
    6754             : 
    6755           8 :         printer_name_orig = talloc_strdup(tctx, info.info2.printername);
    6756             : 
    6757           8 :         q = strrchr(info.info2.printername, '\\');
    6758           8 :         if (q) {
    6759           8 :                 torture_warning(tctx,
    6760             :                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
    6761             :         }
    6762             : 
    6763           8 :         torture_assert(tctx,
    6764             :                 PrinterInfo_to_SetPrinterInfo(tctx, &info, 2, &sinfo), "");
    6765             : 
    6766           8 :         sinfo.info2->printername = printer_name_new;
    6767             : 
    6768           8 :         info_ctr.level = 2;
    6769           8 :         info_ctr.info = sinfo;
    6770             : 
    6771           8 :         torture_assert(tctx,
    6772             :                 test_SetPrinter(tctx, b, &t->handle, &info_ctr, &devmode_ctr, &secdesc_ctr, 0),
    6773             :                 "failed to call SetPrinter level 2");
    6774             : 
    6775           8 :         torture_assert(tctx,
    6776             :                 test_GetPrinter_level(tctx, b, &t->handle, 2, &info),
    6777             :                 "failed to call GetPrinter level 2");
    6778             : 
    6779           8 :         printer_name = talloc_strdup(tctx, info.info2.printername);
    6780             : 
    6781           8 :         q = strrchr(info.info2.printername, '\\');
    6782           8 :         if (q) {
    6783           8 :                 torture_warning(tctx,
    6784             :                         "server returns printername %s incl. servername although we did not set servername", info.info2.printername);
    6785           8 :                 q++;
    6786           8 :                 printer_name = q;
    6787             :         }
    6788             : 
    6789           8 :         torture_assert_str_equal(tctx, printer_name, printer_name_new,
    6790             :                 "new printer name was not set");
    6791             : 
    6792             :         /* samba currently cannot fully rename printers */
    6793           8 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    6794           0 :                 torture_assert(tctx,
    6795             :                         test_OpenPrinter_badname(tctx, b, printer_name_orig),
    6796             :                         "still can open printer with oldname after rename");
    6797             :         } else {
    6798           8 :                 torture_warning(tctx, "*not* checking for open with oldname after rename for samba3");
    6799             :         }
    6800             : 
    6801           8 :         torture_assert(tctx,
    6802             :                 call_OpenPrinterEx(tctx, p, printer_name_new, NULL, &new_handle),
    6803             :                 "failed to open printer with new name");
    6804             : 
    6805           8 :         torture_assert(tctx,
    6806             :                 test_GetPrinter_level(tctx, b, &new_handle, 2, &info),
    6807             :                 "failed to call GetPrinter level 2");
    6808             : 
    6809           8 :         torture_assert_str_equal(tctx, info.info2.printername, printer_name_new,
    6810             :                 "new printer name was not set");
    6811             : 
    6812           8 :         torture_assert(tctx,
    6813             :                 test_ClosePrinter(tctx, b, &new_handle),
    6814             :                 "failed to close printer");
    6815             : 
    6816           8 :         torture_comment(tctx, "Printer rename operations test succeeded\n\n");
    6817             : 
    6818           8 :         return ret;
    6819             : }
    6820             : 
    6821          28 : static bool test_openprinter(struct torture_context *tctx,
    6822             :                              struct dcerpc_binding_handle *b,
    6823             :                              const char *real_printername)
    6824             : {
    6825           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    6826           0 :         struct policy_handle handle;
    6827           0 :         struct spoolss_UserLevel1 userlevel1;
    6828          28 :         const char *printername = NULL;
    6829           0 :         int i;
    6830             : 
    6831           0 :         struct {
    6832             :                 const char *suffix;
    6833             :                 WERROR expected_result;
    6834          28 :         } tests[] = {
    6835             :                 {
    6836             :                         .suffix                 = "rubbish",
    6837             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6838             :                 },{
    6839             :                         .suffix                 = ", LocalOnl",
    6840             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6841             :                 },{
    6842             :                         .suffix                 = ", localOnly",
    6843             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6844             :                 },{
    6845             :                         .suffix                 = ", localonl",
    6846             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6847             :                 },{
    6848             :                         .suffix                 = ",LocalOnl",
    6849             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6850             :                 },{
    6851             :                         .suffix                 = ",localOnl2",
    6852             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6853             :                 },{
    6854             :                         .suffix                 = ", DrvConver2t",
    6855             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6856             :                 },{
    6857             :                         .suffix                 = ", drvconvert",
    6858             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6859             :                 },{
    6860             :                         .suffix                 = ",drvconvert",
    6861             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6862             :                 },{
    6863             :                         .suffix                 = ", DrvConvert",
    6864             :                         .expected_result        = WERR_OK
    6865             :                 },{
    6866             :                         .suffix                 = " , DrvConvert",
    6867             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6868             :                 },{
    6869             :                         .suffix                 = ",DrvConvert",
    6870             :                         .expected_result        = WERR_OK
    6871             :                 },{
    6872             :                         .suffix                 = ", DrvConvertsadfasdf",
    6873             :                         .expected_result        = WERR_OK
    6874             :                 },{
    6875             :                         .suffix                 = ",DrvConvertasdfasd",
    6876             :                         .expected_result        = WERR_OK
    6877             :                 },{
    6878             :                         .suffix                 = ", LocalOnly",
    6879             :                         .expected_result        = WERR_OK
    6880             :                 },{
    6881             :                         .suffix                 = " , LocalOnly",
    6882             :                         .expected_result        = WERR_INVALID_PRINTER_NAME
    6883             :                 },{
    6884             :                         .suffix                 = ",LocalOnly",
    6885             :                         .expected_result        = WERR_OK
    6886             :                 },{
    6887             :                         .suffix                 = ", LocalOnlysagi4gjfkd",
    6888             :                         .expected_result        = WERR_OK
    6889             :                 },{
    6890             :                         .suffix                 = ",LocalOnlysagi4gjfkd",
    6891             :                         .expected_result        = WERR_OK
    6892             :                 }
    6893             :         };
    6894             : 
    6895          28 :         userlevel1.size = 1234;
    6896          28 :         userlevel1.client = "hello";
    6897          28 :         userlevel1.user = "spottyfoot!";
    6898          28 :         userlevel1.build = 1;
    6899          28 :         userlevel1.major = 2;
    6900          28 :         userlevel1.minor = 3;
    6901          28 :         userlevel1.processor = 4;
    6902             : 
    6903          28 :         userlevel_ctr.level = 1;
    6904          28 :         userlevel_ctr.user_info.level1 = &userlevel1;
    6905             : 
    6906          28 :         torture_comment(tctx, "Testing openprinterex printername pattern\n");
    6907             : 
    6908          28 :         torture_assert(tctx,
    6909             :                 test_OpenPrinterEx(tctx, b, real_printername, NULL, NULL, 0,
    6910             :                                    &userlevel_ctr, &handle,
    6911             :                                    WERR_OK),
    6912             :                 "OpenPrinterEx failed");
    6913          28 :         test_ClosePrinter(tctx, b, &handle);
    6914             : 
    6915         560 :         for (i=0; i < ARRAY_SIZE(tests); i++) {
    6916             : 
    6917         532 :                 printername = talloc_asprintf(tctx, "%s%s",
    6918             :                                               real_printername,
    6919             :                                               tests[i].suffix);
    6920             : 
    6921         532 :                 torture_assert(tctx,
    6922             :                         test_OpenPrinterEx(tctx, b, printername, NULL, NULL, 0,
    6923             :                                            &userlevel_ctr, &handle,
    6924             :                                            tests[i].expected_result),
    6925             :                         "OpenPrinterEx failed");
    6926         532 :                 if (W_ERROR_IS_OK(tests[i].expected_result)) {
    6927         224 :                         test_ClosePrinter(tctx, b, &handle);
    6928             :                 }
    6929             :         }
    6930             : 
    6931          28 :         return true;
    6932             : }
    6933             : 
    6934             : 
    6935          20 : static bool test_existing_printer_openprinterex(struct torture_context *tctx,
    6936             :                                                 struct dcerpc_pipe *p,
    6937             :                                                 const char *name,
    6938             :                                                 const char *environment)
    6939             : {
    6940           0 :         struct policy_handle handle;
    6941          20 :         bool ret = true;
    6942          20 :         struct dcerpc_binding_handle *b = p->binding_handle;
    6943             : 
    6944          20 :         if (!test_openprinter(tctx, b, name)) {
    6945           0 :                 return false;
    6946             :         }
    6947             : 
    6948          20 :         if (!call_OpenPrinterEx(tctx, p, name, NULL, &handle)) {
    6949           0 :                 return false;
    6950             :         }
    6951             : 
    6952          20 :         if (!test_PrinterInfo_SD(tctx, b, &handle)) {
    6953           0 :                 ret = false;
    6954             :         }
    6955             : 
    6956          20 :         if (!test_GetPrinter(tctx, b, &handle, environment)) {
    6957           0 :                 ret = false;
    6958             :         }
    6959             : 
    6960          20 :         if (!test_EnumForms_all(tctx, b, &handle, false)) {
    6961           0 :                 ret = false;
    6962             :         }
    6963             : 
    6964          20 :         if (!test_Forms(tctx, b, &handle, false, name, NULL, NULL)) {
    6965           0 :                 ret = false;
    6966             :         }
    6967             : 
    6968          20 :         if (!test_Forms_winreg(tctx, b, &handle, false, name)) {
    6969           0 :                 ret = false;
    6970             :         }
    6971             : 
    6972          20 :         if (!test_EnumPrinterData_all(tctx, p, &handle)) {
    6973           0 :                 ret = false;
    6974             :         }
    6975             : 
    6976          20 :         if (!test_EnumPrinterDataEx(tctx, b, &handle, "PrinterDriverData", NULL, NULL)) {
    6977           0 :                 ret = false;
    6978             :         }
    6979             : 
    6980          20 :         if (!test_EnumPrinterData_consistency(tctx, p, &handle)) {
    6981           0 :                 ret = false;
    6982             :         }
    6983             : 
    6984          20 :         if (!test_printer_all_keys(tctx, b, &handle)) {
    6985           0 :                 ret = false;
    6986             :         }
    6987             : 
    6988          20 :         if (!test_PausePrinter(tctx, b, &handle)) {
    6989           0 :                 ret = false;
    6990             :         }
    6991             : 
    6992          20 :         if (!test_DoPrintTest(tctx, b, &handle)) {
    6993          10 :                 ret = false;
    6994             :         }
    6995             : 
    6996          20 :         if (!test_ResumePrinter(tctx, b, &handle)) {
    6997           0 :                 ret = false;
    6998             :         }
    6999             : 
    7000          20 :         if (!test_SetPrinterData_matrix(tctx, b, &handle, name, NULL, NULL)) {
    7001           0 :                 ret = false;
    7002             :         }
    7003             : 
    7004          20 :         if (!test_SetPrinterDataEx_matrix(tctx, p, &handle, name, NULL, NULL)) {
    7005           0 :                 ret = false;
    7006             :         }
    7007             : 
    7008          20 :         if (!torture_setting_bool(tctx, "samba3", false)) {
    7009           0 :                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
    7010           0 :                         ret = false;
    7011             :                 }
    7012             :         }
    7013             : 
    7014          20 :         if (!test_ClosePrinter(tctx, b, &handle)) {
    7015           0 :                 ret = false;
    7016             :         }
    7017             : 
    7018          20 :         return ret;
    7019             : }
    7020             : 
    7021           4 : static bool test_EnumPrinters_old(struct torture_context *tctx,
    7022             :                                   void *private_data)
    7023             : {
    7024           0 :         struct test_spoolss_context *ctx =
    7025           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7026           0 :         struct spoolss_EnumPrinters r;
    7027           0 :         NTSTATUS status;
    7028           4 :         uint16_t levels[] = {1, 2, 4, 5};
    7029           0 :         int i;
    7030           4 :         bool ret = true;
    7031           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7032           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7033             : 
    7034          20 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7035           0 :                 union spoolss_PrinterInfo *info;
    7036           0 :                 int j;
    7037           0 :                 uint32_t needed;
    7038           0 :                 uint32_t count;
    7039             : 
    7040          16 :                 r.in.flags      = PRINTER_ENUM_LOCAL;
    7041          16 :                 r.in.server     = "";
    7042          16 :                 r.in.level      = levels[i];
    7043          16 :                 r.in.buffer     = NULL;
    7044          16 :                 r.in.offered    = 0;
    7045          16 :                 r.out.needed    = &needed;
    7046          16 :                 r.out.count     = &count;
    7047          16 :                 r.out.info      = &info;
    7048             : 
    7049          16 :                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
    7050             : 
    7051          16 :                 status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
    7052          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
    7053             : 
    7054          16 :                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7055          16 :                         DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7056          16 :                         r.in.buffer = &blob;
    7057          16 :                         r.in.offered = needed;
    7058          16 :                         status = dcerpc_spoolss_EnumPrinters_r(b, tctx, &r);
    7059             :                 }
    7060             : 
    7061          16 :                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
    7062             : 
    7063          16 :                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
    7064             : 
    7065          16 :                 CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
    7066             : 
    7067          16 :                 if (!info) {
    7068           0 :                         torture_comment(tctx, "No printers returned\n");
    7069           0 :                         return true;
    7070             :                 }
    7071             : 
    7072          96 :                 for (j=0;j<count;j++) {
    7073          80 :                         if (r.in.level == 1) {
    7074          20 :                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
    7075           0 :                                 char *slash, *name, *full_name;
    7076          20 :                                 name = unc;
    7077          20 :                                 if (unc[0] == '\\' && unc[1] == '\\') {
    7078           0 :                                         unc +=2;
    7079             :                                 }
    7080          20 :                                 slash = strchr(unc, '\\');
    7081          20 :                                 if (slash) {
    7082           0 :                                         slash++;
    7083           0 :                                         name = slash;
    7084             :                                 }
    7085          20 :                                 full_name = talloc_asprintf(tctx, "\\\\%s\\%s",
    7086             :                                                             dcerpc_server_name(p), name);
    7087          20 :                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, true)) {
    7088           0 :                                         ret = false;
    7089             :                                 }
    7090          20 :                                 if (!test_OpenPrinter(tctx, p, full_name, ctx->environment, true)) {
    7091           0 :                                         ret = false;
    7092             :                                 }
    7093          20 :                                 if (!test_OpenPrinter(tctx, p, name, ctx->environment, false)) {
    7094           0 :                                         ret = false;
    7095             :                                 }
    7096          20 :                                 if (!test_existing_printer_openprinterex(tctx, p, name, ctx->environment)) {
    7097          10 :                                         ret = false;
    7098             :                                 }
    7099             :                         }
    7100             :                 }
    7101             :         }
    7102             : 
    7103           4 :         return ret;
    7104             : }
    7105             : 
    7106           8 : static bool test_EnumPrinters_level(struct torture_context *tctx,
    7107             :                                     struct dcerpc_binding_handle *b,
    7108             :                                     uint32_t flags,
    7109             :                                     const char *servername,
    7110             :                                     uint32_t level,
    7111             :                                     uint32_t *count_p,
    7112             :                                     union spoolss_PrinterInfo **info_p)
    7113             : {
    7114           0 :         struct spoolss_EnumPrinters r;
    7115           0 :         union spoolss_PrinterInfo *info;
    7116           0 :         uint32_t needed;
    7117           0 :         uint32_t count;
    7118             : 
    7119           8 :         r.in.flags      = flags;
    7120           8 :         r.in.server     = servername;
    7121           8 :         r.in.level      = level;
    7122           8 :         r.in.buffer     = NULL;
    7123           8 :         r.in.offered    = 0;
    7124           8 :         r.out.needed    = &needed;
    7125           8 :         r.out.count     = &count;
    7126           8 :         r.out.info      = &info;
    7127             : 
    7128           8 :         torture_comment(tctx, "Testing EnumPrinters(%s) level %u\n",
    7129             :                 r.in.server, r.in.level);
    7130             : 
    7131           8 :         torture_assert_ntstatus_ok(tctx,
    7132             :                 dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
    7133             :                 "EnumPrinters failed");
    7134           8 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7135           8 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7136           8 :                 r.in.buffer = &blob;
    7137           8 :                 r.in.offered = needed;
    7138           8 :                 torture_assert_ntstatus_ok(tctx,
    7139             :                         dcerpc_spoolss_EnumPrinters_r(b, tctx, &r),
    7140             :                         "EnumPrinters failed");
    7141             :         }
    7142             : 
    7143           8 :         torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
    7144             : 
    7145           8 :         CHECK_NEEDED_SIZE_ENUM_LEVEL(spoolss_EnumPrinters, info, r.in.level, count, needed, 4);
    7146             : 
    7147           8 :         if (count_p) {
    7148           8 :                 *count_p = count;
    7149             :         }
    7150           8 :         if (info_p) {
    7151           8 :                 *info_p = info;
    7152             :         }
    7153             : 
    7154           8 :         return true;
    7155             : }
    7156             : 
    7157          40 : static const char *get_short_printername(struct torture_context *tctx,
    7158             :                                          const char *name)
    7159             : {
    7160           0 :         const char *short_name;
    7161             : 
    7162          40 :         if (name[0] == '\\' && name[1] == '\\') {
    7163          20 :                 name += 2;
    7164          20 :                 short_name = strchr(name, '\\');
    7165          20 :                 if (short_name) {
    7166          20 :                         return talloc_strdup(tctx, short_name+1);
    7167             :                 }
    7168             :         }
    7169             : 
    7170          20 :         return name;
    7171             : }
    7172             : 
    7173          40 : static const char *get_full_printername(struct torture_context *tctx,
    7174             :                                         const char *name)
    7175             : {
    7176          40 :         const char *full_name = talloc_strdup(tctx, name);
    7177           0 :         char *p;
    7178             : 
    7179          40 :         if (name && name[0] == '\\' && name[1] == '\\') {
    7180          20 :                 name += 2;
    7181          20 :                 p = strchr(name, '\\');
    7182          20 :                 if (p) {
    7183          20 :                         return full_name;
    7184             :                 }
    7185             :         }
    7186             : 
    7187          20 :         return NULL;
    7188             : }
    7189             : 
    7190          40 : static bool test_OnePrinter_servername(struct torture_context *tctx,
    7191             :                                        struct dcerpc_pipe *p,
    7192             :                                        struct dcerpc_binding_handle *b,
    7193             :                                        const char *servername,
    7194             :                                        const char *printername)
    7195             : {
    7196           0 :         union spoolss_PrinterInfo info;
    7197          40 :         const char *short_name = get_short_printername(tctx, printername);
    7198          40 :         const char *full_name = get_full_printername(tctx, printername);
    7199             : 
    7200          40 :         if (short_name) {
    7201           0 :                 struct policy_handle handle;
    7202          40 :                 torture_assert(tctx,
    7203             :                         call_OpenPrinterEx(tctx, p, short_name, NULL, &handle),
    7204             :                         "failed to open printer");
    7205             : 
    7206          40 :                 torture_assert(tctx,
    7207             :                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
    7208             :                         "failed to get printer info");
    7209             : 
    7210          40 :                 torture_assert_casestr_equal(tctx, info.info2.servername, NULL,
    7211             :                         "unexpected servername");
    7212          40 :                 torture_assert_casestr_equal(tctx, info.info2.printername, short_name,
    7213             :                         "unexpected printername");
    7214             : 
    7215          40 :                 if (info.info2.devmode) {
    7216           0 :                         const char *expected_devicename;
    7217          36 :                         expected_devicename = talloc_strndup(tctx, short_name, MIN(strlen(short_name), 31));
    7218          36 :                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
    7219             :                                 "unexpected devicemode devicename");
    7220             :                 }
    7221             : 
    7222          40 :                 torture_assert(tctx,
    7223             :                         test_ClosePrinter(tctx, b, &handle),
    7224             :                         "failed to close printer");
    7225             :         }
    7226             : 
    7227          40 :         if (full_name) {
    7228           0 :                 struct policy_handle handle;
    7229             : 
    7230          20 :                 torture_assert(tctx,
    7231             :                         call_OpenPrinterEx(tctx, p, full_name, NULL, &handle),
    7232             :                         "failed to open printer");
    7233             : 
    7234          20 :                 torture_assert(tctx,
    7235             :                         test_GetPrinter_level(tctx, b, &handle, 2, &info),
    7236             :                         "failed to get printer info");
    7237             : 
    7238          20 :                 torture_assert_casestr_equal(tctx, info.info2.servername, servername,
    7239             :                         "unexpected servername");
    7240          20 :                 torture_assert_casestr_equal(tctx, info.info2.printername, full_name,
    7241             :                         "unexpected printername");
    7242             : 
    7243          20 :                 if (info.info2.devmode) {
    7244           0 :                         const char *expected_devicename;
    7245          18 :                         expected_devicename = talloc_strndup(tctx, full_name, MIN(strlen(full_name), 31));
    7246          18 :                         torture_assert_casestr_equal(tctx, info.info2.devmode->devicename, expected_devicename,
    7247             :                                 "unexpected devicemode devicename");
    7248             :                 }
    7249             : 
    7250          20 :                 torture_assert(tctx,
    7251             :                         test_ClosePrinter(tctx, b, &handle),
    7252             :                         "failed to close printer");
    7253             :         }
    7254             : 
    7255          40 :         return true;
    7256             : }
    7257             : 
    7258           4 : static bool test_EnumPrinters_servername(struct torture_context *tctx,
    7259             :                                          void *private_data)
    7260             : {
    7261           0 :         struct test_spoolss_context *ctx =
    7262           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7263           0 :         int i;
    7264           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7265           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7266           0 :         uint32_t count;
    7267           0 :         union spoolss_PrinterInfo *info;
    7268           0 :         const char *servername;
    7269           4 :         uint32_t flags = PRINTER_ENUM_NAME|PRINTER_ENUM_LOCAL;
    7270             : 
    7271           4 :         torture_comment(tctx, "Testing servername behaviour in EnumPrinters and GetPrinters\n");
    7272             : 
    7273           4 :         servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    7274             : 
    7275           4 :         torture_assert(tctx,
    7276             :                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
    7277             :                 "failed to enumerate printers");
    7278             : 
    7279          24 :         for (i=0; i < count; i++) {
    7280             : 
    7281          20 :                 torture_assert_casestr_equal(tctx, info[i].info2.servername, servername,
    7282             :                         "unexpected servername");
    7283             : 
    7284          20 :                 torture_assert(tctx,
    7285             :                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
    7286             :                         "failed to check printer");
    7287             :         }
    7288             : 
    7289           4 :         servername = "";
    7290             : 
    7291           4 :         torture_assert(tctx,
    7292             :                 test_EnumPrinters_level(tctx, b, flags, servername, 2, &count, &info),
    7293             :                 "failed to enumerate printers");
    7294             : 
    7295          24 :         for (i=0; i < count; i++) {
    7296             : 
    7297          20 :                 torture_assert_casestr_equal(tctx, info[i].info2.servername, NULL,
    7298             :                         "unexpected servername");
    7299             : 
    7300          20 :                 torture_assert(tctx,
    7301             :                         test_OnePrinter_servername(tctx, p, b, servername, info[i].info2.printername),
    7302             :                         "failed to check printer");
    7303             :         }
    7304             : 
    7305             : 
    7306           4 :         return true;
    7307             : }
    7308             : 
    7309             : #if 0
    7310             : static bool test_GetPrinterDriver(struct torture_context *tctx,
    7311             :                                   struct dcerpc_binding_handle *b,
    7312             :                                   struct policy_handle *handle,
    7313             :                                   const char *driver_name)
    7314             : {
    7315             :         struct spoolss_GetPrinterDriver r;
    7316             :         uint32_t needed;
    7317             : 
    7318             :         r.in.handle = handle;
    7319             :         r.in.architecture = "W32X86";
    7320             :         r.in.level = 1;
    7321             :         r.in.buffer = NULL;
    7322             :         r.in.offered = 0;
    7323             :         r.out.needed = &needed;
    7324             : 
    7325             :         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
    7326             : 
    7327             :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
    7328             :                 "failed to call GetPrinterDriver");
    7329             :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7330             :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7331             :                 r.in.buffer = &blob;
    7332             :                 r.in.offered = needed;
    7333             :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver_r(b, tctx, &r),
    7334             :                         "failed to call GetPrinterDriver");
    7335             :         }
    7336             : 
    7337             :         torture_assert_werr_ok(tctx, r.out.result,
    7338             :                 "failed to call GetPrinterDriver");
    7339             : 
    7340             :         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
    7341             : 
    7342             :         return true;
    7343             : }
    7344             : #endif
    7345             : 
    7346           0 : static bool test_GetPrinterDriver2_level(struct torture_context *tctx,
    7347             :                                          struct dcerpc_binding_handle *b,
    7348             :                                          struct policy_handle *handle,
    7349             :                                          const char *driver_name,
    7350             :                                          const char *architecture,
    7351             :                                          uint32_t level,
    7352             :                                          uint32_t client_major_version,
    7353             :                                          uint32_t client_minor_version,
    7354             :                                          union spoolss_DriverInfo *info_p,
    7355             :                                          WERROR *result_p)
    7356             : 
    7357             : {
    7358           0 :         struct spoolss_GetPrinterDriver2 r;
    7359           0 :         uint32_t needed;
    7360           0 :         uint32_t server_major_version;
    7361           0 :         uint32_t server_minor_version;
    7362             : 
    7363           0 :         r.in.handle = handle;
    7364           0 :         r.in.architecture = architecture;
    7365           0 :         r.in.client_major_version = client_major_version;
    7366           0 :         r.in.client_minor_version = client_minor_version;
    7367           0 :         r.in.buffer = NULL;
    7368           0 :         r.in.offered = 0;
    7369           0 :         r.in.level = level;
    7370           0 :         r.out.needed = &needed;
    7371           0 :         r.out.server_major_version = &server_major_version;
    7372           0 :         r.out.server_minor_version = &server_minor_version;
    7373             : 
    7374           0 :         torture_comment(tctx, "Testing GetPrinterDriver2(%s) level %d\n",
    7375             :                 driver_name, r.in.level);
    7376             : 
    7377           0 :         torture_assert_ntstatus_ok(tctx,
    7378             :                 dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
    7379             :                 "failed to call GetPrinterDriver2");
    7380           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7381           0 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7382           0 :                 r.in.buffer = &blob;
    7383           0 :                 r.in.offered = needed;
    7384           0 :                 torture_assert_ntstatus_ok(tctx,
    7385             :                         dcerpc_spoolss_GetPrinterDriver2_r(b, tctx, &r),
    7386             :                         "failed to call GetPrinterDriver2");
    7387             :         }
    7388             : 
    7389           0 :         if (result_p) {
    7390           0 :                 *result_p = r.out.result;
    7391             :         }
    7392             : 
    7393           0 :         if (W_ERROR_EQUAL(r.out.result, WERR_INVALID_LEVEL)) {
    7394           0 :                 switch (r.in.level) {
    7395           0 :                 case 101:
    7396             :                 case 8:
    7397           0 :                         torture_comment(tctx,
    7398             :                                 "level %d not implemented, not considering as an error\n",
    7399             :                                 r.in.level);
    7400           0 :                         return true;
    7401           0 :                 default:
    7402           0 :                         break;
    7403             :                 }
    7404             :         }
    7405             : 
    7406           0 :         torture_assert_werr_ok(tctx, r.out.result,
    7407             :                 "failed to call GetPrinterDriver2");
    7408             : 
    7409           0 :         CHECK_NEEDED_SIZE_LEVEL(spoolss_DriverInfo, r.out.info, r.in.level, needed, 4);
    7410             : 
    7411           0 :         if (info_p) {
    7412           0 :                 *info_p = *r.out.info;
    7413             :         }
    7414             : 
    7415           0 :         return true;
    7416             : }
    7417             : 
    7418           0 : static bool test_GetPrinterDriver2(struct torture_context *tctx,
    7419             :                                    struct dcerpc_binding_handle *b,
    7420             :                                    struct policy_handle *handle,
    7421             :                                    const char *driver_name,
    7422             :                                    const char *architecture)
    7423             : {
    7424           0 :         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 8, 101 };
    7425           0 :         int i;
    7426             : 
    7427             : 
    7428           0 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7429             : 
    7430           0 :                 torture_assert(tctx,
    7431             :                         test_GetPrinterDriver2_level(tctx, b, handle, driver_name, architecture, levels[i], 3, 0, NULL, NULL),
    7432             :                         "");
    7433             :         }
    7434             : 
    7435           0 :         return true;
    7436             : }
    7437             : 
    7438           4 : static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
    7439             :                                         void *private_data)
    7440             : {
    7441           0 :         struct test_spoolss_context *ctx =
    7442           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    7443           4 :         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
    7444           0 :         int i;
    7445           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    7446           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7447           4 :         const char *server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    7448             : 
    7449           4 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    7450             : 
    7451           0 :                 uint32_t count;
    7452           0 :                 union spoolss_DriverInfo *info;
    7453             : 
    7454           4 :                 torture_assert(tctx,
    7455             :                         test_EnumPrinterDrivers_args(tctx, b, server_name, ctx->environment, levels[i], &count, &info),
    7456             :                         "failed to enumerate drivers");
    7457             : 
    7458           4 :                 if (!info) {
    7459           4 :                         torture_comment(tctx, "No printer drivers returned\n");
    7460           4 :                         break;
    7461             :                 }
    7462             :         }
    7463             : 
    7464           4 :         return true;
    7465             : }
    7466             : 
    7467          16 : static bool test_DeletePrinter(struct torture_context *tctx,
    7468             :                                struct dcerpc_binding_handle *b,
    7469             :                                struct policy_handle *handle)
    7470             : {
    7471           0 :         struct spoolss_DeletePrinter r;
    7472             : 
    7473          16 :         torture_comment(tctx, "Testing DeletePrinter\n");
    7474             : 
    7475          16 :         r.in.handle = handle;
    7476             : 
    7477          16 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter_r(b, tctx, &r),
    7478             :                 "failed to delete printer");
    7479          16 :         torture_assert_werr_ok(tctx, r.out.result,
    7480             :                 "failed to delete printer");
    7481             : 
    7482          16 :         return true;
    7483             : }
    7484             : 
    7485          24 : static bool test_EnumPrinters_findname(struct torture_context *tctx,
    7486             :                                        struct dcerpc_binding_handle *b,
    7487             :                                        uint32_t flags,
    7488             :                                        uint32_t level,
    7489             :                                        const char *name,
    7490             :                                        bool *found)
    7491             : {
    7492           0 :         struct spoolss_EnumPrinters e;
    7493           0 :         uint32_t count;
    7494           0 :         union spoolss_PrinterInfo *info;
    7495           0 :         uint32_t needed;
    7496           0 :         int i;
    7497             : 
    7498          24 :         *found = false;
    7499             : 
    7500          24 :         e.in.flags = flags;
    7501          24 :         e.in.server = NULL;
    7502          24 :         e.in.level = level;
    7503          24 :         e.in.buffer = NULL;
    7504          24 :         e.in.offered = 0;
    7505          24 :         e.out.count = &count;
    7506          24 :         e.out.info = &info;
    7507          24 :         e.out.needed = &needed;
    7508             : 
    7509          24 :         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
    7510             :                 "failed to enum printers");
    7511             : 
    7512          24 :         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
    7513          24 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    7514          24 :                 e.in.buffer = &blob;
    7515          24 :                 e.in.offered = needed;
    7516             : 
    7517          24 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e),
    7518             :                         "failed to enum printers");
    7519             :         }
    7520             : 
    7521          24 :         torture_assert_werr_ok(tctx, e.out.result,
    7522             :                 "failed to enum printers");
    7523             : 
    7524         152 :         for (i=0; i < count; i++) {
    7525             : 
    7526         152 :                 const char *current = NULL;
    7527           0 :                 const char *q;
    7528             : 
    7529         152 :                 switch (level) {
    7530         152 :                 case 1:
    7531         152 :                         current = info[i].info1.name;
    7532         152 :                         break;
    7533             :                 }
    7534             : 
    7535         152 :                 if (strequal(current, name)) {
    7536          24 :                         *found = true;
    7537          24 :                         break;
    7538             :                 }
    7539             : 
    7540         128 :                 q = strrchr(current, '\\');
    7541         128 :                 if (q) {
    7542           0 :                         if (!e.in.server) {
    7543           0 :                                 torture_warning(tctx,
    7544             :                                         "server returns printername %s incl. servername although we did not set servername", current);
    7545             :                         }
    7546           0 :                         q++;
    7547           0 :                         if (strequal(q, name)) {
    7548           0 :                                 *found = true;
    7549           0 :                                 break;
    7550             :                         }
    7551             :                 }
    7552             :         }
    7553             : 
    7554          24 :         return true;
    7555             : }
    7556             : 
    7557           0 : static bool test_AddPrinter_wellknown(struct torture_context *tctx,
    7558             :                                       struct dcerpc_pipe *p,
    7559             :                                       const char *printername,
    7560             :                                       bool ex)
    7561             : {
    7562           0 :         WERROR result;
    7563           0 :         struct spoolss_AddPrinter r;
    7564           0 :         struct spoolss_AddPrinterEx rex;
    7565           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    7566           0 :         struct spoolss_SetPrinterInfo1 info1;
    7567           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    7568           0 :         struct sec_desc_buf secdesc_ctr;
    7569           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    7570           0 :         struct policy_handle handle;
    7571           0 :         bool found = false;
    7572           0 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7573             : 
    7574           0 :         ZERO_STRUCT(devmode_ctr);
    7575           0 :         ZERO_STRUCT(secdesc_ctr);
    7576           0 :         ZERO_STRUCT(userlevel_ctr);
    7577           0 :         ZERO_STRUCT(info1);
    7578             : 
    7579           0 :         torture_comment(tctx, "Testing AddPrinter%s(%s) level 1\n",
    7580             :                         ex ? "Ex":"", printername);
    7581             : 
    7582             :         /* try to add printer to wellknown printer list (level 1) */
    7583             : 
    7584           0 :         userlevel_ctr.level = 1;
    7585             : 
    7586           0 :         info_ctr.info.info1 = &info1;
    7587           0 :         info_ctr.level = 1;
    7588             : 
    7589           0 :         rex.in.server = NULL;
    7590           0 :         rex.in.info_ctr = &info_ctr;
    7591           0 :         rex.in.devmode_ctr = &devmode_ctr;
    7592           0 :         rex.in.secdesc_ctr = &secdesc_ctr;
    7593           0 :         rex.in.userlevel_ctr = &userlevel_ctr;
    7594           0 :         rex.out.handle = &handle;
    7595             : 
    7596           0 :         r.in.server = NULL;
    7597           0 :         r.in.info_ctr = &info_ctr;
    7598           0 :         r.in.devmode_ctr = &devmode_ctr;
    7599           0 :         r.in.secdesc_ctr = &secdesc_ctr;
    7600           0 :         r.out.handle = &handle;
    7601             : 
    7602           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7603             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7604             :                 "failed to add printer");
    7605           0 :         result = ex ? rex.out.result : r.out.result;
    7606           0 :         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
    7607             :                 "unexpected result code");
    7608             : 
    7609           0 :         info1.name = printername;
    7610           0 :         info1.flags = PRINTER_ATTRIBUTE_SHARED;
    7611             : 
    7612           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7613             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7614             :                 "failed to add printer");
    7615           0 :         result = ex ? rex.out.result : r.out.result;
    7616           0 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7617             :                 "unexpected result code");
    7618             : 
    7619             :         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
    7620             :            better do a real check to see the printer is really there */
    7621             : 
    7622           0 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7623             :                                                         PRINTER_ENUM_NETWORK, 1,
    7624             :                                                         printername,
    7625             :                                                         &found),
    7626             :                         "failed to enum printers");
    7627             : 
    7628           0 :         torture_assert(tctx, found, "failed to find newly added printer");
    7629             : 
    7630           0 :         info1.flags = 0;
    7631             : 
    7632           0 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7633             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7634             :                 "failed to add printer");
    7635           0 :         result = ex ? rex.out.result : r.out.result;
    7636           0 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7637             :                 "unexpected result code");
    7638             : 
    7639             :         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
    7640             :            better do a real check to see the printer has really been removed
    7641             :            from the well known printer list */
    7642             : 
    7643           0 :         found = false;
    7644             : 
    7645           0 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7646             :                                                         PRINTER_ENUM_NETWORK, 1,
    7647             :                                                         printername,
    7648             :                                                         &found),
    7649             :                         "failed to enum printers");
    7650             : #if 0
    7651             :         torture_assert(tctx, !found, "printer still in well known printer list");
    7652             : #endif
    7653           0 :         return true;
    7654             : }
    7655             : 
    7656          16 : static bool test_AddPrinter_normal(struct torture_context *tctx,
    7657             :                                    struct dcerpc_pipe *p,
    7658             :                                    struct policy_handle *handle_p,
    7659             :                                    const char *printername,
    7660             :                                    const char *drivername,
    7661             :                                    const char *portname,
    7662             :                                    struct spoolss_DeviceMode *devmode,
    7663             :                                    bool ex)
    7664             : {
    7665           0 :         WERROR result;
    7666           0 :         struct spoolss_AddPrinter r;
    7667           0 :         struct spoolss_AddPrinterEx rex;
    7668           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    7669           0 :         struct spoolss_SetPrinterInfo2 info2;
    7670           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    7671           0 :         struct sec_desc_buf secdesc_ctr;
    7672           0 :         struct spoolss_UserLevelCtr userlevel_ctr;
    7673           0 :         struct policy_handle handle;
    7674          16 :         bool found = false;
    7675          16 :         bool existing_printer_deleted = false;
    7676          16 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7677             : 
    7678          16 :         ZERO_STRUCT(devmode_ctr);
    7679          16 :         ZERO_STRUCT(secdesc_ctr);
    7680          16 :         ZERO_STRUCT(userlevel_ctr);
    7681             : 
    7682          16 :         torture_comment(tctx, "Testing AddPrinter%s(%s) level 2\n",
    7683             :                         ex ? "Ex":"", printername);
    7684             : 
    7685          16 :         devmode_ctr.devmode = devmode;
    7686             : 
    7687          16 :         userlevel_ctr.level = 1;
    7688             : 
    7689          16 :         rex.in.server = NULL;
    7690          16 :         rex.in.info_ctr = &info_ctr;
    7691          16 :         rex.in.devmode_ctr = &devmode_ctr;
    7692          16 :         rex.in.secdesc_ctr = &secdesc_ctr;
    7693          16 :         rex.in.userlevel_ctr = &userlevel_ctr;
    7694          16 :         rex.out.handle = &handle;
    7695             : 
    7696          16 :         r.in.server = NULL;
    7697          16 :         r.in.info_ctr = &info_ctr;
    7698          16 :         r.in.devmode_ctr = &devmode_ctr;
    7699          16 :         r.in.secdesc_ctr = &secdesc_ctr;
    7700          16 :         r.out.handle = &handle;
    7701             : 
    7702          16 :  again:
    7703             : 
    7704             :         /* try to add printer to printer list (level 2) */
    7705             : 
    7706          16 :         ZERO_STRUCT(info2);
    7707             : 
    7708          16 :         info_ctr.info.info2 = &info2;
    7709          16 :         info_ctr.level = 2;
    7710             : 
    7711          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7712             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7713             :                 "failed to add printer");
    7714          16 :         result = ex ? rex.out.result : r.out.result;
    7715          16 :         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
    7716             :                 "unexpected result code");
    7717             : 
    7718          16 :         info2.printername = printername;
    7719             : 
    7720          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7721             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7722             :                 "failed to add printer");
    7723          16 :         result = ex ? rex.out.result : r.out.result;
    7724             : 
    7725          16 :         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
    7726           0 :                 struct policy_handle printer_handle;
    7727             : 
    7728           0 :                 if (existing_printer_deleted) {
    7729           0 :                         torture_fail(tctx, "already deleted printer still existing?");
    7730             :                 }
    7731             : 
    7732           0 :                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, NULL, &printer_handle),
    7733             :                         "failed to open printer handle");
    7734             : 
    7735           0 :                 torture_assert(tctx, test_DeletePrinter(tctx, b, &printer_handle),
    7736             :                         "failed to delete printer");
    7737             : 
    7738           0 :                 torture_assert(tctx, test_ClosePrinter(tctx, b, &printer_handle),
    7739             :                         "failed to close server handle");
    7740             : 
    7741           0 :                 existing_printer_deleted = true;
    7742             : 
    7743           0 :                 goto again;
    7744             :         }
    7745             : 
    7746          16 :         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
    7747             :                 "unexpected result code");
    7748             : 
    7749          16 :         info2.portname = portname;
    7750             : 
    7751          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7752             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7753             :                 "failed to add printer");
    7754          16 :         result = ex ? rex.out.result : r.out.result;
    7755          16 :         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
    7756             :                 "unexpected result code");
    7757             : 
    7758          16 :         info2.drivername = drivername;
    7759             : 
    7760          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7761             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7762             :                 "failed to add printer");
    7763          16 :         result = ex ? rex.out.result : r.out.result;
    7764             : 
    7765             :         /* w2k8r2 allows one to add printer w/o defining printprocessor */
    7766             : 
    7767          16 :         if (!W_ERROR_IS_OK(result)) {
    7768          16 :                 torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
    7769             :                         "unexpected result code");
    7770             : 
    7771          16 :                 info2.printprocessor = "winprint";
    7772             : 
    7773          16 :                 torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7774             :                                                       dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7775             :                         "failed to add printer");
    7776          16 :                 result = ex ? rex.out.result : r.out.result;
    7777          16 :                 torture_assert_werr_ok(tctx, result,
    7778             :                         "failed to add printer");
    7779             :         }
    7780             : 
    7781          16 :         *handle_p = handle;
    7782             : 
    7783             :         /* we are paranoid, really check if the printer is there now */
    7784             : 
    7785          16 :         torture_assert(tctx, test_EnumPrinters_findname(tctx, b,
    7786             :                                                         PRINTER_ENUM_LOCAL, 1,
    7787             :                                                         printername,
    7788             :                                                         &found),
    7789             :                         "failed to enum printers");
    7790          16 :         torture_assert(tctx, found, "failed to find newly added printer");
    7791             : 
    7792          16 :         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx_r(b, tctx, &rex) :
    7793             :                                               dcerpc_spoolss_AddPrinter_r(b, tctx, &r),
    7794             :                 "failed to add printer");
    7795          16 :         result = ex ? rex.out.result : r.out.result;
    7796          16 :         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
    7797             :                 "unexpected result code");
    7798             : 
    7799          16 :         return true;
    7800             : }
    7801             : 
    7802           8 : static bool test_printer_info(struct torture_context *tctx,
    7803             :                               void *private_data)
    7804             : {
    7805           0 :         struct torture_printer_context *t =
    7806           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7807           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7808           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7809             : 
    7810           8 :         bool ret = true;
    7811             : 
    7812           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    7813           8 :                 torture_skip(tctx, "skipping printer info cross tests against samba 3");
    7814             :         }
    7815             : 
    7816           0 :         if (!test_PrinterInfo(tctx, b, &t->handle)) {
    7817           0 :                 ret = false;
    7818             :         }
    7819             : 
    7820           0 :         if (!test_SetPrinter_errors(tctx, b, &t->handle)) {
    7821           0 :                 ret = false;
    7822             :         }
    7823             : 
    7824           0 :         return ret;
    7825             : }
    7826             : 
    7827         160 : static bool test_EnumPrinterKey(struct torture_context *tctx,
    7828             :                                 struct dcerpc_binding_handle *b,
    7829             :                                 struct policy_handle *handle,
    7830             :                                 const char *key_name,
    7831             :                                 const char ***array)
    7832             : {
    7833           0 :         struct spoolss_EnumPrinterKey r;
    7834         160 :         uint32_t needed = 0;
    7835           0 :         union spoolss_KeyNames key_buffer;
    7836         160 :         int32_t offered[] = { 0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5, 256, 512, 1024, 2048 };
    7837           0 :         uint32_t _ndr_size;
    7838           0 :         int i;
    7839             : 
    7840         160 :         r.in.handle = handle;
    7841         160 :         r.in.key_name = key_name;
    7842         160 :         r.out.key_buffer = &key_buffer;
    7843         160 :         r.out.needed = &needed;
    7844         160 :         r.out._ndr_size = &_ndr_size;
    7845             : 
    7846        2560 :         for (i=0; i < ARRAY_SIZE(offered); i++) {
    7847             : 
    7848        2400 :                 if (offered[i] < 0 && needed) {
    7849         800 :                         if (needed <= 4) {
    7850         340 :                                 continue;
    7851             :                         }
    7852         460 :                         r.in.offered = needed + offered[i];
    7853             :                 } else {
    7854        1600 :                         r.in.offered = offered[i];
    7855             :                 }
    7856             : 
    7857        2060 :                 ZERO_STRUCT(key_buffer);
    7858             : 
    7859        2060 :                 torture_comment(tctx, "Testing EnumPrinterKey(%s) with %d offered\n", r.in.key_name, r.in.offered);
    7860             : 
    7861        2060 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
    7862             :                         "failed to call EnumPrinterKey");
    7863        2060 :                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
    7864             : 
    7865        1284 :                         torture_assert(tctx, (_ndr_size == r.in.offered/2),
    7866             :                                 talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
    7867             :                                         _ndr_size, r.in.offered/2));
    7868             : 
    7869        1284 :                         r.in.offered = needed;
    7870        1284 :                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey_r(b, tctx, &r),
    7871             :                                 "failed to call EnumPrinterKey");
    7872             :                 }
    7873             : 
    7874        2060 :                 if (offered[i] > 0) {
    7875        1440 :                         torture_assert_werr_ok(tctx, r.out.result,
    7876             :                                 "failed to call EnumPrinterKey");
    7877             :                 }
    7878             : 
    7879        2060 :                 torture_assert(tctx, (_ndr_size == r.in.offered/2),
    7880             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
    7881             :                                 _ndr_size, r.in.offered/2));
    7882             : 
    7883        2060 :                 torture_assert(tctx, (*r.out.needed <= r.in.offered),
    7884             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= offered %d", *r.out.needed, r.in.offered));
    7885             : 
    7886        2060 :                 torture_assert(tctx, (*r.out.needed <= _ndr_size * 2),
    7887             :                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch: needed %d is not <= _ndr_size %d * 2", *r.out.needed, _ndr_size));
    7888             : 
    7889        2060 :                 if (key_buffer.string_array) {
    7890        2060 :                         uint32_t calc_needed = 0;
    7891             :                         int s;
    7892        4040 :                         for (s=0; key_buffer.string_array[s]; s++) {
    7893        1980 :                                 calc_needed += strlen_m_term(key_buffer.string_array[s])*2;
    7894             :                         }
    7895        2060 :                         if (!key_buffer.string_array[0]) {
    7896         680 :                                 calc_needed += 2;
    7897             :                         }
    7898        2060 :                         calc_needed += 2;
    7899             : 
    7900        2060 :                         torture_assert_int_equal(tctx, *r.out.needed, calc_needed,
    7901             :                                 "EnumPrinterKey unexpected size");
    7902             :                 }
    7903             :         }
    7904             : 
    7905         160 :         if (array) {
    7906          92 :                 *array = key_buffer.string_array;
    7907             :         }
    7908             : 
    7909         160 :         return true;
    7910             : }
    7911             : 
    7912          28 : bool test_printer_all_keys(struct torture_context *tctx,
    7913             :                            struct dcerpc_binding_handle *b,
    7914             :                            struct policy_handle *handle)
    7915             : {
    7916          28 :         const char **key_array = NULL;
    7917           0 :         int i;
    7918             : 
    7919          28 :         torture_comment(tctx, "Testing Printer Keys\n");
    7920             : 
    7921          28 :         torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, "", &key_array),
    7922             :                 "failed to call test_EnumPrinterKey");
    7923             : 
    7924          96 :         for (i=0; key_array && key_array[i]; i++) {
    7925          68 :                 torture_assert(tctx, test_EnumPrinterKey(tctx, b, handle, key_array[i], NULL),
    7926             :                         "failed to call test_EnumPrinterKey");
    7927             :         }
    7928          96 :         for (i=0; key_array && key_array[i]; i++) {
    7929          68 :                 torture_assert(tctx, test_EnumPrinterDataEx(tctx, b, handle, key_array[i], NULL, NULL),
    7930             :                         "failed to call test_EnumPrinterDataEx");
    7931             :         }
    7932             : 
    7933          28 :         torture_comment(tctx, "Printer Keys test succeeded\n\n");
    7934             : 
    7935          28 :         return true;
    7936             : }
    7937             : 
    7938           8 : static bool test_openprinter_wrap(struct torture_context *tctx,
    7939             :                                   void *private_data)
    7940             : {
    7941           0 :         struct torture_printer_context *t =
    7942           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7943           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7944           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7945           8 :         const char *printername = t->info2.printername;
    7946             : 
    7947           8 :         return test_openprinter(tctx, b, printername);
    7948             : }
    7949             : 
    7950           8 : static bool test_csetprinter(struct torture_context *tctx,
    7951             :                              void *private_data)
    7952             : {
    7953           0 :         struct torture_printer_context *t =
    7954           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    7955           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    7956             : 
    7957           8 :         const char *printername = talloc_asprintf(tctx, "%s2", t->info2.printername);
    7958           8 :         const char *drivername = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    7959           8 :         const char *portname = t->info2.portname;
    7960             : 
    7961           0 :         union spoolss_PrinterInfo info;
    7962           0 :         struct policy_handle new_handle, new_handle2;
    7963           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    7964             : 
    7965           8 :         torture_comment(tctx, "Testing c_setprinter\n");
    7966             : 
    7967           8 :         torture_assert(tctx,
    7968             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    7969             :                 "failed to get level 0 printer info");
    7970           8 :         torture_comment(tctx, "csetprinter on initial printer handle: %d\n",
    7971             :                 info.info0.c_setprinter);
    7972             : 
    7973             :         /* check if c_setprinter on 1st handle increases after a printer has
    7974             :          * been added */
    7975             : 
    7976           8 :         torture_assert(tctx,
    7977             :                 test_AddPrinter_normal(tctx, p, &new_handle, printername, drivername, portname, NULL, false),
    7978             :                 "failed to add new printer");
    7979           8 :         torture_assert(tctx,
    7980             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    7981             :                 "failed to get level 0 printer info");
    7982           8 :         torture_comment(tctx, "csetprinter on initial printer handle (after add): %d\n",
    7983             :                 info.info0.c_setprinter);
    7984             : 
    7985             :         /* check if c_setprinter on new handle increases after a printer has
    7986             :          * been added */
    7987             : 
    7988           8 :         torture_assert(tctx,
    7989             :                 test_GetPrinter_level(tctx, b, &new_handle, 0, &info),
    7990             :                 "failed to get level 0 printer info");
    7991           8 :         torture_comment(tctx, "csetprinter on created handle: %d\n",
    7992             :                 info.info0.c_setprinter);
    7993             : 
    7994             :         /* open the new printer and check if c_setprinter increases */
    7995             : 
    7996           8 :         torture_assert(tctx,
    7997             :                 call_OpenPrinterEx(tctx, p, printername, NULL, &new_handle2),
    7998             :                 "failed to open created printer");
    7999           8 :         torture_assert(tctx,
    8000             :                 test_GetPrinter_level(tctx, b, &new_handle2, 0, &info),
    8001             :                 "failed to get level 0 printer info");
    8002           8 :         torture_comment(tctx, "csetprinter on new handle (after openprinter): %d\n",
    8003             :                 info.info0.c_setprinter);
    8004             : 
    8005             :         /* cleanup */
    8006             : 
    8007           8 :         torture_assert(tctx,
    8008             :                 test_ClosePrinter(tctx, b, &new_handle2),
    8009             :                 "failed to close printer");
    8010           8 :         torture_assert(tctx,
    8011             :                 test_DeletePrinter(tctx, b, &new_handle),
    8012             :                 "failed to delete new printer");
    8013             : 
    8014           8 :         return true;
    8015             : }
    8016             : 
    8017           8 : static bool compose_local_driver_directory(struct torture_context *tctx,
    8018             :                                            const char *environment,
    8019             :                                            const char *local_dir,
    8020             :                                            const char **path)
    8021             : {
    8022           0 :         char *p;
    8023             : 
    8024           8 :         p = strrchr(local_dir, '/');
    8025           8 :         if (!p) {
    8026           0 :                 return NULL;
    8027             :         }
    8028           8 :         p++;
    8029             : 
    8030           8 :         if (strequal(environment, SPOOLSS_ARCHITECTURE_x64)) {
    8031           8 :                 if (!strequal(p, "x64")) {
    8032           8 :                         *path = talloc_asprintf(tctx, "%s/x64", local_dir);
    8033             :                 }
    8034           0 :         } else if (strequal(environment, SPOOLSS_ARCHITECTURE_NT_X86)) {
    8035           0 :                 if (!strequal(p, "i386")) {
    8036           0 :                         *path = talloc_asprintf(tctx, "%s/i386", local_dir);
    8037             :                 }
    8038             :         } else {
    8039             :                 torture_assert(tctx, "unknown environment: '%s'\n", environment);
    8040             :         }
    8041             : 
    8042           8 :         return true;
    8043             : }
    8044             : 
    8045             : #if 0
    8046             : static struct spoolss_DeviceMode *torture_devicemode(TALLOC_CTX *mem_ctx,
    8047             :                                                      const char *devicename)
    8048             : {
    8049             :         struct spoolss_DeviceMode *r;
    8050             : 
    8051             :         r = talloc_zero(mem_ctx, struct spoolss_DeviceMode);
    8052             :         if (r == NULL) {
    8053             :                 return NULL;
    8054             :         }
    8055             : 
    8056             :         r->devicename                = talloc_strdup(r, devicename);
    8057             :         r->specversion               = DMSPEC_NT4_AND_ABOVE;
    8058             :         r->driverversion     = 0x0600;
    8059             :         r->size                      = 0x00dc;
    8060             :         r->__driverextra_length = 0;
    8061             :         r->fields            = DEVMODE_FORMNAME |
    8062             :                                   DEVMODE_TTOPTION |
    8063             :                                   DEVMODE_PRINTQUALITY |
    8064             :                                   DEVMODE_DEFAULTSOURCE |
    8065             :                                   DEVMODE_COPIES |
    8066             :                                   DEVMODE_SCALE |
    8067             :                                   DEVMODE_PAPERSIZE |
    8068             :                                   DEVMODE_ORIENTATION;
    8069             :         r->orientation               = DMORIENT_PORTRAIT;
    8070             :         r->papersize         = DMPAPER_LETTER;
    8071             :         r->paperlength               = 0;
    8072             :         r->paperwidth                = 0;
    8073             :         r->scale             = 100;
    8074             :         r->copies            = 55;
    8075             :         r->defaultsource     = DMBIN_FORMSOURCE;
    8076             :         r->printquality              = DMRES_HIGH;
    8077             :         r->color             = DMRES_MONOCHROME;
    8078             :         r->duplex            = DMDUP_SIMPLEX;
    8079             :         r->yresolution               = 0;
    8080             :         r->ttoption          = DMTT_SUBDEV;
    8081             :         r->collate           = DMCOLLATE_FALSE;
    8082             :         r->formname          = talloc_strdup(r, "Letter");
    8083             : 
    8084             :         return r;
    8085             : }
    8086             : #endif
    8087             : 
    8088           4 : static bool test_architecture_buffer(struct torture_context *tctx,
    8089             :                                      void *private_data)
    8090             : {
    8091           0 :         struct test_spoolss_context *ctx =
    8092           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8093             : 
    8094           0 :         struct spoolss_OpenPrinterEx r;
    8095           0 :         struct spoolss_UserLevel1 u1;
    8096           0 :         struct policy_handle handle;
    8097           4 :         uint32_t architectures[] = {
    8098             :                 PROCESSOR_ARCHITECTURE_INTEL,
    8099             :                 PROCESSOR_ARCHITECTURE_IA64,
    8100             :                 PROCESSOR_ARCHITECTURE_AMD64
    8101             :         };
    8102           0 :         uint32_t needed[3];
    8103           0 :         int i;
    8104           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8105           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8106             : 
    8107          16 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8108             : 
    8109          12 :                 torture_comment(tctx, "Testing OpenPrinterEx with architecture %d\n", architectures[i]);
    8110             : 
    8111          12 :                 u1.size = 0;
    8112          12 :                 u1.client = NULL;
    8113          12 :                 u1.user = NULL;
    8114          12 :                 u1.build = 0;
    8115          12 :                 u1.major = 3;
    8116          12 :                 u1.minor = 0;
    8117          12 :                 u1.processor = architectures[i];
    8118             : 
    8119          12 :                 r.in.printername        = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8120          12 :                 r.in.datatype           = NULL;
    8121          12 :                 r.in.devmode_ctr.devmode= NULL;
    8122          12 :                 r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
    8123          12 :                 r.in.userlevel_ctr.level = 1;
    8124          12 :                 r.in.userlevel_ctr.user_info.level1 = &u1;
    8125          12 :                 r.out.handle            = &handle;
    8126             : 
    8127          12 :                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_OpenPrinterEx_r(b, tctx, &r), "");
    8128          12 :                 torture_assert_werr_ok(tctx, r.out.result, "");
    8129             : 
    8130             :                 {
    8131           0 :                         struct spoolss_EnumPrinters e;
    8132           0 :                         uint32_t count;
    8133           0 :                         union spoolss_PrinterInfo *info;
    8134             : 
    8135          12 :                         e.in.flags = PRINTER_ENUM_LOCAL;
    8136          12 :                         e.in.server = NULL;
    8137          12 :                         e.in.level = 2;
    8138          12 :                         e.in.buffer = NULL;
    8139          12 :                         e.in.offered = 0;
    8140          12 :                         e.out.count = &count;
    8141          12 :                         e.out.info = &info;
    8142          12 :                         e.out.needed = &needed[i];
    8143             : 
    8144          12 :                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters_r(b, tctx, &e), "");
    8145             : #if 0
    8146             :                         torture_comment(tctx, "needed was %d\n", needed[i]);
    8147             : #endif
    8148             :                 }
    8149             : 
    8150          12 :                 torture_assert(tctx, test_ClosePrinter(tctx, b, &handle), "");
    8151             :         }
    8152             : 
    8153          12 :         for (i=1; i < ARRAY_SIZE(architectures); i++) {
    8154           8 :                 if (needed[i-1] != needed[i]) {
    8155           0 :                         torture_fail(tctx,
    8156             :                                 talloc_asprintf(tctx, "needed size %d for architecture %d != needed size %d for architecture %d\n",
    8157             :                                                 needed[i-1], architectures[i-1], needed[i], architectures[i]));
    8158             :                 }
    8159             :         }
    8160             : 
    8161           4 :         return true;
    8162             : }
    8163             : 
    8164           8 : static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
    8165             :                                                     struct dcerpc_pipe *p,
    8166             :                                                     const char *architecture,
    8167             :                                                     const char *guid_str,
    8168             :                                                     const char **package_id)
    8169             : {
    8170           0 :         struct spoolss_GetCorePrinterDrivers r;
    8171           0 :         struct spoolss_CorePrinterDriver core_printer_drivers;
    8172           8 :         DATA_BLOB blob = data_blob_talloc_zero(tctx, 2);
    8173           0 :         const char **s;
    8174           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8175           0 :         struct GUID guid;
    8176             : 
    8177           8 :         s = talloc_zero_array(tctx, const char *, 2);
    8178             : 
    8179           8 :         r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8180           8 :         r.in.architecture = "foobar";
    8181           8 :         r.in.core_driver_size = 0;
    8182           8 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8183           8 :         r.in.core_printer_driver_count = 0;
    8184           8 :         r.out.core_printer_drivers = &core_printer_drivers;
    8185             : 
    8186           8 :         torture_assert_ntstatus_ok(tctx,
    8187             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8188             :                 "spoolss_GetCorePrinterDrivers failed");
    8189           0 :         torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
    8190             :                 "spoolss_GetCorePrinterDrivers failed");
    8191             : 
    8192           0 :         guid = GUID_random();
    8193           0 :         s[0] = GUID_string2(tctx, &guid);
    8194             : 
    8195           0 :         torture_assert(tctx,
    8196             :                 push_reg_multi_sz(tctx, &blob, s),
    8197             :                 "push_reg_multi_sz failed");
    8198             : 
    8199           0 :         r.in.core_driver_size = blob.length/2;
    8200           0 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8201           0 :         r.in.core_printer_driver_count = 1;
    8202           0 :         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
    8203             : 
    8204           0 :         torture_assert_ntstatus_ok(tctx,
    8205             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8206             :                 "spoolss_GetCorePrinterDrivers failed");
    8207           0 :         torture_assert_werr_equal(tctx,
    8208             :                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
    8209             :                 "spoolss_GetCorePrinterDrivers failed");
    8210             : 
    8211           0 :         r.in.architecture = architecture;
    8212             : 
    8213           0 :         torture_assert_ntstatus_ok(tctx,
    8214             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8215             :                 "spoolss_GetCorePrinterDrivers failed");
    8216           0 :         torture_assert_werr_equal(tctx,
    8217             :                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
    8218             :                 "spoolss_GetCorePrinterDrivers failed");
    8219             : 
    8220           0 :         s[0] = talloc_strdup(s, guid_str);
    8221             : 
    8222           0 :         torture_assert(tctx,
    8223             :                 push_reg_multi_sz(tctx, &blob, s),
    8224             :                 "push_reg_multi_sz failed");
    8225             : 
    8226           0 :         r.in.core_driver_size = blob.length/2;
    8227           0 :         r.in.core_driver_dependencies = (uint16_t *)blob.data;
    8228           0 :         r.in.core_printer_driver_count = 1;
    8229           0 :         r.out.core_printer_drivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.core_printer_driver_count);
    8230             : 
    8231           0 :         torture_assert_ntstatus_ok(tctx,
    8232             :                 dcerpc_spoolss_GetCorePrinterDrivers_r(b, tctx, &r),
    8233             :                 "spoolss_GetCorePrinterDrivers failed");
    8234           0 :         torture_assert_hresult_ok(tctx, r.out.result,
    8235             :                 "spoolss_GetCorePrinterDrivers failed");
    8236             : 
    8237           0 :         if (package_id) {
    8238           0 :                 *package_id = r.out.core_printer_drivers[0].szPackageID;
    8239             :         }
    8240             : 
    8241           0 :         return true;
    8242             : }
    8243             : 
    8244           4 : static bool test_get_core_printer_drivers(struct torture_context *tctx,
    8245             :                                           void *private_data)
    8246             : {
    8247           0 :         struct test_spoolss_context *ctx =
    8248           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8249             : 
    8250           4 :         const char *architectures[] = {
    8251             :                 SPOOLSS_ARCHITECTURE_NT_X86,
    8252             :                 SPOOLSS_ARCHITECTURE_x64
    8253             :         };
    8254           0 :         int i;
    8255           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8256             : 
    8257           4 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8258             : 
    8259           4 :                 torture_comment(tctx, "Testing GetCorePrinterDrivers(\"%s\",\"%s\")\n",
    8260             :                         architectures[i],
    8261             :                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
    8262             : 
    8263           4 :                 torture_assert(tctx,
    8264             :                         test_get_core_printer_drivers_arch_guid(tctx, p,
    8265             :                                 architectures[i],
    8266             :                                 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
    8267             :                                 NULL),
    8268             :                         "");
    8269             :         }
    8270             : 
    8271           0 :         return true;
    8272             : }
    8273             : 
    8274           4 : static bool test_get_printer_driver_package_path(struct torture_context *tctx,
    8275             :                                                  void *private_data)
    8276             : {
    8277           0 :         struct test_spoolss_context *ctx =
    8278           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8279             : 
    8280           4 :         const char *architectures[] = {
    8281             :                 SPOOLSS_ARCHITECTURE_NT_X86,
    8282             :                 SPOOLSS_ARCHITECTURE_x64
    8283             :         };
    8284           0 :         int i;
    8285           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8286           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8287             : 
    8288           4 :         for (i=0; i < ARRAY_SIZE(architectures); i++) {
    8289           0 :                 struct spoolss_GetPrinterDriverPackagePath r;
    8290           4 :                 uint32_t required = 0;
    8291           4 :                 const char *package_id = NULL;
    8292             : 
    8293           4 :                 test_get_core_printer_drivers_arch_guid(tctx, p,
    8294             :                         architectures[i],
    8295             :                         SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
    8296             :                         &package_id),
    8297             : 
    8298           4 :                 torture_comment(tctx, "Testing GetPrinterDriverPackagePath(\"%s\",\"%s\")\n",
    8299             :                         architectures[i], package_id);
    8300             : 
    8301           4 :                 r.in.servername = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8302           4 :                 r.in.architecture = "foobar";
    8303           4 :                 r.in.language = NULL;
    8304           4 :                 r.in.package_id = "";
    8305           4 :                 r.in.driver_package_cab_size = 0;
    8306           4 :                 r.in.driver_package_cab = NULL;
    8307             : 
    8308           4 :                 r.out.required = &required;
    8309           4 :                 r.out.driver_package_cab = NULL;
    8310             : 
    8311           4 :                 torture_assert_ntstatus_ok(tctx,
    8312             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8313             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8314           0 :                 torture_assert_werr_equal(tctx,
    8315             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
    8316             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8317             : 
    8318           0 :                 r.in.architecture = architectures[i];
    8319             : 
    8320           0 :                 torture_assert_ntstatus_ok(tctx,
    8321             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8322             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8323           0 :                 torture_assert_werr_equal(tctx,
    8324             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
    8325             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8326             : 
    8327           0 :                 r.in.package_id = package_id;
    8328             : 
    8329           0 :                 torture_assert_ntstatus_ok(tctx,
    8330             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8331             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8332           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8333             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8334             : 
    8335           0 :                 r.in.driver_package_cab_size = required;
    8336           0 :                 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
    8337           0 :                 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
    8338             : 
    8339           0 :                 torture_assert_ntstatus_ok(tctx,
    8340             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8341             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8342           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8343             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8344             : 
    8345           0 :                 r.in.servername = NULL;
    8346             : 
    8347           0 :                 torture_assert_ntstatus_ok(tctx,
    8348             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8349             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8350           0 :                 torture_assert_werr_equal(tctx,
    8351             :                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INSUFFICIENT_BUFFER,
    8352             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8353             : 
    8354           0 :                 r.in.driver_package_cab_size = required;
    8355           0 :                 r.in.driver_package_cab = talloc_zero_array(tctx, char, required);
    8356           0 :                 r.out.driver_package_cab = talloc_zero_array(tctx, char, required);
    8357             : 
    8358           0 :                 torture_assert_ntstatus_ok(tctx,
    8359             :                         dcerpc_spoolss_GetPrinterDriverPackagePath_r(b, tctx, &r),
    8360             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8361           0 :                 torture_assert_hresult_ok(tctx, r.out.result,
    8362             :                         "spoolss_GetPrinterDriverPackagePath failed");
    8363             : 
    8364             :         }
    8365             : 
    8366           0 :         return true;
    8367             : }
    8368             : 
    8369           4 : static bool test_get_printer_printserverhandle(struct torture_context *tctx,
    8370             :                                                void *private_data)
    8371             : {
    8372           0 :         struct test_spoolss_context *ctx =
    8373           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8374             : 
    8375           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8376           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8377           4 :         uint32_t levels[] = {0, 1, 2, /* 3,*/ 4, 5, 6, 7, 8};
    8378           0 :         int i;
    8379             : 
    8380          36 :         for (i=0;i<ARRAY_SIZE(levels);i++) {
    8381             : 
    8382          32 :                 torture_assert(tctx,
    8383             :                         test_GetPrinter_level_exp(tctx, b, &ctx->server_handle,
    8384             :                                                   levels[i], WERR_INVALID_LEVEL,
    8385             :                                                   NULL),
    8386             :                         "failed to call GetPrinter");
    8387             :         }
    8388             : 
    8389           4 :         torture_assert(tctx,
    8390             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, NULL),
    8391             :                 "failed to call GetPrinter");
    8392             : 
    8393           4 :         return true;
    8394             : }
    8395             : 
    8396             : #define TEST_SID "S-1-5-21-1234567890-1234567890-1234567890-500"
    8397             : 
    8398           4 : static bool test_set_printer_printserverhandle(struct torture_context *tctx,
    8399             :                                                void *private_data)
    8400             : {
    8401           0 :         struct test_spoolss_context *ctx =
    8402           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8403             : 
    8404           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8405           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8406           0 :         union spoolss_PrinterInfo info;
    8407           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    8408           0 :         struct spoolss_SetPrinterInfo3 info3;
    8409           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    8410           0 :         struct sec_desc_buf secdesc_ctr;
    8411           0 :         struct security_descriptor *sd;
    8412           0 :         struct security_ace *ace;
    8413           0 :         struct dom_sid sid;
    8414           0 :         int i;
    8415             : 
    8416           4 :         torture_assert(tctx,
    8417             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8418             :                 "failed to call GetPrinter");
    8419             : 
    8420           4 :         secdesc_ctr.sd = info.info3.secdesc;
    8421           4 :         secdesc_ctr.sd->owner_sid = NULL;
    8422           4 :         secdesc_ctr.sd->group_sid = NULL;
    8423             : 
    8424           4 :         sd = security_descriptor_copy(tctx, secdesc_ctr.sd);
    8425           4 :         if (sd == NULL) {
    8426           0 :                 return false;
    8427             :         }
    8428             : 
    8429           4 :         ace = security_ace_create(tctx,
    8430             :                                   TEST_SID,
    8431             :                                   SEC_ACE_TYPE_ACCESS_ALLOWED,
    8432             :                                   SEC_STD_REQUIRED,
    8433             :                                   SEC_ACE_FLAG_CONTAINER_INHERIT);
    8434           4 :         torture_assert(tctx, ace, "failed to create ace");
    8435             : 
    8436           4 :         torture_assert_ntstatus_ok(tctx,
    8437             :                 security_descriptor_dacl_add(sd, ace),
    8438             :                 "failed to add ace");
    8439             : 
    8440           4 :         secdesc_ctr.sd = sd;
    8441             : 
    8442           4 :         info3.sec_desc_ptr = 0;
    8443             : 
    8444           4 :         info_ctr.level = 3;
    8445           4 :         info_ctr.info.info3 = &info3;
    8446             : 
    8447           4 :         ZERO_STRUCT(devmode_ctr);
    8448             : 
    8449           4 :         torture_assert(tctx,
    8450             :                 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
    8451             :                                 &devmode_ctr, &secdesc_ctr, 0),
    8452             :                 "failed to call SetPrinter");
    8453             : 
    8454           4 :         torture_assert(tctx,
    8455             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8456             :                 "failed to call GetPrinter");
    8457             : 
    8458          32 :         for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
    8459          32 :                 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
    8460           4 :                         break;
    8461             :                 }
    8462             :         }
    8463             : 
    8464           4 :         if (i == info.info3.secdesc->dacl->num_aces) {
    8465           0 :                 torture_fail(tctx, "ace not present");
    8466             :         }
    8467             : 
    8468           4 :         torture_assert(tctx,
    8469             :                 dom_sid_parse(TEST_SID, &sid),
    8470             :                 "failed to parse sid");
    8471             : 
    8472           4 :         torture_assert_ntstatus_ok(tctx,
    8473             :                 security_descriptor_dacl_del(info.info3.secdesc, &sid),
    8474             :                 "failed to remove ace from sd");
    8475             : 
    8476           4 :         secdesc_ctr.sd = info.info3.secdesc;
    8477             : 
    8478           4 :         torture_assert(tctx,
    8479             :                 test_SetPrinter(tctx, b, &ctx->server_handle, &info_ctr,
    8480             :                                 &devmode_ctr, &secdesc_ctr, 0),
    8481             :                 "failed to call SetPrinter");
    8482             : 
    8483           4 :         torture_assert(tctx,
    8484             :                 test_GetPrinter_level(tctx, b, &ctx->server_handle, 3, &info),
    8485             :                 "failed to call GetPrinter");
    8486             : 
    8487          32 :         for (i = 0; i < info.info3.secdesc->dacl->num_aces; i++) {
    8488          28 :                 if (security_ace_equal(&info.info3.secdesc->dacl->aces[i], ace)) {
    8489           0 :                         torture_fail(tctx, "ace still present");
    8490             :                 }
    8491             :         }
    8492             : 
    8493           4 :         return true;
    8494             : }
    8495             : 
    8496             : 
    8497           4 : static bool test_PrintServer_Forms_Winreg(struct torture_context *tctx,
    8498             :                                           void *private_data)
    8499             : {
    8500           0 :         struct test_spoolss_context *ctx =
    8501           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8502           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8503           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8504             : 
    8505           4 :         return test_Forms_winreg(tctx, b, &ctx->server_handle, true, NULL);
    8506             : }
    8507             : 
    8508           4 : static bool test_PrintServer_Forms(struct torture_context *tctx,
    8509             :                                    void *private_data)
    8510             : {
    8511           0 :         struct test_spoolss_context *ctx =
    8512           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8513           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8514           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8515             : 
    8516           4 :         return test_Forms(tctx, b, &ctx->server_handle, true, NULL, NULL, NULL);
    8517             : }
    8518             : 
    8519           4 : static bool test_PrintServer_EnumForms(struct torture_context *tctx,
    8520             :                                        void *private_data)
    8521             : {
    8522           0 :         struct test_spoolss_context *ctx =
    8523           4 :                 talloc_get_type_abort(private_data, struct test_spoolss_context);
    8524           4 :         struct dcerpc_pipe *p = ctx->spoolss_pipe;
    8525           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8526             : 
    8527           4 :         return test_EnumForms_all(tctx, b, &ctx->server_handle, true);
    8528             : }
    8529             : 
    8530           4 : static bool torture_rpc_spoolss_setup_common(struct torture_context *tctx, struct test_spoolss_context *t)
    8531             : {
    8532           0 :         NTSTATUS status;
    8533             : 
    8534           4 :         status = torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss);
    8535             : 
    8536           4 :         torture_assert_ntstatus_ok(tctx, status, "Error connecting to server");
    8537             : 
    8538           4 :         torture_assert(tctx,
    8539             :                 test_OpenPrinter_server(tctx, t->spoolss_pipe, &t->server_handle),
    8540             :                 "failed to open printserver");
    8541           4 :         torture_assert(tctx,
    8542             :                 test_get_environment(tctx, t->spoolss_pipe->binding_handle, &t->server_handle, &t->environment),
    8543             :                 "failed to get environment");
    8544             : 
    8545           4 :         return true;
    8546             : }
    8547             : 
    8548           4 : static bool torture_rpc_spoolss_setup(struct torture_context *tctx, void **data)
    8549             : {
    8550           0 :         struct test_spoolss_context *t;
    8551             : 
    8552           4 :         *data = t = talloc_zero(tctx, struct test_spoolss_context);
    8553             : 
    8554           4 :         return torture_rpc_spoolss_setup_common(tctx, t);
    8555             : }
    8556             : 
    8557           4 : static bool torture_rpc_spoolss_teardown_common(struct torture_context *tctx, struct test_spoolss_context *t)
    8558             : {
    8559           4 :         test_ClosePrinter(tctx, t->spoolss_pipe->binding_handle, &t->server_handle);
    8560             : 
    8561           4 :         return true;
    8562             : }
    8563             : 
    8564           4 : static bool torture_rpc_spoolss_teardown(struct torture_context *tctx, void *data)
    8565             : {
    8566           4 :         struct test_spoolss_context *t = talloc_get_type(data, struct test_spoolss_context);
    8567           0 :         bool ret;
    8568             : 
    8569           4 :         ret = torture_rpc_spoolss_teardown_common(tctx, t);
    8570           4 :         talloc_free(t);
    8571             : 
    8572           4 :         return ret;
    8573             : }
    8574             : 
    8575           8 : static bool torture_rpc_spoolss_printer_setup_common(struct torture_context *tctx, struct torture_printer_context *t)
    8576             : {
    8577           0 :         struct dcerpc_pipe *p;
    8578           0 :         struct dcerpc_binding_handle *b;
    8579           0 :         const char *server_name_slash;
    8580           0 :         const char *driver_name;
    8581           0 :         const char *printer_name;
    8582           0 :         const char *port_name;
    8583             : 
    8584           8 :         torture_assert_ntstatus_ok(tctx,
    8585             :                 torture_rpc_connection(tctx, &t->spoolss_pipe, &ndr_table_spoolss),
    8586             :                 "Error connecting to server");
    8587             : 
    8588           8 :         p = t->spoolss_pipe;
    8589           8 :         b = p->binding_handle;
    8590           8 :         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8591             : 
    8592           8 :         t->driver.info8.version                      = SPOOLSS_DRIVER_VERSION_200X;
    8593           8 :         t->driver.info8.driver_name          = TORTURE_DRIVER;
    8594           8 :         t->driver.info8.driver_path          = "pscript5.dll";
    8595           8 :         t->driver.info8.data_file            = "cups6.ppd";
    8596           8 :         t->driver.info8.config_file          = "ps5ui.dll";
    8597           8 :         t->driver.info8.help_file            = "pscript.hlp";
    8598           8 :         t->driver.info8.default_datatype     = "RAW";
    8599           8 :         t->driver.info8.dependent_files              = talloc_zero(t, struct spoolss_StringArray);
    8600           8 :         t->driver.info8.dependent_files->string = talloc_zero_array(t, const char *, 8 + 1);
    8601           8 :         t->driver.info8.dependent_files->string[0] = "pscript5.dll";
    8602           8 :         t->driver.info8.dependent_files->string[1] = "cups6.ppd";
    8603           8 :         t->driver.info8.dependent_files->string[2] = "ps5ui.dll";
    8604           8 :         t->driver.info8.dependent_files->string[3] = "pscript.hlp";
    8605           8 :         t->driver.info8.dependent_files->string[4] = "pscript.ntf";
    8606           8 :         t->driver.info8.dependent_files->string[5] = "cups6.ini";
    8607           8 :         t->driver.info8.dependent_files->string[6] = "cupsps6.dll";
    8608           8 :         t->driver.info8.dependent_files->string[7] = "cupsui6.dll";
    8609             : 
    8610           8 :         t->driver.local.driver_directory= "/usr/share/cups/drivers";
    8611             : 
    8612           8 :         t->info2.portname            = "LPT1:";
    8613             : 
    8614           8 :         printer_name = t->info2.printername;
    8615           8 :         port_name = t->info2.portname;
    8616             : 
    8617           8 :         torture_assert(tctx,
    8618             :                 fillup_printserver_info(tctx, p, &t->driver),
    8619             :                 "failed to fillup printserver info");
    8620             : 
    8621           8 :         t->driver.info8.architecture = talloc_strdup(t, t->driver.remote.environment);
    8622             : 
    8623           8 :         torture_assert(tctx,
    8624             :                 compose_local_driver_directory(tctx, t->driver.remote.environment,
    8625             :                                                t->driver.local.driver_directory,
    8626             :                                                &t->driver.local.driver_directory),
    8627             :                 "failed to compose local driver directory");
    8628             : 
    8629           8 :         t->info2.drivername          = "Microsoft XPS Document Writer";
    8630             : 
    8631           8 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
    8632           0 :                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) is present on server\n",
    8633             :                         t->info2.drivername, t->driver.remote.environment);
    8634           0 :                 t->have_driver = true;
    8635           0 :                 goto try_add;
    8636             :         }
    8637             : 
    8638           8 :         torture_comment(tctx, "driver '%s' (architecture: %s, version: 3) does not exist on the server\n",
    8639             :                 t->info2.drivername, t->driver.remote.environment);
    8640             : 
    8641           8 :         t->info2.drivername          = "Microsoft XPS Document Writer v4";
    8642             : 
    8643           8 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, t->driver.remote.environment, 3, t->info2.drivername, NULL)) {
    8644           0 :                 torture_comment(tctx, "driver '%s' (architecture: %s, version: 4) is present on server\n",
    8645             :                         t->info2.drivername, t->driver.remote.environment);
    8646           0 :                 t->have_driver = true;
    8647           0 :                 goto try_add;
    8648             :         }
    8649             : 
    8650           8 :         torture_comment(tctx, "trying to upload own driver\n");
    8651             : 
    8652           8 :         if (!directory_exist(t->driver.local.driver_directory)) {
    8653           8 :                 torture_warning(tctx, "no local driver is available!");
    8654           8 :                 t->have_driver = false;
    8655           8 :                 goto try_add;
    8656             :         }
    8657             : 
    8658           0 :         torture_assert(tctx,
    8659             :                 upload_printer_driver(tctx, dcerpc_server_name(p), &t->driver),
    8660             :                 "failed to upload printer driver");
    8661             : 
    8662           0 :         torture_assert(tctx,
    8663             :                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &t->driver.info8, 0, false, NULL),
    8664             :                 "failed to add driver");
    8665             : 
    8666           0 :         t->added_driver = true;
    8667           0 :         t->have_driver = true;
    8668             : 
    8669           8 :  try_add:
    8670           8 :         driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    8671             : 
    8672           8 :         if (t->wellknown) {
    8673           0 :                 torture_assert(tctx,
    8674             :                         test_AddPrinter_wellknown(tctx, p, printer_name, t->ex),
    8675             :                         "failed to add wellknown printer");
    8676             :         } else {
    8677           8 :                 torture_assert(tctx,
    8678             :                         test_AddPrinter_normal(tctx, p, &t->handle, printer_name, driver_name, port_name, t->devmode, t->ex),
    8679             :                         "failed to add printer");
    8680             :         }
    8681             : 
    8682           8 :         return true;
    8683             : }
    8684             : 
    8685           4 : static bool torture_rpc_spoolss_printer_setup(struct torture_context *tctx, void **data)
    8686             : {
    8687           0 :         struct torture_printer_context *t;
    8688             : 
    8689           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8690             : 
    8691           4 :         t->ex                        = false;
    8692           4 :         t->wellknown         = false;
    8693           4 :         t->info2.printername = TORTURE_PRINTER;
    8694           4 :         t->devmode           = NULL;
    8695             : 
    8696           4 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8697             : }
    8698             : 
    8699           4 : static bool torture_rpc_spoolss_printerex_setup(struct torture_context *tctx, void **data)
    8700             : {
    8701           0 :         struct torture_printer_context *t;
    8702             : 
    8703           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8704             : 
    8705           4 :         t->ex                        = true;
    8706           4 :         t->wellknown         = false;
    8707           4 :         t->info2.printername = TORTURE_PRINTER_EX;
    8708           4 :         t->devmode           = NULL;
    8709             : 
    8710           4 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8711             : }
    8712             : 
    8713           4 : static bool torture_rpc_spoolss_printerwkn_setup(struct torture_context *tctx, void **data)
    8714             : {
    8715           0 :         struct torture_printer_context *t;
    8716             : 
    8717           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8718             : 
    8719           4 :         t->ex                        = false;
    8720           4 :         t->wellknown         = true;
    8721           4 :         t->info2.printername = TORTURE_WELLKNOWN_PRINTER;
    8722           4 :         t->devmode           = NULL;
    8723             : 
    8724             :         /* FIXME */
    8725           4 :         if (t->wellknown) {
    8726           4 :                 torture_skip(tctx, "skipping AddPrinter level 1");
    8727             :         }
    8728             : 
    8729           0 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8730             : }
    8731             : 
    8732           4 : static bool torture_rpc_spoolss_printerexwkn_setup(struct torture_context *tctx, void **data)
    8733             : {
    8734           0 :         struct torture_printer_context *t;
    8735             : 
    8736           4 :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8737             : 
    8738           4 :         t->ex                        = true;
    8739           4 :         t->wellknown         = true;
    8740           4 :         t->info2.printername = TORTURE_WELLKNOWN_PRINTER_EX;
    8741           4 :         t->devmode           = NULL;
    8742             : 
    8743             :         /* FIXME */
    8744           4 :         if (t->wellknown) {
    8745           4 :                 torture_skip(tctx, "skipping AddPrinterEx level 1");
    8746             :         }
    8747             : 
    8748           0 :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8749             : }
    8750             : 
    8751             : #if 0
    8752             : static bool torture_rpc_spoolss_printerdm_setup(struct torture_context *tctx, void **data)
    8753             : {
    8754             :         struct torture_printer_context *t;
    8755             : 
    8756             :         *data = t = talloc_zero(tctx, struct torture_printer_context);
    8757             : 
    8758             :         t->ex                        = true;
    8759             :         t->wellknown         = false;
    8760             :         t->info2.printername = TORTURE_PRINTER_EX;
    8761             :         t->devmode           = torture_devicemode(t, TORTURE_PRINTER_EX);
    8762             : 
    8763             :         return torture_rpc_spoolss_printer_setup_common(tctx, t);
    8764             : }
    8765             : #endif
    8766             : 
    8767             : static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
    8768             :                                            struct dcerpc_binding_handle *b,
    8769             :                                            const char *server,
    8770             :                                            const char *driver,
    8771             :                                            const char *environment,
    8772             :                                            uint32_t delete_flags,
    8773             :                                            uint32_t version,
    8774             :                                            WERROR expected_result);
    8775             : 
    8776          16 : static bool torture_rpc_spoolss_printer_teardown_common(struct torture_context *tctx, struct torture_printer_context *t)
    8777             : {
    8778          16 :         bool found = false;
    8779          16 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8780          16 :         struct dcerpc_binding_handle *b = NULL;
    8781           0 :         const char *server_name_slash;
    8782          16 :         bool ok = true;
    8783             : 
    8784          16 :         if (p == NULL) {
    8785           8 :                 return true;
    8786             :         }
    8787           8 :         b = p->binding_handle;
    8788             : 
    8789           8 :         server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    8790             : 
    8791           8 :         if (!t->wellknown) {
    8792           8 :                 const char *printer_name = t->info2.printername;
    8793             : 
    8794           8 :                 torture_assert_goto(tctx,
    8795             :                         test_DeletePrinter(tctx, b, &t->handle),
    8796             :                         ok,
    8797             :                         remove_driver,
    8798             :                         "failed to delete printer");
    8799             : 
    8800           8 :                 torture_assert_goto(tctx,
    8801             :                         test_EnumPrinters_findname(tctx, b, PRINTER_ENUM_LOCAL, 1,
    8802             :                                                    printer_name, &found),
    8803             :                         ok,
    8804             :                         remove_driver,
    8805             :                         "failed to enumerate printers");
    8806             : 
    8807           8 :                 torture_assert_goto(tctx,
    8808             :                         !found,
    8809             :                         ok,
    8810             :                         remove_driver,
    8811             :                         "deleted printer still there");
    8812             :         }
    8813             : 
    8814             : 
    8815           0 : remove_driver:
    8816           8 :         if (t->added_driver) {
    8817           0 :                 ok = remove_printer_driver(tctx,
    8818             :                                            dcerpc_server_name(p),
    8819             :                                            &t->driver);
    8820           0 :                 if (!ok) {
    8821           0 :                         torture_warning(tctx,
    8822             :                                         "failed to remove printer driver\n");
    8823             :                 }
    8824             : 
    8825           0 :                 ok = test_DeletePrinterDriverEx_exp(tctx, b,
    8826             :                                                     server_name_slash,
    8827             :                                                     t->driver.info8.driver_name,
    8828             :                                                     t->driver.info8.architecture,
    8829             :                                                     DPD_DELETE_ALL_FILES,
    8830           0 :                                                     t->driver.info8.version,
    8831           0 :                                                     WERR_OK);
    8832           0 :                 if (!ok) {
    8833           0 :                         torture_warning(tctx,
    8834             :                                         "failed to delete printer driver via "
    8835             :                                         "spoolss\n");
    8836             :                 }
    8837             :         }
    8838             : 
    8839           8 :         return ok;
    8840             : }
    8841             : 
    8842          16 : static bool torture_rpc_spoolss_printer_teardown(struct torture_context *tctx, void *data)
    8843             : {
    8844          16 :         struct torture_printer_context *t = talloc_get_type(data, struct torture_printer_context);
    8845           0 :         bool ret;
    8846             : 
    8847          16 :         ret = torture_rpc_spoolss_printer_teardown_common(tctx, t);
    8848          16 :         talloc_free(t);
    8849             : 
    8850          16 :         return ret;
    8851             : }
    8852             : 
    8853           8 : static bool test_print_test(struct torture_context *tctx,
    8854             :                             void *private_data)
    8855             : {
    8856           0 :         struct torture_printer_context *t =
    8857           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8858           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8859           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8860             : 
    8861           8 :         torture_assert(tctx,
    8862             :                 test_PausePrinter(tctx, b, &t->handle),
    8863             :                 "failed to pause printer");
    8864             : 
    8865           8 :         torture_assert(tctx,
    8866             :                 test_DoPrintTest(tctx, b, &t->handle),
    8867             :                 "failed to do print test");
    8868             : 
    8869           4 :         torture_assert(tctx,
    8870             :                 test_ResumePrinter(tctx, b, &t->handle),
    8871             :                 "failed to resume printer");
    8872             : 
    8873           4 :         return true;
    8874             : }
    8875             : 
    8876           8 : static bool test_print_test_extended(struct torture_context *tctx,
    8877             :                                      void *private_data)
    8878             : {
    8879           0 :         struct torture_printer_context *t =
    8880           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8881           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8882           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8883           8 :         bool ret = true;
    8884             : 
    8885           8 :         torture_assert(tctx,
    8886             :                 test_PausePrinter(tctx, b, &t->handle),
    8887             :                 "failed to pause printer");
    8888             : 
    8889           8 :         ret = test_DoPrintTest_extended(tctx, b, &t->handle);
    8890           8 :         if (ret == false) {
    8891           4 :                 torture_comment(tctx, "WARNING! failed to do extended print test\n");
    8892           4 :                 if (torture_setting_bool(tctx, "samba3", false)) {
    8893           4 :                         torture_comment(tctx, "non-critical for samba3\n");
    8894           4 :                         ret = true;
    8895           4 :                         tctx->last_result = TORTURE_SKIP;
    8896             :                 }
    8897             :         }
    8898             : 
    8899           8 :         torture_assert(tctx,
    8900             :                 test_ResumePrinter(tctx, b, &t->handle),
    8901             :                 "failed to resume printer");
    8902             : 
    8903           8 :         return ret;
    8904             : }
    8905             : 
    8906           8 : static bool test_print_test_properties(struct torture_context *tctx,
    8907             :                                        void *private_data)
    8908             : {
    8909           0 :         struct torture_printer_context *t =
    8910           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8911           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8912           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8913             : 
    8914           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    8915           8 :                 torture_skip(tctx, "skip printer job property tests against samba");
    8916             :         }
    8917             : 
    8918           0 :         torture_assert(tctx,
    8919             :                 test_PausePrinter(tctx, b, &t->handle),
    8920             :                 "failed to pause printer");
    8921             : 
    8922           0 :         torture_assert(tctx,
    8923             :                 test_DoPrintTest_properties(tctx, b, &t->handle),
    8924             :                 "failed to test print job properties");
    8925             : 
    8926           0 :         torture_assert(tctx,
    8927             :                 test_ResumePrinter(tctx, b, &t->handle),
    8928             :                 "failed to resume printer");
    8929             : 
    8930           0 :         return true;
    8931             : }
    8932             : 
    8933             : /* use smbd file IO to spool a print job */
    8934           8 : static bool test_print_test_smbd(struct torture_context *tctx,
    8935             :                                  void *private_data)
    8936             : {
    8937           0 :         struct torture_printer_context *t =
    8938           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    8939           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    8940           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    8941           0 :         NTSTATUS status;
    8942           0 :         uint32_t count;
    8943           8 :         union spoolss_JobInfo *info = NULL;
    8944           0 :         int i;
    8945             : 
    8946           0 :         struct smb2_tree *tree;
    8947           0 :         struct smb2_handle job_h;
    8948           0 :         struct smbcli_options options;
    8949           8 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
    8950             :         /*
    8951             :          * Do not test against the dynamically added printers, printing via
    8952             :          * smbd means that a different spoolss process may handle the
    8953             :          * OpenPrinter request to the one that handled the AddPrinter request.
    8954             :          * This currently leads to an ugly race condition where one process
    8955             :          * sees the new printer and one doesn't.
    8956             :          */
    8957           8 :         const char *share = TORTURE_PRINTER_STATIC1;
    8958             : 
    8959           8 :         torture_comment(tctx, "Testing smbd job spooling\n");
    8960           8 :         lpcfg_smbcli_options(tctx->lp_ctx, &options);
    8961             : 
    8962           8 :         status = smb2_connect(mem_ctx,
    8963             :                               torture_setting_string(tctx, "host", NULL),
    8964             :                               lpcfg_smb_ports(tctx->lp_ctx),
    8965             :                               share,
    8966             :                               lpcfg_resolve_context(tctx->lp_ctx),
    8967             :                               samba_cmdline_get_creds(),
    8968             :                               &tree,
    8969             :                               tctx->ev,
    8970             :                               &options,
    8971             :                               lpcfg_socket_options(tctx->lp_ctx),
    8972             :                               lpcfg_gensec_settings(tctx, tctx->lp_ctx));
    8973           8 :         if (!NT_STATUS_IS_OK(status)) {
    8974           0 :                 printf("Failed to connect to SMB2 printer %s - %s\n",
    8975             :                        share, nt_errstr(status));
    8976           0 :                 return false;
    8977             :         }
    8978             : 
    8979           8 :         status = torture_smb2_testfile(tree, "smbd_spooler_job", &job_h);
    8980           8 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job create");
    8981             : 
    8982           8 :         status = smb2_util_write(tree, job_h, "exciting print job data", 0,
    8983             :                                  sizeof("exciting print job data"));
    8984           8 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job write");
    8985             : 
    8986             :         /* check back end spoolss job was created */
    8987           8 :         torture_assert(tctx,
    8988             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    8989             :                                    &count, &info),
    8990             :                 "EnumJobs level 1 failed");
    8991             : 
    8992           8 :         for (i = 0; i < count; i++) {
    8993           0 :                 if (!strcmp(info[i].info1.document_name, "smbd_spooler_job")) {
    8994           0 :                         break;
    8995             :                 }
    8996             :         }
    8997           8 :         torture_assert(tctx, (i != count), "smbd_spooler_job not found");
    8998             : 
    8999           0 :         status = smb2_util_close(tree, job_h);
    9000           0 :         torture_assert_ntstatus_ok(tctx, status, "smbd spool job close");
    9001             : 
    9002             :         /* disconnect from printer share */
    9003           0 :         talloc_free(mem_ctx);
    9004             : 
    9005           0 :         return true;
    9006             : }
    9007             : 
    9008           8 : static bool test_print_test_purge(struct torture_context *tctx,
    9009             :                                   void *private_data)
    9010             : {
    9011           0 :         struct torture_printer_context *t =
    9012           8 :            (struct torture_printer_context *)talloc_get_type_abort(private_data,
    9013             :                                                 struct torture_printer_context);
    9014           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9015           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9016           8 :         uint32_t num_jobs = 8;
    9017           0 :         uint32_t *job_ids;
    9018           0 :         int i;
    9019           8 :         bool ret = true;
    9020           0 :         uint32_t count;
    9021           0 :         union spoolss_JobInfo *info;
    9022             : 
    9023           8 :         torture_assert(tctx,
    9024             :                 test_PausePrinter(tctx, b, &t->handle),
    9025             :                 "failed to pause printer");
    9026             : 
    9027           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    9028          72 :         for (i=0; i < num_jobs; i++) {
    9029          64 :                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
    9030             :                                                    "TorturePrintJob",
    9031          64 :                                                    &job_ids[i]);
    9032          64 :                 torture_assert(tctx, ret, "failed to add print job");
    9033             :         }
    9034             : 
    9035           8 :         torture_assert(tctx,
    9036             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9037             :                                    &count, &info),
    9038             :                 "EnumJobs level 1 failed");
    9039             : 
    9040           8 :         torture_assert_int_equal(tctx, count, num_jobs,
    9041             :                                  "unexpected number of jobs in queue");
    9042             : 
    9043           4 :         torture_assert(tctx,
    9044             :                 test_printer_purge(tctx, b, &t->handle),
    9045             :                 "failed to purge printer");
    9046             : 
    9047           4 :         torture_assert(tctx,
    9048             :                 test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9049             :                                    &count, &info),
    9050             :                 "EnumJobs level 1 failed");
    9051             : 
    9052           4 :         torture_assert_int_equal(tctx, count, 0,
    9053             :                                  "unexpected number of jobs in queue");
    9054             : 
    9055           4 :         torture_assert(tctx,
    9056             :                 test_ResumePrinter(tctx, b, &t->handle),
    9057             :                 "failed to resume printer");
    9058             : 
    9059           4 :         return true;
    9060             : }
    9061             : 
    9062           8 : static bool test_printer_sd(struct torture_context *tctx,
    9063             :                             void *private_data)
    9064             : {
    9065           0 :         struct torture_printer_context *t =
    9066           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9067           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9068           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9069             : 
    9070           8 :         torture_assert(tctx,
    9071             :                 test_PrinterInfo_SD(tctx, b, &t->handle),
    9072             :                 "failed to test security descriptors");
    9073             : 
    9074           8 :         return true;
    9075             : }
    9076             : 
    9077           8 : static bool test_printer_dm(struct torture_context *tctx,
    9078             :                             void *private_data)
    9079             : {
    9080           0 :         struct torture_printer_context *t =
    9081           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9082           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9083             : 
    9084           8 :         torture_assert(tctx,
    9085             :                 test_PrinterInfo_DevMode(tctx, p, &t->handle, t->info2.printername, t->devmode),
    9086             :                 "failed to test devicemodes");
    9087             : 
    9088           8 :         return true;
    9089             : }
    9090             : 
    9091           8 : static bool test_printer_info_winreg(struct torture_context *tctx,
    9092             :                                      void *private_data)
    9093             : {
    9094           0 :         struct torture_printer_context *t =
    9095           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9096           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9097             : 
    9098           8 :         torture_assert(tctx,
    9099             :                 test_PrinterInfo_winreg(tctx, p, &t->handle, t->info2.printername),
    9100             :                 "failed to test printer info winreg");
    9101             : 
    9102           8 :         return true;
    9103             : }
    9104             : 
    9105           4 : static bool test_printserver_info_winreg(struct torture_context *tctx,
    9106             :                                          void *private_data)
    9107             : {
    9108           0 :         struct test_spoolss_context *t =
    9109           4 :                 (struct test_spoolss_context *)talloc_get_type_abort(private_data, struct test_spoolss_context);
    9110           4 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9111             : 
    9112           4 :         torture_assert(tctx,
    9113             :                 test_PrintserverInfo_winreg(tctx, p, &t->server_handle),
    9114             :                 "failed to test printserver info winreg");
    9115             : 
    9116           4 :         return true;
    9117             : }
    9118             : 
    9119             : 
    9120           8 : static bool test_printer_change_id(struct torture_context *tctx,
    9121             :                                    void *private_data)
    9122             : {
    9123           0 :         struct torture_printer_context *t =
    9124           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9125           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9126             : 
    9127           8 :         torture_assert(tctx,
    9128             :                 test_ChangeID(tctx, p, &t->handle),
    9129             :                 "failed to test change id");
    9130             : 
    9131           8 :         return true;
    9132             : }
    9133             : 
    9134           8 : static bool test_printer_keys(struct torture_context *tctx,
    9135             :                               void *private_data)
    9136             : {
    9137           0 :         struct torture_printer_context *t =
    9138           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9139           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9140           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9141             : 
    9142           8 :         torture_assert(tctx,
    9143             :                 test_printer_all_keys(tctx, b, &t->handle),
    9144             :                 "failed to test printer keys");
    9145             : 
    9146           8 :         return true;
    9147             : }
    9148             : 
    9149           8 : static bool test_printer_data_consistency(struct torture_context *tctx,
    9150             :                                           void *private_data)
    9151             : {
    9152           0 :         struct torture_printer_context *t =
    9153           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9154           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9155             : 
    9156           8 :         torture_assert(tctx,
    9157             :                 test_EnumPrinterData_consistency(tctx, p, &t->handle),
    9158             :                 "failed to test printer data consistency");
    9159             : 
    9160           8 :         return true;
    9161             : }
    9162             : 
    9163           8 : static bool test_printer_data_keys(struct torture_context *tctx,
    9164             :                                    void *private_data)
    9165             : {
    9166           0 :         struct torture_printer_context *t =
    9167           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9168           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9169             : 
    9170           8 :         torture_assert(tctx,
    9171             :                 test_SetPrinterDataEx_keys(tctx, p, &t->handle),
    9172             :                 "failed to test printer data keys");
    9173             : 
    9174           8 :         return true;
    9175             : }
    9176             : 
    9177           8 : static bool test_printer_data_values(struct torture_context *tctx,
    9178             :                                      void *private_data)
    9179             : {
    9180           0 :         struct torture_printer_context *t =
    9181           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9182           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9183             : 
    9184           8 :         torture_assert(tctx,
    9185             :                 test_SetPrinterDataEx_values(tctx, p, &t->handle),
    9186             :                 "failed to test printer data values");
    9187             : 
    9188           8 :         return true;
    9189             : }
    9190             : 
    9191           8 : static bool test_printer_data_set(struct torture_context *tctx,
    9192             :                                   void *private_data)
    9193             : {
    9194           0 :         struct torture_printer_context *t =
    9195           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9196           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9197             : 
    9198           8 :         torture_assert(tctx,
    9199             :                 test_SetPrinterDataEx_matrix(tctx, p, &t->handle, t->info2.printername, NULL, NULL),
    9200             :                 "failed to test printer data set");
    9201             : 
    9202           8 :         return true;
    9203             : }
    9204             : 
    9205           8 : static bool test_printer_data_winreg(struct torture_context *tctx,
    9206             :                                      void *private_data)
    9207             : {
    9208           0 :         struct torture_printer_context *t =
    9209           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9210           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9211             : 
    9212           8 :         torture_assert(tctx,
    9213             :                 test_PrinterData_winreg(tctx, p, &t->handle, t->info2.printername),
    9214             :                 "failed to test printer data winreg");
    9215             : 
    9216           8 :         return true;
    9217             : }
    9218             : 
    9219           8 : static bool test_printer_data_dsspooler(struct torture_context *tctx,
    9220             :                                         void *private_data)
    9221             : {
    9222           0 :         struct torture_printer_context *t =
    9223           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9224           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9225             : 
    9226           8 :         torture_assert(tctx,
    9227             :                 test_PrinterData_DsSpooler(tctx, p, &t->handle, t->info2.printername),
    9228             :                 "failed to test printer data winreg dsspooler");
    9229             : 
    9230           8 :         return true;
    9231             : }
    9232             : 
    9233           8 : static bool test_printer_ic(struct torture_context *tctx,
    9234             :                             void *private_data)
    9235             : {
    9236           0 :         struct torture_printer_context *t =
    9237           8 :                 talloc_get_type_abort(private_data,
    9238             :                                       struct torture_printer_context);
    9239           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9240           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9241           0 :         struct policy_handle gdi_handle;
    9242             : 
    9243           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    9244           8 :                 torture_skip(tctx, "skip printer information context tests against samba");
    9245             :         }
    9246             : 
    9247             :         {
    9248           0 :                 struct spoolss_CreatePrinterIC r;
    9249           0 :                 struct spoolss_DevmodeContainer devmode_ctr;
    9250             : 
    9251           0 :                 ZERO_STRUCT(devmode_ctr);
    9252             : 
    9253           0 :                 r.in.handle = &t->handle;
    9254           0 :                 r.in.devmode_ctr = &devmode_ctr;
    9255           0 :                 r.out.gdi_handle = &gdi_handle;
    9256             : 
    9257           0 :                 torture_assert_ntstatus_ok(tctx,
    9258             :                         dcerpc_spoolss_CreatePrinterIC_r(b, tctx, &r),
    9259             :                         "CreatePrinterIC failed");
    9260           0 :                 torture_assert_werr_ok(tctx, r.out.result,
    9261             :                         "CreatePrinterIC failed");
    9262             :         }
    9263             : 
    9264             :         {
    9265           0 :                 struct spoolss_PlayGDIScriptOnPrinterIC r;
    9266           0 :                 DATA_BLOB in,out;
    9267           0 :                 int i;
    9268           0 :                 uint32_t num_fonts = 0;
    9269             : 
    9270           0 :                 in = data_blob_string_const("");
    9271             : 
    9272           0 :                 r.in.gdi_handle = &gdi_handle;
    9273           0 :                 r.in.pIn = in.data;
    9274           0 :                 r.in.cIn = in.length;
    9275           0 :                 r.in.ul = 0;
    9276             : 
    9277           0 :                 for (i = 0; i < 4; i++) {
    9278             : 
    9279           0 :                         out = data_blob_talloc_zero(tctx, i);
    9280             : 
    9281           0 :                         r.in.cOut = out.length;
    9282           0 :                         r.out.pOut = out.data;
    9283             : 
    9284           0 :                         torture_assert_ntstatus_ok(tctx,
    9285             :                                 dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9286             :                                 "PlayGDIScriptOnPrinterIC failed");
    9287           0 :                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_ENOUGH_MEMORY,
    9288             :                                 "PlayGDIScriptOnPrinterIC failed");
    9289             :                 }
    9290             : 
    9291           0 :                 out = data_blob_talloc_zero(tctx, 4);
    9292             : 
    9293           0 :                 r.in.cOut = out.length;
    9294           0 :                 r.out.pOut = out.data;
    9295             : 
    9296           0 :                 torture_assert_ntstatus_ok(tctx,
    9297             :                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9298             :                         "PlayGDIScriptOnPrinterIC failed");
    9299           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9300             :                         "PlayGDIScriptOnPrinterIC failed");
    9301             : 
    9302             :                 /* now we should have the required length, so retry with a
    9303             :                  * buffer which is large enough to carry all font ids */
    9304             : 
    9305           0 :                 num_fonts = IVAL(r.out.pOut, 0);
    9306             : 
    9307           0 :                 torture_comment(tctx, "PlayGDIScriptOnPrinterIC gave font count of %d\n", num_fonts);
    9308             : 
    9309           0 :                 out = data_blob_talloc_zero(tctx,
    9310           0 :                         num_fonts * sizeof(struct UNIVERSAL_FONT_ID) + 4);
    9311             : 
    9312           0 :                 r.in.cOut = out.length;
    9313           0 :                 r.out.pOut = out.data;
    9314             : 
    9315           0 :                 torture_assert_ntstatus_ok(tctx,
    9316             :                         dcerpc_spoolss_PlayGDIScriptOnPrinterIC_r(b, tctx, &r),
    9317             :                         "PlayGDIScriptOnPrinterIC failed");
    9318           0 :                 torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9319             :                         "PlayGDIScriptOnPrinterIC failed");
    9320             : 
    9321             :         }
    9322             : 
    9323             :         {
    9324           0 :                 struct spoolss_DeletePrinterIC r;
    9325             : 
    9326           0 :                 r.in.gdi_handle = &gdi_handle;
    9327           0 :                 r.out.gdi_handle = &gdi_handle;
    9328             : 
    9329           0 :                 torture_assert_ntstatus_ok(tctx,
    9330             :                         dcerpc_spoolss_DeletePrinterIC_r(b, tctx, &r),
    9331             :                         "DeletePrinterIC failed");
    9332           0 :                 torture_assert_werr_ok(tctx, r.out.result,
    9333             :                         "DeletePrinterIC failed");
    9334             : 
    9335             :         }
    9336             : 
    9337           0 :         return true;
    9338             : }
    9339             : 
    9340           8 : static bool test_printer_bidi(struct torture_context *tctx,
    9341             :                               void *private_data)
    9342             : {
    9343           0 :         struct torture_printer_context *t =
    9344           8 :                 talloc_get_type_abort(private_data,
    9345             :                                       struct torture_printer_context);
    9346           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9347           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9348           0 :         struct spoolss_SendRecvBidiData r;
    9349           0 :         struct RPC_BIDI_REQUEST_CONTAINER bidi_req;
    9350           8 :         struct RPC_BIDI_RESPONSE_CONTAINER *bidi_rep = NULL;
    9351             : 
    9352           8 :         if (torture_setting_bool(tctx, "samba3", false)) {
    9353           8 :                 torture_skip(tctx, "skip printer bidirectional tests against samba");
    9354             :         }
    9355             : 
    9356           0 :         ZERO_STRUCT(bidi_req);
    9357             : 
    9358           0 :         r.in.hPrinter = t->handle;
    9359           0 :         r.in.pAction = "foobar";
    9360           0 :         r.in.pReqData = &bidi_req;
    9361           0 :         r.out.ppRespData = &bidi_rep;
    9362             : 
    9363           0 :         torture_assert_ntstatus_ok(tctx,
    9364             :                 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
    9365             :                 "SendRecvBidiData failed");
    9366           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
    9367             :                 "SendRecvBidiData failed");
    9368             : 
    9369           0 :         if (!(t->info2.attributes & PRINTER_ATTRIBUTE_ENABLE_BIDI)) {
    9370           0 :                 torture_skip(tctx, "skipping further tests as printer is not BIDI enabled");
    9371             :         }
    9372             : 
    9373           0 :         r.in.pAction = BIDI_ACTION_ENUM_SCHEMA;
    9374             : 
    9375           0 :         torture_assert_ntstatus_ok(tctx,
    9376             :                 dcerpc_spoolss_SendRecvBidiData_r(b, tctx, &r),
    9377             :                 "SendRecvBidiData failed");
    9378           0 :         torture_assert_werr_ok(tctx, r.out.result,
    9379             :                 "SendRecvBidiData failed");
    9380             : 
    9381           0 :         return true;
    9382             : }
    9383             : 
    9384           8 : static bool test_printer_set_publish(struct torture_context *tctx,
    9385             :                                        struct dcerpc_binding_handle *b,
    9386             :                                        struct policy_handle *handle)
    9387             : {
    9388           0 :         union spoolss_PrinterInfo info;
    9389           0 :         struct spoolss_SetPrinterInfo7 info7;
    9390           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    9391           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    9392           0 :         struct sec_desc_buf secdesc_ctr;
    9393             : 
    9394           8 :         info7.guid = "";
    9395           8 :         info7.action = DSPRINT_PUBLISH;
    9396             : 
    9397           8 :         ZERO_STRUCT(info_ctr);
    9398           8 :         ZERO_STRUCT(devmode_ctr);
    9399           8 :         ZERO_STRUCT(secdesc_ctr);
    9400           8 :         info_ctr.level = 7;
    9401           8 :         info_ctr.info.info7 = &info7;
    9402             : 
    9403           8 :         torture_assert(tctx,
    9404             :                        test_SetPrinter(tctx, b, handle, &info_ctr,
    9405             :                                        &devmode_ctr, &secdesc_ctr, 0), "");
    9406             : 
    9407           0 :         torture_assert(tctx,
    9408             :                        test_GetPrinter_level(tctx, b, handle, 2, &info),
    9409             :                        "");
    9410           0 :         torture_assert(tctx,
    9411             :                        (info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
    9412             :                        "info2 publish flag not set");
    9413           0 :         torture_assert(tctx,
    9414             :                        test_GetPrinter_level(tctx, b, handle, 7, &info),
    9415             :                        "");
    9416           0 :         if (info.info7.action & DSPRINT_PENDING) {
    9417           0 :                 torture_comment(tctx, "publish is pending\n");
    9418           0 :                 torture_assert_int_equal(tctx,
    9419             :                                          info.info7.action,
    9420             :                                          (DSPRINT_PENDING | DSPRINT_PUBLISH),
    9421             :                                          "info7 publish flag not set");
    9422             :         } else {
    9423           0 :                 struct GUID guid;
    9424           0 :                 char *ref_guid;
    9425           0 :                 torture_assert_int_equal(tctx,
    9426             :                                          info.info7.action,
    9427             :                                          DSPRINT_PUBLISH,
    9428             :                                          "info7 publish flag not set");
    9429             : 
    9430             :                 /* GUID_from_string is able to parse both plain and
    9431             :                  * curly-braced guids */
    9432           0 :                 torture_assert_ntstatus_ok(tctx,
    9433             :                                            GUID_from_string(info.info7.guid,
    9434             :                                            &guid),
    9435             :                                            "invalid published printer GUID");
    9436             : 
    9437             :                 /* Build reference GUID string */
    9438           0 :                 ref_guid = GUID_string2(tctx, &guid);
    9439           0 :                 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
    9440           0 :                 ref_guid = talloc_strdup_upper(tctx, ref_guid);
    9441           0 :                 torture_assert_not_null(tctx, ref_guid, "ENOMEM");
    9442           0 :                 torture_assert_str_equal(tctx, info.info7.guid, ref_guid,
    9443             :                         "invalid GUID format");
    9444             :         }
    9445             : 
    9446           0 :         return true;
    9447             : }
    9448             : 
    9449           0 : static bool test_printer_set_unpublish(struct torture_context *tctx,
    9450             :                                        struct dcerpc_binding_handle *b,
    9451             :                                        struct policy_handle *handle)
    9452             : {
    9453           0 :         union spoolss_PrinterInfo info;
    9454           0 :         struct spoolss_SetPrinterInfo7 info7;
    9455           0 :         struct spoolss_SetPrinterInfoCtr info_ctr;
    9456           0 :         struct spoolss_DevmodeContainer devmode_ctr;
    9457           0 :         struct sec_desc_buf secdesc_ctr;
    9458             : 
    9459           0 :         info7.action = DSPRINT_UNPUBLISH;
    9460           0 :         info7.guid = "";
    9461             : 
    9462           0 :         ZERO_STRUCT(info_ctr);
    9463           0 :         ZERO_STRUCT(devmode_ctr);
    9464           0 :         ZERO_STRUCT(secdesc_ctr);
    9465           0 :         info_ctr.level = 7;
    9466           0 :         info_ctr.info.info7 = &info7;
    9467             : 
    9468           0 :         torture_assert(tctx,
    9469             :                        test_SetPrinter(tctx, b, handle, &info_ctr,
    9470             :                                        &devmode_ctr, &secdesc_ctr, 0), "");
    9471             : 
    9472           0 :         torture_assert(tctx,
    9473             :                        test_GetPrinter_level(tctx, b, handle, 2, &info),
    9474             :                        "");
    9475           0 :         torture_assert(tctx,
    9476             :                        !(info.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED),
    9477             :                        "info2 publish flag still set");
    9478           0 :         torture_assert(tctx,
    9479             :                        test_GetPrinter_level(tctx, b, handle, 7, &info),
    9480             :                        "");
    9481             : 
    9482           0 :         if (info.info7.action & DSPRINT_PENDING) {
    9483           0 :                 struct GUID guid;
    9484           0 :                 torture_comment(tctx, "unpublish is pending\n");
    9485           0 :                 torture_assert_int_equal(tctx,
    9486             :                                          info.info7.action,
    9487             :                                          (DSPRINT_PENDING | DSPRINT_UNPUBLISH),
    9488             :                                          "info7 unpublish flag not set");
    9489           0 :                 torture_assert_ntstatus_ok(tctx,
    9490             :                                            GUID_from_string(info.info7.guid,
    9491             :                                            &guid),
    9492             :                                            "invalid printer GUID");
    9493             :         } else {
    9494           0 :                 torture_assert_int_equal(tctx,
    9495             :                                          info.info7.action, DSPRINT_UNPUBLISH,
    9496             :                                          "info7 unpublish flag not set");
    9497             :         }
    9498             : 
    9499           0 :         return true;
    9500             : }
    9501             : 
    9502           8 : static bool test_printer_publish_toggle(struct torture_context *tctx,
    9503             :                                            void *private_data)
    9504             : {
    9505           0 :         struct torture_printer_context *t =
    9506           8 :                 talloc_get_type_abort(private_data,
    9507             :                                       struct torture_printer_context);
    9508           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9509           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9510           8 :         struct policy_handle *handle = &t->handle;
    9511           0 :         union spoolss_PrinterInfo info7;
    9512           0 :         union spoolss_PrinterInfo info2;
    9513             : 
    9514             :         /* check publish status via level 7 and level 2 */
    9515           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 7, &info7),
    9516             :                        "");
    9517           8 :         torture_assert(tctx, test_GetPrinter_level(tctx, b, handle, 2, &info2),
    9518             :                        "");
    9519             : 
    9520           8 :         if (info2.info2.attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
    9521           0 :                 torture_assert_int_equal(tctx,
    9522             :                                          info7.info7.action, DSPRINT_PUBLISH,
    9523             :                                          "info7 publish flag not set");
    9524           0 :                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
    9525           0 :                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
    9526             :         } else {
    9527           8 :                 torture_assert_int_equal(tctx,
    9528             :                                          info7.info7.action, DSPRINT_UNPUBLISH,
    9529             :                                          "info7 unpublish flag not set");
    9530           8 :                 torture_assert(tctx, test_printer_set_publish(tctx, b, handle), "");
    9531           0 :                 torture_assert(tctx, test_printer_set_unpublish(tctx, b, handle), "");
    9532             :         }
    9533             : 
    9534           0 :         return true;
    9535             : }
    9536             : 
    9537           8 : static bool test_driver_info_winreg(struct torture_context *tctx,
    9538             :                                     void *private_data)
    9539             : {
    9540           0 :         struct torture_printer_context *t =
    9541           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9542           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9543           8 :         const char *driver_name = t->added_driver ? t->driver.info8.driver_name : t->info2.drivername;
    9544             : 
    9545           8 :         if (!t->have_driver) {
    9546           8 :                 torture_skip(tctx, "skipping driver info winreg test as we don't have a driver");
    9547             :         }
    9548             : 
    9549           0 :         torture_assert(tctx,
    9550             :                 test_DriverInfo_winreg(tctx, p, &t->handle, t->info2.printername, driver_name, t->driver.remote.environment, 3),
    9551             :                 "failed to test driver info winreg");
    9552             : 
    9553           0 :         return true;
    9554             : }
    9555             : 
    9556           8 : static bool test_print_job_enum(struct torture_context *tctx,
    9557             :                                 void *private_data)
    9558             : {
    9559           0 :         struct torture_printer_context *t =
    9560           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9561           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9562           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9563           8 :         bool ret = true;
    9564           8 :         uint32_t num_jobs = 8;
    9565           0 :         uint32_t *job_ids;
    9566           0 :         int i;
    9567           8 :         union spoolss_JobInfo *info = NULL;
    9568           0 :         uint32_t count;
    9569             : 
    9570           8 :         torture_assert(tctx,
    9571             :                 test_PausePrinter(tctx, b, &t->handle),
    9572             :                 "failed to pause printer");
    9573             : 
    9574             :         /* purge in case of any jobs from previous tests */
    9575           8 :         torture_assert(tctx,
    9576             :                 test_printer_purge(tctx, b, &t->handle),
    9577             :                 "failed to purge printer");
    9578             : 
    9579             :         /* enum before jobs, valid level */
    9580           8 :         torture_assert(tctx,
    9581             :                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9582             :                                           &count, &info),
    9583             :                        "EnumJobs with valid level");
    9584           8 :         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
    9585           8 :         torture_assert(tctx,
    9586             :                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
    9587             :                                           &count, &info),
    9588             :                        "EnumJobs with valid level");
    9589           8 :         torture_assert_int_equal(tctx, count, 0, "EnumJobs count");
    9590             :         /* enum before jobs, invalid level - expect failure */
    9591           8 :         torture_assert(tctx,
    9592             :                        test_EnumJobs_args(tctx, b, &t->handle, 100,
    9593             :                                           WERR_INVALID_LEVEL,
    9594             :                                           &count, &info),
    9595             :                        "EnumJobs with invalid level");
    9596             : 
    9597           8 :         job_ids = talloc_zero_array(tctx, uint32_t, num_jobs);
    9598             : 
    9599          72 :         for (i = 0; i < num_jobs; i++) {
    9600          64 :                 ret = test_DoPrintTest_add_one_job(tctx, b, &t->handle,
    9601             :                                                     "TorturePrintJob",
    9602          64 :                                                     &job_ids[i]);
    9603          64 :                 torture_assert(tctx, ret, "failed to add print job");
    9604             :         }
    9605             : 
    9606             :         /* enum after jobs, valid level */
    9607           8 :         torture_assert(tctx,
    9608             :                        test_EnumJobs_args(tctx, b, &t->handle, 1, WERR_OK,
    9609             :                                           &count, &info),
    9610             :                        "EnumJobs with valid level");
    9611           8 :         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
    9612           4 :         torture_assert(tctx,
    9613             :                        test_EnumJobs_args(tctx, b, &t->handle, 2, WERR_OK,
    9614             :                                           &count, &info),
    9615             :                        "EnumJobs with valid level");
    9616           4 :         torture_assert_int_equal(tctx, count, num_jobs, "EnumJobs count");
    9617             :         /* enum after jobs, invalid level - expect failure */
    9618           4 :         torture_assert(tctx,
    9619             :                        test_EnumJobs_args(tctx, b, &t->handle, 100,
    9620             :                                           WERR_INVALID_LEVEL,
    9621             :                                           &count, &info),
    9622             :                        "EnumJobs with invalid level");
    9623             : 
    9624          36 :         for (i = 0; i < num_jobs; i++) {
    9625          32 :                 test_SetJob(tctx, b, &t->handle, job_ids[i], NULL,
    9626             :                             SPOOLSS_JOB_CONTROL_DELETE);
    9627             :         }
    9628             : 
    9629           4 :         torture_assert(tctx,
    9630             :                 test_ResumePrinter(tctx, b, &t->handle),
    9631             :                 "failed to resume printer");
    9632             : 
    9633           4 :         return true;
    9634             : }
    9635             : 
    9636           8 : static bool test_printer_log_jobinfo(struct torture_context *tctx,
    9637             :                                      void *private_data)
    9638             : {
    9639           0 :         struct torture_printer_context *t =
    9640           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9641           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9642           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9643           0 :         struct spoolss_BranchOfficeJobDataContainer info;
    9644           0 :         int i;
    9645             : 
    9646           0 :         struct spoolss_LogJobInfoForBranchOffice r;
    9647             : 
    9648           8 :         torture_comment(tctx, "Testing LogJobInfoForBranchOffice\n");
    9649             : 
    9650           8 :         info.cJobDataEntries = 0;
    9651           8 :         info.JobData = NULL;
    9652             : 
    9653           8 :         r.in.hPrinter = &t->handle;
    9654           8 :         r.in.pBranchOfficeJobDataContainer = &info;
    9655             : 
    9656           8 :         torture_assert_ntstatus_ok(tctx,
    9657             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9658             :                 "LogJobInfoForBranchOffice failed");
    9659           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAMETER,
    9660             :                 "LogJobInfoForBranchOffice failed");
    9661             : 
    9662           0 :         info.cJobDataEntries = 1;
    9663           0 :         info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
    9664             : 
    9665           0 :         info.JobData[0].eEventType = kLogOfflineFileFull;
    9666           0 :         info.JobData[0].JobId = 42;
    9667           0 :         info.JobData[0].JobInfo.LogOfflineFileFull.pMachineName = talloc_strdup(tctx, "mthelena");
    9668             : 
    9669           0 :         torture_assert_ntstatus_ok(tctx,
    9670             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9671             :                 "LogJobInfoForBranchOffice failed");
    9672           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9673             :                 "LogJobInfoForBranchOffice failed");
    9674             : 
    9675           0 :         info.cJobDataEntries = 42;
    9676           0 :         info.JobData = talloc_zero_array(tctx, struct spoolss_BranchOfficeJobData, info.cJobDataEntries);
    9677             : 
    9678           0 :         for (i=0; i < info.cJobDataEntries; i++) {
    9679           0 :                 info.JobData[i].eEventType = kLogOfflineFileFull;
    9680           0 :                 info.JobData[i].JobId = i;
    9681           0 :                 info.JobData[i].JobInfo.LogOfflineFileFull.pMachineName = talloc_asprintf(tctx, "torture_%d", i);
    9682             :         }
    9683             : 
    9684           0 :         torture_assert_ntstatus_ok(tctx,
    9685             :                 dcerpc_spoolss_LogJobInfoForBranchOffice_r(b, tctx, &r),
    9686             :                 "LogJobInfoForBranchOffice failed");
    9687           0 :         torture_assert_werr_equal(tctx, r.out.result, WERR_OK,
    9688             :                 "LogJobInfoForBranchOffice failed");
    9689             : 
    9690           0 :         return true;
    9691             : }
    9692             : 
    9693           8 : static bool test_printer_os_versions(struct torture_context *tctx,
    9694             :                                      void *private_data)
    9695             : {
    9696           0 :         struct torture_printer_context *t =
    9697           8 :                 (struct torture_printer_context *)talloc_get_type_abort(private_data, struct torture_printer_context);
    9698           8 :         struct dcerpc_pipe *p = t->spoolss_pipe;
    9699           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
    9700           0 :         union spoolss_PrinterInfo info;
    9701           0 :         DATA_BLOB blob;
    9702           0 :         uint8_t *data;
    9703           0 :         uint32_t length;
    9704           0 :         struct spoolss_OSVersion osversion;
    9705           0 :         uint8_t os_major, os_minor;
    9706           0 :         uint16_t os_build;
    9707           0 :         struct policy_handle server_handle;
    9708             : 
    9709           8 :         torture_comment(tctx, "Testing OSVersion vs. PRINTER_INFO_STRESS\n");
    9710             : 
    9711           8 :         torture_assert(tctx,
    9712             :                 test_GetPrinter_level(tctx, b, &t->handle, 0, &info),
    9713             :                 "failed to get level 0 printer info");
    9714             : 
    9715           8 :         torture_assert(tctx,
    9716             :                 test_OpenPrinter_server(tctx, p, &server_handle),
    9717             :                 "failed to open printserver");
    9718             : 
    9719           8 :         torture_assert(tctx,
    9720             :                 test_GetPrinterData_checktype(tctx, b, &server_handle, "OSVersion",
    9721             :                                               NULL, NULL, &data, &length),
    9722             :                 "failed to fetch OSVersion printer data");
    9723             : 
    9724           8 :         test_ClosePrinter(tctx, b, &server_handle);
    9725             : 
    9726           8 :         blob = data_blob_const(data, length);
    9727             : 
    9728           8 :         torture_assert_ndr_success(tctx,
    9729             :                 ndr_pull_struct_blob(&blob, tctx, &osversion,
    9730             :                         (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion),
    9731             :                 "failed to pull OSVersion");
    9732             : 
    9733           8 :         os_major = CVAL(&info.info0.version, 0);
    9734           8 :         os_minor = CVAL(&info.info0.version, 1);
    9735           8 :         os_build = SVAL(&info.info0.version, 2);
    9736             : 
    9737           8 :         torture_assert_int_equal(tctx, os_major, osversion.major, "major");
    9738           8 :         torture_assert_int_equal(tctx, os_minor, osversion.minor, "minor");
    9739           8 :         torture_assert_int_equal(tctx, os_build, osversion.build, "build");
    9740             : 
    9741           8 :         return true;
    9742             : }
    9743             : 
    9744             : 
    9745        4708 : void torture_tcase_printer(struct torture_tcase *tcase)
    9746             : {
    9747        4708 :         torture_tcase_add_simple_test(tcase, "openprinter", test_openprinter_wrap);
    9748        4708 :         torture_tcase_add_simple_test(tcase, "csetprinter", test_csetprinter);
    9749        4708 :         torture_tcase_add_simple_test(tcase, "print_test", test_print_test);
    9750        4708 :         torture_tcase_add_simple_test(tcase, "print_test_extended", test_print_test_extended);
    9751        4708 :         torture_tcase_add_simple_test(tcase, "print_test_smbd", test_print_test_smbd);
    9752        4708 :         torture_tcase_add_simple_test(tcase, "print_test_properties", test_print_test_properties);
    9753        4708 :         torture_tcase_add_simple_test(tcase, "print_test_purge", test_print_test_purge);
    9754        4708 :         torture_tcase_add_simple_test(tcase, "printer_info", test_printer_info);
    9755        4708 :         torture_tcase_add_simple_test(tcase, "sd", test_printer_sd);
    9756        4708 :         torture_tcase_add_simple_test(tcase, "dm", test_printer_dm);
    9757        4708 :         torture_tcase_add_simple_test(tcase, "printer_info_winreg", test_printer_info_winreg);
    9758        4708 :         torture_tcase_add_simple_test(tcase, "change_id", test_printer_change_id);
    9759        4708 :         torture_tcase_add_simple_test(tcase, "keys", test_printer_keys);
    9760        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_consistency", test_printer_data_consistency);
    9761        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_keys", test_printer_data_keys);
    9762        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_values", test_printer_data_values);
    9763        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_set", test_printer_data_set);
    9764        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_winreg", test_printer_data_winreg);
    9765        4708 :         torture_tcase_add_simple_test(tcase, "printerdata_dsspooler", test_printer_data_dsspooler);
    9766        4708 :         torture_tcase_add_simple_test(tcase, "driver_info_winreg", test_driver_info_winreg);
    9767        4708 :         torture_tcase_add_simple_test(tcase, "printer_rename", test_printer_rename);
    9768        4708 :         torture_tcase_add_simple_test(tcase, "printer_ic", test_printer_ic);
    9769        4708 :         torture_tcase_add_simple_test(tcase, "bidi", test_printer_bidi);
    9770        4708 :         torture_tcase_add_simple_test(tcase, "publish_toggle",
    9771             :                                       test_printer_publish_toggle);
    9772        4708 :         torture_tcase_add_simple_test(tcase, "print_job_enum", test_print_job_enum);
    9773        4708 :         torture_tcase_add_simple_test(tcase, "log_jobinfo", test_printer_log_jobinfo);
    9774        4708 :         torture_tcase_add_simple_test(tcase, "os_versions", test_printer_os_versions);
    9775        4708 : }
    9776             : 
    9777        2354 : struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
    9778             : {
    9779        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "printer");
    9780         125 :         struct torture_tcase *tcase;
    9781             : 
    9782        2354 :         tcase = torture_suite_add_tcase(suite, "addprinter");
    9783             : 
    9784        2354 :         torture_tcase_set_fixture(tcase,
    9785             :                                   torture_rpc_spoolss_printer_setup,
    9786             :                                   torture_rpc_spoolss_printer_teardown);
    9787             : 
    9788        2354 :         torture_tcase_printer(tcase);
    9789             : 
    9790        2354 :         tcase = torture_suite_add_tcase(suite, "addprinterex");
    9791             : 
    9792        2354 :         torture_tcase_set_fixture(tcase,
    9793             :                                   torture_rpc_spoolss_printerex_setup,
    9794             :                                   torture_rpc_spoolss_printer_teardown);
    9795             : 
    9796        2354 :         torture_tcase_printer(tcase);
    9797             : 
    9798        2354 :         tcase = torture_suite_add_tcase(suite, "addprinterwkn");
    9799             : 
    9800        2354 :         torture_tcase_set_fixture(tcase,
    9801             :                                   torture_rpc_spoolss_printerwkn_setup,
    9802             :                                   torture_rpc_spoolss_printer_teardown);
    9803             : 
    9804        2354 :         tcase = torture_suite_add_tcase(suite, "addprinterexwkn");
    9805             : 
    9806        2354 :         torture_tcase_set_fixture(tcase,
    9807             :                                   torture_rpc_spoolss_printerexwkn_setup,
    9808             :                                   torture_rpc_spoolss_printer_teardown);
    9809             : 
    9810             : #if 0
    9811             :         /* test is not correct */
    9812             :         tcase = torture_suite_add_tcase(suite, "addprinterdm");
    9813             : 
    9814             :         torture_tcase_set_fixture(tcase,
    9815             :                                   torture_rpc_spoolss_printerdm_setup,
    9816             :                                   torture_rpc_spoolss_printer_teardown);
    9817             : 
    9818             :         torture_tcase_printer(tcase);
    9819             : #endif
    9820        2354 :         return suite;
    9821             : }
    9822             : 
    9823        2354 : struct torture_suite *torture_rpc_spoolss(TALLOC_CTX *mem_ctx)
    9824             : {
    9825        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss");
    9826        2354 :         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
    9827             : 
    9828        2354 :         torture_tcase_set_fixture(tcase,
    9829             :                                   torture_rpc_spoolss_setup,
    9830             :                                   torture_rpc_spoolss_teardown);
    9831             : 
    9832        2354 :         torture_tcase_add_simple_test(tcase, "openprinter_badnamelist", test_OpenPrinter_badname_list);
    9833        2354 :         torture_tcase_add_simple_test(tcase, "printer_data_list", test_GetPrinterData_list);
    9834        2354 :         torture_tcase_add_simple_test(tcase, "enum_forms", test_PrintServer_EnumForms);
    9835        2354 :         torture_tcase_add_simple_test(tcase, "forms", test_PrintServer_Forms);
    9836        2354 :         torture_tcase_add_simple_test(tcase, "forms_winreg", test_PrintServer_Forms_Winreg);
    9837        2354 :         torture_tcase_add_simple_test(tcase, "enum_ports", test_EnumPorts);
    9838        2354 :         torture_tcase_add_simple_test(tcase, "add_port", test_AddPort);
    9839        2354 :         torture_tcase_add_simple_test(tcase, "get_printer_driver_directory", test_GetPrinterDriverDirectory);
    9840        2354 :         torture_tcase_add_simple_test(tcase, "get_print_processor_directory", test_GetPrintProcessorDirectory);
    9841        2354 :         torture_tcase_add_simple_test(tcase, "enum_printer_drivers", test_EnumPrinterDrivers);
    9842        2354 :         torture_tcase_add_simple_test(tcase, "enum_monitors", test_EnumMonitors);
    9843        2354 :         torture_tcase_add_simple_test(tcase, "enum_print_processors", test_EnumPrintProcessors);
    9844        2354 :         torture_tcase_add_simple_test(tcase, "print_processors_winreg", test_print_processors_winreg);
    9845        2354 :         torture_tcase_add_simple_test(tcase, "add_processor", test_add_print_processor);
    9846        2354 :         torture_tcase_add_simple_test(tcase, "enum_printprocdata", test_EnumPrintProcessorDataTypes);
    9847        2354 :         torture_tcase_add_simple_test(tcase, "enum_printers", test_EnumPrinters);
    9848        2354 :         torture_tcase_add_simple_test(tcase, "enum_ports_old", test_EnumPorts_old);
    9849        2354 :         torture_tcase_add_simple_test(tcase, "enum_printers_old", test_EnumPrinters_old);
    9850        2354 :         torture_tcase_add_simple_test(tcase, "enum_printers_servername", test_EnumPrinters_servername);
    9851        2354 :         torture_tcase_add_simple_test(tcase, "enum_printer_drivers_old", test_EnumPrinterDrivers_old);
    9852        2354 :         torture_tcase_add_simple_test(tcase, "architecture_buffer", test_architecture_buffer);
    9853        2354 :         torture_tcase_add_simple_test(tcase, "get_core_printer_drivers", test_get_core_printer_drivers);
    9854        2354 :         torture_tcase_add_simple_test(tcase, "get_printer_driver_package_path", test_get_printer_driver_package_path);
    9855        2354 :         torture_tcase_add_simple_test(tcase, "get_printer", test_get_printer_printserverhandle);
    9856        2354 :         torture_tcase_add_simple_test(tcase, "set_printer", test_set_printer_printserverhandle);
    9857        2354 :         torture_tcase_add_simple_test(tcase, "printserver_info_winreg", test_printserver_info_winreg);
    9858        2354 :         torture_tcase_add_simple_test(tcase, "addpermachineconnection", test_addpermachineconnection);
    9859             : 
    9860        2354 :         torture_suite_add_suite(suite, torture_rpc_spoolss_printer(suite));
    9861             : 
    9862        2354 :         return suite;
    9863             : }
    9864             : 
    9865          64 : static bool test_GetPrinterDriverDirectory_getdir(struct torture_context *tctx,
    9866             :                                                   struct dcerpc_binding_handle *b,
    9867             :                                                   const char *server,
    9868             :                                                   const char *environment,
    9869             :                                                   const char **dir_p)
    9870             : {
    9871           0 :         struct spoolss_GetPrinterDriverDirectory r;
    9872           0 :         uint32_t needed;
    9873             : 
    9874          64 :         r.in.server             = server;
    9875          64 :         r.in.environment        = environment;
    9876          64 :         r.in.level              = 1;
    9877          64 :         r.in.buffer             = NULL;
    9878          64 :         r.in.offered            = 0;
    9879          64 :         r.out.needed            = &needed;
    9880             : 
    9881          64 :         torture_assert_ntstatus_ok(tctx,
    9882             :                 dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
    9883             :                 "failed to query driver directory");
    9884             : 
    9885          64 :         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
    9886          64 :                 DATA_BLOB blob = data_blob_talloc_zero(tctx, needed);
    9887          64 :                 r.in.buffer = &blob;
    9888          64 :                 r.in.offered = needed;
    9889             : 
    9890          64 :                 torture_assert_ntstatus_ok(tctx,
    9891             :                         dcerpc_spoolss_GetPrinterDriverDirectory_r(b, tctx, &r),
    9892             :                         "failed to query driver directory");
    9893             :         }
    9894             : 
    9895          64 :         torture_assert_werr_ok(tctx, r.out.result,
    9896             :                 "failed to query driver directory");
    9897             : 
    9898          64 :         if (dir_p) {
    9899          64 :                 *dir_p = r.out.info->info1.directory_name;
    9900             :         }
    9901             : 
    9902          64 :         return true;
    9903             : }
    9904             : 
    9905           0 : static const char *get_driver_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
    9906             : {
    9907           0 :         if (info_ctr == NULL) {
    9908           0 :                 return NULL;
    9909             :         }
    9910             : 
    9911           0 :         switch (info_ctr->level) {
    9912           0 :         case 1:
    9913           0 :                 return info_ctr->info.info1->driver_name;
    9914           0 :         case 2:
    9915           0 :                 return info_ctr->info.info2->driver_name;
    9916           0 :         case 3:
    9917           0 :                 return info_ctr->info.info3->driver_name;
    9918           0 :         case 4:
    9919           0 :                 return info_ctr->info.info4->driver_name;
    9920           0 :         case 6:
    9921           0 :                 return info_ctr->info.info6->driver_name;
    9922           0 :         case 8:
    9923           0 :                 return info_ctr->info.info8->driver_name;
    9924           0 :         default:
    9925           0 :                 return NULL;
    9926             :         }
    9927             : }
    9928             : 
    9929           0 : static const char *get_environment_from_info(struct spoolss_AddDriverInfoCtr *info_ctr)
    9930             : {
    9931           0 :         if (info_ctr == NULL) {
    9932           0 :                 return NULL;
    9933             :         }
    9934             : 
    9935           0 :         switch (info_ctr->level) {
    9936           0 :         case 2:
    9937           0 :                 return info_ctr->info.info2->architecture;
    9938           0 :         case 3:
    9939           0 :                 return info_ctr->info.info3->architecture;
    9940           0 :         case 4:
    9941           0 :                 return info_ctr->info.info4->architecture;
    9942           0 :         case 6:
    9943           0 :                 return info_ctr->info.info6->architecture;
    9944           0 :         case 8:
    9945           0 :                 return info_ctr->info.info8->architecture;
    9946           0 :         default:
    9947           0 :                 return NULL;
    9948             :         }
    9949             : }
    9950             : 
    9951             : 
    9952           0 : static bool test_AddPrinterDriver_exp(struct torture_context *tctx,
    9953             :                                       struct dcerpc_binding_handle *b,
    9954             :                                       const char *servername,
    9955             :                                       struct spoolss_AddDriverInfoCtr *info_ctr,
    9956             :                                       WERROR expected_result)
    9957             : {
    9958           0 :         struct spoolss_AddPrinterDriver r;
    9959           0 :         const char *drivername = get_driver_from_info(info_ctr);
    9960           0 :         const char *environment = get_environment_from_info(info_ctr);
    9961             : 
    9962           0 :         r.in.servername = servername;
    9963           0 :         r.in.info_ctr = info_ctr;
    9964             : 
    9965           0 :         torture_comment(tctx, "Testing AddPrinterDriver(%s) level: %d, environment: '%s'\n",
    9966             :                 drivername, info_ctr->level, environment);
    9967             : 
    9968           0 :         torture_assert_ntstatus_ok(tctx,
    9969             :                 dcerpc_spoolss_AddPrinterDriver_r(b, tctx, &r),
    9970             :                 "spoolss_AddPrinterDriver failed");
    9971           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
    9972             :                 "spoolss_AddPrinterDriver failed with unexpected result");
    9973             : 
    9974           0 :         return true;
    9975             : 
    9976             : }
    9977             : 
    9978           0 : static bool test_AddPrinterDriverEx_exp(struct torture_context *tctx,
    9979             :                                         struct dcerpc_binding_handle *b,
    9980             :                                         const char *servername,
    9981             :                                         struct spoolss_AddDriverInfoCtr *info_ctr,
    9982             :                                         uint32_t flags,
    9983             :                                         WERROR expected_result)
    9984             : {
    9985           0 :         struct spoolss_AddPrinterDriverEx r;
    9986           0 :         const char *drivername = get_driver_from_info(info_ctr);
    9987           0 :         const char *environment = get_environment_from_info(info_ctr);
    9988             : 
    9989           0 :         r.in.servername = servername;
    9990           0 :         r.in.info_ctr = info_ctr;
    9991           0 :         r.in.flags = flags;
    9992             : 
    9993           0 :         torture_comment(tctx, "Testing AddPrinterDriverEx(%s) level: %d, environment: '%s'\n",
    9994             :                 drivername, info_ctr->level, environment);
    9995             : 
    9996           0 :         torture_assert_ntstatus_ok(tctx,
    9997             :                 dcerpc_spoolss_AddPrinterDriverEx_r(b, tctx, &r),
    9998             :                 "AddPrinterDriverEx failed");
    9999           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
   10000             :                 "AddPrinterDriverEx failed with unexpected result");
   10001             : 
   10002           0 :         return true;
   10003             : }
   10004             : 
   10005             : #define ASSERT_DRIVER_PATH(tctx, path, driver_dir, cmt) \
   10006             :         if (path && strlen(path)) {\
   10007             :                 torture_assert_strn_equal(tctx, path, driver_dir, strlen(driver_dir), cmt); \
   10008             :         }
   10009             : 
   10010           0 : static bool test_AddPrinterDriver_args_level_1(struct torture_context *tctx,
   10011             :                                                struct dcerpc_binding_handle *b,
   10012             :                                                const char *server_name,
   10013             :                                                struct spoolss_AddDriverInfo8 *r,
   10014             :                                                uint32_t flags,
   10015             :                                                bool ex,
   10016             :                                                const char *remote_driver_dir)
   10017             : {
   10018           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10019           0 :         struct spoolss_AddDriverInfo1 info1;
   10020             : 
   10021           0 :         ZERO_STRUCT(info1);
   10022             : 
   10023           0 :         info_ctr.level = 1;
   10024           0 :         info_ctr.info.info1 = &info1;
   10025             : 
   10026           0 :         if (ex) {
   10027           0 :                 torture_assert(tctx,
   10028             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
   10029             :                         "failed to test AddPrinterDriverEx level 1");
   10030             :         } else {
   10031           0 :                 torture_assert(tctx,
   10032             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
   10033             :                         "failed to test AddPrinterDriver level 1");
   10034             :         }
   10035             : 
   10036           0 :         info1.driver_name = r->driver_name;
   10037             : 
   10038           0 :         if (ex) {
   10039           0 :                 torture_assert(tctx,
   10040             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_LEVEL),
   10041             :                         "failed to test AddPrinterDriverEx level 1");
   10042             :         } else {
   10043           0 :                 torture_assert(tctx,
   10044             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
   10045             :                         "failed to test AddPrinterDriver level 1");
   10046             :         }
   10047             : 
   10048           0 :         return true;
   10049             : }
   10050             : 
   10051           0 : static bool test_AddPrinterDriver_args_level_2(struct torture_context *tctx,
   10052             :                                                struct dcerpc_binding_handle *b,
   10053             :                                                const char *server_name,
   10054             :                                                struct spoolss_AddDriverInfo8 *r,
   10055             :                                                uint32_t flags,
   10056             :                                                bool ex,
   10057             :                                                const char *remote_driver_dir)
   10058             : {
   10059           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10060           0 :         struct spoolss_AddDriverInfo2 info2;
   10061           0 :         union spoolss_DriverInfo info;
   10062             : 
   10063           0 :         ZERO_STRUCT(info2);
   10064             : 
   10065           0 :         info_ctr.level = 2;
   10066           0 :         info_ctr.info.info2 = &info2;
   10067             : 
   10068           0 :         if (ex) {
   10069           0 :                 torture_assert(tctx,
   10070             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10071             :                         "failed to test AddPrinterDriverEx level 2");
   10072             :         } else {
   10073           0 :                 torture_assert(tctx,
   10074             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10075             :                         "failed to test AddPrinterDriver level 2");
   10076             :         }
   10077             : 
   10078           0 :         info2.driver_name = r->driver_name;
   10079             : 
   10080           0 :         if (ex) {
   10081           0 :                 torture_assert(tctx,
   10082             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10083             :                         "failed to test AddPrinterDriverEx level 2");
   10084             :         } else {
   10085           0 :                 torture_assert(tctx,
   10086             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10087             :                         "failed to test AddPrinterDriver level 2");
   10088             :         }
   10089             : 
   10090           0 :         info2.version = r->version;
   10091             : 
   10092           0 :         if (ex) {
   10093           0 :                 torture_assert(tctx,
   10094             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10095             :                         "failed to test AddPrinterDriverEx level 2");
   10096             :         } else {
   10097           0 :                 torture_assert(tctx,
   10098             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10099             :                         "failed to test AddPrinterDriver level 2");
   10100             :         }
   10101             : 
   10102           0 :         info2.architecture = r->architecture;
   10103             : 
   10104           0 :         if (ex) {
   10105           0 :                 torture_assert(tctx,
   10106             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10107             :                         "failed to test AddPrinterDriverEx level 2");
   10108             :         } else {
   10109           0 :                 torture_assert(tctx,
   10110             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10111             :                         "failed to test AddPrinterDriver level 2");
   10112             :         }
   10113             : 
   10114           0 :         info2.driver_path = r->driver_path;
   10115             : 
   10116           0 :         if (ex) {
   10117           0 :                 torture_assert(tctx,
   10118             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10119             :                         "failed to test AddPrinterDriverEx level 2");
   10120             :         } else {
   10121           0 :                 torture_assert(tctx,
   10122             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10123             :                         "failed to test AddPrinterDriver level 2");
   10124             :         }
   10125             : 
   10126           0 :         info2.data_file = r->data_file;
   10127             : 
   10128           0 :         if (ex) {
   10129           0 :                 torture_assert(tctx,
   10130             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_INVALID_PARAMETER),
   10131             :                         "failed to test AddPrinterDriverEx level 2");
   10132             :         } else {
   10133           0 :                 torture_assert(tctx,
   10134             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_PARAMETER),
   10135             :                         "failed to test AddPrinterDriver level 2");
   10136             :         }
   10137             : 
   10138           0 :         info2.config_file = r->config_file;
   10139             : 
   10140           0 :         if (ex) {
   10141           0 :                 torture_assert(tctx,
   10142             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, 0, WERR_INVALID_PARAMETER),
   10143             :                         "failed to test AddPrinterDriverEx");
   10144             :         }
   10145             : 
   10146           0 :         if (ex) {
   10147           0 :                 torture_assert(tctx,
   10148             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
   10149             :                         "failed to test AddPrinterDriverEx level 2");
   10150             :         } else {
   10151           0 :                 torture_assert(tctx,
   10152             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
   10153             :                         "failed to test AddPrinterDriver level 2");
   10154             :         }
   10155             : 
   10156           0 :         torture_assert(tctx,
   10157             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 2, r->driver_name, &info),
   10158             :                 "failed to find added printer driver");
   10159             : 
   10160           0 :         if (remote_driver_dir) {
   10161           0 :                 ASSERT_DRIVER_PATH(tctx, info.info2.driver_path, remote_driver_dir, "unexpected path");
   10162           0 :                 ASSERT_DRIVER_PATH(tctx, info.info2.data_file, remote_driver_dir, "unexpected path");
   10163           0 :                 ASSERT_DRIVER_PATH(tctx, info.info2.config_file, remote_driver_dir, "unexpected path");
   10164             :         }
   10165             : 
   10166           0 :         return true;
   10167             : }
   10168             : 
   10169           0 : static bool test_AddPrinterDriver_args_level_3(struct torture_context *tctx,
   10170             :                                                struct dcerpc_binding_handle *b,
   10171             :                                                const char *server_name,
   10172             :                                                struct spoolss_AddDriverInfo8 *r,
   10173             :                                                uint32_t flags,
   10174             :                                                bool ex,
   10175             :                                                const char *remote_driver_dir)
   10176             : {
   10177           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10178           0 :         struct spoolss_AddDriverInfo3 info3;
   10179           0 :         union spoolss_DriverInfo info;
   10180             : 
   10181           0 :         info3.driver_name       = r->driver_name;
   10182           0 :         info3.version           = r->version;
   10183           0 :         info3.architecture      = r->architecture;
   10184           0 :         info3.driver_path       = r->driver_path;
   10185           0 :         info3.data_file         = r->data_file;
   10186           0 :         info3.config_file       = r->config_file;
   10187           0 :         info3.help_file         = r->help_file;
   10188           0 :         info3.monitor_name      = r->monitor_name;
   10189           0 :         info3.default_datatype  = r->default_datatype;
   10190           0 :         info3._ndr_size_dependent_files = r->_ndr_size_dependent_files;
   10191           0 :         info3.dependent_files   = r->dependent_files;
   10192             : 
   10193           0 :         info_ctr.level = 3;
   10194           0 :         info_ctr.info.info3 = &info3;
   10195             : 
   10196           0 :         if (ex) {
   10197           0 :                 torture_assert(tctx,
   10198             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
   10199             :                         "failed to test AddPrinterDriverEx level 3");
   10200             :         } else {
   10201           0 :                 torture_assert(tctx,
   10202             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
   10203             :                         "failed to test AddPrinterDriver level 3");
   10204             :         }
   10205             : 
   10206           0 :         torture_assert(tctx,
   10207             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 3, r->driver_name, &info),
   10208             :                 "failed to find added printer driver");
   10209             : 
   10210           0 :         if (remote_driver_dir) {
   10211           0 :                 int i;
   10212           0 :                 ASSERT_DRIVER_PATH(tctx, info.info3.driver_path, remote_driver_dir, "unexpected path");
   10213           0 :                 ASSERT_DRIVER_PATH(tctx, info.info3.data_file, remote_driver_dir, "unexpected path");
   10214           0 :                 ASSERT_DRIVER_PATH(tctx, info.info3.config_file, remote_driver_dir, "unexpected path");
   10215           0 :                 ASSERT_DRIVER_PATH(tctx, info.info3.help_file, remote_driver_dir, "unexpected path");
   10216           0 :                 for (i=0; info.info3.dependent_files && info.info3.dependent_files[i] != NULL; i++) {
   10217           0 :                         ASSERT_DRIVER_PATH(tctx, info.info3.dependent_files[i], remote_driver_dir, "unexpected path");
   10218             :                 }
   10219             :         }
   10220             : 
   10221           0 :         return true;
   10222             : }
   10223             : 
   10224           0 : static bool test_AddPrinterDriver_args_level_4(struct torture_context *tctx,
   10225             :                                                struct dcerpc_binding_handle *b,
   10226             :                                                const char *server_name,
   10227             :                                                struct spoolss_AddDriverInfo8 *r,
   10228             :                                                uint32_t flags,
   10229             :                                                bool ex,
   10230             :                                                const char *remote_driver_dir)
   10231             : {
   10232           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10233           0 :         struct spoolss_AddDriverInfo4 info4;
   10234           0 :         union spoolss_DriverInfo info;
   10235             : 
   10236           0 :         info4.version           = r->version;
   10237           0 :         info4.driver_name       = r->driver_name;
   10238           0 :         info4.architecture      = r->architecture;
   10239           0 :         info4.driver_path       = r->driver_path;
   10240           0 :         info4.data_file         = r->data_file;
   10241           0 :         info4.config_file       = r->config_file;
   10242           0 :         info4.help_file         = r->help_file;
   10243           0 :         info4.monitor_name      = r->monitor_name;
   10244           0 :         info4.default_datatype  = r->default_datatype;
   10245           0 :         info4._ndr_size_dependent_files = r->_ndr_size_dependent_files;
   10246           0 :         info4.dependent_files   = r->dependent_files;
   10247           0 :         info4._ndr_size_previous_names = r->_ndr_size_previous_names;
   10248           0 :         info4.previous_names = r->previous_names;
   10249             : 
   10250           0 :         info_ctr.level = 4;
   10251           0 :         info_ctr.info.info4 = &info4;
   10252             : 
   10253           0 :         if (ex) {
   10254           0 :                 torture_assert(tctx,
   10255             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
   10256             :                         "failed to test AddPrinterDriverEx level 4");
   10257             :         } else {
   10258           0 :                 torture_assert(tctx,
   10259             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_OK),
   10260             :                         "failed to test AddPrinterDriver level 4");
   10261             :         }
   10262             : 
   10263           0 :         torture_assert(tctx,
   10264             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 4, r->driver_name, &info),
   10265             :                 "failed to find added printer driver");
   10266             : 
   10267           0 :         if (remote_driver_dir) {
   10268           0 :                 int i;
   10269           0 :                 ASSERT_DRIVER_PATH(tctx, info.info4.driver_path, remote_driver_dir, "unexpected path");
   10270           0 :                 ASSERT_DRIVER_PATH(tctx, info.info4.data_file, remote_driver_dir, "unexpected path");
   10271           0 :                 ASSERT_DRIVER_PATH(tctx, info.info4.config_file, remote_driver_dir, "unexpected path");
   10272           0 :                 ASSERT_DRIVER_PATH(tctx, info.info4.help_file, remote_driver_dir, "unexpected path");
   10273           0 :                 for (i=0; info.info4.dependent_files && info.info4.dependent_files[i] != NULL; i++) {
   10274           0 :                         ASSERT_DRIVER_PATH(tctx, info.info4.dependent_files[i], remote_driver_dir, "unexpected path");
   10275             :                 }
   10276             :         }
   10277             : 
   10278           0 :         return true;
   10279             : }
   10280             : 
   10281           0 : static bool test_AddPrinterDriver_args_level_6(struct torture_context *tctx,
   10282             :                                                struct dcerpc_binding_handle *b,
   10283             :                                                const char *server_name,
   10284             :                                                struct spoolss_AddDriverInfo8 *r,
   10285             :                                                uint32_t flags,
   10286             :                                                bool ex,
   10287             :                                                const char *remote_driver_dir)
   10288             : {
   10289           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10290           0 :         struct spoolss_AddDriverInfo6 info6;
   10291           0 :         union spoolss_DriverInfo info;
   10292             : 
   10293           0 :         info6.version           = r->version;
   10294           0 :         info6.driver_name       = r->driver_name;
   10295           0 :         info6.architecture      = r->architecture;
   10296           0 :         info6.driver_path       = r->driver_path;
   10297           0 :         info6.data_file         = r->data_file;
   10298           0 :         info6.config_file       = r->config_file;
   10299           0 :         info6.help_file         = r->help_file;
   10300           0 :         info6.monitor_name      = r->monitor_name;
   10301           0 :         info6.default_datatype  = r->default_datatype;
   10302           0 :         info6._ndr_size_dependent_files = r->_ndr_size_dependent_files;
   10303           0 :         info6.dependent_files   = r->dependent_files;
   10304           0 :         info6._ndr_size_previous_names = r->_ndr_size_previous_names;
   10305           0 :         info6.previous_names    = r->previous_names;
   10306           0 :         info6.driver_date       = r->driver_date;
   10307           0 :         info6.driver_version    = r->driver_version;
   10308           0 :         info6.manufacturer_name = r->manufacturer_name;
   10309           0 :         info6.manufacturer_url  = r->manufacturer_url;
   10310           0 :         info6.hardware_id       = r->hardware_id;
   10311           0 :         info6.provider          = r->provider;
   10312             : 
   10313           0 :         info_ctr.level = 6;
   10314           0 :         info_ctr.info.info6 = &info6;
   10315             : 
   10316           0 :         if (ex) {
   10317           0 :                 torture_assert(tctx,
   10318             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
   10319             :                         "failed to test AddPrinterDriverEx level 6");
   10320             :         } else {
   10321           0 :                 torture_assert(tctx,
   10322             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
   10323             :                         "failed to test AddPrinterDriver level 6");
   10324             :         }
   10325             : 
   10326             :         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
   10327             : 
   10328           0 :         if (!ex) {
   10329           0 :                 return true;
   10330             :         }
   10331             : 
   10332           0 :         torture_assert(tctx,
   10333             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 6, r->driver_name, &info),
   10334             :                 "failed to find added printer driver");
   10335             : 
   10336           0 :         if (remote_driver_dir) {
   10337           0 :                 int i;
   10338           0 :                 ASSERT_DRIVER_PATH(tctx, info.info6.driver_path, remote_driver_dir, "unexpected path");
   10339           0 :                 ASSERT_DRIVER_PATH(tctx, info.info6.data_file, remote_driver_dir, "unexpected path");
   10340           0 :                 ASSERT_DRIVER_PATH(tctx, info.info6.config_file, remote_driver_dir, "unexpected path");
   10341           0 :                 ASSERT_DRIVER_PATH(tctx, info.info6.help_file, remote_driver_dir, "unexpected path");
   10342           0 :                 for (i=0; info.info6.dependent_files && info.info6.dependent_files[i] != NULL; i++) {
   10343           0 :                         ASSERT_DRIVER_PATH(tctx, info.info6.dependent_files[i], remote_driver_dir, "unexpected path");
   10344             :                 }
   10345             :         }
   10346             : 
   10347           0 :         torture_assert_nttime_equal(tctx, info.info6.driver_date, info6.driver_date, "driverdate mismatch");
   10348           0 :         torture_assert_u64_equal(tctx, info.info6.driver_version, info6.driver_version, "driverversion mismatch");
   10349             : 
   10350           0 :         return true;
   10351             : }
   10352             : 
   10353           0 : static bool test_AddPrinterDriver_args_level_8(struct torture_context *tctx,
   10354             :                                                struct dcerpc_binding_handle *b,
   10355             :                                                const char *server_name,
   10356             :                                                struct spoolss_AddDriverInfo8 *r,
   10357             :                                                uint32_t flags,
   10358             :                                                bool ex,
   10359             :                                                const char *remote_driver_dir)
   10360             : {
   10361           0 :         struct spoolss_AddDriverInfoCtr info_ctr;
   10362           0 :         union spoolss_DriverInfo info;
   10363             : 
   10364           0 :         info_ctr.level = 8;
   10365           0 :         info_ctr.info.info8 = r;
   10366             : 
   10367           0 :         if (ex) {
   10368           0 :                 torture_assert(tctx,
   10369             :                         test_AddPrinterDriverEx_exp(tctx, b, server_name, &info_ctr, flags, WERR_OK),
   10370             :                         "failed to test AddPrinterDriverEx level 8");
   10371             :         } else {
   10372           0 :                 torture_assert(tctx,
   10373             :                         test_AddPrinterDriver_exp(tctx, b, server_name, &info_ctr, WERR_INVALID_LEVEL),
   10374             :                         "failed to test AddPrinterDriver level 8");
   10375             :         }
   10376             : 
   10377             :         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
   10378             : 
   10379           0 :         if (!ex) {
   10380           0 :                 return true;
   10381             :         }
   10382             : 
   10383           0 :         torture_assert(tctx,
   10384             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name, r->architecture, 8, r->driver_name, &info),
   10385             :                 "failed to find added printer driver");
   10386             : 
   10387           0 :         if (remote_driver_dir) {
   10388           0 :                 int i;
   10389           0 :                 ASSERT_DRIVER_PATH(tctx, info.info8.driver_path, remote_driver_dir, "unexpected path");
   10390           0 :                 ASSERT_DRIVER_PATH(tctx, info.info8.data_file, remote_driver_dir, "unexpected path");
   10391           0 :                 ASSERT_DRIVER_PATH(tctx, info.info8.config_file, remote_driver_dir, "unexpected path");
   10392           0 :                 ASSERT_DRIVER_PATH(tctx, info.info8.help_file, remote_driver_dir, "unexpected path");
   10393           0 :                 for (i=0; info.info8.dependent_files && info.info8.dependent_files[i] != NULL; i++) {
   10394           0 :                         ASSERT_DRIVER_PATH(tctx, info.info8.dependent_files[i], remote_driver_dir, "unexpected path");
   10395             :                 }
   10396             :         }
   10397             : 
   10398           0 :         torture_assert_nttime_equal(tctx, info.info8.driver_date, r->driver_date, "driverdate mismatch");
   10399           0 :         torture_assert_u64_equal(tctx, info.info8.driver_version, r->driver_version, "driverversion mismatch");
   10400             : 
   10401           0 :         return true;
   10402             : }
   10403             : 
   10404             : #undef ASSERT_DRIVER_PATH
   10405             : 
   10406           0 : static bool test_DeletePrinterDriver_exp(struct torture_context *tctx,
   10407             :                                          struct dcerpc_binding_handle *b,
   10408             :                                          const char *server,
   10409             :                                          const char *driver,
   10410             :                                          const char *environment,
   10411             :                                          WERROR expected_result)
   10412             : {
   10413           0 :         struct spoolss_DeletePrinterDriver r;
   10414             : 
   10415           0 :         r.in.server = server;
   10416           0 :         r.in.architecture = environment;
   10417           0 :         r.in.driver = driver;
   10418             : 
   10419           0 :         torture_comment(tctx, "Testing DeletePrinterDriver(%s)\n", driver);
   10420             : 
   10421           0 :         torture_assert_ntstatus_ok(tctx,
   10422             :                 dcerpc_spoolss_DeletePrinterDriver_r(b, tctx, &r),
   10423             :                 "DeletePrinterDriver failed");
   10424           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
   10425             :                 "DeletePrinterDriver failed with unexpected result");
   10426             : 
   10427           0 :         return true;
   10428             : }
   10429             : 
   10430           0 : static bool test_DeletePrinterDriverEx_exp(struct torture_context *tctx,
   10431             :                                            struct dcerpc_binding_handle *b,
   10432             :                                            const char *server,
   10433             :                                            const char *driver,
   10434             :                                            const char *environment,
   10435             :                                            uint32_t delete_flags,
   10436             :                                            uint32_t version,
   10437             :                                            WERROR expected_result)
   10438             : {
   10439           0 :         struct spoolss_DeletePrinterDriverEx r;
   10440             : 
   10441           0 :         r.in.server = server;
   10442           0 :         r.in.architecture = environment;
   10443           0 :         r.in.driver = driver;
   10444           0 :         r.in.delete_flags = delete_flags;
   10445           0 :         r.in.version = version;
   10446             : 
   10447           0 :         torture_comment(tctx, "Testing DeletePrinterDriverEx(%s)\n", driver);
   10448             : 
   10449           0 :         torture_assert_ntstatus_ok(tctx,
   10450             :                 dcerpc_spoolss_DeletePrinterDriverEx_r(b, tctx, &r),
   10451             :                 "DeletePrinterDriverEx failed");
   10452           0 :         torture_assert_werr_equal(tctx, r.out.result, expected_result,
   10453             :                 "DeletePrinterDriverEx failed with unexpected result");
   10454             : 
   10455           0 :         return true;
   10456             : }
   10457             : 
   10458           0 : static bool test_DeletePrinterDriver(struct torture_context *tctx,
   10459             :                                      struct dcerpc_binding_handle *b,
   10460             :                                      const char *server_name,
   10461             :                                      const char *driver,
   10462             :                                      const char *environment)
   10463             : {
   10464           0 :         torture_assert(tctx,
   10465             :                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, "FOOBAR", WERR_INVALID_ENVIRONMENT),
   10466             :                 "failed to delete driver");
   10467             : 
   10468           0 :         torture_assert(tctx,
   10469             :                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_OK),
   10470             :                 "failed to delete driver");
   10471             : 
   10472           0 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
   10473           0 :                 torture_fail(tctx, "deleted driver still enumerated");
   10474             :         }
   10475             : 
   10476           0 :         torture_assert(tctx,
   10477             :                 test_DeletePrinterDriver_exp(tctx, b, server_name, driver, environment, WERR_UNKNOWN_PRINTER_DRIVER),
   10478             :                 "2nd delete failed");
   10479             : 
   10480           0 :         return true;
   10481             : }
   10482             : 
   10483           0 : static bool test_DeletePrinterDriverEx(struct torture_context *tctx,
   10484             :                                        struct dcerpc_binding_handle *b,
   10485             :                                        const char *server_name,
   10486             :                                        const char *driver,
   10487             :                                        const char *environment,
   10488             :                                        uint32_t delete_flags,
   10489             :                                        uint32_t version)
   10490             : {
   10491           0 :         torture_assert(tctx,
   10492             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, "FOOBAR", delete_flags, version, WERR_INVALID_ENVIRONMENT),
   10493             :                 "failed to delete driver");
   10494             : 
   10495           0 :         torture_assert(tctx,
   10496             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_OK),
   10497             :                 "failed to delete driver");
   10498             : 
   10499           0 :         if (test_EnumPrinterDrivers_findone(tctx, b, server_name, environment, 1, driver, NULL)) {
   10500           0 :                 torture_fail(tctx, "deleted driver still enumerated");
   10501             :         }
   10502             : 
   10503           0 :         torture_assert(tctx,
   10504             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name, driver, environment, delete_flags, version, WERR_UNKNOWN_PRINTER_DRIVER),
   10505             :                 "2nd delete failed");
   10506             : 
   10507           0 :         return true;
   10508             : }
   10509             : 
   10510           0 : static bool test_PrinterDriver_args(struct torture_context *tctx,
   10511             :                                     struct dcerpc_binding_handle *b,
   10512             :                                     const char *server_name,
   10513             :                                     uint32_t level,
   10514             :                                     struct spoolss_AddDriverInfo8 *r,
   10515             :                                     uint32_t add_flags,
   10516             :                                     uint32_t delete_flags,
   10517             :                                     uint32_t delete_version,
   10518             :                                     bool ex,
   10519             :                                     const char *remote_driver_dir)
   10520             : {
   10521           0 :         bool ret = true;
   10522             : 
   10523           0 :         switch (level) {
   10524           0 :         case 1:
   10525           0 :                 ret = test_AddPrinterDriver_args_level_1(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10526           0 :                 break;
   10527           0 :         case 2:
   10528           0 :                 ret = test_AddPrinterDriver_args_level_2(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10529           0 :                 break;
   10530           0 :         case 3:
   10531           0 :                 ret = test_AddPrinterDriver_args_level_3(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10532           0 :                 break;
   10533           0 :         case 4:
   10534           0 :                 ret = test_AddPrinterDriver_args_level_4(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10535           0 :                 break;
   10536           0 :         case 6:
   10537           0 :                 ret = test_AddPrinterDriver_args_level_6(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10538           0 :                 break;
   10539           0 :         case 8:
   10540           0 :                 ret = test_AddPrinterDriver_args_level_8(tctx, b, server_name, r, add_flags, ex, remote_driver_dir);
   10541           0 :                 break;
   10542           0 :         default:
   10543           0 :                 return false;
   10544             :         }
   10545             : 
   10546           0 :         if (ret == false) {
   10547           0 :                 return ret;
   10548             :         }
   10549             : 
   10550           0 :         if (level == 1) {
   10551           0 :                 return ret;
   10552             :         }
   10553             : 
   10554             :         /* spoolss_AddPrinterDriver does not deal with level 6 or 8 - gd */
   10555             : 
   10556           0 :         if (!ex && (level == 6 || level == 8)) {
   10557           0 :                 return ret;
   10558             :         }
   10559             : 
   10560             :         {
   10561           0 :                 struct dcerpc_pipe *p2;
   10562           0 :                 struct policy_handle hive_handle;
   10563           0 :                 struct dcerpc_binding_handle *b2;
   10564             : 
   10565           0 :                 torture_assert_ntstatus_ok(tctx,
   10566             :                         torture_rpc_connection(tctx, &p2, &ndr_table_winreg),
   10567             :                         "could not open winreg pipe");
   10568           0 :                 b2 = p2->binding_handle;
   10569             : 
   10570           0 :                 torture_assert(tctx, test_winreg_OpenHKLM(tctx, b2, &hive_handle), "");
   10571             : 
   10572           0 :                 ret = test_GetDriverInfo_winreg(tctx, b, NULL, NULL, r->driver_name, r->architecture, r->version, b2, &hive_handle, server_name);
   10573             : 
   10574           0 :                 test_winreg_CloseKey(tctx, b2, &hive_handle);
   10575             : 
   10576           0 :                 talloc_free(p2);
   10577             :         }
   10578             : 
   10579           0 :         if (ex) {
   10580           0 :                 return test_DeletePrinterDriverEx(tctx, b, server_name, r->driver_name, r->architecture, delete_flags, r->version);
   10581             :         } else {
   10582           0 :                 return test_DeletePrinterDriver(tctx, b, server_name, r->driver_name, r->architecture);
   10583             :         }
   10584             : }
   10585             : 
   10586          64 : static bool fillup_printserver_info(struct torture_context *tctx,
   10587             :                                     struct dcerpc_pipe *p,
   10588             :                                     struct torture_driver_context *d)
   10589             : {
   10590           0 :         struct policy_handle server_handle;
   10591          64 :         struct dcerpc_binding_handle *b = p->binding_handle;
   10592          64 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
   10593             : 
   10594          64 :         torture_assert(tctx,
   10595             :                 test_OpenPrinter_server(tctx, p, &server_handle),
   10596             :                 "failed to open printserver");
   10597          64 :         torture_assert(tctx,
   10598             :                 test_get_environment(tctx, b, &server_handle, &d->remote.environment),
   10599             :                 "failed to get environment");
   10600          64 :         torture_assert(tctx,
   10601             :                 test_ClosePrinter(tctx, b, &server_handle),
   10602             :                 "failed to close printserver");
   10603             : 
   10604          64 :         torture_assert(tctx,
   10605             :                 test_GetPrinterDriverDirectory_getdir(tctx, b, server_name_slash,
   10606             :                         d->local.environment ? d->local.environment : d->remote.environment,
   10607             :                         &d->remote.driver_directory),
   10608             :                 "failed to get driver directory");
   10609             : 
   10610          64 :         return true;
   10611             : }
   10612             : 
   10613           0 : static const char *driver_directory_dir(const char *driver_directory)
   10614             : {
   10615           0 :         char *p;
   10616             : 
   10617           0 :         p = strrchr(driver_directory, '\\');
   10618           0 :         if (p) {
   10619           0 :                 return p+1;
   10620             :         }
   10621             : 
   10622           0 :         return NULL;
   10623             : }
   10624             : 
   10625           0 : static const char *driver_directory_share(struct torture_context *tctx,
   10626             :                                           const char *driver_directory)
   10627             : {
   10628           0 :         const char *p;
   10629           0 :         char *tok;
   10630             : 
   10631           0 :         if (driver_directory[0] == '\\' && driver_directory[1] == '\\') {
   10632           0 :                 driver_directory += 2;
   10633             :         }
   10634             : 
   10635           0 :         p = talloc_strdup(tctx, driver_directory);
   10636             : 
   10637           0 :         torture_assert(tctx,
   10638             :                 next_token_talloc(tctx, &p, &tok, "\\"),
   10639             :                 "cannot explode uri");
   10640           0 :         torture_assert(tctx,
   10641             :                 next_token_talloc(tctx, &p, &tok, "\\"),
   10642             :                 "cannot explode uri");
   10643             : 
   10644           0 :         return tok;
   10645             : }
   10646             : 
   10647             : #define CREATE_PRINTER_DRIVER_PATH(_d, _file) \
   10648             :         talloc_asprintf((_d), "%s\\%s\\%s", (_d)->remote.driver_directory, (_d)->remote.driver_upload_directory, (_file))
   10649             : 
   10650             : 
   10651           0 : static bool create_printer_driver_directory(struct torture_context *tctx,
   10652             :                                             struct smbcli_state *cli,
   10653             :                                             struct torture_driver_context *d)
   10654             : {
   10655           0 :         char *driver_dir;
   10656             : 
   10657           0 :         if (d->remote.driver_upload_directory == NULL) {
   10658           0 :                 return true;
   10659             :         }
   10660             : 
   10661           0 :         driver_dir = talloc_asprintf(tctx,
   10662             :                                      "%s\\%s",
   10663             :                                      driver_directory_dir(d->remote.driver_directory),
   10664             :                                      d->remote.driver_upload_directory);
   10665           0 :         torture_assert_not_null(tctx, driver_dir, "ENOMEM");
   10666             : 
   10667           0 :         torture_comment(tctx,
   10668             :                         "Create remote driver directory: %s\n",
   10669             :                         driver_dir);
   10670             : 
   10671           0 :         torture_assert_ntstatus_ok(tctx,
   10672             :                                    smbcli_mkdir(cli->tree,
   10673             :                                                 driver_dir),
   10674             :                                    "Failed to create driver directory");
   10675             : 
   10676           0 :         return true;
   10677             : }
   10678             : 
   10679           0 : static bool upload_printer_driver_file(struct torture_context *tctx,
   10680             :                                        struct smbcli_state *cli,
   10681             :                                        struct torture_driver_context *d,
   10682             :                                        const char *file_name)
   10683             : {
   10684           0 :         FILE *f;
   10685           0 :         int fnum;
   10686           0 :         uint8_t *buf;
   10687           0 :         int maxwrite = 64512;
   10688           0 :         off_t nread = 0;
   10689           0 :         size_t start = 0;
   10690           0 :         const char *remote_dir = driver_directory_dir(d->remote.driver_directory);
   10691           0 :         const char *remote_name;
   10692           0 :         const char *local_name;
   10693           0 :         const char *p;
   10694             : 
   10695           0 :         if (!file_name || strlen(file_name) == 0) {
   10696           0 :                 return true;
   10697             :         }
   10698             : 
   10699           0 :         p = strrchr(file_name, '\\');
   10700           0 :         if (p == NULL) {
   10701           0 :                 p = file_name;
   10702             :         } else {
   10703           0 :                 p++;
   10704             :         }
   10705             : 
   10706           0 :         local_name = talloc_asprintf(tctx, "%s/%s", d->local.driver_directory, p);
   10707           0 :         torture_assert_not_null(tctx, local_name, "ENOMEM");
   10708           0 :         if (d->remote.driver_upload_directory != NULL) {
   10709           0 :                 remote_name = talloc_asprintf(tctx,
   10710             :                                               "%s\\%s\\%s",
   10711             :                                               remote_dir,
   10712             :                                               d->remote.driver_upload_directory,
   10713             :                                               p);
   10714             :         } else {
   10715           0 :                 remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, p);
   10716             :         }
   10717           0 :         torture_assert_not_null(tctx, remote_name, "ENOMEM");
   10718             : 
   10719           0 :         torture_comment(tctx, "Uploading %s to %s\n", local_name, remote_name);
   10720             : 
   10721           0 :         fnum = smbcli_open(cli->tree, remote_name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
   10722           0 :         if (fnum == -1) {
   10723           0 :                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open remote file: %s\n", remote_name));
   10724             :         }
   10725             : 
   10726           0 :         f = fopen(local_name, "r");
   10727           0 :         if (f == NULL) {
   10728           0 :                 torture_fail(tctx, talloc_asprintf(tctx, "failed to open local file: %s\n", local_name));
   10729             :         }
   10730             : 
   10731           0 :         buf = talloc_array(tctx, uint8_t, maxwrite);
   10732           0 :         if (!buf) {
   10733           0 :                 fclose(f);
   10734           0 :                 return false;
   10735             :         }
   10736             : 
   10737           0 :         while (!feof(f)) {
   10738           0 :                 int n = maxwrite;
   10739           0 :                 int ret;
   10740             : 
   10741           0 :                 if ((n = fread(buf, 1, n, f)) < 1) {
   10742           0 :                         if((n == 0) && feof(f))
   10743           0 :                                 break; /* Empty local file. */
   10744             : 
   10745           0 :                         torture_warning(tctx,
   10746           0 :                                 "failed to read file: %s\n", strerror(errno));
   10747           0 :                         break;
   10748             :                 }
   10749             : 
   10750           0 :                 ret = smbcli_write(cli->tree, fnum, 0, buf, nread + start, n);
   10751             : 
   10752           0 :                 if (n != ret) {
   10753           0 :                         torture_warning(tctx,
   10754             :                                 "failed to write file: %s\n", smbcli_errstr(cli->tree));
   10755           0 :                         break;
   10756             :                 }
   10757             : 
   10758           0 :                 nread += n;
   10759             :         }
   10760             : 
   10761           0 :         fclose(f);
   10762             : 
   10763           0 :         torture_assert_ntstatus_ok(tctx,
   10764             :                 smbcli_close(cli->tree, fnum),
   10765             :                 "failed to close file");
   10766             : 
   10767           0 :         return true;
   10768             : }
   10769             : 
   10770           0 : static bool connect_printer_driver_share(struct torture_context *tctx,
   10771             :                                          const char *server_name,
   10772             :                                          const char *share_name,
   10773             :                                          struct smbcli_state **cli)
   10774             : {
   10775           0 :         struct smbcli_options smb_options;
   10776           0 :         struct smbcli_session_options smb_session_options;
   10777             : 
   10778           0 :         torture_comment(tctx, "Connecting printer driver share '%s' on '%s'\n",
   10779             :                 share_name, server_name);
   10780             : 
   10781           0 :         lpcfg_smbcli_options(tctx->lp_ctx, &smb_options);
   10782           0 :         lpcfg_smbcli_session_options(tctx->lp_ctx, &smb_session_options);
   10783             : 
   10784           0 :         torture_assert_ntstatus_ok(tctx,
   10785             :                 smbcli_full_connection(tctx, cli, server_name,
   10786             :                                         lpcfg_smb_ports(tctx->lp_ctx),
   10787             :                                         share_name, NULL,
   10788             :                                         lpcfg_socket_options(tctx->lp_ctx),
   10789             :                                         samba_cmdline_get_creds(),
   10790             :                                         lpcfg_resolve_context(tctx->lp_ctx),
   10791             :                                         tctx->ev,
   10792             :                                         &smb_options,
   10793             :                                         &smb_session_options,
   10794             :                                         lpcfg_gensec_settings(tctx, tctx->lp_ctx)),
   10795             :                 "failed to open driver share");
   10796             : 
   10797           0 :         return true;
   10798             : }
   10799             : 
   10800           0 : static bool upload_printer_driver(struct torture_context *tctx,
   10801             :                                   const char *server_name,
   10802             :                                   struct torture_driver_context *d)
   10803             : {
   10804           0 :         struct smbcli_state *cli;
   10805           0 :         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
   10806           0 :         int i;
   10807             : 
   10808           0 :         torture_assert(tctx,
   10809             :                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
   10810             :                 "failed to connect to driver share");
   10811             : 
   10812           0 :         torture_comment(tctx, "Uploading printer driver files to \\\\%s\\%s\n",
   10813             :                 server_name, share_name);
   10814             : 
   10815           0 :         torture_assert(tctx,
   10816             :                        create_printer_driver_directory(tctx, cli, d),
   10817             :                        "failed to create driver directory");
   10818             : 
   10819           0 :         torture_assert(tctx,
   10820             :                 upload_printer_driver_file(tctx, cli, d, d->info8.driver_path),
   10821             :                 "failed to upload driver_path");
   10822           0 :         torture_assert(tctx,
   10823             :                 upload_printer_driver_file(tctx, cli, d, d->info8.data_file),
   10824             :                 "failed to upload data_file");
   10825           0 :         torture_assert(tctx,
   10826             :                 upload_printer_driver_file(tctx, cli, d, d->info8.config_file),
   10827             :                 "failed to upload config_file");
   10828           0 :         torture_assert(tctx,
   10829             :                 upload_printer_driver_file(tctx, cli, d, d->info8.help_file),
   10830             :                 "failed to upload help_file");
   10831           0 :         if (d->info8.dependent_files) {
   10832           0 :                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
   10833           0 :                         torture_assert(tctx,
   10834             :                                 upload_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
   10835             :                                 "failed to upload dependent_files");
   10836             :                 }
   10837             :         }
   10838             : 
   10839           0 :         talloc_free(cli);
   10840             : 
   10841           0 :         return true;
   10842             : }
   10843             : 
   10844           0 : static bool check_printer_driver_file(struct torture_context *tctx,
   10845             :                                       struct smbcli_state *cli,
   10846             :                                       struct torture_driver_context *d,
   10847             :                                       const char *file_name)
   10848             : {
   10849           0 :         const char *remote_arch_dir = driver_directory_dir(d->remote.driver_directory);
   10850           0 :         const char *remote_name = talloc_asprintf(tctx, "%s\\%d\\%s",
   10851             :                                                   remote_arch_dir,
   10852           0 :                                                   d->info8.version,
   10853             :                                                   file_name);
   10854           0 :         int fnum;
   10855             : 
   10856           0 :         torture_assert(tctx, (file_name && strlen(file_name) != 0), "invalid filename");
   10857             : 
   10858           0 :         torture_comment(tctx, "checking for driver file at %s\n", remote_name);
   10859             : 
   10860           0 :         fnum = smbcli_open(cli->tree, remote_name, O_RDONLY, DENY_NONE);
   10861           0 :         if (fnum == -1) {
   10862           0 :                 return false;
   10863             :         }
   10864             : 
   10865           0 :         torture_assert_ntstatus_ok(tctx,
   10866             :                 smbcli_close(cli->tree, fnum),
   10867             :                 "failed to close driver file");
   10868             : 
   10869           0 :         return true;
   10870             : }
   10871             : 
   10872           0 : static bool check_printer_driver_files(struct torture_context *tctx,
   10873             :                                        const char *server_name,
   10874             :                                        struct torture_driver_context *d,
   10875             :                                        bool expect_exist)
   10876             : {
   10877           0 :         struct smbcli_state *cli;
   10878           0 :         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
   10879           0 :         int i;
   10880             : 
   10881           0 :         torture_assert(tctx,
   10882             :                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
   10883             :                 "failed to connect to driver share");
   10884             : 
   10885           0 :         torture_comment(tctx, "checking %sexistent driver files at \\\\%s\\%s\n",
   10886             :                         (expect_exist ? "": "non-"),
   10887             :                         server_name, share_name);
   10888             : 
   10889           0 :         if (d->info8.driver_path && d->info8.driver_path[0]) {
   10890           0 :                 torture_assert(tctx,
   10891             :                         check_printer_driver_file(tctx, cli, d, d->info8.driver_path) == expect_exist,
   10892             :                         "failed driver_path check");
   10893             :         }
   10894           0 :         if (d->info8.data_file && d->info8.data_file[0]) {
   10895           0 :                 torture_assert(tctx,
   10896             :                         check_printer_driver_file(tctx, cli, d, d->info8.data_file) == expect_exist,
   10897             :                         "failed data_file check");
   10898             :         }
   10899           0 :         if (d->info8.config_file && d->info8.config_file[0]) {
   10900           0 :                 torture_assert(tctx,
   10901             :                         check_printer_driver_file(tctx, cli, d, d->info8.config_file) == expect_exist,
   10902             :                         "failed config_file check");
   10903             :         }
   10904           0 :         if (d->info8.help_file && d->info8.help_file[0]) {
   10905           0 :                 torture_assert(tctx,
   10906             :                         check_printer_driver_file(tctx, cli, d, d->info8.help_file) == expect_exist,
   10907             :                         "failed help_file check");
   10908             :         }
   10909           0 :         if (d->info8.dependent_files) {
   10910           0 :                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
   10911           0 :                         torture_assert(tctx,
   10912             :                                 check_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]) == expect_exist,
   10913             :                                 "failed dependent_files check");
   10914             :                 }
   10915             :         }
   10916             : 
   10917           0 :         talloc_free(cli);
   10918             : 
   10919           0 :         return true;
   10920             : }
   10921             : 
   10922           0 : static bool remove_printer_driver_file(struct torture_context *tctx,
   10923             :                                        struct smbcli_state *cli,
   10924             :                                        struct torture_driver_context *d,
   10925             :                                        const char *file_name)
   10926             : {
   10927           0 :         const char *remote_name;
   10928           0 :         const char *remote_dir =  driver_directory_dir(d->remote.driver_directory);
   10929             : 
   10930           0 :         if (!file_name || strlen(file_name) == 0) {
   10931           0 :                 return true;
   10932             :         }
   10933             : 
   10934           0 :         remote_name = talloc_asprintf(tctx, "%s\\%s", remote_dir, file_name);
   10935             : 
   10936           0 :         torture_comment(tctx, "Removing %s\n", remote_name);
   10937             : 
   10938           0 :         torture_assert_ntstatus_ok(tctx,
   10939             :                 smbcli_unlink(cli->tree, remote_name),
   10940             :                 "failed to unlink");
   10941             : 
   10942           0 :         return true;
   10943             : }
   10944             : 
   10945           0 : static bool remove_printer_driver(struct torture_context *tctx,
   10946             :                                   const char *server_name,
   10947             :                                   struct torture_driver_context *d)
   10948             : {
   10949           0 :         struct smbcli_state *cli;
   10950           0 :         const char *share_name = driver_directory_share(tctx, d->remote.driver_directory);
   10951           0 :         int i;
   10952             : 
   10953           0 :         torture_assert(tctx,
   10954             :                 connect_printer_driver_share(tctx, server_name, share_name, &cli),
   10955             :                 "failed to connect to driver share");
   10956             : 
   10957           0 :         torture_comment(tctx, "Removing printer driver files from \\\\%s\\%s\n",
   10958             :                 server_name, share_name);
   10959             : 
   10960           0 :         torture_assert(tctx,
   10961             :                 remove_printer_driver_file(tctx, cli, d, d->info8.driver_path),
   10962             :                 "failed to remove driver_path");
   10963           0 :         torture_assert(tctx,
   10964             :                 remove_printer_driver_file(tctx, cli, d, d->info8.data_file),
   10965             :                 "failed to remove data_file");
   10966           0 :         if (!strequal(d->info8.config_file, d->info8.driver_path)) {
   10967           0 :                 torture_assert(tctx,
   10968             :                         remove_printer_driver_file(tctx, cli, d, d->info8.config_file),
   10969             :                         "failed to remove config_file");
   10970             :         }
   10971           0 :         torture_assert(tctx,
   10972             :                 remove_printer_driver_file(tctx, cli, d, d->info8.help_file),
   10973             :                 "failed to remove help_file");
   10974           0 :         if (d->info8.dependent_files) {
   10975           0 :                 for (i=0; d->info8.dependent_files->string && d->info8.dependent_files->string[i] != NULL; i++) {
   10976           0 :                         if (strequal(d->info8.dependent_files->string[i], d->info8.driver_path) ||
   10977           0 :                             strequal(d->info8.dependent_files->string[i], d->info8.data_file) ||
   10978           0 :                             strequal(d->info8.dependent_files->string[i], d->info8.config_file) ||
   10979           0 :                             strequal(d->info8.dependent_files->string[i], d->info8.help_file)) {
   10980           0 :                                 continue;
   10981             :                         }
   10982           0 :                         torture_assert(tctx,
   10983             :                                 remove_printer_driver_file(tctx, cli, d, d->info8.dependent_files->string[i]),
   10984             :                                 "failed to remove dependent_files");
   10985             :                 }
   10986             :         }
   10987             : 
   10988           0 :         talloc_free(cli);
   10989             : 
   10990           0 :         return true;
   10991             : 
   10992             : }
   10993             : 
   10994          32 : static bool test_add_driver_arg(struct torture_context *tctx,
   10995             :                                 struct dcerpc_pipe *p,
   10996             :                                 struct torture_driver_context *d)
   10997             : {
   10998          32 :         bool ret = true;
   10999          32 :         struct dcerpc_binding_handle *b = p->binding_handle;
   11000          32 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
   11001          32 :         uint32_t levels[] = { 1, 2, 3, 4, 6, 8 };
   11002           0 :         int i;
   11003           0 :         struct spoolss_AddDriverInfo8 info8;
   11004          32 :         uint32_t add_flags = APD_COPY_NEW_FILES;
   11005          32 :         uint32_t delete_flags = 0;
   11006             : 
   11007          32 :         ZERO_STRUCT(info8);
   11008             : 
   11009          32 :         torture_comment(tctx, "Testing PrinterDriver%s '%s' for environment '%s'\n",
   11010          32 :                 d->ex ? "Ex" : "", d->info8.driver_name, d->local.environment);
   11011             : 
   11012          32 :         torture_assert(tctx,
   11013             :                 fillup_printserver_info(tctx, p, d),
   11014             :                 "failed to fillup printserver info");
   11015             : 
   11016          32 :         if (!directory_exist(d->local.driver_directory)) {
   11017          32 :                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
   11018             :         }
   11019             : 
   11020           0 :         torture_assert(tctx,
   11021             :                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
   11022             :                 "failed to upload printer driver");
   11023             : 
   11024           0 :         info8 = d->info8;
   11025           0 :         if (d->info8.dependent_files) {
   11026           0 :                 info8.dependent_files = talloc_zero(tctx, struct spoolss_StringArray);
   11027           0 :                 if (d->info8.dependent_files->string) {
   11028           0 :                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
   11029           0 :                         }
   11030           0 :                         info8.dependent_files->string = talloc_zero_array(info8.dependent_files, const char *, i+1);
   11031           0 :                         for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
   11032           0 :                                 info8.dependent_files->string[i] = talloc_strdup(info8.dependent_files->string, d->info8.dependent_files->string[i]);
   11033             :                         }
   11034             :                 }
   11035             :         }
   11036             : 
   11037           0 :         for (i=0; i < ARRAY_SIZE(levels); i++) {
   11038             : 
   11039           0 :                 if (torture_setting_bool(tctx, "samba3", false)) {
   11040           0 :                         switch (levels[i]) {
   11041           0 :                         case 2:
   11042             :                         case 4:
   11043           0 :                                 torture_comment(tctx, "skipping level %d against samba\n", levels[i]);
   11044           0 :                                 continue;
   11045           0 :                         default:
   11046           0 :                                 break;
   11047             :                         }
   11048             :                 }
   11049           0 :                 if (torture_setting_bool(tctx, "w2k3", false)) {
   11050           0 :                         switch (levels[i]) {
   11051           0 :                         case 8:
   11052           0 :                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
   11053           0 :                                 continue;
   11054           0 :                         default:
   11055           0 :                                 break;
   11056             :                         }
   11057             :                 }
   11058             : 
   11059           0 :                 torture_comment(tctx,
   11060             :                         "Testing PrinterDriver%s '%s' add & delete level %d\n",
   11061           0 :                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
   11062             : 
   11063           0 :                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
   11064             :         }
   11065             : 
   11066           0 :         info8.driver_path       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.driver_path);
   11067           0 :         info8.data_file         = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.data_file);
   11068           0 :         if (d->info8.config_file) {
   11069           0 :                 info8.config_file       = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.config_file);
   11070             :         }
   11071           0 :         if (d->info8.help_file) {
   11072           0 :                 info8.help_file = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.help_file);
   11073             :         }
   11074           0 :         if (d->info8.dependent_files && d->info8.dependent_files->string) {
   11075           0 :                 for (i=0; d->info8.dependent_files->string[i] != NULL; i++) {
   11076           0 :                         info8.dependent_files->string[i] = talloc_asprintf(tctx, "%s\\%s", d->remote.driver_directory, d->info8.dependent_files->string[i]);
   11077             :                 }
   11078             :         }
   11079             : 
   11080           0 :         for (i=0; i < ARRAY_SIZE(levels); i++) {
   11081             : 
   11082           0 :                 if (torture_setting_bool(tctx, "samba3", false)) {
   11083           0 :                         switch (levels[i]) {
   11084           0 :                         case 2:
   11085             :                         case 4:
   11086           0 :                                 continue;
   11087           0 :                         default:
   11088           0 :                                 break;
   11089             :                         }
   11090             :                 }
   11091           0 :                 if (torture_setting_bool(tctx, "w2k3", false)) {
   11092           0 :                         switch (levels[i]) {
   11093           0 :                         case 8:
   11094           0 :                                 torture_comment(tctx, "skipping level %d against w2k3\n", levels[i]);
   11095           0 :                                 continue;
   11096           0 :                         default:
   11097           0 :                                 break;
   11098             :                         }
   11099             :                 }
   11100             : 
   11101           0 :                 torture_comment(tctx,
   11102             :                         "Testing PrinterDriver%s '%s' add & delete level %d (full unc paths)\n",
   11103           0 :                                 d->ex ? "Ex" : "", info8.driver_name, levels[i]);
   11104             : 
   11105           0 :                 ret &= test_PrinterDriver_args(tctx, b, server_name_slash, levels[i], &info8, add_flags, delete_flags, d->info8.version, d->ex, d->remote.driver_directory);
   11106             :         }
   11107             : 
   11108           0 :         torture_assert(tctx,
   11109             :                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
   11110             :                 "failed to remove printer driver");
   11111             : 
   11112           0 :         torture_comment(tctx, "\n");
   11113             : 
   11114           0 :         return ret;
   11115             : }
   11116             : 
   11117           4 : static bool test_add_driver_ex_64(struct torture_context *tctx,
   11118             :                                   struct dcerpc_pipe *p)
   11119             : {
   11120           0 :         struct torture_driver_context *d;
   11121             : 
   11122           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11123             : 
   11124           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
   11125           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/x64");
   11126             : 
   11127           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11128           4 :         d->info8.driver_name         = TORTURE_DRIVER_EX;
   11129           4 :         d->info8.architecture                = d->local.environment;
   11130           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11131           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11132           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11133           4 :         d->ex                                = true;
   11134             : 
   11135           4 :         return test_add_driver_arg(tctx, p, d);
   11136             : }
   11137             : 
   11138           4 : static bool test_add_driver_ex_32(struct torture_context *tctx,
   11139             :                                   struct dcerpc_pipe *p)
   11140             : {
   11141           0 :         struct torture_driver_context *d;
   11142             : 
   11143           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11144             : 
   11145           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
   11146           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/i386");
   11147             : 
   11148           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11149           4 :         d->info8.driver_name         = TORTURE_DRIVER_EX;
   11150           4 :         d->info8.architecture                = d->local.environment;
   11151           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11152           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11153           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11154           4 :         d->ex                                = true;
   11155             : 
   11156           4 :         return test_add_driver_arg(tctx, p, d);
   11157             : }
   11158             : 
   11159           4 : static bool test_add_driver_64(struct torture_context *tctx,
   11160             :                                struct dcerpc_pipe *p)
   11161             : {
   11162           0 :         struct torture_driver_context *d;
   11163             : 
   11164           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11165             : 
   11166           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
   11167           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/x64");
   11168             : 
   11169           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11170           4 :         d->info8.driver_name         = TORTURE_DRIVER_ADD;
   11171           4 :         d->info8.architecture                = d->local.environment;
   11172           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11173           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11174           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11175           4 :         d->ex                                = false;
   11176             : 
   11177           4 :         return test_add_driver_arg(tctx, p, d);
   11178             : }
   11179             : 
   11180           4 : static bool test_add_driver_32(struct torture_context *tctx,
   11181             :                                struct dcerpc_pipe *p)
   11182             : {
   11183           0 :         struct torture_driver_context *d;
   11184             : 
   11185           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11186             : 
   11187           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
   11188           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/i386");
   11189             : 
   11190           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11191           4 :         d->info8.driver_name         = TORTURE_DRIVER_ADD;
   11192           4 :         d->info8.architecture                = d->local.environment;
   11193           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11194           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11195           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11196           4 :         d->ex                                = false;
   11197             : 
   11198           4 :         return test_add_driver_arg(tctx, p, d);
   11199             : }
   11200             : 
   11201           4 : static bool test_add_driver_adobe(struct torture_context *tctx,
   11202             :                                   struct dcerpc_pipe *p)
   11203             : {
   11204           0 :         struct torture_driver_context *d;
   11205             : 
   11206           4 :         if (!torture_setting_bool(tctx, "samba3", false)) {
   11207           0 :                 torture_skip(tctx, "skipping adobe test which only works against samba3");
   11208             :         }
   11209             : 
   11210           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11211             : 
   11212           4 :         d->local.environment         = talloc_strdup(d, "Windows 4.0");
   11213           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
   11214             : 
   11215           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_9X;
   11216           4 :         d->info8.driver_name         = TORTURE_DRIVER_ADOBE;
   11217           4 :         d->info8.architecture                = d->local.environment;
   11218           4 :         d->info8.driver_path         = talloc_strdup(d, "ADOBEPS4.DRV");
   11219           4 :         d->info8.data_file           = talloc_strdup(d, "DEFPRTR2.PPD");
   11220           4 :         d->info8.config_file         = talloc_strdup(d, "ADOBEPS4.DRV");
   11221             : #if 0
   11222             :         d->info8.help_file           = talloc_strdup(d, "ADOBEPS4.HLP");
   11223             :         d->info8.monitor_name                = talloc_strdup(d, "PSMON.DLL");
   11224             : #endif
   11225           4 :         d->ex                                = false;
   11226             : 
   11227           4 :         return test_add_driver_arg(tctx, p, d);
   11228             : }
   11229             : 
   11230           4 : static bool test_add_driver_adobe_cupsaddsmb(struct torture_context *tctx,
   11231             :                                              struct dcerpc_pipe *p)
   11232             : {
   11233           0 :         struct torture_driver_context *d;
   11234           0 :         struct spoolss_StringArray *a;
   11235             : 
   11236           4 :         if (!torture_setting_bool(tctx, "samba3", false)) {
   11237           0 :                 torture_skip(tctx, "skipping cupsaddsmb test which only works against samba3");
   11238             :         }
   11239             : 
   11240           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11241             : 
   11242           4 :         d->local.environment         = talloc_strdup(d, "Windows 4.0");
   11243           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/adobe/");
   11244             : 
   11245           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_9X;
   11246           4 :         d->info8.driver_name         = TORTURE_DRIVER_ADOBE_CUPSADDSMB;
   11247           4 :         d->info8.architecture                = d->local.environment;
   11248           4 :         d->info8.driver_path         = talloc_strdup(d, "ADOBEPS4.DRV");
   11249           4 :         d->info8.data_file           = talloc_strdup(d, "DEFPRTR2.PPD");
   11250           4 :         d->info8.config_file         = NULL;
   11251           4 :         d->info8.help_file           = talloc_strdup(d, "ADOBEPS4.HLP");
   11252           4 :         d->info8.monitor_name                = talloc_strdup(d, "PSMON.DLL");
   11253           4 :         d->info8.default_datatype    = talloc_strdup(d, "RAW");
   11254             : 
   11255           4 :         a                               = talloc_zero(d, struct spoolss_StringArray);
   11256           4 :         a->string                    = talloc_zero_array(a, const char *, 7);
   11257           4 :         a->string[0]                 = talloc_strdup(a->string, "ADOBEPS4.DRV");
   11258           4 :         a->string[1]                 = talloc_strdup(a->string, "DEFPRTR2.PPD");
   11259           4 :         a->string[2]                 = talloc_strdup(a->string, "ADOBEPS4.HLP");
   11260           4 :         a->string[3]                 = talloc_strdup(a->string, "PSMON.DLL");
   11261           4 :         a->string[4]                 = talloc_strdup(a->string, "ADFONTS.MFM");
   11262           4 :         a->string[5]                 = talloc_strdup(a->string, "ICONLIB.DLL");
   11263             : 
   11264           4 :         d->info8.dependent_files     = a;
   11265           4 :         d->ex                                = false;
   11266             : 
   11267           4 :         return test_add_driver_arg(tctx, p, d);
   11268             : }
   11269             : 
   11270           4 : static bool test_add_driver_timestamps(struct torture_context *tctx,
   11271             :                                        struct dcerpc_pipe *p)
   11272             : {
   11273           0 :         struct torture_driver_context *d;
   11274           4 :         struct timeval t = timeval_current();
   11275             : 
   11276           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11277             : 
   11278           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
   11279           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/i386");
   11280             : 
   11281           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11282           4 :         d->info8.driver_name         = TORTURE_DRIVER_TIMESTAMPS;
   11283           4 :         d->info8.architecture                = d->local.environment;
   11284           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11285           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11286           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11287           4 :         d->info8.driver_date         = timeval_to_nttime(&t);
   11288           4 :         d->ex                                = true;
   11289             : 
   11290           4 :         torture_assert(tctx,
   11291             :                 test_add_driver_arg(tctx, p, d),
   11292             :                 "");
   11293             : 
   11294           4 :         unix_to_nt_time(&d->info8.driver_date, 1);
   11295             : 
   11296           4 :         torture_assert(tctx,
   11297             :                 test_add_driver_arg(tctx, p, d),
   11298             :                 "");
   11299             : 
   11300           4 :         return true;
   11301             : }
   11302             : 
   11303           4 : static bool test_multiple_drivers(struct torture_context *tctx,
   11304             :                                   struct dcerpc_pipe *p)
   11305             : {
   11306           0 :         struct torture_driver_context *d;
   11307           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
   11308           4 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
   11309           0 :         int i;
   11310           0 :         struct spoolss_AddDriverInfo8 info8;
   11311           4 :         uint32_t add_flags = APD_COPY_NEW_FILES;
   11312           4 :         uint32_t delete_flags = 0;
   11313             : 
   11314           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11315             : 
   11316           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_NT_X86);
   11317           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/i386");
   11318             : 
   11319           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11320           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11321           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11322           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11323           4 :         d->info8.architecture           = d->local.environment;
   11324           4 :         d->ex                                = true;
   11325             : 
   11326           4 :         torture_assert(tctx,
   11327             :                 fillup_printserver_info(tctx, p, d),
   11328             :                 "failed to fillup printserver info");
   11329             : 
   11330           4 :         if (!directory_exist(d->local.driver_directory)) {
   11331           4 :                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
   11332             :         }
   11333             : 
   11334           0 :         torture_assert(tctx,
   11335             :                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
   11336             :                 "failed to upload printer driver");
   11337             : 
   11338           0 :         info8 = d->info8;
   11339             : 
   11340           0 :         for (i=0; i < 3; i++) {
   11341           0 :                 info8.driver_name               = talloc_asprintf(d, "torture_test_driver_%d", i);
   11342             : 
   11343           0 :                 torture_assert(tctx,
   11344             :                         test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &info8, add_flags, true, NULL),
   11345             :                         "failed to add driver");
   11346             :         }
   11347             : 
   11348           0 :         torture_assert(tctx,
   11349             :                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_0", info8.architecture, delete_flags, info8.version),
   11350             :                 "failed to delete driver");
   11351             : 
   11352           0 :         torture_assert(tctx,
   11353             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_1", NULL),
   11354             :                 "torture_test_driver_1 no longer on the server");
   11355             : 
   11356           0 :         torture_assert(tctx,
   11357             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
   11358             :                 "torture_test_driver_2 no longer on the server");
   11359             : 
   11360           0 :         torture_assert(tctx,
   11361             :                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_1", info8.architecture, delete_flags, info8.version),
   11362             :                 "failed to delete driver");
   11363             : 
   11364           0 :         torture_assert(tctx,
   11365             :                 test_EnumPrinterDrivers_findone(tctx, b, server_name_slash, info8.architecture, 3, "torture_test_driver_2", NULL),
   11366             :                 "torture_test_driver_2 no longer on the server");
   11367             : 
   11368           0 :         torture_assert(tctx,
   11369             :                 test_DeletePrinterDriverEx(tctx, b, server_name_slash, "torture_test_driver_2", info8.architecture, delete_flags, info8.version),
   11370             :                 "failed to delete driver");
   11371             : 
   11372           0 :         torture_assert(tctx,
   11373             :                 remove_printer_driver(tctx, dcerpc_server_name(p), d),
   11374             :                 "failed to remove printer driver");
   11375             : 
   11376           0 :         return true;
   11377             : }
   11378             : 
   11379           8 : static bool test_driver_copy_from_directory(struct torture_context *tctx,
   11380             :                                             struct dcerpc_pipe *p,
   11381             :                                             const char *architecture)
   11382             : {
   11383           0 :         struct torture_driver_context *d;
   11384           0 :         struct spoolss_StringArray *a;
   11385           8 :         uint32_t add_flags = APD_COPY_NEW_FILES|APD_COPY_FROM_DIRECTORY|APD_RETURN_BLOCKING_STATUS_CODE;
   11386           8 :         uint32_t delete_flags = DPD_DELETE_ALL_FILES;
   11387           8 :         struct dcerpc_binding_handle *b = p->binding_handle;
   11388           8 :         const char *server_name_slash = talloc_asprintf(tctx,
   11389             :                                                         "\\\\%s",
   11390             :                                                         dcerpc_server_name(p));
   11391           8 :         struct GUID guid = GUID_random();
   11392           8 :         bool ok = false;
   11393             : 
   11394           8 :         d = talloc_zero(tctx, struct torture_driver_context);
   11395           8 :         torture_assert_not_null(tctx, d, "ENOMEM");
   11396             : 
   11397           8 :         d->local.environment         = talloc_strdup(d, architecture);
   11398           8 :         torture_assert_not_null_goto(tctx, d->local.environment, ok, done, "ENOMEM");
   11399             : 
   11400           8 :         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
   11401           4 :                 d->local.driver_directory =
   11402           4 :                         talloc_strdup(d, "/usr/share/cups/drivers/x64");
   11403             :         } else {
   11404           4 :                 d->local.driver_directory =
   11405           4 :                         talloc_strdup(d, "/usr/share/cups/drivers/i386");
   11406             :         }
   11407           8 :         torture_assert_not_null_goto(tctx, d->local.driver_directory, ok, done, "ENOMEM");
   11408             : 
   11409           8 :         d->remote.driver_upload_directory = GUID_string2(d, &guid);
   11410           8 :         torture_assert_not_null_goto(tctx, d->remote.driver_upload_directory, ok, done, "ENOMEM");
   11411             : 
   11412           8 :         torture_assert(tctx,
   11413             :                        fillup_printserver_info(tctx, p, d),
   11414             :                        "failed to fillup printserver info");
   11415             : 
   11416           8 :         d->ex                                = true;
   11417           8 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11418           8 :         d->info8.driver_name         = TORTURE_DRIVER_COPY_DIR;
   11419           8 :         d->info8.architecture                = d->local.environment;
   11420             : 
   11421           8 :         d->info8.driver_path         = CREATE_PRINTER_DRIVER_PATH(d, "pscript5.dll");
   11422           8 :         torture_assert_not_null_goto(tctx, d->info8.driver_path, ok, done, "ENOMEM");
   11423           8 :         d->info8.data_file           = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ppd");
   11424           8 :         torture_assert_not_null_goto(tctx, d->info8.data_file, ok, done, "ENOMEM");
   11425           8 :         d->info8.config_file         = CREATE_PRINTER_DRIVER_PATH(d, "cupsui6.dll");
   11426           8 :         torture_assert_not_null_goto(tctx, d->info8.config_file, ok, done, "ENOMEM");
   11427           8 :         d->info8.help_file           = CREATE_PRINTER_DRIVER_PATH(d, "pscript.hlp");
   11428           8 :         torture_assert_not_null_goto(tctx, d->info8.help_file, ok, done, "ENOMEM");
   11429             : 
   11430           8 :         a                               = talloc_zero(d, struct spoolss_StringArray);
   11431           8 :         torture_assert_not_null_goto(tctx, a, ok, done, "ENOMEM");
   11432           8 :         a->string                    = talloc_zero_array(a, const char *, 3);
   11433           8 :         torture_assert_not_null_goto(tctx, a->string, ok, done, "ENOMEM");
   11434           8 :         a->string[0]                 = CREATE_PRINTER_DRIVER_PATH(d, "cups6.inf");
   11435           8 :         torture_assert_not_null_goto(tctx, a->string[0], ok, done, "ENOMEM");
   11436           8 :         a->string[1]                 = CREATE_PRINTER_DRIVER_PATH(d, "cups6.ini");
   11437           8 :         torture_assert_not_null_goto(tctx, a->string[1], ok, done, "ENOMEM");
   11438             : 
   11439           8 :         d->info8.dependent_files     = a;
   11440             : 
   11441           8 :         if (!directory_exist(d->local.driver_directory)) {
   11442           8 :                 torture_skip(tctx,
   11443             :                              "Skipping Printer Driver test as no local drivers "
   11444             :                              "are available");
   11445             :         }
   11446             : 
   11447           0 :         torture_assert(tctx,
   11448             :                        upload_printer_driver(tctx, dcerpc_server_name(p), d),
   11449             :                        "failed to upload printer driver");
   11450             : 
   11451           0 :         torture_assert(tctx,
   11452             :                        test_AddPrinterDriver_args_level_3(tctx,
   11453             :                                                           b,
   11454             :                                                           server_name_slash,
   11455             :                                                           &d->info8,
   11456             :                                                           add_flags,
   11457             :                                                           true,
   11458             :                                                           NULL),
   11459             :                        "failed to add driver");
   11460             : 
   11461           0 :         torture_assert(tctx,
   11462             :                        test_DeletePrinterDriverEx(tctx,
   11463             :                                                   b,
   11464             :                                                   server_name_slash,
   11465             :                                                   d->info8.driver_name,
   11466             :                                                   d->local.environment,
   11467             :                                                   delete_flags,
   11468             :                                                   d->info8.version),
   11469             :                        "failed to delete driver");
   11470             : 
   11471           0 :         torture_assert(tctx,
   11472             :                        check_printer_driver_files(tctx,
   11473             :                                                   dcerpc_server_name(p),
   11474             :                                                   d,
   11475             :                                                   false),
   11476             :                        "printer driver file check failed");
   11477             : 
   11478           0 :         ok = true;
   11479           0 : done:
   11480           0 :         talloc_free(d);
   11481           0 :         return ok;
   11482             : }
   11483             : 
   11484           4 : static bool test_driver_copy_from_directory_64(struct torture_context *tctx,
   11485             :                                                struct dcerpc_pipe *p)
   11486             : {
   11487           4 :         return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_x64);
   11488             : }
   11489             : 
   11490           4 : static bool test_driver_copy_from_directory_32(struct torture_context *tctx,
   11491             :                                                struct dcerpc_pipe *p)
   11492             : {
   11493           4 :         return test_driver_copy_from_directory(tctx, p, SPOOLSS_ARCHITECTURE_NT_X86);
   11494             : }
   11495             : 
   11496           4 : static bool test_del_driver_all_files(struct torture_context *tctx,
   11497             :                                       struct dcerpc_pipe *p)
   11498             : {
   11499           0 :         struct torture_driver_context *d;
   11500           0 :         struct spoolss_StringArray *a;
   11501           4 :         uint32_t add_flags = APD_COPY_NEW_FILES;
   11502           4 :         uint32_t delete_flags = DPD_DELETE_ALL_FILES;
   11503           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
   11504           4 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
   11505             : 
   11506           4 :         d = talloc_zero(tctx, struct torture_driver_context);
   11507             : 
   11508           4 :         d->local.environment         = talloc_strdup(d, SPOOLSS_ARCHITECTURE_x64);
   11509           4 :         d->local.driver_directory    = talloc_strdup(d, "/usr/share/cups/drivers/x64");
   11510             : 
   11511           4 :         d->ex                                = true;
   11512           4 :         d->info8.version             = SPOOLSS_DRIVER_VERSION_200X;
   11513           4 :         d->info8.driver_name         = TORTURE_DRIVER_DELETER;
   11514           4 :         d->info8.architecture                = d->local.environment;
   11515           4 :         d->info8.driver_path         = talloc_strdup(d, "pscript5.dll");
   11516           4 :         d->info8.data_file           = talloc_strdup(d, "cups6.ppd");
   11517           4 :         d->info8.config_file         = talloc_strdup(d, "cupsui6.dll");
   11518           4 :         d->info8.help_file           = talloc_strdup(d, "pscript.hlp");
   11519             : 
   11520           4 :         a                               = talloc_zero(d, struct spoolss_StringArray);
   11521           4 :         a->string                    = talloc_zero_array(a, const char *, 3);
   11522           4 :         a->string[0]                 = talloc_strdup(a->string, "cups6.inf");
   11523           4 :         a->string[1]                 = talloc_strdup(a->string, "cups6.ini");
   11524             : 
   11525           4 :         d->info8.dependent_files     = a;
   11526             : 
   11527           4 :         torture_assert(tctx,
   11528             :                 fillup_printserver_info(tctx, p, d),
   11529             :                 "failed to fillup printserver info");
   11530             : 
   11531           4 :         if (!directory_exist(d->local.driver_directory)) {
   11532           4 :                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
   11533             :         }
   11534             : 
   11535           0 :         torture_assert(tctx,
   11536             :                 upload_printer_driver(tctx, dcerpc_server_name(p), d),
   11537             :                 "failed to upload printer driver");
   11538             : 
   11539           0 :         torture_assert(tctx,
   11540             :                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d->info8, add_flags, true, NULL),
   11541             :                 "failed to add driver");
   11542             : 
   11543           0 :         torture_assert(tctx,
   11544             :                 test_DeletePrinterDriverEx(tctx, b, server_name_slash,
   11545             :                                            d->info8.driver_name,
   11546             :                                            d->info8.architecture,
   11547             :                                            delete_flags,
   11548             :                                            d->info8.version),
   11549             :                 "failed to delete driver");
   11550             : 
   11551           0 :         torture_assert(tctx,
   11552             :                 check_printer_driver_files(tctx, dcerpc_server_name(p), d, false),
   11553             :                 "printer driver file check failed");
   11554             : 
   11555           0 :         talloc_free(d);
   11556           0 :         return true;
   11557             : }
   11558             : 
   11559           4 : static bool test_del_driver_unused_files(struct torture_context *tctx,
   11560             :                                          struct dcerpc_pipe *p)
   11561             : {
   11562           0 :         struct torture_driver_context *d1;
   11563           0 :         struct torture_driver_context *d2;
   11564           4 :         uint32_t add_flags = APD_COPY_NEW_FILES;
   11565           4 :         struct dcerpc_binding_handle *b = p->binding_handle;
   11566           4 :         const char *server_name_slash = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
   11567             : 
   11568           4 :         d1 = talloc_zero(tctx, struct torture_driver_context);
   11569           4 :         d1->ex                               = true;
   11570             : 
   11571           4 :         d1->local.environment                = talloc_strdup(d1, SPOOLSS_ARCHITECTURE_x64);
   11572           4 :         d1->local.driver_directory   = talloc_strdup(d1, "/usr/share/cups/drivers/x64");
   11573             : 
   11574           4 :         d1->info8.version            = SPOOLSS_DRIVER_VERSION_200X;
   11575           4 :         d1->info8.driver_name                = TORTURE_DRIVER_DELETER;
   11576           4 :         d1->info8.architecture               = NULL;
   11577           4 :         d1->info8.driver_path                = talloc_strdup(d1, "pscript5.dll");
   11578           4 :         d1->info8.data_file          = talloc_strdup(d1, "cups6.ppd");
   11579           4 :         d1->info8.config_file                = talloc_strdup(d1, "cupsui6.dll");
   11580           4 :         d1->info8.help_file          = talloc_strdup(d1, "pscript.hlp");
   11581           4 :         d1->info8.architecture               = d1->local.environment;
   11582             : 
   11583           4 :         d2 = talloc_zero(tctx, struct torture_driver_context);
   11584           4 :         d2->ex                               = true;
   11585             : 
   11586           4 :         d2->local.environment                = talloc_strdup(d2, SPOOLSS_ARCHITECTURE_x64);
   11587           4 :         d2->local.driver_directory   = talloc_strdup(d2, "/usr/share/cups/drivers/x64");
   11588             : 
   11589           4 :         d2->info8.version            = SPOOLSS_DRIVER_VERSION_200X;
   11590           4 :         d2->info8.driver_name                = TORTURE_DRIVER_DELETERIN;
   11591           4 :         d2->info8.architecture               = NULL;
   11592           4 :         d2->info8.driver_path                = talloc_strdup(d2, "pscript5.dll");  /* overlapping */
   11593           4 :         d2->info8.data_file          = talloc_strdup(d2, "cupsps6.dll");
   11594           4 :         d2->info8.config_file                = talloc_strdup(d2, "cups6.ini");
   11595           4 :         d2->info8.help_file          = talloc_strdup(d2, "pscript.hlp");   /* overlapping */
   11596           4 :         d2->info8.architecture               = d2->local.environment;
   11597             : 
   11598           4 :         torture_assert(tctx,
   11599             :                 fillup_printserver_info(tctx, p, d1),
   11600             :                 "failed to fillup printserver info");
   11601           4 :         torture_assert(tctx,
   11602             :                 fillup_printserver_info(tctx, p, d2),
   11603             :                 "failed to fillup printserver info");
   11604             : 
   11605           4 :         if (!directory_exist(d1->local.driver_directory)) {
   11606           4 :                 torture_skip(tctx, "Skipping Printer Driver test as no local driver is available");
   11607             :         }
   11608             : 
   11609           0 :         torture_assert(tctx,
   11610             :                 upload_printer_driver(tctx, dcerpc_server_name(p), d1),
   11611             :                 "failed to upload printer driver");
   11612           0 :         torture_assert(tctx,
   11613             :                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d1->info8, add_flags, true, NULL),
   11614             :                 "failed to add driver");
   11615             : 
   11616           0 :         torture_assert(tctx,
   11617             :                 upload_printer_driver(tctx, dcerpc_server_name(p), d2),
   11618             :                 "failed to upload printer driver");
   11619           0 :         torture_assert(tctx,
   11620             :                 test_AddPrinterDriver_args_level_3(tctx, b, server_name_slash, &d2->info8, add_flags, true, NULL),
   11621             :                 "failed to add driver");
   11622             : 
   11623             :         /* some files are in use by a separate driver, should fail */
   11624           0 :         torture_assert(tctx,
   11625             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
   11626             :                                                d1->info8.driver_name,
   11627             :                                                d1->info8.architecture,
   11628             :                                                DPD_DELETE_ALL_FILES,
   11629             :                                                d1->info8.version,
   11630             :                                                WERR_PRINTER_DRIVER_IN_USE),
   11631             :                 "invalid delete driver response");
   11632             : 
   11633             :         /* should only delete files not in use by other driver */
   11634           0 :         torture_assert(tctx,
   11635             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
   11636             :                                                d1->info8.driver_name,
   11637             :                                                d1->info8.architecture,
   11638             :                                                DPD_DELETE_UNUSED_FILES,
   11639             :                                                d1->info8.version,
   11640             :                                                WERR_OK),
   11641             :                 "failed to delete driver (unused files)");
   11642             : 
   11643             :         /* check non-overlapping were deleted */
   11644           0 :         d1->info8.driver_path = NULL;
   11645           0 :         d1->info8.help_file = NULL;
   11646           0 :         torture_assert(tctx,
   11647             :                 check_printer_driver_files(tctx, dcerpc_server_name(p), d1, false),
   11648             :                 "printer driver file check failed");
   11649             :         /* d2 files should be uneffected */
   11650           0 :         torture_assert(tctx,
   11651             :                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, true),
   11652             :                 "printer driver file check failed");
   11653             : 
   11654           0 :         torture_assert(tctx,
   11655             :                 test_DeletePrinterDriverEx_exp(tctx, b, server_name_slash,
   11656             :                                                d2->info8.driver_name,
   11657             :                                                d2->info8.architecture,
   11658             :                                                DPD_DELETE_ALL_FILES,
   11659             :                                                d2->info8.version,
   11660             :                                                WERR_OK),
   11661             :                 "failed to delete driver");
   11662             : 
   11663           0 :         torture_assert(tctx,
   11664             :                 check_printer_driver_files(tctx, dcerpc_server_name(p), d2, false),
   11665             :                 "printer driver file check failed");
   11666             : 
   11667           0 :         talloc_free(d1);
   11668           0 :         talloc_free(d2);
   11669           0 :         return true;
   11670             : }
   11671             : 
   11672        2354 : struct torture_suite *torture_rpc_spoolss_driver(TALLOC_CTX *mem_ctx)
   11673             : {
   11674        2354 :         struct torture_suite *suite = torture_suite_create(mem_ctx, "spoolss.driver");
   11675             : 
   11676        2354 :         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
   11677             :                                                         "driver", &ndr_table_spoolss);
   11678        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_64", test_add_driver_64);
   11679        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_ex_64", test_add_driver_ex_64);
   11680             : 
   11681        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_32", test_add_driver_32);
   11682        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_ex_32", test_add_driver_ex_32);
   11683             : 
   11684        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_adobe", test_add_driver_adobe);
   11685             : 
   11686        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_adobe_cupsaddsmb", test_add_driver_adobe_cupsaddsmb);
   11687             : 
   11688        2354 :         torture_rpc_tcase_add_test(tcase, "add_driver_timestamps", test_add_driver_timestamps);
   11689             : 
   11690        2354 :         torture_rpc_tcase_add_test(tcase, "multiple_drivers", test_multiple_drivers);
   11691             : 
   11692        2354 :         torture_rpc_tcase_add_test(tcase,
   11693             :                                    "test_driver_copy_from_directory_64",
   11694             :                                    test_driver_copy_from_directory_64);
   11695             : 
   11696        2354 :         torture_rpc_tcase_add_test(tcase,
   11697             :                                    "test_driver_copy_from_directory_32",
   11698             :                                    test_driver_copy_from_directory_32);
   11699             : 
   11700        2354 :         torture_rpc_tcase_add_test(tcase, "del_driver_all_files", test_del_driver_all_files);
   11701             : 
   11702        2354 :         torture_rpc_tcase_add_test(tcase, "del_driver_unused_files", test_del_driver_unused_files);
   11703             : 
   11704        2354 :         return suite;
   11705             : }

Generated by: LCOV version 1.14