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