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