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