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