1de3266f2b9837a5bd83dec4e362508902c00483
[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    Copyright (C) Guenther Deschner 2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include "torture/rpc/rpc.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_spoolss_c.h"
29 #include "param/param.h"
30
31 #define TORTURE_WELLKNOWN_PRINTER       "torture_wkn_printer"
32 #define TORTURE_PRINTER                 "torture_printer"
33 #define TORTURE_WELLKNOWN_PRINTER_EX    "torture_wkn_printer_ex"
34 #define TORTURE_PRINTER_EX              "torture_printer_ex"
35
36 struct test_spoolss_context {
37         /* print server handle */
38         struct policy_handle server_handle;
39
40         /* for EnumPorts */
41         uint32_t port_count[3];
42         union spoolss_PortInfo *ports[3];
43
44         /* for EnumPrinterDrivers */
45         uint32_t driver_count[7];
46         union spoolss_DriverInfo *drivers[7];
47
48         /* for EnumMonitors */
49         uint32_t monitor_count[3];
50         union spoolss_MonitorInfo *monitors[3];
51
52         /* for EnumPrintProcessors */
53         uint32_t print_processor_count[2];
54         union spoolss_PrintProcessorInfo *print_processors[2];
55
56         /* for EnumPrinters */
57         uint32_t printer_count[6];
58         union spoolss_PrinterInfo *printers[6];
59 };
60
61 #define COMPARE_STRING(tctx, c,r,e) \
62         torture_assert_str_equal(tctx, c.e, r.e, "invalid value")
63
64 /* not every compiler supports __typeof__() */
65 #if (__GNUC__ >= 3)
66 #define _CHECK_FIELD_SIZE(c,r,e,type) do {\
67         if (sizeof(__typeof__(c.e)) != sizeof(type)) { \
68                 torture_fail(tctx, #c "." #e "field is not " #type "\n"); \
69         }\
70         if (sizeof(__typeof__(r.e)) != sizeof(type)) { \
71                 torture_fail(tctx, #r "." #e "field is not " #type "\n"); \
72         }\
73 } while(0)
74 #else
75 #define _CHECK_FIELD_SIZE(c,r,e,type) do {} while(0)
76 #endif
77
78 #define COMPARE_UINT32(tctx, c, r, e) do {\
79         _CHECK_FIELD_SIZE(c, r, e, uint32_t); \
80         torture_assert_int_equal(tctx, c.e, r.e, "invalid value"); \
81 } while(0)
82
83 #define COMPARE_STRING_ARRAY(tctx, c,r,e)
84
85 static bool test_OpenPrinter_server(struct torture_context *tctx,
86                                     struct dcerpc_pipe *p,
87                                     struct policy_handle *server_handle)
88 {
89         NTSTATUS status;
90         struct spoolss_OpenPrinter op;
91
92         op.in.printername       = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
93         op.in.datatype          = NULL;
94         op.in.devmode_ctr.devmode= NULL;
95         op.in.access_mask       = 0;
96         op.out.handle           = server_handle;
97
98         torture_comment(tctx, "Testing OpenPrinter(%s)\n", op.in.printername);
99
100         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
101         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_OpenPrinter failed");
102         torture_assert_werr_ok(tctx, op.out.result, "dcerpc_spoolss_OpenPrinter failed");
103
104         return true;
105 }
106
107 static bool test_EnumPorts(struct torture_context *tctx,
108                            struct dcerpc_pipe *p,
109                            struct test_spoolss_context *ctx)
110 {
111         NTSTATUS status;
112         struct spoolss_EnumPorts r;
113         uint16_t levels[] = { 1, 2 };
114         int i, j;
115
116         for (i=0;i<ARRAY_SIZE(levels);i++) {
117                 int level = levels[i];
118                 DATA_BLOB blob;
119                 uint32_t needed;
120                 uint32_t count;
121                 union spoolss_PortInfo *info;
122
123                 r.in.servername = "";
124                 r.in.level = level;
125                 r.in.buffer = NULL;
126                 r.in.offered = 0;
127                 r.out.needed = &needed;
128                 r.out.count = &count;
129                 r.out.info = &info;
130
131                 torture_comment(tctx, "Testing EnumPorts level %u\n", r.in.level);
132
133                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
134                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
135                 if (W_ERROR_IS_OK(r.out.result)) {
136                         /* TODO: do some more checks here */
137                         continue;
138                 }
139                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
140                         "EnumPorts unexpected return code");
141
142                 blob = data_blob_talloc(ctx, NULL, needed);
143                 data_blob_clear(&blob);
144                 r.in.buffer = &blob;
145                 r.in.offered = needed;
146
147                 status = dcerpc_spoolss_EnumPorts(p, ctx, &r);
148                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPorts failed");
149
150                 torture_assert_werr_ok(tctx, r.out.result, "EnumPorts failed");
151
152                 torture_assert(tctx, info, "EnumPorts returned no info");
153
154                 ctx->port_count[level]  = count;
155                 ctx->ports[level]       = info;
156         }
157
158         for (i=1;i<ARRAY_SIZE(levels);i++) {
159                 int level = levels[i];
160                 int old_level = levels[i-1];
161                 torture_assert_int_equal(tctx, ctx->port_count[level], ctx->port_count[old_level],
162                         "EnumPorts invalid value");
163         }
164         /* if the array sizes are not the same we would maybe segfault in the following code */
165
166         for (i=0;i<ARRAY_SIZE(levels);i++) {
167                 int level = levels[i];
168                 for (j=0;j<ctx->port_count[level];j++) {
169                         union spoolss_PortInfo *cur = &ctx->ports[level][j];
170                         union spoolss_PortInfo *ref = &ctx->ports[2][j];
171                         switch (level) {
172                         case 1:
173                                 COMPARE_STRING(tctx, cur->info1, ref->info2, port_name);
174                                 break;
175                         case 2:
176                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
177                                 break;
178                         }
179                 }
180         }
181
182         return true;
183 }
184
185 static bool test_GetPrintProcessorDirectory(struct torture_context *tctx,
186                                             struct dcerpc_pipe *p,
187                                             struct test_spoolss_context *ctx)
188 {
189         NTSTATUS status;
190         struct spoolss_GetPrintProcessorDirectory r;
191         struct {
192                 uint16_t level;
193                 const char *server;
194         } levels[] = {{
195                         .level  = 1,
196                         .server = NULL
197                 },{
198                         .level  = 1,
199                         .server = ""
200                 },{
201                         .level  = 78,
202                         .server = ""
203                 },{
204                         .level  = 1,
205                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
206                 },{
207                         .level  = 1024,
208                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
209                 }
210         };
211         int i;
212         uint32_t needed;
213
214         for (i=0;i<ARRAY_SIZE(levels);i++) {
215                 int level = levels[i].level;
216                 DATA_BLOB blob;
217
218                 r.in.server             = levels[i].server;
219                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
220                 r.in.level              = level;
221                 r.in.buffer             = NULL;
222                 r.in.offered            = 0;
223                 r.out.needed            = &needed;
224
225                 torture_comment(tctx, "Testing GetPrintProcessorDirectory level %u\n", r.in.level);
226
227                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
228                 torture_assert_ntstatus_ok(tctx, status,
229                         "dcerpc_spoolss_GetPrintProcessorDirectory failed");
230                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
231                         "GetPrintProcessorDirectory unexpected return code");
232
233                 blob = data_blob_talloc(ctx, NULL, needed);
234                 data_blob_clear(&blob);
235                 r.in.buffer = &blob;
236                 r.in.offered = needed;
237
238                 status = dcerpc_spoolss_GetPrintProcessorDirectory(p, ctx, &r);
239                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrintProcessorDirectory failed");
240
241                 torture_assert_werr_ok(tctx, r.out.result, "GetPrintProcessorDirectory failed");
242         }
243
244         return true;
245 }
246
247
248 static bool test_GetPrinterDriverDirectory(struct torture_context *tctx,
249                                            struct dcerpc_pipe *p,
250                                            struct test_spoolss_context *ctx)
251 {
252         NTSTATUS status;
253         struct spoolss_GetPrinterDriverDirectory r;
254         struct {
255                 uint16_t level;
256                 const char *server;
257         } levels[] = {{
258                         .level  = 1,
259                         .server = NULL
260                 },{
261                         .level  = 1,
262                         .server = ""
263                 },{
264                         .level  = 78,
265                         .server = ""
266                 },{
267                         .level  = 1,
268                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
269                 },{
270                         .level  = 1024,
271                         .server = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p))
272                 }
273         };
274         int i;
275         uint32_t needed;
276
277         for (i=0;i<ARRAY_SIZE(levels);i++) {
278                 int level = levels[i].level;
279                 DATA_BLOB blob;
280
281                 r.in.server             = levels[i].server;
282                 r.in.environment        = SPOOLSS_ARCHITECTURE_NT_X86;
283                 r.in.level              = level;
284                 r.in.buffer             = NULL;
285                 r.in.offered            = 0;
286                 r.out.needed            = &needed;
287
288                 torture_comment(tctx, "Testing GetPrinterDriverDirectory level %u\n", r.in.level);
289
290                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
291                 torture_assert_ntstatus_ok(tctx, status,
292                         "dcerpc_spoolss_GetPrinterDriverDirectory failed");
293                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
294                         "GetPrinterDriverDirectory unexpected return code");
295
296                 blob = data_blob_talloc(ctx, NULL, needed);
297                 data_blob_clear(&blob);
298                 r.in.buffer = &blob;
299                 r.in.offered = needed;
300
301                 status = dcerpc_spoolss_GetPrinterDriverDirectory(p, ctx, &r);
302                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_GetPrinterDriverDirectory failed");
303
304                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterDriverDirectory failed");
305         }
306
307         return true;
308 }
309
310 static bool test_EnumPrinterDrivers(struct torture_context *tctx,
311                                     struct dcerpc_pipe *p,
312                                     struct test_spoolss_context *ctx,
313                                     const char *architecture)
314 {
315         NTSTATUS status;
316         struct spoolss_EnumPrinterDrivers r;
317         uint16_t levels[] = { 1, 2, 3, 4, 5, 6 };
318         int i, j;
319
320         for (i=0;i<ARRAY_SIZE(levels);i++) {
321                 int level = levels[i];
322                 DATA_BLOB blob;
323                 uint32_t needed;
324                 uint32_t count;
325                 union spoolss_DriverInfo *info;
326
327                 /* FIXME: gd, come back and fix "" as server, and handle
328                  * priority of returned error codes in torture test and samba 3
329                  * server */
330
331                 r.in.server             = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
332                 r.in.environment        = architecture;
333                 r.in.level              = level;
334                 r.in.buffer             = NULL;
335                 r.in.offered            = 0;
336                 r.out.needed            = &needed;
337                 r.out.count             = &count;
338                 r.out.info              = &info;
339
340                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u (%s)\n", r.in.level, r.in.environment);
341
342                 status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
343                 torture_assert_ntstatus_ok(tctx, status,
344                                            "dcerpc_spoolss_EnumPrinterDrivers failed");
345                 if (W_ERROR_IS_OK(r.out.result)) {
346                         /* TODO: do some more checks here */
347                         continue;
348                 }
349                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
350                         blob = data_blob_talloc(ctx, NULL, needed);
351                         data_blob_clear(&blob);
352                         r.in.buffer = &blob;
353                         r.in.offered = needed;
354
355                         status = dcerpc_spoolss_EnumPrinterDrivers(p, ctx, &r);
356                         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinterDrivers failed");
357                 }
358
359                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
360
361                 ctx->driver_count[level]        = count;
362                 ctx->drivers[level]             = info;
363         }
364
365         for (i=1;i<ARRAY_SIZE(levels);i++) {
366                 int level = levels[i];
367                 int old_level = levels[i-1];
368
369                 torture_assert_int_equal(tctx, ctx->driver_count[level], ctx->driver_count[old_level],
370                         "EnumPrinterDrivers invalid value");
371         }
372
373         for (i=0;i<ARRAY_SIZE(levels);i++) {
374                 int level = levels[i];
375
376                 for (j=0;j<ctx->driver_count[level];j++) {
377                         union spoolss_DriverInfo *cur = &ctx->drivers[level][j];
378                         union spoolss_DriverInfo *ref = &ctx->drivers[6][j];
379                         switch (level) {
380                         case 1:
381                                 COMPARE_STRING(tctx, cur->info1, ref->info6, driver_name);
382                                 break;
383                         case 2:
384                                 COMPARE_UINT32(tctx, cur->info2, ref->info6, version);
385                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_name);
386                                 COMPARE_STRING(tctx, cur->info2, ref->info6, architecture);
387                                 COMPARE_STRING(tctx, cur->info2, ref->info6, driver_path);
388                                 COMPARE_STRING(tctx, cur->info2, ref->info6, data_file);
389                                 COMPARE_STRING(tctx, cur->info2, ref->info6, config_file);
390                                 break;
391                         case 3:
392                                 COMPARE_UINT32(tctx, cur->info3, ref->info6, version);
393                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_name);
394                                 COMPARE_STRING(tctx, cur->info3, ref->info6, architecture);
395                                 COMPARE_STRING(tctx, cur->info3, ref->info6, driver_path);
396                                 COMPARE_STRING(tctx, cur->info3, ref->info6, data_file);
397                                 COMPARE_STRING(tctx, cur->info3, ref->info6, config_file);
398                                 COMPARE_STRING(tctx, cur->info3, ref->info6, help_file);
399                                 COMPARE_STRING_ARRAY(tctx, cur->info3, ref->info6, dependent_files);
400                                 COMPARE_STRING(tctx, cur->info3, ref->info6, monitor_name);
401                                 COMPARE_STRING(tctx, cur->info3, ref->info6, default_datatype);
402                                 break;
403                         case 4:
404                                 COMPARE_UINT32(tctx, cur->info4, ref->info6, version);
405                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_name);
406                                 COMPARE_STRING(tctx, cur->info4, ref->info6, architecture);
407                                 COMPARE_STRING(tctx, cur->info4, ref->info6, driver_path);
408                                 COMPARE_STRING(tctx, cur->info4, ref->info6, data_file);
409                                 COMPARE_STRING(tctx, cur->info4, ref->info6, config_file);
410                                 COMPARE_STRING(tctx, cur->info4, ref->info6, help_file);
411                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, dependent_files);
412                                 COMPARE_STRING(tctx, cur->info4, ref->info6, monitor_name);
413                                 COMPARE_STRING(tctx, cur->info4, ref->info6, default_datatype);
414                                 COMPARE_STRING_ARRAY(tctx, cur->info4, ref->info6, previous_names);
415                                 break;
416                         case 5:
417                                 COMPARE_UINT32(tctx, cur->info5, ref->info6, version);
418                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_name);
419                                 COMPARE_STRING(tctx, cur->info5, ref->info6, architecture);
420                                 COMPARE_STRING(tctx, cur->info5, ref->info6, driver_path);
421                                 COMPARE_STRING(tctx, cur->info5, ref->info6, data_file);
422                                 COMPARE_STRING(tctx, cur->info5, ref->info6, config_file);
423                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_attributes);*/
424                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info6, config_version);*/
425                                 /*TODO: ! COMPARE_UINT32(tctx, cur->info5, ref->info6, driver_version); */
426                                 break;
427                         case 6:
428                                 /* level 6 is our reference, and it makes no sense to compare it to itself */
429                                 break;
430                         }
431                 }
432         }
433
434         return true;
435 }
436
437 static bool test_EnumMonitors(struct torture_context *tctx,
438                               struct dcerpc_pipe *p,
439                               struct test_spoolss_context *ctx)
440 {
441         NTSTATUS status;
442         struct spoolss_EnumMonitors r;
443         uint16_t levels[] = { 1, 2 };
444         int i, j;
445
446         for (i=0;i<ARRAY_SIZE(levels);i++) {
447                 int level = levels[i];
448                 DATA_BLOB blob;
449                 uint32_t needed;
450                 uint32_t count;
451                 union spoolss_MonitorInfo *info;
452
453                 r.in.servername = "";
454                 r.in.level = level;
455                 r.in.buffer = NULL;
456                 r.in.offered = 0;
457                 r.out.needed = &needed;
458                 r.out.count = &count;
459                 r.out.info = &info;
460
461                 torture_comment(tctx, "Testing EnumMonitors level %u\n", r.in.level);
462
463                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
464                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
465                 if (W_ERROR_IS_OK(r.out.result)) {
466                         /* TODO: do some more checks here */
467                         continue;
468                 }
469                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
470                         "EnumMonitors failed");
471
472                 blob = data_blob_talloc(ctx, NULL, needed);
473                 data_blob_clear(&blob);
474                 r.in.buffer = &blob;
475                 r.in.offered = needed;
476
477                 status = dcerpc_spoolss_EnumMonitors(p, ctx, &r);
478                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumMonitors failed");
479
480                 torture_assert_werr_ok(tctx, r.out.result, "EnumMonitors failed");
481
482                 ctx->monitor_count[level]       = count;
483                 ctx->monitors[level]            = info;
484         }
485
486         for (i=1;i<ARRAY_SIZE(levels);i++) {
487                 int level = levels[i];
488                 int old_level = levels[i-1];
489                 torture_assert_int_equal(tctx, ctx->monitor_count[level], ctx->monitor_count[old_level],
490                                          "EnumMonitors invalid value");
491         }
492
493         for (i=0;i<ARRAY_SIZE(levels);i++) {
494                 int level = levels[i];
495                 for (j=0;j<ctx->monitor_count[level];j++) {
496                         union spoolss_MonitorInfo *cur = &ctx->monitors[level][j];
497                         union spoolss_MonitorInfo *ref = &ctx->monitors[2][j];
498                         switch (level) {
499                         case 1:
500                                 COMPARE_STRING(tctx, cur->info1, ref->info2, monitor_name);
501                                 break;
502                         case 2:
503                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
504                                 break;
505                         }
506                 }
507         }
508
509         return true;
510 }
511
512 static bool test_EnumPrintProcessors(struct torture_context *tctx,
513                                      struct dcerpc_pipe *p,
514                                      struct test_spoolss_context *ctx)
515 {
516         NTSTATUS status;
517         struct spoolss_EnumPrintProcessors r;
518         uint16_t levels[] = { 1 };
519         int i, j;
520
521         for (i=0;i<ARRAY_SIZE(levels);i++) {
522                 int level = levels[i];
523                 DATA_BLOB blob;
524                 uint32_t needed;
525                 uint32_t count;
526                 union spoolss_PrintProcessorInfo *info;
527
528                 r.in.servername = "";
529                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
530                 r.in.level = level;
531                 r.in.buffer = NULL;
532                 r.in.offered = 0;
533                 r.out.needed = &needed;
534                 r.out.count = &count;
535                 r.out.info = &info;
536
537                 torture_comment(tctx, "Testing EnumPrintProcessors level %u\n", r.in.level);
538
539                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
540                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
541                 if (W_ERROR_IS_OK(r.out.result)) {
542                         /* TODO: do some more checks here */
543                         continue;
544                 }
545                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
546                         "EnumPrintProcessors unexpected return code");
547
548                 blob = data_blob_talloc(ctx, NULL, needed);
549                 data_blob_clear(&blob);
550                 r.in.buffer = &blob;
551                 r.in.offered = needed;
552
553                 status = dcerpc_spoolss_EnumPrintProcessors(p, ctx, &r);
554                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcessors failed");
555
556                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcessors failed");
557
558                 ctx->print_processor_count[level]       = count;
559                 ctx->print_processors[level]            = info;
560         }
561
562         for (i=1;i<ARRAY_SIZE(levels);i++) {
563                 int level = levels[i];
564                 int old_level = levels[i-1];
565                 torture_assert_int_equal(tctx, ctx->print_processor_count[level], ctx->print_processor_count[old_level],
566                         "EnumPrintProcessors failed");
567         }
568
569         for (i=0;i<ARRAY_SIZE(levels);i++) {
570                 int level = levels[i];
571                 for (j=0;j<ctx->print_processor_count[level];j++) {
572 #if 0
573                         union spoolss_PrintProcessorInfo *cur = &ctx->print_processors[level][j];
574                         union spoolss_PrintProcessorInfo *ref = &ctx->print_processors[1][j];
575 #endif
576                         switch (level) {
577                         case 1:
578                                 /* level 1 is our reference, and it makes no sense to compare it to itself */
579                                 break;
580                         }
581                 }
582         }
583
584         return true;
585 }
586
587 static bool test_EnumPrintProcDataTypes(struct torture_context *tctx,
588                                         struct dcerpc_pipe *p,
589                                         struct test_spoolss_context *ctx)
590 {
591         NTSTATUS status;
592         struct spoolss_EnumPrintProcDataTypes r;
593         uint16_t levels[] = { 1 };
594         int i;
595
596         for (i=0;i<ARRAY_SIZE(levels);i++) {
597                 int level = levels[i];
598                 DATA_BLOB blob;
599                 uint32_t needed;
600                 uint32_t count;
601                 union spoolss_PrintProcDataTypesInfo *info;
602
603                 r.in.servername = "";
604                 r.in.print_processor_name = "winprint";
605                 r.in.level = level;
606                 r.in.buffer = NULL;
607                 r.in.offered = 0;
608                 r.out.needed = &needed;
609                 r.out.count = &count;
610                 r.out.info = &info;
611
612                 torture_comment(tctx, "Testing EnumPrintProcDataTypes level %u\n", r.in.level);
613
614                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
615                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataType failed");
616                 if (W_ERROR_IS_OK(r.out.result)) {
617                         /* TODO: do some more checks here */
618                         continue;
619                 }
620                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
621                         "EnumPrintProcDataTypes unexpected return code");
622
623                 blob = data_blob_talloc(ctx, NULL, needed);
624                 data_blob_clear(&blob);
625                 r.in.buffer = &blob;
626                 r.in.offered = needed;
627
628                 status = dcerpc_spoolss_EnumPrintProcDataTypes(p, ctx, &r);
629                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrintProcDataTypes failed");
630
631                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrintProcDataTypes failed");
632         }
633
634         return true;
635 }
636
637
638 static bool test_EnumPrinters(struct torture_context *tctx,
639                               struct dcerpc_pipe *p,
640                               struct test_spoolss_context *ctx)
641 {
642         struct spoolss_EnumPrinters r;
643         NTSTATUS status;
644         uint16_t levels[] = { 0, 1, 2, 4, 5 };
645         int i, j;
646
647         for (i=0;i<ARRAY_SIZE(levels);i++) {
648                 int level = levels[i];
649                 DATA_BLOB blob;
650                 uint32_t needed;
651                 uint32_t count;
652                 union spoolss_PrinterInfo *info;
653
654                 r.in.flags      = PRINTER_ENUM_LOCAL;
655                 r.in.server     = "";
656                 r.in.level      = level;
657                 r.in.buffer     = NULL;
658                 r.in.offered    = 0;
659                 r.out.needed    = &needed;
660                 r.out.count     = &count;
661                 r.out.info      = &info;
662
663                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
664
665                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
666                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
667                 if (W_ERROR_IS_OK(r.out.result)) {
668                         /* TODO: do some more checks here */
669                         continue;
670                 }
671                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
672                         "EnumPrinters unexpected return code");
673
674                 blob = data_blob_talloc(ctx, NULL, needed);
675                 data_blob_clear(&blob);
676                 r.in.buffer = &blob;
677                 r.in.offered = needed;
678
679                 status = dcerpc_spoolss_EnumPrinters(p, ctx, &r);
680                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EnumPrinters failed");
681
682                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
683
684                 ctx->printer_count[level]       = count;
685                 ctx->printers[level]            = info;
686         }
687
688         for (i=1;i<ARRAY_SIZE(levels);i++) {
689                 int level = levels[i];
690                 int old_level = levels[i-1];
691                 torture_assert_int_equal(tctx, ctx->printer_count[level], ctx->printer_count[old_level],
692                                          "EnumPrinters invalid value");
693         }
694
695         for (i=0;i<ARRAY_SIZE(levels);i++) {
696                 int level = levels[i];
697                 for (j=0;j<ctx->printer_count[level];j++) {
698                         union spoolss_PrinterInfo *cur = &ctx->printers[level][j];
699                         union spoolss_PrinterInfo *ref = &ctx->printers[2][j];
700                         switch (level) {
701                         case 0:
702                                 COMPARE_STRING(tctx, cur->info0, ref->info2, printername);
703                                 COMPARE_STRING(tctx, cur->info0, ref->info2, servername);
704                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, cjobs);
705                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, total_jobs);
706                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_bytes);
707                                 COMPARE_SPOOLSS_TIME(cur->info0, ref->info2, spoolss_Time time);
708                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, global_counter);
709                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, total_pages);
710                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, version);
711                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown10);
712                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown11);
713                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown12);
714                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, session_counter);
715                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown14);
716                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, printer_errors);
717                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown16);
718                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown17);
719                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown18);
720                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown19);
721                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, change_id);
722                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown21);*/
723                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, status);
724                                 /*COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown23);
725                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, c_setprinter);
726                                 COMPARE_UINT16(cur->info0, ref->info2, unknown25);
727                                 COMPARE_UINT16(cur->info0, ref->info2, unknown26);
728                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown27);
729                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown28);
730                                 COMPARE_UINT32(tctx, cur->info0, ref->info2, unknown29);*/
731                                 break;
732                         case 1:
733                                 /*COMPARE_UINT32(tctx, cur->info1, ref->info2, flags);*/
734                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, name);*/
735                                 /*COMPARE_STRING(tctx, cur->info1, ref->info2, description);*/
736                                 COMPARE_STRING(tctx, cur->info1, ref->info2, comment);
737                                 break;
738                         case 2:
739                                 /* level 2 is our reference, and it makes no sense to compare it to itself */
740                                 break;
741                         case 4:
742                                 COMPARE_STRING(tctx, cur->info4, ref->info2, printername);
743                                 COMPARE_STRING(tctx, cur->info4, ref->info2, servername);
744                                 COMPARE_UINT32(tctx, cur->info4, ref->info2, attributes);
745                                 break;
746                         case 5:
747                                 COMPARE_STRING(tctx, cur->info5, ref->info2, printername);
748                                 COMPARE_STRING(tctx, cur->info5, ref->info2, portname);
749                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, attributes);
750                                 /*COMPARE_UINT32(tctx, cur->info5, ref->info2, device_not_selected_timeout);
751                                 COMPARE_UINT32(tctx, cur->info5, ref->info2, transmission_retry_timeout);*/
752                                 break;
753                         }
754                 }
755         }
756
757         /* TODO:
758          *      - verify that the port of a printer was in the list returned by EnumPorts
759          */
760
761         return true;
762 }
763
764 static bool test_GetPrinter(struct torture_context *tctx,
765                             struct dcerpc_pipe *p,
766                      struct policy_handle *handle)
767 {
768         NTSTATUS status;
769         struct spoolss_GetPrinter r;
770         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
771         int i;
772         uint32_t needed;
773
774         for (i=0;i<ARRAY_SIZE(levels);i++) {
775                 r.in.handle = handle;
776                 r.in.level = levels[i];
777                 r.in.buffer = NULL;
778                 r.in.offered = 0;
779                 r.out.needed = &needed;
780
781                 torture_comment(tctx, "Testing GetPrinter level %u\n", r.in.level);
782
783                 status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
784                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
785
786                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
787                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
788                         data_blob_clear(&blob);
789                         r.in.buffer = &blob;
790                         r.in.offered = needed;
791                         status = dcerpc_spoolss_GetPrinter(p, tctx, &r);
792                 }
793
794                 torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
795
796                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinter failed");
797         }
798
799         return true;
800 }
801
802 static bool test_SetPrinter_errors(struct torture_context *tctx,
803                                    struct dcerpc_pipe *p,
804                                    struct policy_handle *handle)
805 {
806         struct spoolss_SetPrinter r;
807         uint16_t levels[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
808         int i;
809
810         struct spoolss_SetPrinterInfoCtr info_ctr;
811         struct spoolss_DevmodeContainer devmode_ctr;
812         struct sec_desc_buf secdesc_ctr;
813
814         info_ctr.level = 0;
815         info_ctr.info.info0 = NULL;
816
817         ZERO_STRUCT(devmode_ctr);
818         ZERO_STRUCT(secdesc_ctr);
819
820         r.in.handle = handle;
821         r.in.info_ctr = &info_ctr;
822         r.in.devmode_ctr = &devmode_ctr;
823         r.in.secdesc_ctr = &secdesc_ctr;
824         r.in.command = 0;
825
826         torture_comment(tctx, "Testing SetPrinter all zero\n");
827
828         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
829                 "failed to call SetPrinter");
830         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
831                 "failed to call SetPrinter");
832
833  again:
834         for (i=0; i < ARRAY_SIZE(levels); i++) {
835
836                 struct spoolss_SetPrinterInfo0 info0;
837                 struct spoolss_SetPrinterInfo1 info1;
838                 struct spoolss_SetPrinterInfo2 info2;
839                 struct spoolss_SetPrinterInfo3 info3;
840                 struct spoolss_SetPrinterInfo4 info4;
841                 struct spoolss_SetPrinterInfo5 info5;
842                 struct spoolss_SetPrinterInfo6 info6;
843                 struct spoolss_SetPrinterInfo7 info7;
844                 struct spoolss_DeviceModeInfo info8;
845                 struct spoolss_DeviceModeInfo info9;
846
847
848                 info_ctr.level = levels[i];
849                 switch (levels[i]) {
850                 case 0:
851                         ZERO_STRUCT(info0);
852                         info_ctr.info.info0 = &info0;
853                         break;
854                 case 1:
855                         ZERO_STRUCT(info1);
856                         info_ctr.info.info1 = &info1;
857                         break;
858                 case 2:
859                         ZERO_STRUCT(info2);
860                         info_ctr.info.info2 = &info2;
861                         break;
862                 case 3:
863                         ZERO_STRUCT(info3);
864                         info_ctr.info.info3 = &info3;
865                         break;
866                 case 4:
867                         ZERO_STRUCT(info4);
868                         info_ctr.info.info4 = &info4;
869                         break;
870                 case 5:
871                         ZERO_STRUCT(info5);
872                         info_ctr.info.info5 = &info5;
873                         break;
874                 case 6:
875                         ZERO_STRUCT(info6);
876                         info_ctr.info.info6 = &info6;
877                         break;
878                 case 7:
879                         ZERO_STRUCT(info7);
880                         info_ctr.info.info7 = &info7;
881                         break;
882                 case 8:
883                         ZERO_STRUCT(info8);
884                         info_ctr.info.info8 = &info8;
885                         break;
886                 case 9:
887                         ZERO_STRUCT(info9);
888                         info_ctr.info.info9 = &info9;
889                         break;
890                 }
891
892                 torture_comment(tctx, "Testing SetPrinter level %d, command %d\n",
893                         info_ctr.level, r.in.command);
894
895                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_SetPrinter(p, tctx, &r),
896                         "failed to call SetPrinter");
897
898                 switch (r.in.command) {
899                 case SPOOLSS_PRINTER_CONTROL_UNPAUSE: /* 0 */
900                         /* is ignored for all levels other then 0 */
901                         if (info_ctr.level > 0) {
902                                 /* ignored then */
903                                 break;
904                         }
905                 case SPOOLSS_PRINTER_CONTROL_PAUSE: /* 1 */
906                 case SPOOLSS_PRINTER_CONTROL_RESUME: /* 2 */
907                 case SPOOLSS_PRINTER_CONTROL_PURGE: /* 3 */
908                         if (info_ctr.level > 0) {
909                                 /* is invalid for all levels other then 0 */
910                                 torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
911                                         "unexpected error code returned");
912                                 continue;
913                         } else {
914                                 torture_assert_werr_ok(tctx, r.out.result,
915                                         "failed to call SetPrinter with non 0 command");
916                                 continue;
917                         }
918                         break;
919
920                 case SPOOLSS_PRINTER_CONTROL_SET_STATUS: /* 4 */
921                         /* FIXME: gd needs further investigation */
922                 default:
923                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PRINTER_COMMAND,
924                                 "unexpected error code returned");
925                         continue;
926                 }
927
928                 switch (info_ctr.level) {
929                 case 1:
930                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL,
931                                 "unexpected error code returned");
932                         break;
933                 case 2:
934                         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_PRINTER_DRIVER,
935                                 "unexpected error code returned");
936                         break;
937                 case 3:
938                 case 4:
939                 case 5:
940                 case 7:
941                         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM,
942                                 "unexpected error code returned");
943                         break;
944                 case 9:
945                         torture_assert_werr_equal(tctx, r.out.result, WERR_NOT_SUPPORTED,
946                                 "unexpected error code returned");
947                         break;
948                 default:
949                         torture_assert_werr_ok(tctx, r.out.result,
950                                 "failed to call SetPrinter");
951                         break;
952                 }
953         }
954
955         if (r.in.command < 5) {
956                 r.in.command++;
957                 goto again;
958         }
959
960         return true;
961 }
962
963 static void clear_info2(struct spoolss_SetPrinterInfoCtr *r)
964 {
965         if ((r->level == 2) && (r->info.info2)) {
966                 r->info.info2->secdesc = NULL;
967                 r->info.info2->devmode = NULL;
968         }
969 }
970
971 static bool test_PrinterInfo(struct torture_context *tctx,
972                              struct dcerpc_pipe *p,
973                              struct policy_handle *handle)
974 {
975         NTSTATUS status;
976         struct spoolss_SetPrinter s;
977         struct spoolss_GetPrinter q;
978         struct spoolss_GetPrinter q0;
979         struct spoolss_SetPrinterInfoCtr info_ctr;
980         union spoolss_PrinterInfo info;
981         struct spoolss_DevmodeContainer devmode_ctr;
982         struct sec_desc_buf secdesc_ctr;
983         uint32_t needed;
984         bool ret = true;
985         int i;
986
987         uint32_t status_list[] = {
988                 /* these do not stick
989                 PRINTER_STATUS_PAUSED,
990                 PRINTER_STATUS_ERROR,
991                 PRINTER_STATUS_PENDING_DELETION, */
992                 PRINTER_STATUS_PAPER_JAM,
993                 PRINTER_STATUS_PAPER_OUT,
994                 PRINTER_STATUS_MANUAL_FEED,
995                 PRINTER_STATUS_PAPER_PROBLEM,
996                 PRINTER_STATUS_OFFLINE,
997                 PRINTER_STATUS_IO_ACTIVE,
998                 PRINTER_STATUS_BUSY,
999                 PRINTER_STATUS_PRINTING,
1000                 PRINTER_STATUS_OUTPUT_BIN_FULL,
1001                 PRINTER_STATUS_NOT_AVAILABLE,
1002                 PRINTER_STATUS_WAITING,
1003                 PRINTER_STATUS_PROCESSING,
1004                 PRINTER_STATUS_INITIALIZING,
1005                 PRINTER_STATUS_WARMING_UP,
1006                 PRINTER_STATUS_TONER_LOW,
1007                 PRINTER_STATUS_NO_TONER,
1008                 PRINTER_STATUS_PAGE_PUNT,
1009                 PRINTER_STATUS_USER_INTERVENTION,
1010                 PRINTER_STATUS_OUT_OF_MEMORY,
1011                 PRINTER_STATUS_DOOR_OPEN,
1012                 PRINTER_STATUS_SERVER_UNKNOWN,
1013                 PRINTER_STATUS_POWER_SAVE,
1014                 /* these do not stick
1015                 0x02000000,
1016                 0x04000000,
1017                 0x08000000,
1018                 0x10000000,
1019                 0x20000000,
1020                 0x40000000,
1021                 0x80000000 */
1022         };
1023         uint32_t default_attribute = PRINTER_ATTRIBUTE_LOCAL;
1024         uint32_t attribute_list[] = {
1025                 PRINTER_ATTRIBUTE_QUEUED,
1026                 /* fails with WERR_INVALID_DATATYPE:
1027                 PRINTER_ATTRIBUTE_DIRECT, */
1028                 /* does not stick
1029                 PRINTER_ATTRIBUTE_DEFAULT, */
1030                 PRINTER_ATTRIBUTE_SHARED,
1031                 /* does not stick
1032                 PRINTER_ATTRIBUTE_NETWORK, */
1033                 PRINTER_ATTRIBUTE_HIDDEN,
1034                 PRINTER_ATTRIBUTE_LOCAL,
1035                 PRINTER_ATTRIBUTE_ENABLE_DEVQ,
1036                 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS,
1037                 PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST,
1038                 PRINTER_ATTRIBUTE_WORK_OFFLINE,
1039                 /* does not stick
1040                 PRINTER_ATTRIBUTE_ENABLE_BIDI, */
1041                 /* fails with WERR_INVALID_DATATYPE:
1042                 PRINTER_ATTRIBUTE_RAW_ONLY, */
1043                 /* these do not stick
1044                 PRINTER_ATTRIBUTE_PUBLISHED,
1045                 PRINTER_ATTRIBUTE_FAX,
1046                 PRINTER_ATTRIBUTE_TS,
1047                 0x00010000,
1048                 0x00020000,
1049                 0x00040000,
1050                 0x00080000,
1051                 0x00100000,
1052                 0x00200000,
1053                 0x00400000,
1054                 0x00800000,
1055                 0x01000000,
1056                 0x02000000,
1057                 0x04000000,
1058                 0x08000000,
1059                 0x10000000,
1060                 0x20000000,
1061                 0x40000000,
1062                 0x80000000 */
1063         };
1064
1065         ZERO_STRUCT(devmode_ctr);
1066         ZERO_STRUCT(secdesc_ctr);
1067
1068         s.in.handle = handle;
1069         s.in.command = 0;
1070         s.in.info_ctr = &info_ctr;
1071         s.in.devmode_ctr = &devmode_ctr;
1072         s.in.secdesc_ctr = &secdesc_ctr;
1073
1074         q.in.handle = handle;
1075         q.out.info = &info;
1076         q0 = q;
1077
1078 #define TESTGETCALL(call, r) \
1079                 r.in.buffer = NULL; \
1080                 r.in.offered = 0;\
1081                 r.out.needed = &needed; \
1082                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1083                 if (!NT_STATUS_IS_OK(status)) { \
1084                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1085                                r.in.level, nt_errstr(status), __location__); \
1086                         ret = false; \
1087                         break; \
1088                 }\
1089                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {\
1090                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed); \
1091                         data_blob_clear(&blob); \
1092                         r.in.buffer = &blob; \
1093                         r.in.offered = needed; \
1094                 }\
1095                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1096                 if (!NT_STATUS_IS_OK(status)) { \
1097                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1098                                r.in.level, nt_errstr(status), __location__); \
1099                         ret = false; \
1100                         break; \
1101                 } \
1102                 if (!W_ERROR_IS_OK(r.out.result)) { \
1103                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1104                                r.in.level, win_errstr(r.out.result), __location__); \
1105                         ret = false; \
1106                         break; \
1107                 }
1108
1109
1110 #define TESTSETCALL_EXP(call, r, err) \
1111                 clear_info2(&info_ctr);\
1112                 status = dcerpc_spoolss_ ##call(p, tctx, &r); \
1113                 if (!NT_STATUS_IS_OK(status)) { \
1114                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1115                                r.in.info_ctr->level, nt_errstr(status), __location__); \
1116                         ret = false; \
1117                         break; \
1118                 } \
1119                 if (!W_ERROR_IS_OK(err)) { \
1120                         if (!W_ERROR_EQUAL(err, r.out.result)) { \
1121                                 torture_comment(tctx, #call " level %u failed - %s, expected %s (%s)\n", \
1122                                        r.in.info_ctr->level, win_errstr(r.out.result), win_errstr(err), __location__); \
1123                                 ret = false; \
1124                         } \
1125                         break; \
1126                 } \
1127                 if (!W_ERROR_IS_OK(r.out.result)) { \
1128                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
1129                                r.in.info_ctr->level, win_errstr(r.out.result), __location__); \
1130                         ret = false; \
1131                         break; \
1132                 }
1133
1134 #define TESTSETCALL(call, r) \
1135         TESTSETCALL_EXP(call, r, WERR_OK)
1136
1137 #define STRING_EQUAL(s1, s2, field) \
1138                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
1139                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1140                                #field, s2, __location__); \
1141                         ret = false; \
1142                         break; \
1143                 }
1144
1145 #define MEM_EQUAL(s1, s2, length, field) \
1146                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
1147                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
1148                                #field, (const char *)s2, __location__); \
1149                         ret = false; \
1150                         break; \
1151                 }
1152
1153 #define INT_EQUAL(i1, i2, field) \
1154                 if (i1 != i2) { \
1155                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
1156                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
1157                         ret = false; \
1158                         break; \
1159                 }
1160
1161 #define TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, err) do { \
1162                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1163                 q.in.level = lvl1; \
1164                 TESTGETCALL(GetPrinter, q) \
1165                 info_ctr.level = lvl1; \
1166                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1167                 info_ctr.info.info ## lvl1->field1 = value;\
1168                 TESTSETCALL_EXP(SetPrinter, s, err) \
1169                 info_ctr.info.info ## lvl1->field1 = ""; \
1170                 TESTGETCALL(GetPrinter, q) \
1171                 info_ctr.info.info ## lvl1->field1 = value; \
1172                 STRING_EQUAL(info_ctr.info.info ## lvl1->field1, value, field1); \
1173                 q.in.level = lvl2; \
1174                 TESTGETCALL(GetPrinter, q) \
1175                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1176                 STRING_EQUAL(info_ctr.info.info ## lvl2->field2, value, field2); \
1177         } while (0)
1178
1179 #define TEST_PRINTERINFO_STRING(lvl1, field1, lvl2, field2, value) do { \
1180         TEST_PRINTERINFO_STRING_EXP_ERR(lvl1, field1, lvl2, field2, value, WERR_OK); \
1181         } while (0);
1182
1183 #define TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value) do { \
1184                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
1185                 q.in.level = lvl1; \
1186                 TESTGETCALL(GetPrinter, q) \
1187                 info_ctr.level = lvl1; \
1188                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1189                 info_ctr.info.info ## lvl1->field1 = value; \
1190                 TESTSETCALL(SetPrinter, s) \
1191                 info_ctr.info.info ## lvl1->field1 = 0; \
1192                 TESTGETCALL(GetPrinter, q) \
1193                 info_ctr.info.info ## lvl1 = (struct spoolss_SetPrinterInfo ## lvl1 *)&q.out.info->info ## lvl1; \
1194                 INT_EQUAL(info_ctr.info.info ## lvl1->field1, exp_value, field1); \
1195                 q.in.level = lvl2; \
1196                 TESTGETCALL(GetPrinter, q) \
1197                 info_ctr.info.info ## lvl2 = (struct spoolss_SetPrinterInfo ## lvl2 *)&q.out.info->info ## lvl2; \
1198                 INT_EQUAL(info_ctr.info.info ## lvl2->field2, exp_value, field1); \
1199         } while (0)
1200
1201 #define TEST_PRINTERINFO_INT(lvl1, field1, lvl2, field2, value) do { \
1202         TEST_PRINTERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value); \
1203         } while (0)
1204
1205         q0.in.level = 0;
1206         do { TESTGETCALL(GetPrinter, q0) } while (0);
1207
1208         TEST_PRINTERINFO_STRING(2, comment,  1, comment, "xx2-1 comment");
1209         TEST_PRINTERINFO_STRING(2, comment,  2, comment, "xx2-2 comment");
1210
1211         /* level 0 printername does not stick */
1212 /*      TEST_PRINTERINFO_STRING(2, printername,  0, printername, "xx2-0 printer"); */
1213         TEST_PRINTERINFO_STRING(2, printername,  1, name,        "xx2-1 printer");
1214         TEST_PRINTERINFO_STRING(2, printername,  2, printername, "xx2-2 printer");
1215         TEST_PRINTERINFO_STRING(2, printername,  4, printername, "xx2-4 printer");
1216         TEST_PRINTERINFO_STRING(2, printername,  5, printername, "xx2-5 printer");
1217 /*      TEST_PRINTERINFO_STRING(4, printername,  0, printername, "xx4-0 printer"); */
1218         TEST_PRINTERINFO_STRING(4, printername,  1, name,        "xx4-1 printer");
1219         TEST_PRINTERINFO_STRING(4, printername,  2, printername, "xx4-2 printer");
1220         TEST_PRINTERINFO_STRING(4, printername,  4, printername, "xx4-4 printer");
1221         TEST_PRINTERINFO_STRING(4, printername,  5, printername, "xx4-5 printer");
1222 /*      TEST_PRINTERINFO_STRING(5, printername,  0, printername, "xx5-0 printer"); */
1223         TEST_PRINTERINFO_STRING(5, printername,  1, name,        "xx5-1 printer");
1224         TEST_PRINTERINFO_STRING(5, printername,  2, printername, "xx5-2 printer");
1225         TEST_PRINTERINFO_STRING(5, printername,  4, printername, "xx5-4 printer");
1226         TEST_PRINTERINFO_STRING(5, printername,  5, printername, "xx5-5 printer");
1227
1228         /* servername can be set but does not stick
1229         TEST_PRINTERINFO_STRING(2, servername,  0, servername, "xx2-0 servername");
1230         TEST_PRINTERINFO_STRING(2, servername,  2, servername, "xx2-2 servername");
1231         TEST_PRINTERINFO_STRING(2, servername,  4, servername, "xx2-4 servername");
1232         */
1233
1234         /* passing an invalid port will result in WERR_UNKNOWN_PORT */
1235         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  2, portname, "xx2-2 portname", WERR_UNKNOWN_PORT);
1236         TEST_PRINTERINFO_STRING_EXP_ERR(2, portname,  5, portname, "xx2-5 portname", WERR_UNKNOWN_PORT);
1237         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  2, portname, "xx5-2 portname", WERR_UNKNOWN_PORT);
1238         TEST_PRINTERINFO_STRING_EXP_ERR(5, portname,  5, portname, "xx5-5 portname", WERR_UNKNOWN_PORT);
1239
1240         TEST_PRINTERINFO_STRING(2, sharename,   2, sharename,   "xx2-2 sharename");
1241         /* passing an invalid driver will result in WERR_UNKNOWN_PRINTER_DRIVER */
1242         TEST_PRINTERINFO_STRING_EXP_ERR(2, drivername,  2, drivername,  "xx2-2 drivername", WERR_UNKNOWN_PRINTER_DRIVER);
1243         TEST_PRINTERINFO_STRING(2, location,    2, location,    "xx2-2 location");
1244         /* passing an invalid sepfile will result in WERR_INVALID_SEPARATOR_FILE */
1245         TEST_PRINTERINFO_STRING_EXP_ERR(2, sepfile,     2, sepfile,     "xx2-2 sepfile", WERR_INVALID_SEPARATOR_FILE);
1246         /* passing an invalid printprocessor will result in WERR_UNKNOWN_PRINTPROCESSOR */
1247         TEST_PRINTERINFO_STRING_EXP_ERR(2, printprocessor, 2, printprocessor, "xx2-2 printprocessor", WERR_UNKNOWN_PRINTPROCESSOR);
1248         TEST_PRINTERINFO_STRING(2, datatype,    2, datatype,    "xx2-2 datatype");
1249         TEST_PRINTERINFO_STRING(2, parameters,  2, parameters,  "xx2-2 parameters");
1250
1251         for (i=0; i < ARRAY_SIZE(attribute_list); i++) {
1252 /*              TEST_PRINTERINFO_INT_EXP(2, attributes, 1, flags,
1253                         attribute_list[i],
1254                         (attribute_list[i] | default_attribute)
1255                         ); */
1256                 TEST_PRINTERINFO_INT_EXP(2, attributes, 2, attributes,
1257                         attribute_list[i],
1258                         (attribute_list[i] | default_attribute)
1259                         );
1260                 TEST_PRINTERINFO_INT_EXP(2, attributes, 4, attributes,
1261                         attribute_list[i],
1262                         (attribute_list[i] | default_attribute)
1263                         );
1264                 TEST_PRINTERINFO_INT_EXP(2, attributes, 5, attributes,
1265                         attribute_list[i],
1266                         (attribute_list[i] | default_attribute)
1267                         );
1268 /*              TEST_PRINTERINFO_INT_EXP(4, attributes, 1, flags,
1269                         attribute_list[i],
1270                         (attribute_list[i] | default_attribute)
1271                         ); */
1272                 TEST_PRINTERINFO_INT_EXP(4, attributes, 2, attributes,
1273                         attribute_list[i],
1274                         (attribute_list[i] | default_attribute)
1275                         );
1276                 TEST_PRINTERINFO_INT_EXP(4, attributes, 4, attributes,
1277                         attribute_list[i],
1278                         (attribute_list[i] | default_attribute)
1279                         );
1280                 TEST_PRINTERINFO_INT_EXP(4, attributes, 5, attributes,
1281                         attribute_list[i],
1282                         (attribute_list[i] | default_attribute)
1283                         );
1284 /*              TEST_PRINTERINFO_INT_EXP(5, attributes, 1, flags,
1285                         attribute_list[i],
1286                         (attribute_list[i] | default_attribute)
1287                         ); */
1288                 TEST_PRINTERINFO_INT_EXP(5, attributes, 2, attributes,
1289                         attribute_list[i],
1290                         (attribute_list[i] | default_attribute)
1291                         );
1292                 TEST_PRINTERINFO_INT_EXP(5, attributes, 4, attributes,
1293                         attribute_list[i],
1294                         (attribute_list[i] | default_attribute)
1295                         );
1296                 TEST_PRINTERINFO_INT_EXP(5, attributes, 5, attributes,
1297                         attribute_list[i],
1298                         (attribute_list[i] | default_attribute)
1299                         );
1300         }
1301
1302         for (i=0; i < ARRAY_SIZE(status_list); i++) {
1303                 /* level 2 sets do not stick
1304                 TEST_PRINTERINFO_INT(2, status, 0, status, status_list[i]);
1305                 TEST_PRINTERINFO_INT(2, status, 2, status, status_list[i]);
1306                 TEST_PRINTERINFO_INT(2, status, 6, status, status_list[i]); */
1307                 TEST_PRINTERINFO_INT(6, status, 0, status, status_list[i]);
1308                 TEST_PRINTERINFO_INT(6, status, 2, status, status_list[i]);
1309                 TEST_PRINTERINFO_INT(6, status, 6, status, status_list[i]);
1310         }
1311
1312         /* priorities need to be between 0 and 99
1313            passing an invalid priority will result in WERR_INVALID_PRIORITY */
1314         TEST_PRINTERINFO_INT(2, priority,       2, priority, 0);
1315         TEST_PRINTERINFO_INT(2, priority,       2, priority, 1);
1316         TEST_PRINTERINFO_INT(2, priority,       2, priority, 99);
1317         /* TEST_PRINTERINFO_INT(2, priority,    2, priority, 100); */
1318         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 0);
1319         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 1);
1320         TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 99);
1321         /* TEST_PRINTERINFO_INT(2, defaultpriority,2, defaultpriority, 100); */
1322
1323         TEST_PRINTERINFO_INT(2, starttime,      2, starttime, __LINE__);
1324         TEST_PRINTERINFO_INT(2, untiltime,      2, untiltime, __LINE__);
1325
1326         /* does not stick
1327         TEST_PRINTERINFO_INT(2, cjobs,          2, cjobs, __LINE__);
1328         TEST_PRINTERINFO_INT(2, averageppm,     2, averageppm, __LINE__); */
1329
1330         /* does not stick
1331         TEST_PRINTERINFO_INT(5, device_not_selected_timeout, 5, device_not_selected_timeout, __LINE__);
1332         TEST_PRINTERINFO_INT(5, transmission_retry_timeout, 5, transmission_retry_timeout, __LINE__); */
1333
1334         /* FIXME: gd also test devmode and secdesc behavior */
1335
1336         {
1337                 /* verify composition of level 1 description field */
1338                 const char *description;
1339                 const char *tmp;
1340
1341                 q0.in.level = 1;
1342                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1343
1344                 description = talloc_strdup(tctx, q0.out.info->info1.description);
1345
1346                 q0.in.level = 2;
1347                 do { TESTGETCALL(GetPrinter, q0) } while (0);
1348
1349                 tmp = talloc_asprintf(tctx, "%s,%s,%s",
1350                         q0.out.info->info2.printername,
1351                         q0.out.info->info2.drivername,
1352                         q0.out.info->info2.location);
1353
1354                 do { STRING_EQUAL(description, tmp, "description")} while (0);
1355         }
1356
1357         return ret;
1358 }
1359
1360
1361 static bool test_ClosePrinter(struct torture_context *tctx,
1362                               struct dcerpc_pipe *p,
1363                               struct policy_handle *handle)
1364 {
1365         NTSTATUS status;
1366         struct spoolss_ClosePrinter r;
1367
1368         r.in.handle = handle;
1369         r.out.handle = handle;
1370
1371         torture_comment(tctx, "Testing ClosePrinter\n");
1372
1373         status = dcerpc_spoolss_ClosePrinter(p, tctx, &r);
1374         torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
1375
1376         return true;
1377 }
1378
1379 static bool test_GetForm(struct torture_context *tctx,
1380                          struct dcerpc_pipe *p,
1381                          struct policy_handle *handle,
1382                          const char *form_name,
1383                          uint32_t level)
1384 {
1385         NTSTATUS status;
1386         struct spoolss_GetForm r;
1387         uint32_t needed;
1388
1389         r.in.handle = handle;
1390         r.in.form_name = form_name;
1391         r.in.level = level;
1392         r.in.buffer = NULL;
1393         r.in.offered = 0;
1394         r.out.needed = &needed;
1395
1396         torture_comment(tctx, "Testing GetForm level %d\n", r.in.level);
1397
1398         status = dcerpc_spoolss_GetForm(p, tctx, &r);
1399         torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1400
1401         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1402                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1403                 data_blob_clear(&blob);
1404                 r.in.buffer = &blob;
1405                 r.in.offered = needed;
1406                 status = dcerpc_spoolss_GetForm(p, tctx, &r);
1407                 torture_assert_ntstatus_ok(tctx, status, "GetForm failed");
1408
1409                 torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1410
1411                 torture_assert(tctx, r.out.info, "No form info returned");
1412         }
1413
1414         torture_assert_werr_ok(tctx, r.out.result, "GetForm failed");
1415
1416         return true;
1417 }
1418
1419 static bool test_EnumForms(struct torture_context *tctx,
1420                            struct dcerpc_pipe *p,
1421                            struct policy_handle *handle, bool print_server)
1422 {
1423         NTSTATUS status;
1424         struct spoolss_EnumForms r;
1425         bool ret = true;
1426         uint32_t needed;
1427         uint32_t count;
1428         uint32_t levels[] = { 1, 2 };
1429         int i;
1430
1431         for (i=0; i<ARRAY_SIZE(levels); i++) {
1432
1433                 union spoolss_FormInfo *info;
1434
1435                 r.in.handle = handle;
1436                 r.in.level = levels[i];
1437                 r.in.buffer = NULL;
1438                 r.in.offered = 0;
1439                 r.out.needed = &needed;
1440                 r.out.count = &count;
1441                 r.out.info = &info;
1442
1443                 torture_comment(tctx, "Testing EnumForms level %d\n", levels[i]);
1444
1445                 status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1446                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1447
1448                 if ((r.in.level == 2) && (W_ERROR_EQUAL(r.out.result, WERR_UNKNOWN_LEVEL))) {
1449                         break;
1450                 }
1451
1452                 if (print_server && W_ERROR_EQUAL(r.out.result, WERR_BADFID))
1453                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1454
1455                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1456                         int j;
1457                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1458                         data_blob_clear(&blob);
1459                         r.in.buffer = &blob;
1460                         r.in.offered = needed;
1461
1462                         status = dcerpc_spoolss_EnumForms(p, tctx, &r);
1463
1464                         torture_assert(tctx, info, "No forms returned");
1465
1466                         for (j = 0; j < count; j++) {
1467                                 if (!print_server)
1468                                         ret &= test_GetForm(tctx, p, handle, info[j].info1.form_name, levels[i]);
1469                         }
1470                 }
1471
1472                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1473
1474                 torture_assert_werr_ok(tctx, r.out.result, "EnumForms failed");
1475         }
1476
1477         return true;
1478 }
1479
1480 static bool test_DeleteForm(struct torture_context *tctx,
1481                             struct dcerpc_pipe *p,
1482                             struct policy_handle *handle,
1483                             const char *form_name)
1484 {
1485         NTSTATUS status;
1486         struct spoolss_DeleteForm r;
1487
1488         r.in.handle = handle;
1489         r.in.form_name = form_name;
1490
1491         status = dcerpc_spoolss_DeleteForm(p, tctx, &r);
1492
1493         torture_assert_ntstatus_ok(tctx, status, "DeleteForm failed");
1494
1495         torture_assert_werr_ok(tctx, r.out.result, "DeleteForm failed");
1496
1497         return true;
1498 }
1499
1500 static bool test_AddForm(struct torture_context *tctx,
1501                          struct dcerpc_pipe *p,
1502                          struct policy_handle *handle, bool print_server)
1503 {
1504         struct spoolss_AddForm r;
1505         struct spoolss_AddFormInfo1 addform;
1506         const char *form_name = "testform3";
1507         NTSTATUS status;
1508         bool ret = true;
1509
1510         r.in.handle     = handle;
1511         r.in.level      = 1;
1512         r.in.info.info1 = &addform;
1513         addform.flags           = SPOOLSS_FORM_USER;
1514         addform.form_name       = form_name;
1515         addform.size.width      = 50;
1516         addform.size.height     = 25;
1517         addform.area.left       = 5;
1518         addform.area.top        = 10;
1519         addform.area.right      = 45;
1520         addform.area.bottom     = 15;
1521
1522         status = dcerpc_spoolss_AddForm(p, tctx, &r);
1523
1524         torture_assert_ntstatus_ok(tctx, status, "AddForm failed");
1525
1526         torture_assert_werr_ok(tctx, r.out.result, "AddForm failed");
1527
1528         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1529
1530         {
1531                 struct spoolss_SetForm sf;
1532                 struct spoolss_AddFormInfo1 setform;
1533
1534                 sf.in.handle    = handle;
1535                 sf.in.form_name = form_name;
1536                 sf.in.level     = 1;
1537                 sf.in.info.info1= &setform;
1538                 setform.flags           = addform.flags;
1539                 setform.form_name       = addform.form_name;
1540                 setform.size            = addform.size;
1541                 setform.area            = addform.area;
1542
1543                 setform.size.width      = 1234;
1544
1545                 status = dcerpc_spoolss_SetForm(p, tctx, &sf);
1546
1547                 torture_assert_ntstatus_ok(tctx, status, "SetForm failed");
1548
1549                 torture_assert_werr_ok(tctx, r.out.result, "SetForm failed");
1550         }
1551
1552         if (!print_server) ret &= test_GetForm(tctx, p, handle, form_name, 1);
1553
1554         {
1555                 struct spoolss_EnumForms e;
1556                 union spoolss_FormInfo *info;
1557                 uint32_t needed;
1558                 uint32_t count;
1559                 bool found = false;
1560
1561                 e.in.handle = handle;
1562                 e.in.level = 1;
1563                 e.in.buffer = NULL;
1564                 e.in.offered = 0;
1565                 e.out.needed = &needed;
1566                 e.out.count = &count;
1567                 e.out.info = &info;
1568
1569                 torture_comment(tctx, "Testing EnumForms level 1\n");
1570
1571                 status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1572                 torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
1573
1574                 if (print_server && W_ERROR_EQUAL(e.out.result, WERR_BADFID))
1575                         torture_fail(tctx, "EnumForms on the PrintServer isn't supported by test server (NT4)");
1576
1577                 if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
1578                         int j;
1579                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1580                         data_blob_clear(&blob);
1581                         e.in.buffer = &blob;
1582                         e.in.offered = needed;
1583
1584                         status = dcerpc_spoolss_EnumForms(p, tctx, &e);
1585
1586                         torture_assert(tctx, info, "No forms returned");
1587
1588                         for (j = 0; j < count; j++) {
1589                                 if (strequal(form_name, info[j].info1.form_name)) {
1590                                         found = true;
1591                                         break;
1592                                 }
1593                         }
1594                 }
1595                 torture_assert(tctx, found, "Newly added form not found in enum call");
1596         }
1597
1598         if (!test_DeleteForm(tctx, p, handle, form_name)) {
1599                 ret = false;
1600         }
1601
1602         return ret;
1603 }
1604
1605 static bool test_EnumPorts_old(struct torture_context *tctx,
1606                                struct dcerpc_pipe *p)
1607 {
1608         NTSTATUS status;
1609         struct spoolss_EnumPorts r;
1610         uint32_t needed;
1611         uint32_t count;
1612         union spoolss_PortInfo *info;
1613
1614         r.in.servername = talloc_asprintf(tctx, "\\\\%s",
1615                                           dcerpc_server_name(p));
1616         r.in.level = 2;
1617         r.in.buffer = NULL;
1618         r.in.offered = 0;
1619         r.out.needed = &needed;
1620         r.out.count = &count;
1621         r.out.info = &info;
1622
1623         torture_comment(tctx, "Testing EnumPorts\n");
1624
1625         status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1626
1627         torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1628
1629         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1630                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1631                 data_blob_clear(&blob);
1632                 r.in.buffer = &blob;
1633                 r.in.offered = needed;
1634
1635                 status = dcerpc_spoolss_EnumPorts(p, tctx, &r);
1636                 torture_assert_ntstatus_ok(tctx, status, "EnumPorts failed");
1637
1638                 torture_assert(tctx, info, "No ports returned");
1639         }
1640
1641         return true;
1642 }
1643
1644 static bool test_AddPort(struct torture_context *tctx,
1645                          struct dcerpc_pipe *p)
1646 {
1647         NTSTATUS status;
1648         struct spoolss_AddPort r;
1649
1650         r.in.server_name = talloc_asprintf(tctx, "\\\\%s",
1651                                            dcerpc_server_name(p));
1652         r.in.unknown = 0;
1653         r.in.monitor_name = "foo";
1654
1655         torture_comment(tctx, "Testing AddPort\n");
1656
1657         status = dcerpc_spoolss_AddPort(p, tctx, &r);
1658
1659         torture_assert_ntstatus_ok(tctx, status, "AddPort failed");
1660
1661         /* win2k3 returns WERR_NOT_SUPPORTED */
1662
1663 #if 0
1664
1665         if (!W_ERROR_IS_OK(r.out.result)) {
1666                 printf("AddPort failed - %s\n", win_errstr(r.out.result));
1667                 return false;
1668         }
1669
1670 #endif
1671
1672         return true;
1673 }
1674
1675 static bool test_GetJob(struct torture_context *tctx,
1676                         struct dcerpc_pipe *p,
1677                         struct policy_handle *handle, uint32_t job_id)
1678 {
1679         NTSTATUS status;
1680         struct spoolss_GetJob r;
1681         union spoolss_JobInfo info;
1682         uint32_t needed;
1683         uint32_t levels[] = {1, 2 /* 3, 4 */};
1684         uint32_t i;
1685
1686         r.in.handle = handle;
1687         r.in.job_id = job_id;
1688         r.in.level = 0;
1689         r.in.buffer = NULL;
1690         r.in.offered = 0;
1691         r.out.needed = &needed;
1692         r.out.info = &info;
1693
1694         torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1695
1696         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1697         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "Unexpected return code");
1698
1699         for (i = 0; i < ARRAY_SIZE(levels); i++) {
1700
1701                 torture_comment(tctx, "Testing GetJob level %d\n", r.in.level);
1702
1703                 needed = 0;
1704
1705                 r.in.level = levels[i];
1706                 r.in.offered = 0;
1707                 r.in.buffer = NULL;
1708
1709                 status = dcerpc_spoolss_GetJob(p, tctx, &r);
1710                 torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1711
1712                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1713                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1714                         data_blob_clear(&blob);
1715                         r.in.buffer = &blob;
1716                         r.in.offered = needed;
1717
1718                         status = dcerpc_spoolss_GetJob(p, tctx, &r);
1719                         torture_assert_ntstatus_ok(tctx, status, "GetJob failed");
1720
1721                 }
1722                 torture_assert(tctx, r.out.info, "No job info returned");
1723                 torture_assert_werr_ok(tctx, r.out.result, "GetJob failed");
1724         }
1725
1726         return true;
1727 }
1728
1729 static bool test_SetJob(struct torture_context *tctx,
1730                         struct dcerpc_pipe *p,
1731                         struct policy_handle *handle, uint32_t job_id,
1732                         enum spoolss_JobControl command)
1733 {
1734         NTSTATUS status;
1735         struct spoolss_SetJob r;
1736
1737         r.in.handle     = handle;
1738         r.in.job_id     = job_id;
1739         r.in.ctr        = NULL;
1740         r.in.command    = command;
1741
1742         switch (command) {
1743         case SPOOLSS_JOB_CONTROL_PAUSE:
1744                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_PAUSE\n");
1745                 break;
1746         case SPOOLSS_JOB_CONTROL_RESUME:
1747                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESUME\n");
1748                 break;
1749         case SPOOLSS_JOB_CONTROL_CANCEL:
1750                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_CANCEL\n");
1751                 break;
1752         case SPOOLSS_JOB_CONTROL_RESTART:
1753                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RESTART\n");
1754                 break;
1755         case SPOOLSS_JOB_CONTROL_DELETE:
1756                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_DELETE\n");
1757                 break;
1758         case SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER:
1759                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER\n");
1760                 break;
1761         case SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED:
1762                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED\n");
1763                 break;
1764         case SPOOLSS_JOB_CONTROL_RETAIN:
1765                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RETAIN\n");
1766                 break;
1767         case SPOOLSS_JOB_CONTROL_RELEASE:
1768                 torture_comment(tctx, "Testing SetJob: SPOOLSS_JOB_CONTROL_RELEASE\n");
1769                 break;
1770         default:
1771                 torture_comment(tctx, "Testing SetJob\n");
1772                 break;
1773         }
1774
1775         status = dcerpc_spoolss_SetJob(p, tctx, &r);
1776         torture_assert_ntstatus_ok(tctx, status, "SetJob failed");
1777         torture_assert_werr_ok(tctx, r.out.result, "SetJob failed");
1778
1779         return true;
1780 }
1781
1782 static bool test_AddJob(struct torture_context *tctx,
1783                         struct dcerpc_pipe *p,
1784                         struct policy_handle *handle)
1785 {
1786         NTSTATUS status;
1787         struct spoolss_AddJob r;
1788         uint32_t needed;
1789
1790         r.in.level = 0;
1791         r.in.handle = handle;
1792         r.in.offered = 0;
1793         r.out.needed = &needed;
1794         r.in.buffer = r.out.buffer = NULL;
1795
1796         torture_comment(tctx, "Testing AddJob\n");
1797
1798         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1799         torture_assert_werr_equal(tctx, r.out.result, WERR_UNKNOWN_LEVEL, "AddJob failed");
1800
1801         r.in.level = 1;
1802
1803         status = dcerpc_spoolss_AddJob(p, tctx, &r);
1804         torture_assert_werr_equal(tctx, r.out.result, WERR_INVALID_PARAM, "AddJob failed");
1805
1806         return true;
1807 }
1808
1809
1810 static bool test_EnumJobs(struct torture_context *tctx,
1811                           struct dcerpc_pipe *p,
1812                           struct policy_handle *handle)
1813 {
1814         NTSTATUS status;
1815         struct spoolss_EnumJobs r;
1816         uint32_t needed;
1817         uint32_t count;
1818         union spoolss_JobInfo *info;
1819
1820         r.in.handle = handle;
1821         r.in.firstjob = 0;
1822         r.in.numjobs = 0xffffffff;
1823         r.in.level = 1;
1824         r.in.buffer = NULL;
1825         r.in.offered = 0;
1826         r.out.needed = &needed;
1827         r.out.count = &count;
1828         r.out.info = &info;
1829
1830         torture_comment(tctx, "Testing EnumJobs\n");
1831
1832         status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1833
1834         torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
1835
1836         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
1837                 int j;
1838                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
1839                 data_blob_clear(&blob);
1840                 r.in.buffer = &blob;
1841                 r.in.offered = needed;
1842
1843                 status = dcerpc_spoolss_EnumJobs(p, tctx, &r);
1844
1845                 torture_assert(tctx, info, "No jobs returned");
1846
1847                 for (j = 0; j < count; j++) {
1848
1849                         test_GetJob(tctx, p, handle, info[j].info1.job_id);
1850
1851                         /* FIXME - gd */
1852                         if (!torture_setting_bool(tctx, "samba3", false)) {
1853                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_PAUSE);
1854                                 test_SetJob(tctx, p, handle, info[j].info1.job_id, SPOOLSS_JOB_CONTROL_RESUME);
1855                         }
1856                 }
1857
1858         } else {
1859                 torture_assert_werr_ok(tctx, r.out.result, "EnumJobs failed");
1860         }
1861
1862         return true;
1863 }
1864
1865 static bool test_DoPrintTest(struct torture_context *tctx,
1866                              struct dcerpc_pipe *p,
1867                              struct policy_handle *handle)
1868 {
1869         bool ret = true;
1870         NTSTATUS status;
1871         struct spoolss_StartDocPrinter s;
1872         struct spoolss_DocumentInfo1 info1;
1873         struct spoolss_StartPagePrinter sp;
1874         struct spoolss_WritePrinter w;
1875         struct spoolss_EndPagePrinter ep;
1876         struct spoolss_EndDocPrinter e;
1877         int i;
1878         uint32_t job_id;
1879         uint32_t num_written;
1880
1881         torture_comment(tctx, "Testing StartDocPrinter\n");
1882
1883         s.in.handle             = handle;
1884         s.in.level              = 1;
1885         s.in.info.info1         = &info1;
1886         s.out.job_id            = &job_id;
1887         info1.document_name     = "TorturePrintJob";
1888         info1.output_file       = NULL;
1889         info1.datatype          = "RAW";
1890
1891         status = dcerpc_spoolss_StartDocPrinter(p, tctx, &s);
1892         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_StartDocPrinter failed");
1893         torture_assert_werr_ok(tctx, s.out.result, "StartDocPrinter failed");
1894
1895         for (i=1; i < 4; i++) {
1896                 torture_comment(tctx, "Testing StartPagePrinter: Page[%d]\n", i);
1897
1898                 sp.in.handle            = handle;
1899
1900                 status = dcerpc_spoolss_StartPagePrinter(p, tctx, &sp);
1901                 torture_assert_ntstatus_ok(tctx, status,
1902                                            "dcerpc_spoolss_StartPagePrinter failed");
1903                 torture_assert_werr_ok(tctx, sp.out.result, "StartPagePrinter failed");
1904
1905                 torture_comment(tctx, "Testing WritePrinter: Page[%d]\n", i);
1906
1907                 w.in.handle             = handle;
1908                 w.in.data               = data_blob_string_const(talloc_asprintf(tctx,"TortureTestPage: %d\nData\n",i));
1909                 w.out.num_written       = &num_written;
1910
1911                 status = dcerpc_spoolss_WritePrinter(p, tctx, &w);
1912                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_WritePrinter failed");
1913                 torture_assert_werr_ok(tctx, w.out.result, "WritePrinter failed");
1914
1915                 torture_comment(tctx, "Testing EndPagePrinter: Page[%d]\n", i);
1916
1917                 ep.in.handle            = handle;
1918
1919                 status = dcerpc_spoolss_EndPagePrinter(p, tctx, &ep);
1920                 torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndPagePrinter failed");
1921                 torture_assert_werr_ok(tctx, ep.out.result, "EndPagePrinter failed");
1922         }
1923
1924         torture_comment(tctx, "Testing EndDocPrinter\n");
1925
1926         e.in.handle = handle;
1927
1928         status = dcerpc_spoolss_EndDocPrinter(p, tctx, &e);
1929         torture_assert_ntstatus_ok(tctx, status, "dcerpc_spoolss_EndDocPrinter failed");
1930         torture_assert_werr_ok(tctx, e.out.result, "EndDocPrinter failed");
1931
1932         ret &= test_AddJob(tctx, p, handle);
1933         ret &= test_EnumJobs(tctx, p, handle);
1934
1935         ret &= test_SetJob(tctx, p, handle, job_id, SPOOLSS_JOB_CONTROL_DELETE);
1936
1937         return ret;
1938 }
1939
1940 static bool test_PausePrinter(struct torture_context *tctx,
1941                               struct dcerpc_pipe *p,
1942                               struct policy_handle *handle)
1943 {
1944         NTSTATUS status;
1945         struct spoolss_SetPrinter r;
1946         struct spoolss_SetPrinterInfoCtr info_ctr;
1947         struct spoolss_DevmodeContainer devmode_ctr;
1948         struct sec_desc_buf secdesc_ctr;
1949
1950         info_ctr.level = 0;
1951         info_ctr.info.info0 = NULL;
1952
1953         ZERO_STRUCT(devmode_ctr);
1954         ZERO_STRUCT(secdesc_ctr);
1955
1956         r.in.handle             = handle;
1957         r.in.info_ctr           = &info_ctr;
1958         r.in.devmode_ctr        = &devmode_ctr;
1959         r.in.secdesc_ctr        = &secdesc_ctr;
1960         r.in.command            = SPOOLSS_PRINTER_CONTROL_PAUSE;
1961
1962         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_PAUSE\n");
1963
1964         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1965
1966         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
1967
1968         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
1969
1970         return true;
1971 }
1972
1973 static bool test_ResumePrinter(struct torture_context *tctx,
1974                                struct dcerpc_pipe *p,
1975                                struct policy_handle *handle)
1976 {
1977         NTSTATUS status;
1978         struct spoolss_SetPrinter r;
1979         struct spoolss_SetPrinterInfoCtr info_ctr;
1980         struct spoolss_DevmodeContainer devmode_ctr;
1981         struct sec_desc_buf secdesc_ctr;
1982
1983         info_ctr.level = 0;
1984         info_ctr.info.info0 = NULL;
1985
1986         ZERO_STRUCT(devmode_ctr);
1987         ZERO_STRUCT(secdesc_ctr);
1988
1989         r.in.handle             = handle;
1990         r.in.info_ctr           = &info_ctr;
1991         r.in.devmode_ctr        = &devmode_ctr;
1992         r.in.secdesc_ctr        = &secdesc_ctr;
1993         r.in.command            = SPOOLSS_PRINTER_CONTROL_RESUME;
1994
1995         torture_comment(tctx, "Testing SetPrinter: SPOOLSS_PRINTER_CONTROL_RESUME\n");
1996
1997         status = dcerpc_spoolss_SetPrinter(p, tctx, &r);
1998
1999         torture_assert_ntstatus_ok(tctx, status, "SetPrinter failed");
2000
2001         torture_assert_werr_ok(tctx, r.out.result, "SetPrinter failed");
2002
2003         return true;
2004 }
2005
2006 static bool test_GetPrinterData(struct torture_context *tctx,
2007                                 struct dcerpc_pipe *p,
2008                                 struct policy_handle *handle,
2009                                 const char *value_name)
2010 {
2011         NTSTATUS status;
2012         struct spoolss_GetPrinterData r;
2013         uint32_t needed;
2014         enum winreg_Type type;
2015         union spoolss_PrinterData data;
2016
2017         r.in.handle = handle;
2018         r.in.value_name = value_name;
2019         r.in.offered = 0;
2020         r.out.needed = &needed;
2021         r.out.type = &type;
2022         r.out.data = &data;
2023
2024         torture_comment(tctx, "Testing GetPrinterData\n");
2025
2026         status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2027         torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2028
2029         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2030                 r.in.offered = needed;
2031
2032                 status = dcerpc_spoolss_GetPrinterData(p, tctx, &r);
2033                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed");
2034
2035                 torture_assert_werr_ok(tctx, r.out.result, "GetPrinterData failed");
2036         }
2037
2038         return true;
2039 }
2040
2041 static bool test_GetPrinterDataEx(struct torture_context *tctx,
2042                                   struct dcerpc_pipe *p,
2043                                   struct policy_handle *handle,
2044                                   const char *key_name,
2045                                   const char *value_name)
2046 {
2047         NTSTATUS status;
2048         struct spoolss_GetPrinterDataEx r;
2049         enum winreg_Type type;
2050         uint32_t needed;
2051
2052         r.in.handle = handle;
2053         r.in.key_name = key_name;
2054         r.in.value_name = value_name;
2055         r.in.offered = 0;
2056         r.out.type = &type;
2057         r.out.needed = &needed;
2058         r.out.buffer = NULL;
2059
2060         torture_comment(tctx, "Testing GetPrinterDataEx\n");
2061
2062         status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2063         if (!NT_STATUS_IS_OK(status)) {
2064                 if (NT_STATUS_EQUAL(status,NT_STATUS_NET_WRITE_FAULT) &&
2065                     p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
2066                         torture_skip(tctx, "GetPrinterDataEx not supported by server\n");
2067                 }
2068                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2069         }
2070
2071         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
2072                 r.in.offered = needed;
2073                 r.out.buffer = talloc_array(tctx, uint8_t, needed);
2074
2075                 status = dcerpc_spoolss_GetPrinterDataEx(p, tctx, &r);
2076                 torture_assert_ntstatus_ok(tctx, status, "GetPrinterDataEx failed");
2077
2078                 torture_assert_werr_ok(tctx, r.out.result,  "GetPrinterDataEx failed");
2079         }
2080
2081         return true;
2082 }
2083
2084 static bool test_EnumPrinterData(struct torture_context *tctx, struct dcerpc_pipe *p,
2085                                  struct policy_handle *handle)
2086 {
2087         NTSTATUS status;
2088         struct spoolss_EnumPrinterData r;
2089
2090         ZERO_STRUCT(r);
2091         r.in.handle = handle;
2092         r.in.enum_index = 0;
2093
2094         do {
2095                 uint32_t value_size = 0;
2096                 uint32_t data_size = 0;
2097                 enum winreg_Type type = 0;
2098
2099                 r.in.value_offered = value_size;
2100                 r.out.value_needed = &value_size;
2101                 r.in.data_offered = data_size;
2102                 r.out.data_needed = &data_size;
2103
2104                 r.out.type = &type;
2105                 r.out.data = talloc_zero_array(tctx, uint8_t, 0);
2106
2107                 torture_comment(tctx, "Testing EnumPrinterData\n");
2108
2109                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2110
2111                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2112
2113                 r.in.value_offered = value_size;
2114                 r.out.value_name = talloc_zero_array(tctx, const char, value_size);
2115                 r.in.data_offered = data_size;
2116                 r.out.data = talloc_zero_array(tctx, uint8_t, data_size);
2117
2118                 status = dcerpc_spoolss_EnumPrinterData(p, tctx, &r);
2119
2120                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterData failed");
2121
2122                 torture_assert(tctx, test_GetPrinterData(tctx, p, handle, r.out.value_name),
2123                         talloc_asprintf(tctx, "failed to call GetPrinterData for %s\n", r.out.value_name));
2124
2125                 torture_assert(tctx, test_GetPrinterDataEx(tctx, p, handle, "PrinterDriverData", r.out.value_name),
2126                         talloc_asprintf(tctx, "failed to call GetPrinterDataEx on PrinterDriverData for %s\n", r.out.value_name));
2127
2128                 r.in.enum_index++;
2129
2130         } while (W_ERROR_IS_OK(r.out.result));
2131
2132         return true;
2133 }
2134
2135 static bool test_EnumPrinterDataEx(struct torture_context *tctx,
2136                                    struct dcerpc_pipe *p,
2137                                    struct policy_handle *handle)
2138 {
2139         NTSTATUS status;
2140         struct spoolss_EnumPrinterDataEx r;
2141         struct spoolss_PrinterEnumValues *info;
2142         uint32_t needed;
2143         uint32_t count;
2144
2145         r.in.handle = handle;
2146         r.in.key_name = "PrinterDriverData";
2147         r.in.offered = 0;
2148         r.out.needed = &needed;
2149         r.out.count = &count;
2150         r.out.info = &info;
2151
2152         torture_comment(tctx, "Testing EnumPrinterDataEx\n");
2153
2154         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2155         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2156
2157         r.in.offered = needed;
2158
2159         status = dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r);
2160
2161         torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDataEx failed");
2162
2163         return true;
2164 }
2165
2166
2167 static bool test_DeletePrinterData(struct torture_context *tctx,
2168                                    struct dcerpc_pipe *p,
2169                                    struct policy_handle *handle,
2170                                    const char *value_name)
2171 {
2172         NTSTATUS status;
2173         struct spoolss_DeletePrinterData r;
2174
2175         r.in.handle = handle;
2176         r.in.value_name = value_name;
2177
2178         torture_comment(tctx, "Testing DeletePrinterData\n");
2179
2180         status = dcerpc_spoolss_DeletePrinterData(p, tctx, &r);
2181
2182         torture_assert_ntstatus_ok(tctx, status, "DeletePrinterData failed");
2183
2184         return true;
2185 }
2186
2187 static bool test_SetPrinterData(struct torture_context *tctx,
2188                                 struct dcerpc_pipe *p,
2189                                 struct policy_handle *handle)
2190 {
2191         NTSTATUS status;
2192         struct spoolss_SetPrinterData r;
2193         const char *value_name = "spottyfoot";
2194
2195         r.in.handle = handle;
2196         r.in.value_name = value_name;
2197         r.in.type = REG_SZ;
2198         r.in.data.string = "dog";
2199
2200         torture_comment(tctx, "Testing SetPrinterData\n");
2201
2202         status = dcerpc_spoolss_SetPrinterData(p, tctx, &r);
2203
2204         torture_assert_ntstatus_ok(tctx, status, "SetPrinterData failed");
2205
2206         if (!test_GetPrinterData(tctx, p, handle, value_name)) {
2207                 return false;
2208         }
2209
2210         if (!test_DeletePrinterData(tctx, p, handle, value_name)) {
2211                 return false;
2212         }
2213
2214         return true;
2215 }
2216
2217 static bool test_SecondaryClosePrinter(struct torture_context *tctx,
2218                                        struct dcerpc_pipe *p,
2219                                        struct policy_handle *handle)
2220 {
2221         NTSTATUS status;
2222         struct dcerpc_binding *b;
2223         struct dcerpc_pipe *p2;
2224         struct spoolss_ClosePrinter cp;
2225
2226         /* only makes sense on SMB */
2227         if (p->conn->transport.transport != NCACN_NP) {
2228                 return true;
2229         }
2230
2231         torture_comment(tctx, "testing close on secondary pipe\n");
2232
2233         status = dcerpc_parse_binding(tctx, p->conn->binding_string, &b);
2234         torture_assert_ntstatus_ok(tctx, status, "Failed to parse dcerpc binding");
2235
2236         status = dcerpc_secondary_connection(p, &p2, b);
2237         torture_assert_ntstatus_ok(tctx, status, "Failed to create secondary connection");
2238
2239         status = dcerpc_bind_auth_none(p2, &ndr_table_spoolss);
2240         torture_assert_ntstatus_ok(tctx, status, "Failed to create bind on secondary connection");
2241
2242         cp.in.handle = handle;
2243         cp.out.handle = handle;
2244
2245         status = dcerpc_spoolss_ClosePrinter(p2, tctx, &cp);
2246         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NET_WRITE_FAULT,
2247                         "ERROR: Allowed close on secondary connection");
2248
2249         torture_assert_int_equal(tctx, p2->last_fault_code, DCERPC_FAULT_CONTEXT_MISMATCH,
2250                                  "Unexpected fault code");
2251
2252         talloc_free(p2);
2253
2254         return true;
2255 }
2256
2257 static bool test_OpenPrinter_badname(struct torture_context *tctx,
2258                                      struct dcerpc_pipe *p, const char *name)
2259 {
2260         NTSTATUS status;
2261         struct spoolss_OpenPrinter op;
2262         struct spoolss_OpenPrinterEx opEx;
2263         struct policy_handle handle;
2264         bool ret = true;
2265
2266         op.in.printername       = name;
2267         op.in.datatype          = NULL;
2268         op.in.devmode_ctr.devmode= NULL;
2269         op.in.access_mask       = 0;
2270         op.out.handle           = &handle;
2271
2272         torture_comment(tctx, "\nTesting OpenPrinter(%s) with bad name\n", op.in.printername);
2273
2274         status = dcerpc_spoolss_OpenPrinter(p, tctx, &op);
2275         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2276         if (!W_ERROR_EQUAL(WERR_INVALID_PRINTER_NAME,op.out.result)) {
2277                 torture_comment(tctx, "OpenPrinter(%s) unexpected result[%s] should be WERR_INVALID_PRINTER_NAME\n",
2278                         name, win_errstr(op.out.result));
2279         }
2280
2281         if (W_ERROR_IS_OK(op.out.result)) {
2282                 ret &=test_ClosePrinter(tctx, p, &handle);
2283         }
2284
2285         opEx.in.printername             = name;
2286         opEx.in.datatype                = NULL;
2287         opEx.in.devmode_ctr.devmode     = NULL;
2288         opEx.in.access_mask             = 0;
2289         opEx.in.level                   = 1;
2290         opEx.in.userlevel.level1        = NULL;
2291         opEx.out.handle                 = &handle;
2292
2293         torture_comment(tctx, "Testing OpenPrinterEx(%s) with bad name\n", opEx.in.printername);
2294
2295         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &opEx);
2296         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2297         if (!W_ERROR_EQUAL(WERR_INVALID_PARAM,opEx.out.result)) {
2298                 torture_comment(tctx, "OpenPrinterEx(%s) unexpected result[%s] should be WERR_INVALID_PARAM\n",
2299                         name, win_errstr(opEx.out.result));
2300         }
2301
2302         if (W_ERROR_IS_OK(opEx.out.result)) {
2303                 ret &=test_ClosePrinter(tctx, p, &handle);
2304         }
2305
2306         return ret;
2307 }
2308
2309 static bool test_OpenPrinter(struct torture_context *tctx,
2310                              struct dcerpc_pipe *p,
2311                              const char *name)
2312 {
2313         NTSTATUS status;
2314         struct spoolss_OpenPrinter r;
2315         struct policy_handle handle;
2316         bool ret = true;
2317
2318         r.in.printername        = talloc_asprintf(tctx, "\\\\%s\\%s", dcerpc_server_name(p), name);
2319         r.in.datatype           = NULL;
2320         r.in.devmode_ctr.devmode= NULL;
2321         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2322         r.out.handle            = &handle;
2323
2324         torture_comment(tctx, "Testing OpenPrinter(%s)\n", r.in.printername);
2325
2326         status = dcerpc_spoolss_OpenPrinter(p, tctx, &r);
2327
2328         torture_assert_ntstatus_ok(tctx, status, "OpenPrinter failed");
2329
2330         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinter failed");
2331
2332         if (!test_GetPrinter(tctx, p, &handle)) {
2333                 ret = false;
2334         }
2335
2336         if (!torture_setting_bool(tctx, "samba3", false)) {
2337                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2338                         ret = false;
2339                 }
2340         }
2341
2342         if (!test_ClosePrinter(tctx, p, &handle)) {
2343                 ret = false;
2344         }
2345
2346         return ret;
2347 }
2348
2349 static bool call_OpenPrinterEx(struct torture_context *tctx,
2350                                struct dcerpc_pipe *p,
2351                                const char *name, struct policy_handle *handle)
2352 {
2353         struct spoolss_OpenPrinterEx r;
2354         struct spoolss_UserLevel1 userlevel1;
2355         NTSTATUS status;
2356
2357         if (name && name[0]) {
2358                 r.in.printername = talloc_asprintf(tctx, "\\\\%s\\%s",
2359                                                    dcerpc_server_name(p), name);
2360         } else {
2361                 r.in.printername = talloc_asprintf(tctx, "\\\\%s",
2362                                                    dcerpc_server_name(p));
2363         }
2364
2365         r.in.datatype           = NULL;
2366         r.in.devmode_ctr.devmode= NULL;
2367         r.in.access_mask        = SEC_FLAG_MAXIMUM_ALLOWED;
2368         r.in.level              = 1;
2369         r.in.userlevel.level1   = &userlevel1;
2370         r.out.handle = handle;
2371
2372         userlevel1.size = 1234;
2373         userlevel1.client = "hello";
2374         userlevel1.user = "spottyfoot!";
2375         userlevel1.build = 1;
2376         userlevel1.major = 2;
2377         userlevel1.minor = 3;
2378         userlevel1.processor = 4;
2379
2380         torture_comment(tctx, "Testing OpenPrinterEx(%s)\n", r.in.printername);
2381
2382         status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &r);
2383
2384         torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
2385
2386         torture_assert_werr_ok(tctx, r.out.result, "OpenPrinterEx failed");
2387
2388         return true;
2389 }
2390
2391 static bool test_OpenPrinterEx(struct torture_context *tctx,
2392                                struct dcerpc_pipe *p,
2393                                const char *name)
2394 {
2395         struct policy_handle handle;
2396         bool ret = true;
2397
2398         if (!call_OpenPrinterEx(tctx, p, name, &handle)) {
2399                 return false;
2400         }
2401
2402         if (!test_GetPrinter(tctx, p, &handle)) {
2403                 ret = false;
2404         }
2405
2406         if (!test_EnumForms(tctx, p, &handle, false)) {
2407                 ret = false;
2408         }
2409
2410         if (!test_AddForm(tctx, p, &handle, false)) {
2411                 ret = false;
2412         }
2413
2414         if (!test_EnumPrinterData(tctx, p, &handle)) {
2415                 ret = false;
2416         }
2417
2418         if (!test_EnumPrinterDataEx(tctx, p, &handle)) {
2419                 ret = false;
2420         }
2421
2422         if (!test_printer_keys(tctx, p, &handle)) {
2423                 ret = false;
2424         }
2425
2426         if (!test_PausePrinter(tctx, p, &handle)) {
2427                 ret = false;
2428         }
2429
2430         if (!test_DoPrintTest(tctx, p, &handle)) {
2431                 ret = false;
2432         }
2433
2434         if (!test_ResumePrinter(tctx, p, &handle)) {
2435                 ret = false;
2436         }
2437
2438         if (!test_SetPrinterData(tctx, p, &handle)) {
2439                 ret = false;
2440         }
2441
2442         if (!torture_setting_bool(tctx, "samba3", false)) {
2443                 if (!test_SecondaryClosePrinter(tctx, p, &handle)) {
2444                         ret = false;
2445                 }
2446         }
2447
2448         if (!test_ClosePrinter(tctx, p, &handle)) {
2449                 ret = false;
2450         }
2451
2452         return ret;
2453 }
2454
2455 static bool test_EnumPrinters_old(struct torture_context *tctx, struct dcerpc_pipe *p)
2456 {
2457         struct spoolss_EnumPrinters r;
2458         NTSTATUS status;
2459         uint16_t levels[] = {1, 2, 4, 5};
2460         int i;
2461         bool ret = true;
2462
2463         for (i=0;i<ARRAY_SIZE(levels);i++) {
2464                 union spoolss_PrinterInfo *info;
2465                 int j;
2466                 uint32_t needed;
2467                 uint32_t count;
2468
2469                 r.in.flags      = PRINTER_ENUM_LOCAL;
2470                 r.in.server     = "";
2471                 r.in.level      = levels[i];
2472                 r.in.buffer     = NULL;
2473                 r.in.offered    = 0;
2474                 r.out.needed    = &needed;
2475                 r.out.count     = &count;
2476                 r.out.info      = &info;
2477
2478                 torture_comment(tctx, "Testing EnumPrinters level %u\n", r.in.level);
2479
2480                 status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2481                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2482
2483                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2484                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2485                         data_blob_clear(&blob);
2486                         r.in.buffer = &blob;
2487                         r.in.offered = needed;
2488                         status = dcerpc_spoolss_EnumPrinters(p, tctx, &r);
2489                 }
2490
2491                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed");
2492
2493                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinters failed");
2494
2495                 if (!info) {
2496                         torture_comment(tctx, "No printers returned\n");
2497                         return true;
2498                 }
2499
2500                 for (j=0;j<count;j++) {
2501                         if (r.in.level == 1) {
2502                                 char *unc = talloc_strdup(tctx, info[j].info1.name);
2503                                 char *slash, *name;
2504                                 name = unc;
2505                                 if (unc[0] == '\\' && unc[1] == '\\') {
2506                                         unc +=2;
2507                                 }
2508                                 slash = strchr(unc, '\\');
2509                                 if (slash) {
2510                                         slash++;
2511                                         name = slash;
2512                                 }
2513                                 if (!test_OpenPrinter(tctx, p, name)) {
2514                                         ret = false;
2515                                 }
2516                                 if (!test_OpenPrinterEx(tctx, p, name)) {
2517                                         ret = false;
2518                                 }
2519                         }
2520                 }
2521         }
2522
2523         return ret;
2524 }
2525
2526 static bool test_GetPrinterDriver(struct torture_context *tctx,
2527                                   struct dcerpc_pipe *p,
2528                                   struct policy_handle *handle,
2529                                   const char *driver_name)
2530 {
2531         struct spoolss_GetPrinterDriver r;
2532         uint32_t needed;
2533
2534         r.in.handle = handle;
2535         r.in.architecture = "W32X86";
2536         r.in.level = 1;
2537         r.in.buffer = NULL;
2538         r.in.offered = 0;
2539         r.out.needed = &needed;
2540
2541         torture_comment(tctx, "Testing GetPrinterDriver level %d\n", r.in.level);
2542
2543         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2544                 "failed to call GetPrinterDriver");
2545         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2546                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2547                 data_blob_clear(&blob);
2548                 r.in.buffer = &blob;
2549                 r.in.offered = needed;
2550                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver(p, tctx, &r),
2551                         "failed to call GetPrinterDriver");
2552         }
2553
2554         torture_assert_werr_ok(tctx, r.out.result,
2555                 "failed to call GetPrinterDriver");
2556
2557         return true;
2558 }
2559
2560 static bool test_GetPrinterDriver2(struct torture_context *tctx,
2561                                    struct dcerpc_pipe *p,
2562                                    struct policy_handle *handle,
2563                                    const char *driver_name)
2564 {
2565         struct spoolss_GetPrinterDriver2 r;
2566         uint32_t needed;
2567         uint32_t server_major_version;
2568         uint32_t server_minor_version;
2569
2570         r.in.handle = handle;
2571         r.in.architecture = "W32X86";
2572         r.in.level = 1;
2573         r.in.buffer = NULL;
2574         r.in.offered = 0;
2575         r.in.client_major_version = 0;
2576         r.in.client_minor_version = 0;
2577         r.out.needed = &needed;
2578         r.out.server_major_version = &server_major_version;
2579         r.out.server_minor_version = &server_minor_version;
2580
2581         torture_comment(tctx, "Testing GetPrinterDriver2 level %d\n", r.in.level);
2582
2583         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2584                 "failed to call GetPrinterDriver2");
2585         if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2586                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2587                 data_blob_clear(&blob);
2588                 r.in.buffer = &blob;
2589                 r.in.offered = needed;
2590                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_GetPrinterDriver2(p, tctx, &r),
2591                         "failed to call GetPrinterDriver2");
2592         }
2593
2594         torture_assert_werr_ok(tctx, r.out.result,
2595                 "failed to call GetPrinterDriver2");
2596
2597         return true;
2598 }
2599
2600 static bool test_EnumPrinterDrivers_old(struct torture_context *tctx,
2601                                         struct dcerpc_pipe *p)
2602 {
2603         struct spoolss_EnumPrinterDrivers r;
2604         NTSTATUS status;
2605         uint16_t levels[] = {1, 2, 3, 4, 5, 6};
2606         int i;
2607
2608         for (i=0;i<ARRAY_SIZE(levels);i++) {
2609
2610                 uint32_t needed;
2611                 uint32_t count;
2612                 union spoolss_DriverInfo *info;
2613
2614                 r.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2615                 r.in.environment = SPOOLSS_ARCHITECTURE_NT_X86;
2616                 r.in.level = levels[i];
2617                 r.in.buffer = NULL;
2618                 r.in.offered = 0;
2619                 r.out.needed = &needed;
2620                 r.out.count = &count;
2621                 r.out.info = &info;
2622
2623                 torture_comment(tctx, "Testing EnumPrinterDrivers level %u\n", r.in.level);
2624
2625                 status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2626
2627                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2628
2629                 if (W_ERROR_EQUAL(r.out.result, WERR_INSUFFICIENT_BUFFER)) {
2630                         DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2631                         data_blob_clear(&blob);
2632                         r.in.buffer = &blob;
2633                         r.in.offered = needed;
2634                         status = dcerpc_spoolss_EnumPrinterDrivers(p, tctx, &r);
2635                 }
2636
2637                 torture_assert_ntstatus_ok(tctx, status, "EnumPrinterDrivers failed");
2638
2639                 torture_assert_werr_ok(tctx, r.out.result, "EnumPrinterDrivers failed");
2640
2641                 if (!info) {
2642                         torture_comment(tctx, "No printer drivers returned\n");
2643                         break;
2644                 }
2645         }
2646
2647         return true;
2648 }
2649
2650 static bool test_DeletePrinter(struct torture_context *tctx,
2651                                struct dcerpc_pipe *p,
2652                                struct policy_handle *handle)
2653 {
2654         struct spoolss_DeletePrinter r;
2655
2656         torture_comment(tctx, "Testing DeletePrinter\n");
2657
2658         r.in.handle = handle;
2659
2660         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_DeletePrinter(p, tctx, &r),
2661                 "failed to delete printer");
2662         torture_assert_werr_ok(tctx, r.out.result,
2663                 "failed to delete printer");
2664
2665         return true;
2666 }
2667
2668 static bool test_EnumPrinters_findname(struct torture_context *tctx,
2669                                        struct dcerpc_pipe *p,
2670                                        uint32_t flags,
2671                                        uint32_t level,
2672                                        const char *name,
2673                                        bool *found)
2674 {
2675         struct spoolss_EnumPrinters e;
2676         uint32_t count;
2677         union spoolss_PrinterInfo *info;
2678         uint32_t needed;
2679         int i;
2680
2681         *found = false;
2682
2683         e.in.flags = flags;
2684         e.in.server = NULL;
2685         e.in.level = level;
2686         e.in.buffer = NULL;
2687         e.in.offered = 0;
2688         e.out.count = &count;
2689         e.out.info = &info;
2690         e.out.needed = &needed;
2691
2692         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2693                 "failed to enum printers");
2694
2695         if (W_ERROR_EQUAL(e.out.result, WERR_INSUFFICIENT_BUFFER)) {
2696                 DATA_BLOB blob = data_blob_talloc(tctx, NULL, needed);
2697                 data_blob_clear(&blob);
2698                 e.in.buffer = &blob;
2699                 e.in.offered = needed;
2700
2701                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinters(p, tctx, &e),
2702                         "failed to enum printers");
2703         }
2704
2705         torture_assert_werr_ok(tctx, e.out.result,
2706                 "failed to enum printers");
2707
2708         for (i=0; i < count; i++) {
2709
2710                 const char *current = NULL;
2711
2712                 switch (level) {
2713                 case 1:
2714                         current = info[i].info1.name;
2715                         break;
2716                 }
2717
2718                 if (strequal(current, name)) {
2719                         *found = true;
2720                         break;
2721                 }
2722         }
2723
2724         return true;
2725 }
2726
2727 static bool test_AddPrinter_wellknown(struct torture_context *tctx,
2728                                       struct dcerpc_pipe *p,
2729                                       const char *printername,
2730                                       bool ex)
2731 {
2732         WERROR result;
2733         struct spoolss_AddPrinter r;
2734         struct spoolss_AddPrinterEx rex;
2735         struct spoolss_SetPrinterInfoCtr info_ctr;
2736         struct spoolss_SetPrinterInfo1 info1;
2737         struct spoolss_DevmodeContainer devmode_ctr;
2738         struct sec_desc_buf secdesc_ctr;
2739         struct spoolss_UserLevelCtr userlevel_ctr;
2740         struct policy_handle handle;
2741         bool found = false;
2742
2743         ZERO_STRUCT(devmode_ctr);
2744         ZERO_STRUCT(secdesc_ctr);
2745         ZERO_STRUCT(userlevel_ctr);
2746         ZERO_STRUCT(info1);
2747
2748         torture_comment(tctx, "Testing AddPrinter%s level 1\n", ex ? "Ex":"");
2749
2750         /* try to add printer to wellknown printer list (level 1) */
2751
2752         userlevel_ctr.level = 1;
2753
2754         info_ctr.info.info1 = &info1;
2755         info_ctr.level = 1;
2756
2757         rex.in.server = NULL;
2758         rex.in.info_ctr = &info_ctr;
2759         rex.in.devmode_ctr = &devmode_ctr;
2760         rex.in.secdesc_ctr = &secdesc_ctr;
2761         rex.in.userlevel_ctr = &userlevel_ctr;
2762         rex.out.handle = &handle;
2763
2764         r.in.server = NULL;
2765         r.in.info_ctr = &info_ctr;
2766         r.in.devmode_ctr = &devmode_ctr;
2767         r.in.secdesc_ctr = &secdesc_ctr;
2768         r.out.handle = &handle;
2769
2770         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2771                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2772                 "failed to add printer");
2773         result = ex ? rex.out.result : r.out.result;
2774         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2775                 "unexpected result code");
2776
2777         info1.name = printername;
2778         info1.flags = PRINTER_ATTRIBUTE_SHARED;
2779
2780         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2781                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2782                 "failed to add printer");
2783         result = ex ? rex.out.result : r.out.result;
2784         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2785                 "unexpected result code");
2786
2787         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2788            better do a real check to see the printer is really there */
2789
2790         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2791                                                         PRINTER_ENUM_NETWORK, 1,
2792                                                         printername,
2793                                                         &found),
2794                         "failed to enum printers");
2795
2796         torture_assert(tctx, found, "failed to find newly added printer");
2797
2798         info1.flags = 0;
2799
2800         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2801                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2802                 "failed to add printer");
2803         result = ex ? rex.out.result : r.out.result;
2804         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2805                 "unexpected result code");
2806
2807         /* bizarre protocol, WERR_PRINTER_ALREADY_EXISTS means success here,
2808            better do a real check to see the printer has really been removed
2809            from the well known printer list */
2810
2811         found = false;
2812
2813         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2814                                                         PRINTER_ENUM_NETWORK, 1,
2815                                                         printername,
2816                                                         &found),
2817                         "failed to enum printers");
2818 #if 0
2819         torture_assert(tctx, !found, "printer still in well known printer list");
2820 #endif
2821         return true;
2822 }
2823
2824 static bool test_AddPrinter_normal(struct torture_context *tctx,
2825                                    struct dcerpc_pipe *p,
2826                                    struct policy_handle *handle_p,
2827                                    const char *printername,
2828                                    const char *drivername,
2829                                    const char *portname,
2830                                    bool ex)
2831 {
2832         WERROR result;
2833         struct spoolss_AddPrinter r;
2834         struct spoolss_AddPrinterEx rex;
2835         struct spoolss_SetPrinterInfoCtr info_ctr;
2836         struct spoolss_SetPrinterInfo2 info2;
2837         struct spoolss_DevmodeContainer devmode_ctr;
2838         struct sec_desc_buf secdesc_ctr;
2839         struct spoolss_UserLevelCtr userlevel_ctr;
2840         struct policy_handle handle;
2841         bool found = false;
2842
2843         ZERO_STRUCT(devmode_ctr);
2844         ZERO_STRUCT(secdesc_ctr);
2845         ZERO_STRUCT(userlevel_ctr);
2846
2847         torture_comment(tctx, "Testing AddPrinter%s level 2\n", ex ? "Ex":"");
2848
2849         userlevel_ctr.level = 1;
2850
2851         rex.in.server = NULL;
2852         rex.in.info_ctr = &info_ctr;
2853         rex.in.devmode_ctr = &devmode_ctr;
2854         rex.in.secdesc_ctr = &secdesc_ctr;
2855         rex.in.userlevel_ctr = &userlevel_ctr;
2856         rex.out.handle = &handle;
2857
2858         r.in.server = NULL;
2859         r.in.info_ctr = &info_ctr;
2860         r.in.devmode_ctr = &devmode_ctr;
2861         r.in.secdesc_ctr = &secdesc_ctr;
2862         r.out.handle = &handle;
2863
2864  again:
2865
2866         /* try to add printer to printer list (level 2) */
2867
2868         ZERO_STRUCT(info2);
2869
2870         info_ctr.info.info2 = &info2;
2871         info_ctr.level = 2;
2872
2873         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2874                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2875                 "failed to add printer");
2876         result = ex ? rex.out.result : r.out.result;
2877         torture_assert_werr_equal(tctx, result, WERR_INVALID_PRINTER_NAME,
2878                 "unexpected result code");
2879
2880         info2.printername = printername;
2881
2882         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2883                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2884                 "failed to add printer");
2885         result = ex ? rex.out.result : r.out.result;
2886
2887         if (W_ERROR_EQUAL(result, WERR_PRINTER_ALREADY_EXISTS)) {
2888                 struct policy_handle printer_handle;
2889
2890                 torture_assert(tctx, call_OpenPrinterEx(tctx, p, printername, &printer_handle),
2891                         "failed to open printer handle");
2892
2893                 torture_assert(tctx, test_DeletePrinter(tctx, p, &printer_handle),
2894                         "failed to delete printer");
2895
2896                 torture_assert(tctx, test_ClosePrinter(tctx, p, &printer_handle),
2897                         "failed to close server handle");
2898
2899                 goto again;
2900         }
2901
2902         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PORT,
2903                 "unexpected result code");
2904
2905         info2.portname = portname;
2906
2907         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2908                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2909                 "failed to add printer");
2910         result = ex ? rex.out.result : r.out.result;
2911         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTER_DRIVER,
2912                 "unexpected result code");
2913
2914         info2.drivername = drivername;
2915
2916         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2917                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2918                 "failed to add printer");
2919         result = ex ? rex.out.result : r.out.result;
2920         torture_assert_werr_equal(tctx, result, WERR_UNKNOWN_PRINTPROCESSOR,
2921                 "unexpected result code");
2922
2923         info2.printprocessor = "winprint";
2924
2925         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2926                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2927                 "failed to add printer");
2928         result = ex ? rex.out.result : r.out.result;
2929         torture_assert_werr_ok(tctx, result,
2930                 "failed to add printer");
2931
2932         *handle_p = handle;
2933
2934         /* we are paranoid, really check if the printer is there now */
2935
2936         torture_assert(tctx, test_EnumPrinters_findname(tctx, p,
2937                                                         PRINTER_ENUM_LOCAL, 1,
2938                                                         printername,
2939                                                         &found),
2940                         "failed to enum printers");
2941         torture_assert(tctx, found, "failed to find newly added printer");
2942
2943         torture_assert_ntstatus_ok(tctx, ex ? dcerpc_spoolss_AddPrinterEx(p, tctx, &rex) :
2944                                               dcerpc_spoolss_AddPrinter(p, tctx, &r),
2945                 "failed to add printer");
2946         result = ex ? rex.out.result : r.out.result;
2947         torture_assert_werr_equal(tctx, result, WERR_PRINTER_ALREADY_EXISTS,
2948                 "unexpected result code");
2949
2950         return true;
2951 }
2952
2953 static bool test_AddPrinterEx(struct torture_context *tctx,
2954                               struct dcerpc_pipe *p,
2955                               struct policy_handle *handle_p,
2956                               const char *printername,
2957                               const char *drivername,
2958                               const char *portname)
2959 {
2960         bool ret = true;
2961
2962         if (!torture_setting_bool(tctx, "samba3", false)) {
2963                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER_EX, true)) {
2964                         torture_comment(tctx, "failed to add printer to well known list\n");
2965                         ret = false;
2966                 }
2967         }
2968
2969         if (!test_AddPrinter_normal(tctx, p, handle_p,
2970                                     printername, drivername, portname,
2971                                     true)) {
2972                 torture_comment(tctx, "failed to add printer to printer list\n");
2973                 ret = false;
2974         }
2975
2976         return ret;
2977 }
2978
2979 static bool test_AddPrinter(struct torture_context *tctx,
2980                             struct dcerpc_pipe *p,
2981                             struct policy_handle *handle_p,
2982                             const char *printername,
2983                             const char *drivername,
2984                             const char *portname)
2985 {
2986         bool ret = true;
2987
2988         if (!torture_setting_bool(tctx, "samba3", false)) {
2989                 if (!test_AddPrinter_wellknown(tctx, p, TORTURE_WELLKNOWN_PRINTER, false)) {
2990                         torture_comment(tctx, "failed to add printer to well known list\n");
2991                         ret = false;
2992                 }
2993         }
2994
2995         if (!test_AddPrinter_normal(tctx, p, handle_p,
2996                                     printername, drivername, portname,
2997                                     false)) {
2998                 torture_comment(tctx, "failed to add printer to printer list\n");
2999                 ret = false;
3000         }
3001
3002         return ret;
3003 }
3004
3005 static bool test_printer_info(struct torture_context *tctx,
3006                               struct dcerpc_pipe *p,
3007                               struct policy_handle *handle)
3008 {
3009         bool ret = true;
3010
3011         if (!test_PrinterInfo(tctx, p, handle)) {
3012                 ret = false;
3013         }
3014
3015         if (!test_SetPrinter_errors(tctx, p, handle)) {
3016                 ret = false;
3017         }
3018
3019         return ret;
3020 }
3021
3022 bool test_printer_keys(struct torture_context *tctx,
3023                        struct dcerpc_pipe *p,
3024                        struct policy_handle *handle)
3025 {
3026         const char **key_array = NULL;
3027         int i;
3028
3029         {
3030                 struct spoolss_EnumPrinterKey r;
3031                 uint32_t needed;
3032                 struct spoolss_StringArray2 key_buffer;
3033
3034                 r.in.handle = handle;
3035                 r.in.key_name = "";
3036                 r.in.offered = 0;
3037                 r.out.key_buffer = &key_buffer;
3038                 r.out.needed = &needed;
3039
3040                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3041                         "failed to call EnumPrinterKey");
3042                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3043                         torture_assert(tctx, (key_buffer._ndr_size == 0),
3044                                 talloc_asprintf(tctx, "EnumPrinterKey did not return 0 _ndr_size (but %d), windows clients would abort here!", key_buffer._ndr_size));
3045
3046                         r.in.offered = needed;
3047                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterKey(p, tctx, &r),
3048                                 "failed to call EnumPrinterKey");
3049                 }
3050                 torture_assert_werr_ok(tctx, r.out.result,
3051                         "failed to call EnumPrinterKey");
3052
3053                 torture_assert(tctx, (key_buffer._ndr_size * 2 == needed),
3054                         talloc_asprintf(tctx, "EnumPrinterKey size mismatch, _ndr_size %d (expected %d)",
3055                         key_buffer._ndr_size, needed/2));
3056
3057                 key_array = key_buffer.string;
3058         }
3059
3060         for (i=0; key_array && key_array[i]; i++) {
3061                 struct spoolss_EnumPrinterDataEx r;
3062                 uint32_t count;
3063                 struct spoolss_PrinterEnumValues *info;
3064                 uint32_t needed;
3065
3066                 r.in.handle = handle;
3067                 r.in.key_name = key_array[i];
3068                 r.in.offered = 0;
3069                 r.out.count = &count;
3070                 r.out.info = &info;
3071                 r.out.needed = &needed;
3072
3073                 torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3074                         "failed to call EnumPrinterDataEx");
3075                 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
3076                         r.in.offered = needed;
3077                         torture_assert_ntstatus_ok(tctx, dcerpc_spoolss_EnumPrinterDataEx(p, tctx, &r),
3078                                 "failed to call EnumPrinterDataEx");
3079                 }
3080                 torture_assert_werr_ok(tctx, r.out.result,
3081                         "failed to call EnumPrinterDataEx");
3082         }
3083
3084         return true;
3085 }
3086
3087 static bool test_printer(struct torture_context *tctx,
3088                          struct dcerpc_pipe *p)
3089 {
3090         bool ret = true;
3091         struct policy_handle handle[2];
3092         bool found = false;
3093         const char *drivername = "Microsoft XPS Document Writer";
3094         const char *portname = "LPT1:";
3095
3096         /* test printer created via AddPrinter */
3097
3098         if (!test_AddPrinter(tctx, p, &handle[0], TORTURE_PRINTER, drivername, portname)) {
3099                 return false;
3100         }
3101
3102         if (!test_printer_info(tctx, p, &handle[0])) {
3103                 ret = false;
3104         }
3105
3106         if (!test_printer_keys(tctx, p, &handle[0])) {
3107                 ret = false;
3108         }
3109
3110         if (!test_DeletePrinter(tctx, p, &handle[0])) {
3111                 ret = false;
3112         }
3113
3114         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3115                                         TORTURE_PRINTER, &found)) {
3116                 ret = false;
3117         }
3118
3119         torture_assert(tctx, !found, "deleted printer still there");
3120
3121         /* test printer created via AddPrinterEx */
3122
3123         if (!test_AddPrinterEx(tctx, p, &handle[1], TORTURE_PRINTER_EX, drivername, portname)) {
3124                 return false;
3125         }
3126
3127         if (!test_printer_info(tctx, p, &handle[1])) {
3128                 ret = false;
3129         }
3130
3131         if (!test_printer_keys(tctx, p, &handle[1])) {
3132                 ret = false;
3133         }
3134
3135         if (!test_DeletePrinter(tctx, p, &handle[1])) {
3136                 ret = false;
3137         }
3138
3139         if (!test_EnumPrinters_findname(tctx, p, PRINTER_ENUM_LOCAL, 1,
3140                                         TORTURE_PRINTER_EX, &found)) {
3141                 ret = false;
3142         }
3143
3144         torture_assert(tctx, !found, "deleted printer still there");
3145
3146         return ret;
3147 }
3148
3149 bool torture_rpc_spoolss(struct torture_context *torture)
3150 {
3151         NTSTATUS status;
3152         struct dcerpc_pipe *p;
3153         bool ret = true;
3154         struct test_spoolss_context *ctx;
3155
3156         status = torture_rpc_connection(torture, &p, &ndr_table_spoolss);
3157         if (!NT_STATUS_IS_OK(status)) {
3158                 return false;
3159         }
3160
3161         ctx = talloc_zero(torture, struct test_spoolss_context);
3162
3163         ret &= test_OpenPrinter_server(torture, p, &ctx->server_handle);
3164
3165         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "W3SvcInstalled");
3166         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "BeepEnabled");
3167         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "EventLog");
3168         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopup");
3169         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "NetPopupToComputer");
3170         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MajorVersion");
3171         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "MinorVersion");
3172         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DefaultSpoolDirectory");
3173         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "Architecture");
3174         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DsPresent");
3175         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersion");
3176         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "OSVersionEx");
3177         ret &= test_GetPrinterData(torture, p, &ctx->server_handle, "DNSMachineName");
3178         ret &= test_EnumForms(torture, p, &ctx->server_handle, true);
3179         ret &= test_AddForm(torture, p, &ctx->server_handle, true);
3180         ret &= test_EnumPorts(torture, p, ctx);
3181         ret &= test_GetPrinterDriverDirectory(torture, p, ctx);
3182         ret &= test_GetPrintProcessorDirectory(torture, p, ctx);
3183         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_NT_X86);
3184         ret &= test_EnumPrinterDrivers(torture, p, ctx, SPOOLSS_ARCHITECTURE_ALL);
3185         ret &= test_EnumMonitors(torture, p, ctx);
3186         ret &= test_EnumPrintProcessors(torture, p, ctx);
3187         ret &= test_EnumPrintProcDataTypes(torture, p, ctx);
3188         ret &= test_EnumPrinters(torture, p, ctx);
3189         ret &= test_OpenPrinter_badname(torture, p, "__INVALID_PRINTER__");
3190         ret &= test_OpenPrinter_badname(torture, p, "\\\\__INVALID_HOST__");
3191         ret &= test_OpenPrinter_badname(torture, p, "");
3192         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\");
3193         ret &= test_OpenPrinter_badname(torture, p, "\\\\\\__INVALID_PRINTER__");
3194         ret &= test_OpenPrinter_badname(torture, p, talloc_asprintf(torture, "\\\\%s\\", dcerpc_server_name(p)));
3195         ret &= test_OpenPrinter_badname(torture, p,
3196                                         talloc_asprintf(torture, "\\\\%s\\__INVALID_PRINTER__", dcerpc_server_name(p)));
3197
3198
3199         ret &= test_AddPort(torture, p);
3200         ret &= test_EnumPorts_old(torture, p);
3201         ret &= test_EnumPrinters_old(torture, p);
3202         ret &= test_EnumPrinterDrivers_old(torture, p);
3203
3204         return ret;
3205 }
3206
3207 struct torture_suite *torture_rpc_spoolss_printer(TALLOC_CTX *mem_ctx)
3208 {
3209         struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-PRINTER");
3210
3211         struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
3212                                                         "printer", &ndr_table_spoolss);
3213
3214         torture_rpc_tcase_add_test(tcase, "printer", test_printer);
3215
3216         return suite;
3217 }