Merge commit 'origin/master' into libcli-auth-merge-without-netlogond
[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                 /* 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         uint32_t levels[] = {1, 2 /* 3, 4 */};
1068         uint32_t i;
1069
1070         r.in.handle = handle;
1071         r.in.job_id = job_id;
1072         r.in.level = 0;
1073         r.in.buffer = NULL;
1074         r.in.offered = 0;
1075         r.out.needed = &needed;
1076
1077         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1078
1079         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1080         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1081
1082         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1083
1084                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1085
1086                 r.in.level = levels[i];
1087                 r.in.offered = 0;
1088
1089                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1090                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1091
1092                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1093                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1094                         data_blob_clear(&blob);
1095                         r.in.buffer = &blob;
1096                         r.in.offered = needed;
1097
1098                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1099                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1100
1101                 }
1102                 torture_assert(tctx, r.out.info, "No job info returned");
1103                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1104         }
1105
1106         return true;
1107 }
1108
1109 static bool test_SetJob(struct torture_context *tctx, 
1110                         struct dcerpc_pipe *p, 
1111                         struct policy_handle *handle, uint32_t job_id, 
1112                         enum spoolss_JobControl command)
1113 {
1114         NTSTATUS status;
1115         struct spoolss_SetJob r;
1116
1117         r.in.handle     = handle;
1118         r.in.job_id     = job_id;
1119         r.in.ctr        = NULL;
1120         r.in.command    = command;
1121
1122         switch (command) {
1123         case SPOOLSS_JOB_CONTROL_PAUSE:
1124                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1125                 break;
1126         case SPOOLSS_JOB_CONTROL_RESUME:
1127                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1128                 break;
1129         case SPOOLSS_JOB_CONTROL_CANCEL:
1130                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1131                 break;
1132         case SPOOLSS_JOB_CONTROL_RESTART:
1133                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1134                 break;
1135         case SPOOLSS_JOB_CONTROL_DELETE:
1136                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1137                 break;
1138         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1139                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1140                 break;
1141         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1142                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1143                 break;
1144         case SPOOLSS_JOB_CONTROL_RETAIN:
1145                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1146                 break;
1147         case SPOOLSS_JOB_CONTROL_RELEASE:
1148                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1149                 break;
1150         default:
1151                 torture_comment(tctx, "Testing SetJob\n");
1152                 break;
1153         }
1154
1155         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1156         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1157         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1158
1159         return true;
1160 }
1161
1162 static bool test_AddJob(struct torture_context *tctx,
1163                         struct dcerpc_pipe *p,
1164                         struct policy_handle *handle)
1165 {
1166         NTSTATUS status;
1167         struct spoolss_AddJob r;
1168         uint32_t needed;
1169
1170         r.in.level = 0;
1171         r.in.handle = handle;
1172         r.in.offered = 0;
1173         r.out.needed = &needed;
1174         r.in.buffer = r.out.buffer = NULL;
1175
1176         torture_comment(tctx, "Testing AddJob\n");
1177
1178         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1179         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1180
1181         r.in.level = 1;
1182
1183         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1184         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1185
1186         return true;
1187 }
1188
1189
1190 static bool test_EnumJobs(struct torture_context *tctx, 
1191                           struct dcerpc_pipe *p, 
1192                           struct policy_handle *handle)
1193 {
1194         NTSTATUS status;
1195         struct spoolss_EnumJobs r;
1196         uint32_t needed;
1197         uint32_t count;
1198         union spoolss_JobInfo *info;
1199
1200         r.in.handle = handle;
1201         r.in.firstjob = 0;
1202         r.in.numjobs = 0xffffffff;
1203         r.in.level = 1;
1204         r.in.buffer = NULL;
1205         r.in.offered = 0;
1206         r.out.needed = &needed;
1207         r.out.count = &count;
1208         r.out.info = &info;
1209
1210         torture_comment(tctx, "Testing EnumJobs\n");
1211
1212         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1213
1214         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1215
1216         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1217                 int j;
1218                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1219                 data_blob_clear(&blob);
1220                 r.in.buffer = &blob;
1221                 r.in.offered = needed;
1222
1223                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1224
1225                 torture_assert(tctx, info, "No jobs returned");
1226
1227                 for (j = 0; j < count; j++) {
1228
1229                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1230
1231                         /* FIXME - gd */
1232                         if (!torture_setting_bool(tctx, "samba3", false)) {
1233                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1234                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1235                         }
1236                 }
1237
1238         } else {
1239                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1240         }
1241
1242         return true;
1243 }
1244
1245 static bool test_DoPrintTest(struct torture_context *tctx, 
1246                              struct dcerpc_pipe *p, 
1247                              struct policy_handle *handle)
1248 {
1249         bool ret = true;
1250         NTSTATUS status;
1251         struct spoolss_StartDocPrinter s;
1252         struct spoolss_DocumentInfo1 info1;
1253         struct spoolss_StartPagePrinter sp;
1254         struct spoolss_WritePrinter w;
1255         struct spoolss_EndPagePrinter ep;
1256         struct spoolss_EndDocPrinter e;
1257         int i;
1258         uint32_t job_id;
1259         uint32_t num_written;
1260
1261         torture_comment(tctx, "Testing StartDocPrinter\n");
1262
1263         s.in.handle             = handle;
1264         s.in.level              = 1;
1265         s.in.info.info1         = &info1;
1266         s.out.job_id            = &job_id;
1267         info1.document_name     = "TorturePrintJob";
1268         info1.output_file       = NULL;
1269         info1.datatype          = "RAW";
1270
1271         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1272         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1273         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1274
1275         for (i=1; i < 4; i++) {
1276                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1277
1278                 sp.in.handle            = handle;
1279
1280                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1281                 torture_assert_ntstatus_ok(tctx, status, 
1282                                            "dcerpc_spoolss_StartPagePrinter failed");
1283                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1284
1285                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1286
1287                 w.in.handle             = handle;
1288                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1289                 w.out.num_written       = &num_written;
1290
1291                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1292                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1293                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1294
1295                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1296
1297                 ep.in.handle            = handle;
1298
1299                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1300                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1301                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1302         }
1303
1304         torture_comment(tctx, "Testing EndDocPrinter\n");
1305
1306         e.in.handle = handle;
1307
1308         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1309         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1310         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1311
1312         ret &= test_AddJob(tctx, p, handle);
1313         ret &= test_EnumJobs(tctx, p, handle);
1314
1315         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1316
1317         return ret;
1318 }
1319
1320 static bool test_PausePrinter(struct torture_context *tctx, 
1321                               struct dcerpc_pipe *p, 
1322                               struct policy_handle *handle)
1323 {
1324         NTSTATUS status;
1325         struct spoolss_SetPrinter r;
1326         struct spoolss_SetPrinterInfoCtr info_ctr;
1327         struct spoolss_DevmodeContainer devmode_ctr;
1328         struct sec_desc_buf secdesc_ctr;
1329
1330         info_ctr.level = 0;
1331         info_ctr.info.info0 = NULL;
1332
1333         ZERO_STRUCT(devmode_ctr);
1334         ZERO_STRUCT(secdesc_ctr);
1335
1336         r.in.handle             = handle;
1337         r.in.info_ctr           = &info_ctr;
1338         r.in.devmode_ctr        = &devmode_ctr;
1339         r.in.secdesc_ctr        = &secdesc_ctr;
1340         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1341
1342         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1343
1344         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1345
1346         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1347
1348         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1349
1350         return true;
1351 }
1352
1353 static bool test_ResumePrinter(struct torture_context *tctx, 
1354                                struct dcerpc_pipe *p, 
1355                                struct policy_handle *handle)
1356 {
1357         NTSTATUS status;
1358         struct spoolss_SetPrinter r;
1359         struct spoolss_SetPrinterInfoCtr info_ctr;
1360         struct spoolss_DevmodeContainer devmode_ctr;
1361         struct sec_desc_buf secdesc_ctr;
1362
1363         info_ctr.level = 0;
1364         info_ctr.info.info0 = NULL;
1365
1366         ZERO_STRUCT(devmode_ctr);
1367         ZERO_STRUCT(secdesc_ctr);
1368
1369         r.in.handle             = handle;
1370         r.in.info_ctr           = &info_ctr;
1371         r.in.devmode_ctr        = &devmode_ctr;
1372         r.in.secdesc_ctr        = &secdesc_ctr;
1373         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1374
1375         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1376
1377         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1378
1379         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1380
1381         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1382
1383         return true;
1384 }
1385
1386 static bool test_GetPrinterData(struct torture_context *tctx, 
1387                                 struct dcerpc_pipe *p, 
1388                                 struct policy_handle *handle, 
1389                                 const char *value_name)
1390 {
1391         NTSTATUS status;
1392         struct spoolss_GetPrinterData r;
1393         uint32_t needed;
1394         enum winreg_Type type;
1395         union spoolss_PrinterData data;
1396
1397         r.in.handle = handle;
1398         r.in.value_name = value_name;
1399         r.in.offered = 0;
1400         r.out.needed = &needed;
1401         r.out.type = &type;
1402         r.out.data = &data;
1403
1404         torture_comment(tctx, "Testing GetPrinterData\n");
1405
1406         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1407         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1408
1409         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1410                 r.in.offered = needed;
1411
1412                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
1413                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
1414
1415                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
1416         }
1417
1418         return true;
1419 }
1420
1421 static bool test_GetPrinterDataEx(struct torture_context *tctx, 
1422                                   struct dcerpc_pipe *p, 
1423                                   struct policy_handle *handle, 
1424                                   const char *key_name,
1425                                   const char *value_name)
1426 {
1427         NTSTATUS status;
1428         struct spoolss_GetPrinterDataEx r;
1429         enum winreg_Type type;
1430         uint32_t needed;
1431
1432         r.in.handle = handle;
1433         r.in.key_name = key_name;
1434         r.in.value_name = value_name;
1435         r.in.offered = 0;
1436         r.out.type = &type;
1437         r.out.needed = &needed;
1438         r.out.buffer = NULL;
1439
1440         torture_comment(tctx, "Testing GetPrinterDataEx\n");
1441
1442         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1443         if (!NT_STATUS_IS_OK(status)) {
1444                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
1445                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
1446                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
1447                 }
1448                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1449         }
1450
1451         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
1452                 r.in.offered = needed;
1453                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
1454
1455                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
1456                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
1457
1458                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
1459         }
1460
1461         return true;
1462 }
1463
1464 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p, 
1465                                  struct policy_handle *handle)
1466 {
1467         NTSTATUS status;
1468         struct spoolss_EnumPrinterData r;
1469
1470         ZERO_STRUCT(r);
1471         r.in.handle = handle;
1472         r.in.enum_index = 0;
1473
1474         do {
1475                 uint32_t value_size = 0;
1476                 uint32_t data_size = 0;
1477                 enum winreg_Type type = 0;
1478
1479                 r.in.value_offered = value_size;
1480                 r.out.value_needed = &value_size;
1481                 r.in.data_offered = data_size;
1482                 r.out.data_needed = &data_size;
1483
1484                 r.out.type = &type;
1485                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
1486
1487                 torture_comment(tctx, "Testing EnumPrinterData\n");
1488
1489                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1490
1491                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1492
1493                 r.in.value_offered = value_size;
1494                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
1495                 r.in.data_offered = data_size;
1496                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
1497
1498                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
1499
1500                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
1501                 
1502                 test_GetPrinterData(tctx, p, handle, r.out.value_name);
1503
1504                 test_GetPrinterDataEx(tctx, 
1505                         p, handle, "PrinterDriverData", 
1506                         r.out.value_name);
1507
1508                 r.in.enum_index++;
1509
1510         } while (W_ERROR_IS_OK(r.out.result));
1511
1512         return true;
1513 }
1514
1515 static bool test_EnumPrinterDataEx(struct torture_context *tctx, 
1516                                    struct dcerpc_pipe *p, 
1517                                    struct policy_handle *handle)
1518 {
1519         NTSTATUS status;
1520         struct spoolss_EnumPrinterDataEx r;
1521         struct spoolss_PrinterEnumValues *info;
1522         uint32_t needed;
1523         uint32_t count;
1524
1525         r.in.handle = handle;
1526         r.in.key_name = "PrinterDriverData";
1527         r.in.offered = 0;
1528         r.out.needed = &needed;
1529         r.out.count = &count;
1530         r.out.info = &info;
1531
1532         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
1533
1534         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1535         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1536
1537         r.in.offered = needed;
1538
1539         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
1540
1541         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
1542
1543         return true;
1544 }
1545
1546
1547 static bool test_DeletePrinterData(struct torture_context *tctx, 
1548                                    struct dcerpc_pipe *p, 
1549                                    struct policy_handle *handle, 
1550                                    const char *value_name)
1551 {
1552         NTSTATUS status;
1553         struct spoolss_DeletePrinterData r;
1554
1555         r.in.handle = handle;
1556         r.in.value_name = value_name;
1557
1558         torture_comment(tctx, "Testing DeletePrinterData\n");
1559
1560         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
1561
1562         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
1563
1564         return true;
1565 }
1566
1567 static bool test_SetPrinterData(struct torture_context *tctx, 
1568                                 struct dcerpc_pipe *p, 
1569                                 struct policy_handle *handle)
1570 {
1571         NTSTATUS status;
1572         struct spoolss_SetPrinterData r;
1573         const char *value_name = "spottyfoot";
1574         
1575         r.in.handle = handle;
1576         r.in.value_name = value_name;
1577         r.in.type = REG_SZ;
1578         r.in.data.string = "dog";
1579
1580         torture_comment(tctx, "Testing SetPrinterData\n");
1581
1582         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
1583
1584         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
1585
1586         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
1587                 return false;
1588         }
1589
1590         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
1591                 return false;
1592         }
1593
1594         return true;
1595 }
1596
1597 static bool test_SecondaryClosePrinter(struct torture_context *tctx, 
1598                                        struct dcerpc_pipe *p, 
1599                                        struct policy_handle *handle)
1600 {
1601         NTSTATUS status;
1602         struct dcerpc_binding *b;
1603         struct dcerpc_pipe *p2;
1604         struct spoolss_ClosePrinter cp;
1605
1606         /* only makes sense on SMB */
1607         if (p->conn->transport.transport != NCACN_NP) {
1608                 return true;
1609         }
1610
1611         torture_comment(tctx, "testing close on secondary pipe\n");
1612
1613         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
1614         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
1615
1616         status = dcerpc_secondary_connection(p, &p2, b);
1617         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
1618
1619         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
1620         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
1621
1622         cp.in.handle = handle;
1623         cp.out.handle = handle;
1624
1625         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
1626         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
1627                         "ERROR: Allowed close on secondary connection");
1628
1629         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH, 
1630                                  "Unexpected fault code");
1631
1632         talloc_free(p2);
1633
1634         return true;
1635 }
1636
1637 static bool test_OpenPrinter_badname(struct torture_context *tctx, 
1638                                      struct dcerpc_pipe *p, const char *name)
1639 {
1640         NTSTATUS status;
1641         struct spoolss_OpenPrinter op;
1642         struct spoolss_OpenPrinterEx opEx;
1643         struct policy_handle handle;
1644         bool ret = true;
1645
1646         op.in.printername       = name;
1647         op.in.datatype          = NULL;
1648         op.in.devmode_ctr.devmode= NULL;
1649         op.in.access_mask       = 0;
1650         op.out.handle           = &handle;
1651
1652         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
1653
1654         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
1655         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1656         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
1657                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
1658                         name, win_errstr(op.out.result));
1659         }
1660
1661         if (W_ERROR_IS_OK(op.out.result)) {
1662                 ret &=test_ClosePrinter(tctx, p, &handle);
1663         }
1664
1665         opEx.in.printername             = name;
1666         opEx.in.datatype                = NULL;
1667         opEx.in.devmode_ctr.devmode     = NULL;
1668         opEx.in.access_mask             = 0;
1669         opEx.in.level                   = 1;
1670         opEx.in.userlevel.level1        = NULL;
1671         opEx.out.handle                 = &handle;
1672
1673         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
1674
1675         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
1676         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1677         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
1678                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
1679                         name, win_errstr(opEx.out.result));
1680         }
1681
1682         if (W_ERROR_IS_OK(opEx.out.result)) {
1683                 ret &=test_ClosePrinter(tctx, p, &handle);
1684         }
1685
1686         return ret;
1687 }
1688
1689 static bool test_OpenPrinter(struct torture_context *tctx, 
1690                              struct dcerpc_pipe *p, 
1691                              const char *name)
1692 {
1693         NTSTATUS status;
1694         struct spoolss_OpenPrinter r;
1695         struct policy_handle handle;
1696         bool ret = true;
1697
1698         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
1699         r.in.datatype           = NULL;
1700         r.in.devmode_ctr.devmode= NULL;
1701         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1702         r.out.handle            = &handle;
1703
1704         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
1705
1706         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
1707
1708         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
1709
1710         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
1711
1712         if (!test_GetPrinter(tctx, p, &handle)) {
1713                 ret = false;
1714         }
1715
1716         if (!torture_setting_bool(tctx, "samba3", false)) {
1717                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1718                         ret = false;
1719                 }
1720         }
1721
1722         if (!test_ClosePrinter(tctx, p, &handle)) {
1723                 ret = false;
1724         }
1725
1726         return ret;
1727 }
1728
1729 static bool call_OpenPrinterEx(struct torture_context *tctx, 
1730                                struct dcerpc_pipe *p, 
1731                                const char *name, struct policy_handle *handle)
1732 {
1733         struct spoolss_OpenPrinterEx r;
1734         struct spoolss_UserLevel1 userlevel1;
1735         NTSTATUS status;
1736
1737         if (name && name[0]) {
1738                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s", 
1739                                                    dcerpc_server_name(p), name);
1740         } else {
1741                 r.in.printername = talloc_asprintf(tctx, "\\\\%s", 
1742                                                    dcerpc_server_name(p));
1743         }
1744
1745         r.in.datatype           = NULL;
1746         r.in.devmode_ctr.devmode= NULL;
1747         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
1748         r.in.level              = 1;
1749         r.in.userlevel.level1   = &userlevel1;
1750         r.out.handle = handle;
1751
1752         userlevel1.size = 1234;
1753         userlevel1.client = "hello";
1754         userlevel1.user = "spottyfoot!";
1755         userlevel1.build = 1;
1756         userlevel1.major = 2;
1757         userlevel1.minor = 3;
1758         userlevel1.processor = 4;
1759
1760         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
1761
1762         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
1763
1764         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
1765         
1766         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
1767
1768         return true;
1769 }
1770
1771 static bool test_OpenPrinterEx(struct torture_context *tctx, 
1772                                struct dcerpc_pipe *p, 
1773                                const char *name)
1774 {
1775         struct policy_handle handle;
1776         bool ret = true;
1777
1778         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
1779                 return false;
1780         }
1781
1782         if (!test_GetPrinter(tctx, p, &handle)) {
1783                 ret = false;
1784         }
1785
1786         if (!test_EnumForms(tctx, p, &handle, false)) {
1787                 ret = false;
1788         }
1789
1790         if (!test_AddForm(tctx, p, &handle, false)) {
1791                 ret = false;
1792         }
1793
1794         if (!test_EnumPrinterData(tctx, p, &handle)) {
1795                 ret = false;
1796         }
1797
1798         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
1799                 ret = false;
1800         }
1801
1802         if (!test_PausePrinter(tctx, p, &handle)) {
1803                 ret = false;
1804         }
1805
1806         if (!test_DoPrintTest(tctx, p, &handle)) {
1807                 ret = false;
1808         }
1809
1810         if (!test_ResumePrinter(tctx, p, &handle)) {
1811                 ret = false;
1812         }
1813
1814         if (!test_SetPrinterData(tctx, p, &handle)) {
1815                 ret = false;
1816         }
1817
1818         if (!torture_setting_bool(tctx, "samba3", false)) {
1819                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
1820                         ret = false;
1821                 }
1822         }
1823
1824         if (!test_ClosePrinter(tctx, p, &handle)) {
1825                 ret = false;
1826         }
1827         
1828         return ret;
1829 }
1830
1831 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
1832 {
1833         struct spoolss_EnumPrinters r;
1834         NTSTATUS status;
1835         uint16_t levels[] = {1, 2, 4, 5};
1836         int i;
1837         bool ret = true;
1838
1839         for (i=0;i<ARRAY_SIZE(levels);i++) {
1840                 union spoolss_PrinterInfo *info;
1841                 int j;
1842                 uint32_t needed;
1843                 uint32_t count;
1844
1845                 r.in.flags      = PRINTER_ENUM_LOCAL;
1846                 r.in.server     = "";
1847                 r.in.level      = levels[i];
1848                 r.in.buffer     = NULL;
1849                 r.in.offered    = 0;
1850                 r.out.needed    = &needed;
1851                 r.out.count     = &count;
1852                 r.out.info      = &info;
1853
1854                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
1855
1856                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1857                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1858
1859                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1860                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1861                         data_blob_clear(&blob);
1862                         r.in.buffer = &blob;
1863                         r.in.offered = needed;
1864                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
1865                 }
1866
1867                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
1868
1869                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
1870
1871                 if (!info) {
1872                         torture_comment(tctx, "No printers returned\n");
1873                         return true;
1874                 }
1875
1876                 for (j=0;j<count;j++) {
1877                         if (r.in.level == 1) {
1878                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
1879                                 char *slash, *name;
1880                                 name = unc;
1881                                 if (unc[0] == '\\' && unc[1] == '\\') {
1882                                         unc +=2;
1883                                 }
1884                                 slash = strchr(unc, '\\');
1885                                 if (slash) {
1886                                         slash++;
1887                                         name = slash;
1888                                 }
1889                                 if (!test_OpenPrinter(tctx, p, name)) {
1890                                         ret = false;
1891                                 }
1892                                 if (!test_OpenPrinterEx(tctx, p, name)) {
1893                                         ret = false;
1894                                 }
1895                         }
1896                 }
1897         }
1898
1899         return ret;
1900 }
1901
1902 #if 0
1903 static bool test_GetPrinterDriver2(struct dcerpc_pipe *p, 
1904                                    struct policy_handle *handle, 
1905                                    const char *driver_name)
1906 {
1907         NTSTATUS status;
1908         struct spoolss_GetPrinterDriver2 r;
1909         uint32_t needed;
1910         uint32_t server_major_version;
1911         uint32_t server_minor_version;
1912
1913         r.in.handle = handle;
1914         r.in.architecture = "W32X86";
1915         r.in.level = 1;
1916         r.in.buffer = NULL;
1917         r.in.offered = 0;
1918         r.in.client_major_version = 0;
1919         r.in.client_minor_version = 0;
1920         r.out.needed = &needed;
1921         r.out.server_major_version = &server_major_version;
1922         r.out.server_minor_version = &server_minor_version;
1923
1924         printf("Testing GetPrinterDriver2\n");
1925
1926         status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1927         if (!NT_STATUS_IS_OK(status)) {
1928                 printf("GetPrinterDriver2 failed - %s\n", nt_errstr(status));
1929                 return false;
1930         }
1931
1932         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1933                 r.in.offered = needed;
1934                 status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r);
1935         }
1936                 
1937         if (!NT_STATUS_IS_OK(status)) {
1938                 printf("GetPrinterDriver2 failed - %s\n", 
1939                        nt_errstr(status));
1940                 return false;
1941         }
1942
1943         if (!W_ERROR_IS_OK(r.out.result)) {
1944                 printf("GetPrinterDriver2 failed - %s\n", 
1945                        win_errstr(r.out.result));
1946                 return false;
1947         }
1948
1949         return true;
1950 }
1951 #endif
1952
1953 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx, 
1954                                         struct dcerpc_pipe *p)
1955 {
1956         struct spoolss_EnumPrinterDrivers r;
1957         NTSTATUS status;
1958         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
1959         int i;
1960
1961         for (i=0;i<ARRAY_SIZE(levels);i++) {
1962
1963                 uint32_t needed;
1964                 uint32_t count;
1965                 union spoolss_DriverInfo *info;
1966
1967                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1968                 r.in.environment = "Windows NT x86";
1969                 r.in.level = levels[i];
1970                 r.in.buffer = NULL;
1971                 r.in.offered = 0;
1972                 r.out.needed = &needed;
1973                 r.out.count = &count;
1974                 r.out.info = &info;
1975
1976                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
1977
1978                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1979
1980                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1981
1982                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1983                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1984                         data_blob_clear(&blob);
1985                         r.in.buffer = &blob;
1986                         r.in.offered = needed;
1987                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
1988                 }
1989
1990                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
1991
1992                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
1993
1994                 if (!info) {
1995                         torture_comment(tctx, "No printer drivers returned\n");
1996                         break;
1997                 }
1998         }
1999
2000         return true;
2001 }
2002
2003 bool torture_rpc_spoolss(struct torture_context *torture)
2004 {
2005         NTSTATUS status;
2006         struct dcerpc_pipe *p;
2007         bool ret = true;
2008         struct test_spoolss_context *ctx;
2009
2010         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
2011         if (!NT_STATUS_IS_OK(status)) {
2012                 return false;
2013         }
2014
2015         ctx = talloc_zero(torture, struct test_spoolss_context);
2016
2017         ret &= test_OpenPrinter_server(torture, p, ctx);
2018
2019         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
2020         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
2021         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
2022         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
2023         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
2024         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
2025         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
2026         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
2027         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
2028         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
2029         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
2030         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
2031         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
2032         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
2033         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
2034         ret &= test_EnumPorts(torture, p, ctx);
2035         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
2036         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
2037         ret &= test_EnumPrinterDrivers(torture, p, ctx);
2038         ret &= test_EnumMonitors(torture, p, ctx);
2039         ret &= test_EnumPrintProcessors(torture, p, ctx);
2040         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
2041         ret &= test_EnumPrinters(torture, p, ctx);
2042         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
2043         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
2044         ret &= test_OpenPrinter_badname(torture, p, "");
2045         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
2046         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
2047         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
2048         ret &= test_OpenPrinter_badname(torture, p, 
2049                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
2050
2051
2052         ret &= test_AddPort(torture, p);
2053         ret &= test_EnumPorts_old(torture, p);
2054         ret &= test_EnumPrinters_old(torture, p);
2055         ret &= test_EnumPrinterDrivers_old(torture, p);
2056
2057         return ret;
2058 }