root/source4/torture/rpc/spoolss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_OpenPrinter_server
  2. test_EnumPorts
  3. test_GetPrintProcessorDirectory
  4. test_GetPrinterDriverDirectory
  5. test_EnumPrinterDrivers
  6. test_EnumMonitors
  7. test_EnumPrintProcessors
  8. test_EnumPrintProcDataTypes
  9. test_EnumPrinters
  10. test_GetPrinter
  11. test_ClosePrinter
  12. test_GetForm
  13. test_EnumForms
  14. test_DeleteForm
  15. test_AddForm
  16. test_EnumPorts_old
  17. test_AddPort
  18. test_GetJob
  19. test_SetJob
  20. test_AddJob
  21. test_EnumJobs
  22. test_DoPrintTest
  23. test_PausePrinter
  24. test_ResumePrinter
  25. test_GetPrinterData
  26. test_GetPrinterDataEx
  27. test_EnumPrinterData
  28. test_EnumPrinterDataEx
  29. test_DeletePrinterData
  30. test_SetPrinterData
  31. test_SecondaryClosePrinter
  32. test_OpenPrinter_badname
  33. test_OpenPrinter
  34. call_OpenPrinterEx
  35. test_OpenPrinterEx
  36. test_EnumPrinters_old
  37. test_GetPrinterDriver2
  38. test_EnumPrinterDrivers_old
  39. torture_rpc_spoolss

   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    
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 #include "torture/torture.h"
  25 #include "torture/rpc/rpc.h"
  26 #include "librpc/gen_ndr/ndr_spoolss_c.h"
  27 
  28 struct test_spoolss_context {
  29         /* print server handle */
  30         struct policy_handle server_handle;
  31 
  32         /* for EnumPorts */
  33         uint32_t port_count[3];
  34         union spoolss_PortInfo *ports[3];
  35 
  36         /* for EnumPrinterDrivers */
  37         uint32_t driver_count[7];
  38         union spoolss_DriverInfo *drivers[7];
  39 
  40         /* for EnumMonitors */
  41         uint32_t monitor_count[3];
  42         union spoolss_MonitorInfo *monitors[3];
  43 
  44         /* for EnumPrintProcessors */
  45         uint32_t print_processor_count[2];
  46         union spoolss_PrintProcessorInfo *print_processors[2];
  47 
  48         /* for EnumPrinters */
  49         uint32_t printer_count[6];
  50         union spoolss_PrinterInfo *printers[6];
  51 };
  52 
  53 #define COMPARE_STRING(tctx, c,r,e) \
  54         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
  55 
  56 /* not every compiler supports __typeof__() */
  57 #if (__GNUC__ >= 3)
  58 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
  59         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
  60                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
  61         }\
  62         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
  63                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
  64         }\
  65 } while(0)
  66 #else
  67 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
  68 #endif
  69 
  70 #define COMPARE_UINT32(tctx, c, r, e) do {\
  71         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
  72         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
  73 } while(0)
  74 
  75 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
  76 
  77 static bool test_OpenPrinter_server(struct torture_context *tctx, struct dcerpc_pipe *p, struct test_spoolss_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
  78 {
  79         NTSTATUS status;
  80         struct spoolss_OpenPrinter op;
  81 
  82         op.in.printername       = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
  83         op.in.datatype          = NULL;
  84         op.in.devmode_ctr.devmode= NULL;
  85         op.in.access_mask       = 0;
  86         op.out.handle           = &ctx->server_handle;
  87 
  88         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
  89 
  90         status = dcerpc_spoolss_OpenPrinter(p, ctx, &op);
  91         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
  92         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed"); 
  93 
  94         return true;
  95 }
  96 
  97 static bool test_EnumPorts(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  98                            struct dcerpc_pipe *p, 
  99                            struct test_spoolss_context *ctx)
 100 {
 101         NTSTATUS status;
 102         struct spoolss_EnumPorts r;
 103         uint16_t levels[] = { 1, 2 };
 104         int i, j;
 105 
 106         for (i=0;i<ARRAY_SIZE(levels);i++) {
 107                 int level = levels[i];
 108                 DATA_BLOB blob;
 109                 uint32_t needed;
 110                 uint32_t count;
 111                 union spoolss_PortInfo *info;
 112 
 113                 r.in.servername = "";
 114                 r.in.level = level;
 115                 r.in.buffer = NULL;
 116                 r.in.offered = 0;
 117                 r.out.needed = &needed;
 118                 r.out.count = &count;
 119                 r.out.info = &info;
 120 
 121                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
 122 
 123                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
 124                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
 125                 if (W_ERROR_IS_OK(r.out.result)) {
 126                         /* TODO: do some more checks here */
 127                         continue;
 128                 }
 129                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
 130                         "EnumPorts unexpected return code");
 131 
 132                 blob = data_blob_talloc(ctx, NULL, needed);
 133                 data_blob_clear(&blob);
 134                 r.in.buffer = &blob;
 135                 r.in.offered = needed;
 136 
 137                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
 138                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
 139 
 140                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
 141 
 142                 torture_assert(tctx, info, "EnumPorts returned no info");
 143 
 144                 ctx->port_count[level]  = count;
 145                 ctx->ports[level]       = info;
 146         }
 147 
 148         for (i=1;i<ARRAY_SIZE(levels);i++) {
 149                 int level = levels[i];
 150                 int old_level = levels[i-1];
 151                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level], 
 152                         "EnumPorts invalid value");
 153         }
 154         /* if the array sizes are not the same we would maybe segfault in the following code */
 155 
 156         for (i=0;i<ARRAY_SIZE(levels);i++) {
 157                 int level = levels[i];
 158                 for (j=0;j<ctx->port_count[level];j++) {
 159                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
 160                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
 161                         switch (level) {
 162                         case 1:
 163                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
 164                                 break;
 165                         case 2:
 166                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
 167                                 break;
 168                         }
 169                 }
 170         }
 171 
 172         return true;
 173 }
 174 
 175 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
     /* [<][>][^][v][top][bottom][index][help] */
 176                                             struct dcerpc_pipe *p,
 177                                             struct test_spoolss_context *ctx)
 178 {
 179         NTSTATUS status;
 180         struct spoolss_GetPrintProcessorDirectory r;
 181         struct {
 182                 uint16_t level;
 183                 const char *server;
 184         } levels[] = {{
 185                         .level  = 1,
 186                         .server = NULL
 187                 },{
 188                         .level  = 1,
 189                         .server = ""
 190                 },{
 191                         .level  = 78,
 192                         .server = ""
 193                 },{
 194                         .level  = 1,
 195                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
 196                 },{
 197                         .level  = 1024,
 198                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
 199                 }
 200         };
 201         int i;
 202         uint32_t needed;
 203 
 204         for (i=0;i<ARRAY_SIZE(levels);i++) {
 205                 int level = levels[i].level;
 206                 DATA_BLOB blob;
 207 
 208                 r.in.server             = levels[i].server;
 209                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
 210                 r.in.level              = level;
 211                 r.in.buffer             = NULL;
 212                 r.in.offered            = 0;
 213                 r.out.needed            = &needed;
 214 
 215                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
 216 
 217                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
 218                 torture_assert_ntstatus_ok(tctx, status,
 219                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
 220                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
 221                         "GetPrintProcessorDirectory unexpected return code");
 222 
 223                 blob = data_blob_talloc(ctx, NULL, needed);
 224                 data_blob_clear(&blob);
 225                 r.in.buffer = &blob;
 226                 r.in.offered = needed;
 227 
 228                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
 229                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
 230 
 231                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
 232         }
 233 
 234         return true;
 235 }
 236 
 237 
 238 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 239                                            struct dcerpc_pipe *p, 
 240                                            struct test_spoolss_context *ctx)
 241 {
 242         NTSTATUS status;
 243         struct spoolss_GetPrinterDriverDirectory r;
 244         struct {
 245                 uint16_t level;
 246                 const char *server;
 247         } levels[] = {{
 248                         .level  = 1,
 249                         .server = NULL
 250                 },{
 251                         .level  = 1,
 252                         .server = ""
 253                 },{
 254                         .level  = 78,
 255                         .server = ""
 256                 },{
 257                         .level  = 1,
 258                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
 259                 },{
 260                         .level  = 1024,
 261                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
 262                 }
 263         };
 264         int i;
 265         uint32_t needed;
 266 
 267         for (i=0;i<ARRAY_SIZE(levels);i++) {
 268                 int level = levels[i].level;
 269                 DATA_BLOB blob;
 270 
 271                 r.in.server             = levels[i].server;
 272                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
 273                 r.in.level              = level;
 274                 r.in.buffer             = NULL;
 275                 r.in.offered            = 0;
 276                 r.out.needed            = &needed;
 277 
 278                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
 279 
 280                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
 281                 torture_assert_ntstatus_ok(tctx, status, 
 282                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
 283                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
 284                         "GetPrinterDriverDirectory unexpected return code");
 285 
 286                 blob = data_blob_talloc(ctx, NULL, needed);
 287                 data_blob_clear(&blob);
 288                 r.in.buffer = &blob;
 289                 r.in.offered = needed;
 290 
 291                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
 292                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
 293 
 294                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
 295         }
 296 
 297         return true;
 298 }
 299 
 300 static bool test_EnumPrinterDrivers(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 301                                     struct dcerpc_pipe *p,
 302                                     struct test_spoolss_context *ctx)
 303 {
 304         NTSTATUS status;
 305         struct spoolss_EnumPrinterDrivers r;
 306         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
 307         int i, j;
 308 
 309         for (i=0;i<ARRAY_SIZE(levels);i++) {
 310                 int level = levels[i];
 311                 DATA_BLOB blob;
 312                 uint32_t needed;
 313                 uint32_t count;
 314                 union spoolss_DriverInfo *info;
 315 
 316                 /* FIXME: gd, come back and fix "" as server, and handle
 317                  * priority of returned error codes in torture test and samba 3
 318                  * server */
 319 
 320                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
 321                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
 322                 r.in.level              = level;
 323                 r.in.buffer             = NULL;
 324                 r.in.offered            = 0;
 325                 r.out.needed            = &needed;
 326                 r.out.count             = &count;
 327                 r.out.info              = &info;
 328 
 329                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
 330 
 331                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
 332                 torture_assert_ntstatus_ok(tctx, status, 
 333                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
 334                 if (W_ERROR_IS_OK(r.out.result)) {
 335                         /* TODO: do some more checks here */
 336                         continue;
 337                 }
 338                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
 339                         blob = data_blob_talloc(ctx, NULL, needed);
 340                         data_blob_clear(&blob);
 341                         r.in.buffer = &blob;
 342                         r.in.offered = needed;
 343 
 344                         status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
 345                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
 346                 }
 347 
 348                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
 349 
 350                 ctx->driver_count[level]        = count;
 351                 ctx->drivers[level]             = info;
 352         }
 353 
 354         for (i=1;i<ARRAY_SIZE(levels);i++) {
 355                 int level = levels[i];
 356                 int old_level = levels[i-1];
 357                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
 358                         "EnumPrinterDrivers invalid value");
 359         }
 360 
 361         for (i=0;i<ARRAY_SIZE(levels);i++) {
 362                 int level = levels[i];
 363                 for (j=0;j<ctx->driver_count[level];j++) {
 364                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
 365                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
 366                         switch (level) {
 367                         case 1:
 368                                 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
 369                                 break;
 370                         case 2:
 371                                 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
 372                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
 373                                 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
 374                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
 375                                 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
 376                                 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
 377                                 break;
 378                         case 3:
 379                                 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
 380                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
 381                                 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
 382                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
 383                                 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
 384                                 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
 385                                 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
 386                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
 387                                 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
 388                                 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
 389                                 break;
 390                         case 4:
 391                                 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
 392                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
 393                                 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
 394                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
 395                                 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
 396                                 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
 397                                 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
 398                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
 399                                 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
 400                                 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
 401                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
 402                                 break;
 403                         case 5:
 404                                 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
 405                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
 406                                 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
 407                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
 408                                 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
 409                                 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
 410                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
 411                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
 412                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
 413                                 break;
 414                         case 6:
 415                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
 416                                 break;
 417                         }
 418                 }
 419         }
 420 
 421         return true;
 422 }
 423 
 424 static bool test_EnumMonitors(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 425                               struct dcerpc_pipe *p, 
 426                               struct test_spoolss_context *ctx)
 427 {
 428         NTSTATUS status;
 429         struct spoolss_EnumMonitors r;
 430         uint16_t levels[] = { 1, 2 };
 431         int i, j;
 432 
 433         for (i=0;i<ARRAY_SIZE(levels);i++) {
 434                 int level = levels[i];
 435                 DATA_BLOB blob;
 436                 uint32_t needed;
 437                 uint32_t count;
 438                 union spoolss_MonitorInfo *info;
 439 
 440                 r.in.servername = "";
 441                 r.in.level = level;
 442                 r.in.buffer = NULL;
 443                 r.in.offered = 0;
 444                 r.out.needed = &needed;
 445                 r.out.count = &count;
 446                 r.out.info = &info;
 447 
 448                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
 449 
 450                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
 451                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
 452                 if (W_ERROR_IS_OK(r.out.result)) {
 453                         /* TODO: do some more checks here */
 454                         continue;
 455                 }
 456                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
 457                         "EnumMonitors failed");
 458 
 459                 blob = data_blob_talloc(ctx, NULL, needed);
 460                 data_blob_clear(&blob);
 461                 r.in.buffer = &blob;
 462                 r.in.offered = needed;
 463 
 464                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
 465                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
 466 
 467                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
 468 
 469                 ctx->monitor_count[level]       = count;
 470                 ctx->monitors[level]            = info;
 471         }
 472 
 473         for (i=1;i<ARRAY_SIZE(levels);i++) {
 474                 int level = levels[i];
 475                 int old_level = levels[i-1];
 476                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level], 
 477                                          "EnumMonitors invalid value");
 478         }
 479 
 480         for (i=0;i<ARRAY_SIZE(levels);i++) {
 481                 int level = levels[i];
 482                 for (j=0;j<ctx->monitor_count[level];j++) {
 483                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
 484                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
 485                         switch (level) {
 486                         case 1:
 487                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
 488                                 break;
 489                         case 2:
 490                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
 491                                 break;
 492                         }
 493                 }
 494         }
 495 
 496         return true;
 497 }
 498 
 499 static bool test_EnumPrintProcessors(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 500                                      struct dcerpc_pipe *p,
 501                                      struct test_spoolss_context *ctx)
 502 {
 503         NTSTATUS status;
 504         struct spoolss_EnumPrintProcessors r;
 505         uint16_t levels[] = { 1 };
 506         int i, j;
 507 
 508         for (i=0;i<ARRAY_SIZE(levels);i++) {
 509                 int level = levels[i];
 510                 DATA_BLOB blob;
 511                 uint32_t needed;
 512                 uint32_t count;
 513                 union spoolss_PrintProcessorInfo *info;
 514 
 515                 r.in.servername = "";
 516                 r.in.environment = "Windows NT x86";
 517                 r.in.level = level;
 518                 r.in.buffer = NULL;
 519                 r.in.offered = 0;
 520                 r.out.needed = &needed;
 521                 r.out.count = &count;
 522                 r.out.info = &info;
 523 
 524                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
 525 
 526                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
 527                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
 528                 if (W_ERROR_IS_OK(r.out.result)) {
 529                         /* TODO: do some more checks here */
 530                         continue;
 531                 }
 532                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
 533                         "EnumPrintProcessors unexpected return code");
 534 
 535                 blob = data_blob_talloc(ctx, NULL, needed);
 536                 data_blob_clear(&blob);
 537                 r.in.buffer = &blob;
 538                 r.in.offered = needed;
 539 
 540                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
 541                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
 542 
 543                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
 544 
 545                 ctx->print_processor_count[level]       = count;
 546                 ctx->print_processors[level]            = info;
 547         }
 548 
 549         for (i=1;i<ARRAY_SIZE(levels);i++) {
 550                 int level = levels[i];
 551                 int old_level = levels[i-1];
 552                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
 553                         "EnumPrintProcessors failed");
 554         }
 555 
 556         for (i=0;i<ARRAY_SIZE(levels);i++) {
 557                 int level = levels[i];
 558                 for (j=0;j<ctx->print_processor_count[level];j++) {
 559 #if 0
 560                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
 561                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
 562 #endif
 563                         switch (level) {
 564                         case 1:
 565                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
 566                                 break;
 567                         }
 568                 }
 569         }
 570 
 571         return true;
 572 }
 573 
 574 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
     /* [<][>][^][v][top][bottom][index][help] */
 575                                         struct dcerpc_pipe *p,
 576                                         struct test_spoolss_context *ctx)
 577 {
 578         NTSTATUS status;
 579         struct spoolss_EnumPrintProcDataTypes r;
 580         uint16_t levels[] = { 1 };
 581         int i;
 582 
 583         for (i=0;i<ARRAY_SIZE(levels);i++) {
 584                 int level = levels[i];
 585                 DATA_BLOB blob;
 586                 uint32_t needed;
 587                 uint32_t count;
 588                 union spoolss_PrintProcDataTypesInfo *info;
 589 
 590                 r.in.servername = "";
 591                 r.in.print_processor_name = "winprint";
 592                 r.in.level = level;
 593                 r.in.buffer = NULL;
 594                 r.in.offered = 0;
 595                 r.out.needed = &needed;
 596                 r.out.count = &count;
 597                 r.out.info = &info;
 598 
 599                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
 600 
 601                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
 602                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
 603                 if (W_ERROR_IS_OK(r.out.result)) {
 604                         /* TODO: do some more checks here */
 605                         continue;
 606                 }
 607                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
 608                         "EnumPrintProcDataTypes unexpected return code");
 609 
 610                 blob = data_blob_talloc(ctx, NULL, needed);
 611                 data_blob_clear(&blob);
 612                 r.in.buffer = &blob;
 613                 r.in.offered = needed;
 614 
 615                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
 616                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
 617 
 618                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
 619         }
 620 
 621         return true;
 622 }
 623 
 624 
 625 static bool test_EnumPrinters(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 626                               struct dcerpc_pipe *p,
 627                               struct test_spoolss_context *ctx)
 628 {
 629         struct spoolss_EnumPrinters r;
 630         NTSTATUS status;
 631         uint16_t levels[] = { 0, 1, 2, 4, 5 };
 632         int i, j;
 633 
 634         for (i=0;i<ARRAY_SIZE(levels);i++) {
 635                 int level = levels[i];
 636                 DATA_BLOB blob;
 637                 uint32_t needed;
 638                 uint32_t count;
 639                 union spoolss_PrinterInfo *info;
 640 
 641                 r.in.flags      = PRINTER_ENUM_LOCAL;
 642                 r.in.server     = "";
 643                 r.in.level      = level;
 644                 r.in.buffer     = NULL;
 645                 r.in.offered    = 0;
 646                 r.out.needed    = &needed;
 647                 r.out.count     = &count;
 648                 r.out.info      = &info;
 649 
 650                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
 651 
 652                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
 653                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
 654                 if (W_ERROR_IS_OK(r.out.result)) {
 655                         /* TODO: do some more checks here */
 656                         continue;
 657                 }
 658                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER, 
 659                         "EnumPrinters unexpected return code");
 660 
 661                 blob = data_blob_talloc(ctx, NULL, needed);
 662                 data_blob_clear(&blob);
 663                 r.in.buffer = &blob;
 664                 r.in.offered = needed;
 665 
 666                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
 667                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
 668 
 669                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
 670 
 671                 ctx->printer_count[level]       = count;
 672                 ctx->printers[level]            = info;
 673         }
 674 
 675         for (i=1;i<ARRAY_SIZE(levels);i++) {
 676                 int level = levels[i];
 677                 int old_level = levels[i-1];
 678                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
 679                                          "EnumPrinters invalid value");
 680         }
 681 
 682         for (i=0;i<ARRAY_SIZE(levels);i++) {
 683                 int level = levels[i];
 684                 for (j=0;j<ctx->printer_count[level];j++) {
 685                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
 686                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
 687                         switch (level) {
 688                         case 0:
 689                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
 690                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
 691                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
 692                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
 693                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
 694                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);                
 695                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
 696                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
 697                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
 698                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
 699                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
 700                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
 701                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
 702                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
 703                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
 704                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
 705                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
 706                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
 707                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
 708                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
 709                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
 710                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
 711                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
 712                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
 713                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
 714                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
 715                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
 716                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
 717                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
 718                                 break;
 719                         case 1:
 720                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
 721                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
 722                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
 723                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
 724                                 break;
 725                         case 2:
 726                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
 727                                 break;
 728                         case 4:
 729                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
 730                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
 731                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
 732                                 break;
 733                         case 5:
 734                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
 735                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
 736                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
 737                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
 738                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
 739                                 break;
 740                         }
 741                 }
 742         }
 743 
 744         /* TODO:
 745          *      - verify that the port of a printer was in the list returned by EnumPorts
 746          */
 747 
 748         return true;
 749 }
 750 
 751 static bool test_GetPrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 752                             struct dcerpc_pipe *p, 
 753                      struct policy_handle *handle)
 754 {
 755         NTSTATUS status;
 756         struct spoolss_GetPrinter r;
 757         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
 758         int i;
 759         uint32_t needed;
 760         
 761         for (i=0;i<ARRAY_SIZE(levels);i++) {
 762                 r.in.handle = handle;
 763                 r.in.level = levels[i];
 764                 r.in.buffer = NULL;
 765                 r.in.offered = 0;
 766                 r.out.needed = &needed;
 767 
 768                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
 769 
 770                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
 771                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
 772                 
 773                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
 774                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
 775                         data_blob_clear(&blob);
 776                         r.in.buffer = &blob;
 777                         r.in.offered = needed;
 778                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
 779                 }
 780                 
 781                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
 782 
 783                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
 784         }
 785 
 786         return true;
 787 }
 788 
 789 
 790 static bool test_ClosePrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 791                               struct dcerpc_pipe *p, 
 792                               struct policy_handle *handle)
 793 {
 794         NTSTATUS status;
 795         struct spoolss_ClosePrinter r;
 796 
 797         r.in.handle = handle;
 798         r.out.handle = handle;
 799 
 800         torture_comment(tctx, "Testing ClosePrinter\n");
 801 
 802         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
 803         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
 804 
 805         return true;
 806 }
 807 
 808 static bool test_GetForm(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 809                          struct dcerpc_pipe *p, 
 810                          struct policy_handle *handle, 
 811                          const char *form_name,
 812                          uint32_t level)
 813 {
 814         NTSTATUS status;
 815         struct spoolss_GetForm r;
 816         uint32_t needed;
 817 
 818         r.in.handle = handle;
 819         r.in.form_name = form_name;
 820         r.in.level = level;
 821         r.in.buffer = NULL;
 822         r.in.offered = 0;
 823         r.out.needed = &needed;
 824 
 825         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
 826 
 827         status = dcerpc_spoolss_GetForm(p, tctx, &r);
 828         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
 829 
 830         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
 831                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
 832                 data_blob_clear(&blob);
 833                 r.in.buffer = &blob;
 834                 r.in.offered = needed;
 835                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
 836                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
 837 
 838                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
 839 
 840                 torture_assert(tctx, r.out.info, "No form info returned");
 841         }
 842 
 843         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
 844 
 845         return true;
 846 }
 847 
 848 static bool test_EnumForms(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 849                            struct dcerpc_pipe *p, 
 850                            struct policy_handle *handle, bool print_server)
 851 {
 852         NTSTATUS status;
 853         struct spoolss_EnumForms r;
 854         bool ret = true;
 855         uint32_t needed;
 856         uint32_t count;
 857         uint32_t levels[] = { 1, 2 };
 858         int i;
 859 
 860         for (i=0; i<ARRAY_SIZE(levels); i++) {
 861 
 862                 union spoolss_FormInfo *info;
 863 
 864                 r.in.handle = handle;
 865                 r.in.level = levels[i];
 866                 r.in.buffer = NULL;
 867                 r.in.offered = 0;
 868                 r.out.needed = &needed;
 869                 r.out.count = &count;
 870                 r.out.info = &info;
 871 
 872                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
 873 
 874                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
 875                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
 876 
 877                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
 878                         break;
 879                 }
 880 
 881                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
 882                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
 883 
 884                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
 885                         int j;
 886                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
 887                         data_blob_clear(&blob);
 888                         r.in.buffer = &blob;
 889                         r.in.offered = needed;
 890 
 891                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
 892 
 893                         torture_assert(tctx, info, "No forms returned");
 894 
 895                         for (j = 0; j < count; j++) {
 896                                 if (!print_server)
 897                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
 898                         }
 899                 }
 900 
 901                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
 902 
 903                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
 904         }
 905 
 906         return true;
 907 }
 908 
 909 static bool test_DeleteForm(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 910                             struct dcerpc_pipe *p, 
 911                             struct policy_handle *handle, 
 912                             const char *form_name)
 913 {
 914         NTSTATUS status;
 915         struct spoolss_DeleteForm r;
 916 
 917         r.in.handle = handle;
 918         r.in.form_name = form_name;
 919 
 920         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
 921 
 922         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
 923 
 924         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
 925 
 926         return true;
 927 }
 928 
 929 static bool test_AddForm(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 930                          struct dcerpc_pipe *p, 
 931                          struct policy_handle *handle, bool print_server)
 932 {
 933         struct spoolss_AddForm r;
 934         struct spoolss_AddFormInfo1 addform;
 935         const char *form_name = "testform3";
 936         NTSTATUS status;
 937         bool ret = true;
 938 
 939         r.in.handle     = handle;
 940         r.in.level      = 1;
 941         r.in.info.info1 = &addform;
 942         addform.flags           = SPOOLSS_FORM_USER;
 943         addform.form_name       = form_name;
 944         addform.size.width      = 50;
 945         addform.size.height     = 25;
 946         addform.area.left       = 5;
 947         addform.area.top        = 10;
 948         addform.area.right      = 45;
 949         addform.area.bottom     = 15;
 950 
 951         status = dcerpc_spoolss_AddForm(p, tctx, &r);
 952 
 953         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
 954 
 955         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
 956 
 957         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
 958 
 959         {
 960                 struct spoolss_SetForm sf;
 961                 struct spoolss_AddFormInfo1 setform;
 962 
 963                 sf.in.handle    = handle;
 964                 sf.in.form_name = form_name;
 965                 sf.in.level     = 1;
 966                 sf.in.info.info1= &setform;
 967                 setform.flags           = addform.flags;
 968                 setform.form_name       = addform.form_name;
 969                 setform.size            = addform.size;
 970                 setform.area            = addform.area;
 971 
 972                 setform.size.width      = 1234;
 973 
 974                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
 975 
 976                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
 977 
 978                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
 979         }
 980 
 981         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
 982 
 983         if (!test_DeleteForm(tctx, p, handle, form_name)) {
 984                 ret = false;
 985         }
 986 
 987         return ret;
 988 }
 989 
 990 static bool test_EnumPorts_old(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 991                                struct dcerpc_pipe *p)
 992 {
 993         NTSTATUS status;
 994         struct spoolss_EnumPorts r;
 995         uint32_t needed;
 996         uint32_t count;
 997         union spoolss_PortInfo *info;
 998 
 999         r.in.servername = talloc_asprintf(tctx, "\\\\%s", 
1000                                           dcerpc_server_name(p));
1001         r.in.level = 2;
1002         r.in.buffer = NULL;
1003         r.in.offered = 0;
1004         r.out.needed = &needed;
1005         r.out.count = &count;
1006         r.out.info = &info;
1007 
1008         torture_comment(tctx, "Testing EnumPorts\n");
1009 
1010         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1011 
1012         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1013 
1014         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1015                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1016                 data_blob_clear(&blob);
1017                 r.in.buffer = &blob;
1018                 r.in.offered = needed;
1019 
1020                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1021                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1022 
1023                 torture_assert(tctx, info, "No ports returned");
1024         }
1025 
1026         return true;
1027 }
1028 
1029 static bool test_AddPort(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1030                          struct dcerpc_pipe *p)
1031 {
1032         NTSTATUS status;
1033         struct spoolss_AddPort r;
1034 
1035         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", 
1036                                            dcerpc_server_name(p));
1037         r.in.unknown = 0;
1038         r.in.monitor_name = "foo";
1039 
1040         torture_comment(tctx, "Testing AddPort\n");
1041 
1042         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1043 
1044         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1045 
1046         /* win2k3 returns WERR_NOT_SUPPORTED */
1047 
1048 #if 0
1049 
1050         if (!W_ERROR_IS_OK(r.out.result)) {
1051                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1052                 return false;
1053         }
1054 
1055 #endif
1056 
1057         return true;
1058 }
1059 
1060 static bool test_GetJob(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1061                         struct dcerpc_pipe *p, 
1062                         struct policy_handle *handle, uint32_t job_id)
1063 {
1064         NTSTATUS status;
1065         struct spoolss_GetJob r;
1066         uint32_t needed;
1067         uint32_t levels[] = {1, 2 /* 3, 4 */};
1068         uint32_t i;
1069 
1070         r.in.handle = handle;
1071         r.in.job_id = job_id;
1072         r.in.level = 0;
1073         r.in.buffer = NULL;
1074         r.in.offered = 0;
1075         r.out.needed = &needed;
1076 
1077         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1078 
1079         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1080         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1081 
1082         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1083 
1084                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1085 
1086                 r.in.level = levels[i];
1087                 r.in.offered = 0;
1088 
1089                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1090                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1091 
1092                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1093                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1094                         data_blob_clear(&blob);
1095                         r.in.buffer = &blob;
1096                         r.in.offered = needed;
1097 
1098                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1099                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1100 
1101                 }
1102                 torture_assert(tctx, r.out.info, "No job info returned");
1103                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1104         }
1105 
1106         return true;
1107 }
1108 
1109 static bool test_SetJob(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1110                         struct dcerpc_pipe *p, 
1111                         struct policy_handle *handle, uint32_t job_id, 
1112                         enum spoolss_JobControl command)
1113 {
1114         NTSTATUS status;
1115         struct spoolss_SetJob r;
1116 
1117         r.in.handle     = handle;
1118         r.in.job_id     = job_id;
1119         r.in.ctr        = NULL;
1120         r.in.command    = command;
1121 
1122         switch (command) {
1123         case SPOOLSS_JOB_CONTROL_PAUSE:
1124                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1125                 break;
1126         case SPOOLSS_JOB_CONTROL_RESUME:
1127                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1128                 break;
1129         case SPOOLSS_JOB_CONTROL_CANCEL:
1130                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1131                 break;
1132         case SPOOLSS_JOB_CONTROL_RESTART:
1133                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1134                 break;
1135         case SPOOLSS_JOB_CONTROL_DELETE:
1136                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1137                 break;
1138         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1139                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1140                 break;
1141         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1142                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1143                 break;
1144         case SPOOLSS_JOB_CONTROL_RETAIN:
1145                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1146                 break;
1147         case SPOOLSS_JOB_CONTROL_RELEASE:
1148                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1149                 break;
1150         default:
1151                 torture_comment(tctx, "Testing SetJob\n");
1152                 break;
1153         }
1154 
1155         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1156         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1157         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1158 
1159         return true;
1160 }
1161 
1162 static bool test_AddJob(struct torture_context *tctx,
     /* [<][>][^][v][top][bottom][index][help] */
1163                         struct dcerpc_pipe *p,
1164                         struct policy_handle *handle)
1165 {
1166         NTSTATUS status;
1167         struct spoolss_AddJob r;
1168         uint32_t needed;
1169 
1170         r.in.level = 0;
1171         r.in.handle = handle;
1172         r.in.offered = 0;
1173         r.out.needed = &needed;
1174         r.in.buffer = r.out.buffer = NULL;
1175 
1176         torture_comment(tctx, "Testing AddJob\n");
1177 
1178         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1179         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1180 
1181         r.in.level = 1;
1182 
1183         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1184         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1185 
1186         return true;
1187 }
1188 
1189 
1190 static bool test_EnumJobs(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1191                           struct dcerpc_pipe *p, 
1192                           struct policy_handle *handle)
1193 {
1194         NTSTATUS status;
1195         struct spoolss_EnumJobs r;
1196         uint32_t needed;
1197         uint32_t count;
1198         union spoolss_JobInfo *info;
1199 
1200         r.in.handle = handle;
1201         r.in.firstjob = 0;
1202         r.in.numjobs = 0xffffffff;
1203         r.in.level = 1;
1204         r.in.buffer = NULL;
1205         r.in.offered = 0;
1206         r.out.needed = &needed;
1207         r.out.count = &count;
1208         r.out.info = &info;
1209 
1210         torture_comment(tctx, "Testing EnumJobs\n");
1211 
1212         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1213 
1214         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1215 
1216         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1217                 int j;
1218                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1219                 data_blob_clear(&blob);
1220                 r.in.buffer = &blob;
1221                 r.in.offered = needed;
1222 
1223                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1224 
1225                 torture_assert(tctx, info, "No jobs returned");
1226 
1227                 for (j = 0; j < count; j++) {
1228 
1229                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1230 
1231                         /* FIXME - gd */
1232                         if (!torture_setting_bool(tctx, "samba3", false)) {
1233                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1234                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1235                         }
1236                 }
1237 
1238         } else {
1239                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1240         }
1241 
1242         return true;
1243 }
1244 
1245 static bool test_DoPrintTest(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1246                              struct dcerpc_pipe *p, 
1247                              struct policy_handle *handle)
1248 {
1249         bool ret = true;
1250         NTSTATUS status;
1251         struct spoolss_StartDocPrinter s;
1252         struct spoolss_DocumentInfo1 info1;
1253         struct spoolss_StartPagePrinter sp;
1254         struct spoolss_WritePrinter w;
1255         struct spoolss_EndPagePrinter ep;
1256         struct spoolss_EndDocPrinter e;
1257         int i;
1258         uint32_t job_id;
1259         uint32_t num_written;
1260 
1261         torture_comment(tctx, "Testing StartDocPrinter\n");
1262 
1263         s.in.handle             = handle;
1264         s.in.level              = 1;
1265         s.in.info.info1         = &info1;
1266         s.out.job_id            = &job_id;
1267         info1.document_name     = "TorturePrintJob";
1268         info1.output_file       = NULL;
1269         info1.datatype          = "RAW";
1270 
1271         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1272         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1273         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1274 
1275         for (i=1; i < 4; i++) {
1276                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1277 
1278                 sp.in.handle            = handle;
1279 
1280                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1281                 torture_assert_ntstatus_ok(tctx, status, 
1282                                            "dcerpc_spoolss_StartPagePrinter failed");
1283                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1284 
1285                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1286 
1287                 w.in.handle             = handle;
1288                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1289                 w.out.num_written       = &num_written;
1290 
1291                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1292                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1293                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1294 
1295                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1296 
1297                 ep.in.handle            = handle;
1298 
1299                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1300                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1301                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1302         }
1303 
1304         torture_comment(tctx, "Testing EndDocPrinter\n");
1305 
1306         e.in.handle = handle;
1307 
1308         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1309         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1310         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1311 
1312         ret &= test_AddJob(tctx, p, handle);
1313         ret &= test_EnumJobs(tctx, p, handle);
1314 
1315         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1316 
1317         return ret;
1318 }
1319 
1320 static bool test_PausePrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1321                               struct dcerpc_pipe *p, 
1322                               struct policy_handle *handle)
1323 {
1324         NTSTATUS status;
1325         struct spoolss_SetPrinter r;
1326         struct spoolss_SetPrinterInfoCtr info_ctr;
1327         struct spoolss_DevmodeContainer devmode_ctr;
1328         struct sec_desc_buf secdesc_ctr;
1329 
1330         info_ctr.level = 0;
1331         info_ctr.info.info0 = NULL;
1332 
1333         ZERO_STRUCT(devmode_ctr);
1334         ZERO_STRUCT(secdesc_ctr);
1335 
1336         r.in.handle             = handle;
1337         r.in.info_ctr           = &info_ctr;
1338         r.in.devmode_ctr        = &devmode_ctr;
1339         r.in.secdesc_ctr        = &secdesc_ctr;
1340         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1341 
1342         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1343 
1344         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1345 
1346         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1347 
1348         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1349 
1350         return true;
1351 }
1352 
1353 static bool test_ResumePrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1354                                struct dcerpc_pipe *p, 
1355                                struct policy_handle *handle)
1356 {
1357         NTSTATUS status;
1358         struct spoolss_SetPrinter r;
1359         struct spoolss_SetPrinterInfoCtr info_ctr;
1360         struct spoolss_DevmodeContainer devmode_ctr;
1361         struct sec_desc_buf secdesc_ctr;
1362 
1363         info_ctr.level = 0;
1364         info_ctr.info.info0 = NULL;
1365 
1366         ZERO_STRUCT(devmode_ctr);
1367         ZERO_STRUCT(secdesc_ctr);
1368 
1369         r.in.handle             = handle;
1370         r.in.info_ctr           = &info_ctr;
1371         r.in.devmode_ctr        = &devmode_ctr;
1372         r.in.secdesc_ctr        = &secdesc_ctr;
1373         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1374 
1375         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1376 
1377         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1378 
1379         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1380 
1381         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1382 
1383         return true;
1384 }
1385 
1386 static bool test_GetPrinterData(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1387                                 struct dcerpc_pipe *p, 
1388                                 struct policy_handle *handle, 
1389                                 const char *value_name)
1390 {
1391         NTSTATUS status;
1392         struct spoolss_GetPrinterData r;
1393         uint32_t needed;
1394         enum winreg_Type type;
1395         union spoolss_PrinterData data;
1396 
1397         r.in.handle = handle;
1398         r.in.value_name = value_name;
1399         r.in.offered = 0;
1400         r.out.needed = &needed;
1401         r.out.type = &type;
1402         r.out.data = &data;
1403 
1404         torture_comment(tctx, "Testing GetPrinterData\n");
1405 
1406         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1407         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1408 
1409         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1410                 r.in.offered = needed;
1411 
1412                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1413                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1414 
1415                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1416         }
1417 
1418         return true;
1419 }
1420 
1421 static bool test_GetPrinterDataEx(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1422                                   struct dcerpc_pipe *p, 
1423                                   struct policy_handle *handle, 
1424                                   const char *key_name,
1425                                   const char *value_name)
1426 {
1427         NTSTATUS status;
1428         struct spoolss_GetPrinterDataEx r;
1429         enum winreg_Type type;
1430         uint32_t needed;
1431 
1432         r.in.handle = handle;
1433         r.in.key_name = key_name;
1434         r.in.value_name = value_name;
1435         r.in.offered = 0;
1436         r.out.type = &type;
1437         r.out.needed = &needed;
1438         r.out.buffer = NULL;
1439 
1440         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1441 
1442         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1443         if (!NT_STATUS_IS_OK(status)) {
1444                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1445                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1446                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1447                 }
1448                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1449         }
1450 
1451         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1452                 r.in.offered = needed;
1453                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1454 
1455                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1456                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1457 
1458                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1459         }
1460 
1461         return true;
1462 }
1463 
1464 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p, 
     /* [<][>][^][v][top][bottom][index][help] */
1465                                  struct policy_handle *handle)
1466 {
1467         NTSTATUS status;
1468         struct spoolss_EnumPrinterData r;
1469 
1470         ZERO_STRUCT(r);
1471         r.in.handle = handle;
1472         r.in.enum_index = 0;
1473 
1474         do {
1475                 uint32_t value_size = 0;
1476                 uint32_t data_size = 0;
1477                 enum winreg_Type type = 0;
1478 
1479                 r.in.value_offered = value_size;
1480                 r.out.value_needed = &value_size;
1481                 r.in.data_offered = data_size;
1482                 r.out.data_needed = &data_size;
1483 
1484                 r.out.type = &type;
1485                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1486 
1487                 torture_comment(tctx, "Testing EnumPrinterData\n");
1488 
1489                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1490 
1491                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1492 
1493                 r.in.value_offered = value_size;
1494                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1495                 r.in.data_offered = data_size;
1496                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1497 
1498                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1499 
1500                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1501                 
1502                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1503 
1504                 test_GetPrinterDataEx(tctx, 
1505                         p, handle, "PrinterDriverData", 
1506                         r.out.value_name);
1507 
1508                 r.in.enum_index++;
1509 
1510         } while (W_ERROR_IS_OK(r.out.result));
1511 
1512         return true;
1513 }
1514 
1515 static bool test_EnumPrinterDataEx(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1516                                    struct dcerpc_pipe *p, 
1517                                    struct policy_handle *handle)
1518 {
1519         NTSTATUS status;
1520         struct spoolss_EnumPrinterDataEx r;
1521         struct spoolss_PrinterEnumValues *info;
1522         uint32_t needed;
1523         uint32_t count;
1524 
1525         r.in.handle = handle;
1526         r.in.key_name = "PrinterDriverData";
1527         r.in.offered = 0;
1528         r.out.needed = &needed;
1529         r.out.count = &count;
1530         r.out.info = &info;
1531 
1532         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1533 
1534         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1535         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1536 
1537         r.in.offered = needed;
1538 
1539         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1540 
1541         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1542 
1543         return true;
1544 }
1545 
1546 
1547 static bool test_DeletePrinterData(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1548                                    struct dcerpc_pipe *p, 
1549                                    struct policy_handle *handle, 
1550                                    const char *value_name)
1551 {
1552         NTSTATUS status;
1553         struct spoolss_DeletePrinterData r;
1554 
1555         r.in.handle = handle;
1556         r.in.value_name = value_name;
1557 
1558         torture_comment(tctx, "Testing DeletePrinterData\n");
1559 
1560         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1561 
1562         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1563 
1564         return true;
1565 }
1566 
1567 static bool test_SetPrinterData(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1568                                 struct dcerpc_pipe *p, 
1569                                 struct policy_handle *handle)
1570 {
1571         NTSTATUS status;
1572         struct spoolss_SetPrinterData r;
1573         const char *value_name = "spottyfoot";
1574         
1575         r.in.handle = handle;
1576         r.in.value_name = value_name;
1577         r.in.type = REG_SZ;
1578         r.in.data.string = "dog";
1579 
1580         torture_comment(tctx, "Testing SetPrinterData\n");
1581 
1582         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1583 
1584         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1585 
1586         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1587                 return false;
1588         }
1589 
1590         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1591                 return false;
1592         }
1593 
1594         return true;
1595 }
1596 
1597 static bool test_SecondaryClosePrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1598                                        struct dcerpc_pipe *p, 
1599                                        struct policy_handle *handle)
1600 {
1601         NTSTATUS status;
1602         struct dcerpc_binding *b;
1603         struct dcerpc_pipe *p2;
1604         struct spoolss_ClosePrinter cp;
1605 
1606         /* only makes sense on SMB */
1607         if (p->conn->transport.transport != NCACN_NP) {
1608                 return true;
1609         }
1610 
1611         torture_comment(tctx, "testing close on secondary pipe\n");
1612 
1613         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1614         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1615 
1616         status = dcerpc_secondary_connection(p, &p2, b);
1617         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1618 
1619         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1620         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1621 
1622         cp.in.handle = handle;
1623         cp.out.handle = handle;
1624 
1625         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1626         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1627                         "ERROR: Allowed close on secondary connection");
1628 
1629         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, 
1630                                  "Unexpected fault code");
1631 
1632         talloc_free(p2);
1633 
1634         return true;
1635 }
1636 
1637 static bool test_OpenPrinter_badname(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1638                                      struct dcerpc_pipe *p, const char *name)
1639 {
1640         NTSTATUS status;
1641         struct spoolss_OpenPrinter op;
1642         struct spoolss_OpenPrinterEx opEx;
1643         struct policy_handle handle;
1644         bool ret = true;
1645 
1646         op.in.printername       = name;
1647         op.in.datatype          = NULL;
1648         op.in.devmode_ctr.devmode= NULL;
1649         op.in.access_mask       = 0;
1650         op.out.handle           = &handle;
1651 
1652         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1653 
1654         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1655         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1656         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1657                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1658                         name, win_errstr(op.out.result));
1659         }
1660 
1661         if (W_ERROR_IS_OK(op.out.result)) {
1662                 ret &=test_ClosePrinter(tctx, p, &handle);
1663         }
1664 
1665         opEx.in.printername             = name;
1666         opEx.in.datatype                = NULL;
1667         opEx.in.devmode_ctr.devmode     = NULL;
1668         opEx.in.access_mask             = 0;
1669         opEx.in.level                   = 1;
1670         opEx.in.userlevel.level1        = NULL;
1671         opEx.out.handle                 = &handle;
1672 
1673         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1674 
1675         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1676         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1677         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1678                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1679                         name, win_errstr(opEx.out.result));
1680         }
1681 
1682         if (W_ERROR_IS_OK(opEx.out.result)) {
1683                 ret &=test_ClosePrinter(tctx, p, &handle);
1684         }
1685 
1686         return ret;
1687 }
1688 
1689 static bool test_OpenPrinter(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1690                              struct dcerpc_pipe *p, 
1691                              const char *name)
1692 {
1693         NTSTATUS status;
1694         struct spoolss_OpenPrinter r;
1695         struct policy_handle handle;
1696         bool ret = true;
1697 
1698         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1699         r.in.datatype           = NULL;
1700         r.in.devmode_ctr.devmode= NULL;
1701         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1702         r.out.handle            = &handle;
1703 
1704         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1705 
1706         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1707 
1708         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1709 
1710         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1711 
1712         if (!test_GetPrinter(tctx, p, &handle)) {
1713                 ret = false;
1714         }
1715 
1716         if (!torture_setting_bool(tctx, "samba3", false)) {
1717                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1718                         ret = false;
1719                 }
1720         }
1721 
1722         if (!test_ClosePrinter(tctx, p, &handle)) {
1723                 ret = false;
1724         }
1725 
1726         return ret;
1727 }
1728 
1729 static bool call_OpenPrinterEx(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1730                                struct dcerpc_pipe *p, 
1731                                const char *name, struct policy_handle *handle)
1732 {
1733         struct spoolss_OpenPrinterEx r;
1734         struct spoolss_UserLevel1 userlevel1;
1735         NTSTATUS status;
1736 
1737         if (name && name[0]) {
1738                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", 
1739                                                    dcerpc_server_name(p), name);
1740         } else {
1741                 r.in.printername = talloc_asprintf(tctx, "\\\\%s", 
1742                                                    dcerpc_server_name(p));
1743         }
1744 
1745         r.in.datatype           = NULL;
1746         r.in.devmode_ctr.devmode= NULL;
1747         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1748         r.in.level              = 1;
1749         r.in.userlevel.level1   = &userlevel1;
1750         r.out.handle = handle;
1751 
1752         userlevel1.size = 1234;
1753         userlevel1.client = "hello";
1754         userlevel1.user = "spottyfoot!";
1755         userlevel1.build = 1;
1756         userlevel1.major = 2;
1757         userlevel1.minor = 3;
1758         userlevel1.processor = 4;
1759 
1760         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1761 
1762         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1763 
1764         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1765         
1766         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1767 
1768         return true;
1769 }
1770 
1771 static bool test_OpenPrinterEx(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1772                                struct dcerpc_pipe *p, 
1773                                const char *name)
1774 {
1775         struct policy_handle handle;
1776         bool ret = true;
1777 
1778         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1779                 return false;
1780         }
1781 
1782         if (!test_GetPrinter(tctx, p, &handle)) {
1783                 ret = false;
1784         }
1785 
1786         if (!test_EnumForms(tctx, p, &handle, false)) {
1787                 ret = false;
1788         }
1789 
1790         if (!test_AddForm(tctx, p, &handle, false)) {
1791                 ret = false;
1792         }
1793 
1794         if (!test_EnumPrinterData(tctx, p, &handle)) {
1795                 ret = false;
1796         }
1797 
1798         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1799                 ret = false;
1800         }
1801 
1802         if (!test_PausePrinter(tctx, p, &handle)) {
1803                 ret = false;
1804         }
1805 
1806         if (!test_DoPrintTest(tctx, p, &handle)) {
1807                 ret = false;
1808         }
1809 
1810         if (!test_ResumePrinter(tctx, p, &handle)) {
1811                 ret = false;
1812         }
1813 
1814         if (!test_SetPrinterData(tctx, p, &handle)) {
1815                 ret = false;
1816         }
1817 
1818         if (!torture_setting_bool(tctx, "samba3", false)) {
1819                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1820                         ret = false;
1821                 }
1822         }
1823 
1824         if (!test_ClosePrinter(tctx, p, &handle)) {
1825                 ret = false;
1826         }
1827         
1828         return ret;
1829 }
1830 
1831 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
     /* [<][>][^][v][top][bottom][index][help] */
1832 {
1833         struct spoolss_EnumPrinters r;
1834         NTSTATUS status;
1835         uint16_t levels[] = {1, 2, 4, 5};
1836         int i;
1837         bool ret = true;
1838 
1839         for (i=0;i<ARRAY_SIZE(levels);i++) {
1840                 union spoolss_PrinterInfo *info;
1841                 int j;
1842                 uint32_t needed;
1843                 uint32_t count;
1844 
1845                 r.in.flags      = PRINTER_ENUM_LOCAL;
1846                 r.in.server     = "";
1847                 r.in.level      = levels[i];
1848                 r.in.buffer     = NULL;
1849                 r.in.offered    = 0;
1850                 r.out.needed    = &needed;
1851                 r.out.count     = &count;
1852                 r.out.info      = &info;
1853 
1854                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1855 
1856                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1857                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1858 
1859                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1860                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1861                         data_blob_clear(&blob);
1862                         r.in.buffer = &blob;
1863                         r.in.offered = needed;
1864                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1865                 }
1866 
1867                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1868 
1869                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1870 
1871                 if (!info) {
1872                         torture_comment(tctx, "No printers returned\n");
1873                         return true;
1874                 }
1875 
1876                 for (j=0;j<count;j++) {
1877                         if (r.in.level == 1) {
1878                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
1879                                 char *slash, *name;
1880                                 name = unc;
1881                                 if (unc[0] == '\\' && unc[1] == '\\') {
1882                                         unc +=2;
1883                                 }
1884                                 slash = strchr(unc, '\\');
1885                                 if (slash) {
1886                                         slash++;
1887                                         name = slash;
1888                                 }
1889                                 if (!test_OpenPrinter(tctx, p, name)) {
1890                                         ret = false;
1891                                 }
1892                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1893                                         ret = false;
1894                                 }
1895                         }
1896                 }
1897         }
1898 
1899         return ret;
1900 }
1901 
1902 #if 0
1903 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p, 
     /* [<][>][^][v][top][bottom][index][help] */
1904                                    struct policy_handle *handle, 
1905                                    const char *driver_name)
1906 {
1907         NTSTATUS status;
1908         struct spoolss_GetPrinterDriver2 r;
1909         uint32_t needed;
1910         uint32_t server_major_version;
1911         uint32_t server_minor_version;
1912 
1913         r.in.handle = handle;
1914         r.in.architecture = "W32X86";
1915         r.in.level = 1;
1916         r.in.buffer = NULL;
1917         r.in.offered = 0;
1918         r.in.client_major_version = 0;
1919         r.in.client_minor_version = 0;
1920         r.out.needed = &needed;
1921         r.out.server_major_version = &server_major_version;
1922         r.out.server_minor_version = &server_minor_version;
1923 
1924         printf("Testing GetPrinterDriver2\n");
1925 
1926         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1927         if (!NT_STATUS_IS_OK(status)) {
1928                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1929                 return false;
1930         }
1931 
1932         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1933                 r.in.offered = needed;
1934                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1935         }
1936                 
1937         if (!NT_STATUS_IS_OK(status)) {
1938                 printf("GetPrinterDriver2 failed - %s\n", 
1939                        nt_errstr(status));
1940                 return false;
1941         }
1942 
1943         if (!W_ERROR_IS_OK(r.out.result)) {
1944                 printf("GetPrinterDriver2 failed - %s\n", 
1945                        win_errstr(r.out.result));
1946                 return false;
1947         }
1948 
1949         return true;
1950 }
1951 #endif
1952 
1953 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx, 
     /* [<][>][^][v][top][bottom][index][help] */
1954                                         struct dcerpc_pipe *p)
1955 {
1956         struct spoolss_EnumPrinterDrivers r;
1957         NTSTATUS status;
1958         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1959         int i;
1960 
1961         for (i=0;i<ARRAY_SIZE(levels);i++) {
1962 
1963                 uint32_t needed;
1964                 uint32_t count;
1965                 union spoolss_DriverInfo *info;
1966 
1967                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1968                 r.in.environment = "Windows NT x86";
1969                 r.in.level = levels[i];
1970                 r.in.buffer = NULL;
1971                 r.in.offered = 0;
1972                 r.out.needed = &needed;
1973                 r.out.count = &count;
1974                 r.out.info = &info;
1975 
1976                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1977 
1978                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1979 
1980                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1981 
1982                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1983                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1984                         data_blob_clear(&blob);
1985                         r.in.buffer = &blob;
1986                         r.in.offered = needed;
1987                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1988                 }
1989 
1990                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1991 
1992                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1993 
1994                 if (!info) {
1995                         torture_comment(tctx, "No printer drivers returned\n");
1996                         break;
1997                 }
1998         }
1999 
2000         return true;
2001 }
2002 
2003 bool torture_rpc_spoolss(struct torture_context *torture)
     /* [<][>][^][v][top][bottom][index][help] */
2004 {
2005         NTSTATUS status;
2006         struct dcerpc_pipe *p;
2007         bool ret = true;
2008         struct test_spoolss_context *ctx;
2009 
2010         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2011         if (!NT_STATUS_IS_OK(status)) {
2012                 return false;
2013         }
2014 
2015         ctx = talloc_zero(torture, struct test_spoolss_context);
2016 
2017         ret &= test_OpenPrinter_server(torture, p, ctx);
2018 
2019         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2020         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2021         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2022         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2023         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2024         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2025         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2026         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2027         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2028         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2029         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2030         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2031         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2032         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2033         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2034         ret &= test_EnumPorts(torture, p, ctx);
2035         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2036         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2037         ret &= test_EnumPrinterDrivers(torture, p, ctx);
2038         ret &= test_EnumMonitors(torture, p, ctx);
2039         ret &= test_EnumPrintProcessors(torture, p, ctx);
2040         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2041         ret &= test_EnumPrinters(torture, p, ctx);
2042         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2043         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2044         ret &= test_OpenPrinter_badname(torture, p, "");
2045         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2046         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2047         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2048         ret &= test_OpenPrinter_badname(torture, p, 
2049                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2050 
2051 
2052         ret &= test_AddPort(torture, p);
2053         ret &= test_EnumPorts_old(torture, p);
2054         ret &= test_EnumPrinters_old(torture, p);
2055         ret &= test_EnumPrinterDrivers_old(torture, p);
2056 
2057         return ret;
2058 }

/* [<][>][^][v][top][bottom][index][help] */