d80f2f74c653a441e44c4d68b391373ee3e5e439
[samba.git] / source4 / torture / rpc / iremotewinspool.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for iremotewinspool rpc operations
4
5    Copyright (C) Guenther Deschner 2013
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "librpc/gen_ndr/ndr_winspool.h"
24 #include "librpc/gen_ndr/ndr_winspool_c.h"
25 #include "librpc/gen_ndr/ndr_spoolss_c.h"
26 #include "torture/rpc/torture_rpc.h"
27 #include "libcli/registry/util_reg.h"
28
29 struct test_iremotewinspool_context {
30         struct GUID object_uuid;
31         struct dcerpc_pipe *iremotewinspool_pipe;
32         struct policy_handle server_handle;
33         const char *environment;
34 };
35
36 enum client_os_version
37 {
38         WIN_2000,
39         WIN_VISTA,
40         WIN_SERVER_2008,
41         WIN_7,
42         WIN_SERVER_2008R2,
43         WIN_8,
44         WIN_SERVER_2012,
45         WIN_10,
46         WIN_SERVER_2016
47 };
48
49 static struct spoolss_UserLevel1 test_get_client_info(struct torture_context *tctx,
50                                                       enum client_os_version os,
51                                                       enum spoolss_MajorVersion major_number,
52                                                       enum spoolss_MinorVersion minor_number)
53 {
54         struct spoolss_UserLevel1 level1;
55
56         level1.size     = 28;
57         level1.client   = talloc_asprintf(tctx, "\\\\%s", "mthelena");
58         level1.user     = "GD";
59         level1.processor = PROCESSOR_ARCHITECTURE_AMD64;
60         level1.major    = major_number;
61         level1.minor    = minor_number;
62
63         switch (os) {
64                 case WIN_SERVER_2016:
65                 case WIN_10:
66                         level1.build = 10586;
67                         break;
68                 case WIN_SERVER_2012:
69                 case WIN_8:
70                         level1.build = 9200;
71                         break;
72                 case WIN_SERVER_2008R2:
73                 case WIN_7:
74                         level1.build = 7007;
75                         break;
76                 case WIN_SERVER_2008:
77                 case WIN_VISTA:
78                         level1.build = 6000;
79                         break;
80                 case WIN_2000:
81                         level1.build = 1382;
82                         break;
83                 default:
84                         level1.build = 7007;
85         }
86
87         return level1;
88 }
89
90 static bool test_AsyncOpenPrinter_byprinter(struct torture_context *tctx,
91                                             struct test_iremotewinspool_context *ctx,
92                                             struct dcerpc_pipe *p,
93                                             const char *printer_name,
94                                             struct spoolss_UserLevel1 cinfo,
95                                             struct policy_handle *handle)
96 {
97         struct dcerpc_binding_handle *b = p->binding_handle;
98         struct spoolss_DevmodeContainer devmode_ctr;
99         struct spoolss_UserLevelCtr client_info_ctr;
100         uint32_t access_mask = SERVER_ALL_ACCESS;
101         struct winspool_AsyncOpenPrinter r;
102
103         ZERO_STRUCT(devmode_ctr);
104
105         client_info_ctr.level = 1;
106         client_info_ctr.user_info.level1 = &cinfo;
107
108         r.in.pPrinterName       = printer_name;
109         r.in.pDatatype          = NULL;
110         r.in.pDevModeContainer  = &devmode_ctr;
111         r.in.AccessRequired     = access_mask;
112         r.in.pClientInfo        = &client_info_ctr;
113         r.out.pHandle           = handle;
114
115         torture_assert_ntstatus_ok(tctx,
116                 dcerpc_winspool_AsyncOpenPrinter_r(b, tctx, &r),
117                 "AsyncOpenPrinter failed");
118         torture_assert_werr_ok(tctx, r.out.result,
119                 "AsyncOpenPrinter failed");
120
121         return true;
122 }
123
124 static bool test_AsyncClosePrinter_byhandle(struct torture_context *tctx,
125                                             struct test_iremotewinspool_context *ctx,
126                                             struct dcerpc_pipe *p,
127                                             struct policy_handle *handle)
128 {
129         struct dcerpc_binding_handle *b = p->binding_handle;
130
131         struct winspool_AsyncClosePrinter r;
132
133         r.in.phPrinter = handle;
134         r.out.phPrinter = handle;
135
136         torture_assert_ntstatus_ok(tctx,
137                 dcerpc_winspool_AsyncClosePrinter_r(b, tctx, &r),
138                 "AsyncClosePrinter failed");
139         torture_assert_werr_ok(tctx, r.out.result,
140                 "AsyncClosePrinter failed");
141
142         return true;
143 }
144
145 static bool test_AsyncGetPrinterData_checktype(struct torture_context *tctx,
146                                                struct dcerpc_binding_handle *b,
147                                                struct policy_handle *handle,
148                                                const char *value_name,
149                                                enum winreg_Type *expected_type,
150                                                enum winreg_Type *type_p,
151                                                uint8_t **data_p,
152                                                uint32_t *needed_p)
153 {
154         struct winspool_AsyncGetPrinterData r;
155         enum winreg_Type type;
156         uint32_t needed;
157
158         r.in.hPrinter = *handle;
159         r.in.pValueName = value_name;
160         r.in.nSize = 0;
161         r.out.pType = &type;
162         r.out.pData = talloc_zero_array(tctx, uint8_t, r.in.nSize);
163         r.out.pcbNeeded = &needed;
164
165         torture_comment(tctx, "Testing AsyncGetPrinterData(%s)\n",
166                 r.in.pValueName);
167
168         torture_assert_ntstatus_ok(tctx,
169                 dcerpc_winspool_AsyncGetPrinterData_r(b, tctx, &r),
170                 "AsyncGetPrinterData failed");
171
172         if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
173                 if (expected_type) {
174                         torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
175                 }
176                 r.in.nSize = needed;
177                 r.out.pData = talloc_zero_array(tctx, uint8_t, r.in.nSize);
178
179                 torture_assert_ntstatus_ok(tctx,
180                         dcerpc_winspool_AsyncGetPrinterData_r(b, tctx, &r),
181                         "AsyncGetPrinterData failed");
182         }
183
184         torture_assert_werr_ok(tctx, r.out.result,
185                 "AsyncGetPrinterData failed");
186
187         if (type_p) {
188                 *type_p = type;
189         }
190
191         if (data_p) {
192                 *data_p = r.out.pData;
193         }
194
195         if (needed_p) {
196                 *needed_p = needed;
197         }
198
199         return true;
200 }
201
202 static bool test_AsyncGetPrinterData_args(struct torture_context *tctx,
203                                           struct dcerpc_binding_handle *b,
204                                           struct policy_handle *handle,
205                                           const char *value_name,
206                                           enum winreg_Type *type_p,
207                                           uint8_t **data_p,
208                                           uint32_t *needed_p)
209 {
210         return test_AsyncGetPrinterData_checktype(tctx, b, handle,
211                                                   value_name,
212                                                   NULL,
213                                                   type_p, data_p, needed_p);
214 }
215
216 static bool test_get_environment(struct torture_context *tctx,
217                                  struct dcerpc_binding_handle *b,
218                                  struct policy_handle *handle,
219                                  const char **architecture)
220 {
221         DATA_BLOB blob;
222         enum winreg_Type type;
223         uint8_t *data;
224         uint32_t needed;
225
226         torture_assert(tctx,
227                 test_AsyncGetPrinterData_args(tctx, b, handle, "Architecture", &type, &data, &needed),
228                 "failed to get Architecture");
229
230         torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
231
232         blob = data_blob_const(data, needed);
233
234         torture_assert(tctx,
235                 pull_reg_sz(tctx, &blob, architecture),
236                 "failed to pull environment");
237
238         return true;
239 }
240
241 static bool torture_rpc_iremotewinspool_setup_common(struct torture_context *tctx,
242                                                      struct test_iremotewinspool_context *t)
243 {
244         const char *printer_name;
245         struct spoolss_UserLevel1 client_info;
246         struct dcerpc_binding *binding;
247
248         torture_assert_ntstatus_ok(tctx,
249                 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &t->object_uuid),
250                 "failed to parse GUID");
251
252         torture_assert_ntstatus_ok(tctx,
253                 torture_rpc_binding(tctx, &binding),
254                 "failed to retrieve torture binding");
255
256         torture_assert_ntstatus_ok(tctx,
257                 dcerpc_binding_set_object(binding, t->object_uuid),
258                 "failed to set object_uuid");
259
260         torture_assert_ntstatus_ok(tctx,
261                 torture_rpc_connection_with_binding(tctx, binding, &t->iremotewinspool_pipe, &ndr_table_iremotewinspool),
262                 "Error connecting to server");
263
264         printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(t->iremotewinspool_pipe));
265
266         client_info = test_get_client_info(tctx, WIN_2000, 3, SPOOLSS_MINOR_VERSION_0);
267
268         torture_assert(tctx,
269                 test_AsyncOpenPrinter_byprinter(tctx, t,
270                                                 t->iremotewinspool_pipe, printer_name,
271                                                 client_info, &t->server_handle),
272                                                 "failed to open printserver");
273         torture_assert(tctx,
274                 test_get_environment(tctx,
275                                      t->iremotewinspool_pipe->binding_handle,
276                                      &t->server_handle, &t->environment),
277                                      "failed to get environment");
278
279         return true;
280 }
281
282 static bool torture_rpc_iremotewinspool_setup(struct torture_context *tctx,
283                                               void **data)
284 {
285         struct test_iremotewinspool_context *t;
286
287         *data = t = talloc_zero(tctx, struct test_iremotewinspool_context);
288
289         return torture_rpc_iremotewinspool_setup_common(tctx, t);
290 }
291
292 static bool torture_rpc_iremotewinspool_teardown_common(struct torture_context *tctx,
293                                                         struct test_iremotewinspool_context *t)
294 {
295
296         test_AsyncClosePrinter_byhandle(tctx, t, t->iremotewinspool_pipe, &t->server_handle);
297
298         return true;
299 }
300
301 static bool torture_rpc_iremotewinspool_teardown(struct torture_context *tctx,
302                                                  void *data)
303 {
304         struct test_iremotewinspool_context *t = talloc_get_type(data, struct test_iremotewinspool_context);
305         bool ret;
306
307         ret = torture_rpc_iremotewinspool_teardown_common(tctx, t);
308         talloc_free(t);
309
310         return ret;
311 }
312
313 static bool test_AsyncClosePrinter(struct torture_context *tctx,
314                                    void *private_data)
315 {
316         struct test_iremotewinspool_context *ctx =
317                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
318
319         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
320         const char *printer_name;
321         struct spoolss_UserLevel1 client_info;
322         struct policy_handle handle;
323
324         printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
325
326         client_info = test_get_client_info(tctx, WIN_2000, 3, SPOOLSS_MINOR_VERSION_0);
327
328         torture_assert(tctx,
329                 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
330                 "failed to test AsyncOpenPrinter");
331
332         torture_assert(tctx,
333                 test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle),
334                 "failed to test AsyncClosePrinter");
335
336         return true;
337 }
338
339 static bool test_AsyncOpenPrinter(struct torture_context *tctx,
340                                   void *private_data)
341 {
342         struct test_iremotewinspool_context *ctx =
343                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
344
345         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
346         const char *printer_name;
347         struct spoolss_UserLevel1 client_info;
348         struct policy_handle handle;
349
350         printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
351
352         client_info = test_get_client_info(tctx, WIN_2000, 3, SPOOLSS_MINOR_VERSION_0);
353
354         torture_assert(tctx,
355                 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
356                 "failed to test AsyncOpenPrinter");
357
358         test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle);
359
360         return true;
361 }
362
363 static struct spoolss_NotifyOption *setup_printserver_NotifyOption(struct torture_context *tctx)
364 {
365         struct spoolss_NotifyOption *o;
366
367         o = talloc_zero(tctx, struct spoolss_NotifyOption);
368         if (o == NULL) {
369                 return NULL;
370         }
371
372         o->version = 2;
373         o->flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
374
375         o->count = 2;
376         o->types = talloc_zero_array(o, struct spoolss_NotifyOptionType, o->count);
377         if (o->types == NULL) {
378                 talloc_free(o);
379                 return NULL;
380         }
381
382         o->types[0].type = PRINTER_NOTIFY_TYPE;
383         o->types[0].count = 1;
384         o->types[0].fields = talloc_array(o->types, union spoolss_Field, o->types[0].count);
385         if (o->types[0].fields == NULL) {
386                 talloc_free(o);
387                 return NULL;
388         }
389         o->types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
390
391         o->types[1].type = JOB_NOTIFY_TYPE;
392         o->types[1].count = 1;
393         o->types[1].fields = talloc_array(o->types, union spoolss_Field, o->types[1].count);
394         if (o->types[1].fields == NULL) {
395                 talloc_free(o);
396                 return NULL;
397         }
398         o->types[1].fields[0].field = JOB_NOTIFY_FIELD_MACHINE_NAME;
399
400         return o;
401 }
402
403 static bool test_SyncUnRegisterForRemoteNotifications_args(struct torture_context *tctx,
404                                                            struct dcerpc_pipe *p,
405                                                            struct policy_handle *notify_handle)
406 {
407         struct winspool_SyncUnRegisterForRemoteNotifications r;
408         struct dcerpc_binding_handle *b = p->binding_handle;
409
410         r.in.phRpcHandle = notify_handle;
411         r.out.phRpcHandle = notify_handle;
412
413         torture_assert_ntstatus_ok(tctx,
414                 dcerpc_winspool_SyncUnRegisterForRemoteNotifications_r(b, tctx, &r),
415                 "SyncUnRegisterForRemoteNotifications failed");
416         torture_assert_hresult_ok(tctx, r.out.result,
417                 "SyncUnRegisterForRemoteNotifications failed");
418
419         return true;
420 }
421
422 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
423                                                          struct dcerpc_pipe *p,
424                                                          struct policy_handle *server_handle,
425                                                          struct policy_handle *notify_handle);
426
427 static bool test_SyncUnRegisterForRemoteNotifications(struct torture_context *tctx,
428                                                       void *private_data)
429 {
430         struct test_iremotewinspool_context *ctx =
431                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
432         struct policy_handle notify_handle;
433
434         torture_assert(tctx,
435                 test_SyncRegisterForRemoteNotifications_args(tctx,
436                                                              ctx->iremotewinspool_pipe,
437                                                              &ctx->server_handle,
438                                                              &notify_handle),
439                 "failed to test SyncRegisterForRemoteNotifications");
440
441         torture_assert(tctx,
442                 test_SyncUnRegisterForRemoteNotifications_args(tctx,
443                                                                ctx->iremotewinspool_pipe,
444                                                                &notify_handle),
445                 "failed to test UnSyncRegisterForRemoteNotifications");
446
447         return true;
448 }
449
450 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
451                                                          struct dcerpc_pipe *p,
452                                                          struct policy_handle *server_handle,
453                                                          struct policy_handle *notify_handle)
454 {
455         struct dcerpc_binding_handle *b = p->binding_handle;
456
457         struct winspool_SyncRegisterForRemoteNotifications r;
458         struct winspool_PrintPropertiesCollection NotifyFilter;
459         struct winspool_PrintNamedProperty *c;
460         struct spoolss_NotifyOption *options;
461
462         ZERO_STRUCT(NotifyFilter);
463
464         options = setup_printserver_NotifyOption(tctx);
465         torture_assert(tctx, options, "out of memory");
466
467         c = talloc_zero_array(tctx, struct winspool_PrintNamedProperty, 4);
468         torture_assert(tctx, c, "out of memory");
469
470         c[0].propertyName = "RemoteNotifyFilter Flags";
471         c[0].propertyValue.PropertyType = winspool_PropertyTypeInt32;
472         c[0].propertyValue.value.propertyInt32 = 0xff;
473
474         c[1].propertyName = "RemoteNotifyFilter Options";
475         c[1].propertyValue.PropertyType = winspool_PropertyTypeInt32;
476         c[1].propertyValue.value.propertyInt32 = 0;
477
478         c[2].propertyName = "RemoteNotifyFilter Color";
479         c[2].propertyValue.PropertyType = winspool_PropertyTypeInt32;
480         c[2].propertyValue.value.propertyInt32 = 0;
481
482         c[3].propertyName = "RemoteNotifyFilter NotifyOptions";
483         c[3].propertyValue.PropertyType = winspool_PropertyTypeNotificationOptions;
484         c[3].propertyValue.value.propertyOptionsContainer.pOptions = options;
485
486         NotifyFilter.numberOfProperties = 4;
487         NotifyFilter.propertiesCollection = c;
488
489         r.in.hPrinter = *server_handle;
490         r.in.pNotifyFilter = &NotifyFilter;
491         r.out.phRpcHandle = notify_handle;
492
493         torture_assert_ntstatus_ok(tctx,
494                 dcerpc_winspool_SyncRegisterForRemoteNotifications_r(b, tctx, &r),
495                 "SyncRegisterForRemoteNotifications failed");
496         torture_assert_hresult_ok(tctx, r.out.result,
497                 "SyncRegisterForRemoteNotifications failed");
498
499         return true;
500 }
501
502 static bool test_SyncRegisterForRemoteNotifications(struct torture_context *tctx,
503                                                     void *private_data)
504 {
505         struct test_iremotewinspool_context *ctx =
506                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
507         struct policy_handle notify_handle;
508
509         torture_assert(tctx,
510                 test_SyncRegisterForRemoteNotifications_args(tctx,
511                                                              ctx->iremotewinspool_pipe,
512                                                              &ctx->server_handle,
513                                                              &notify_handle),
514                 "failed to test SyncRegisterForRemoteNotifications");
515
516         test_SyncUnRegisterForRemoteNotifications_args(tctx, ctx->iremotewinspool_pipe, &notify_handle);
517
518         return true;
519 }
520
521 static bool test_AsyncUploadPrinterDriverPackage(struct torture_context *tctx,
522                                                  void *private_data)
523 {
524         struct test_iremotewinspool_context *ctx =
525                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
526
527         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
528         struct dcerpc_binding_handle *b = p->binding_handle;
529
530         struct winspool_AsyncUploadPrinterDriverPackage r;
531         uint32_t pcchDestInfPath = 0;
532
533         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
534         r.in.pszInfPath = "";
535         r.in.pszEnvironment = "";
536         r.in.dwFlags = 0;
537         r.in.pszDestInfPath = NULL;
538         r.in.pcchDestInfPath = &pcchDestInfPath;
539         r.out.pszDestInfPath = NULL;
540         r.out.pcchDestInfPath = &pcchDestInfPath;
541
542         torture_assert_ntstatus_ok(tctx,
543                 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
544                 "AsyncUploadPrinterDriverPackage failed");
545         torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
546                 "AsyncUploadPrinterDriverPackage failed");
547
548         pcchDestInfPath = 260;
549         r.in.pszDestInfPath = talloc_zero_array(tctx, uint16_t, pcchDestInfPath);
550         r.out.pszDestInfPath = talloc_zero_array(tctx, uint16_t, pcchDestInfPath);
551
552         torture_assert_ntstatus_ok(tctx,
553                 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
554                 "AsyncUploadPrinterDriverPackage failed");
555         torture_assert_werr_equal(tctx,
556                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
557                 "AsyncUploadPrinterDriverPackage failed");
558
559         r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
560
561         torture_assert_ntstatus_ok(tctx,
562                 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
563                 "AsyncUploadPrinterDriverPackage failed");
564         torture_assert_werr_equal(tctx,
565                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
566                 "AsyncUploadPrinterDriverPackage failed");
567
568         r.in.pszInfPath = "\\\\mthelena\\print$\\x64\\{BD443844-ED00-4D96-8CAE-95E49492312A}\\prnbrcl1.inf";
569
570         torture_assert_ntstatus_ok(tctx,
571                 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
572                 "AsyncUploadPrinterDriverPackage failed");
573         torture_assert_werr_equal(tctx,
574                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
575                 "AsyncUploadPrinterDriverPackage failed");
576
577         return true;
578 }
579
580 static bool test_AsyncEnumPrinters(struct torture_context *tctx,
581                                    void *private_data)
582 {
583         struct test_iremotewinspool_context *ctx =
584                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
585
586         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
587         struct dcerpc_binding_handle *b = p->binding_handle;
588
589         struct winspool_AsyncEnumPrinters r;
590         uint32_t levels[] = { 1, 2, /*3,*/ 4, 5 };
591         int i;
592
593         uint32_t needed;
594         uint32_t returned;
595
596         for (i = 0; i < ARRAY_SIZE(levels); i++) {
597
598                 r.in.Flags = PRINTER_ENUM_LOCAL;
599                 r.in.pName = NULL;
600                 r.in.Level = levels[i];
601                 r.in.cbBuf = 0;
602                 r.in.pPrinterEnum = NULL;
603                 r.out.pcbNeeded = &needed;
604                 r.out.pcReturned = &returned;
605                 r.out.pPrinterEnum = NULL;
606
607                 torture_assert_ntstatus_ok(tctx,
608                         dcerpc_winspool_AsyncEnumPrinters_r(b, tctx, &r),
609                         "AsyncEnumPrinters failed");
610                 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
611                         "AsyncEnumPrinters failed");
612
613                 r.in.cbBuf = needed;
614                 r.in.pPrinterEnum = talloc_zero_array(tctx, uint8_t, r.in.cbBuf);
615                 r.out.pPrinterEnum = r.in.pPrinterEnum;
616
617                 torture_assert_ntstatus_ok(tctx,
618                         dcerpc_winspool_AsyncEnumPrinters_r(b, tctx, &r),
619                         "AsyncEnumPrinters failed");
620                 torture_assert_werr_ok(tctx, r.out.result,
621                         "AsyncEnumPrinters failed");
622         }
623
624         return true;
625 }
626
627 static bool test_AsyncGetPrinterData(struct torture_context *tctx,
628                                      void *private_data)
629 {
630         struct test_iremotewinspool_context *ctx =
631                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
632
633         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
634         struct dcerpc_binding_handle *b = p->binding_handle;
635         DATA_BLOB blob;
636         const char *s;
637         bool ok;
638
639         uint32_t pType;
640         uint32_t pcbNeeded;
641         uint8_t *pData;
642
643         torture_assert(tctx,
644                 test_AsyncGetPrinterData_args(tctx, b, &ctx->server_handle,
645                                               "MajorVersion",
646                                               &pType, &pData, &pcbNeeded),
647                 "failed to check for MajorVersion");
648
649         torture_assert_int_equal(tctx, pcbNeeded, 4, "pcbNeeded");
650         torture_assert_int_equal(tctx, pType, REG_DWORD, "pType");
651         torture_assert_int_equal(tctx, IVAL(pData, 0), 3, "pData");
652
653         torture_assert(tctx,
654                 test_AsyncGetPrinterData_args(tctx, b, &ctx->server_handle,
655                                               "Architecture",
656                                               &pType, &pData, &pcbNeeded),
657                 "failed to check for Architecture");
658
659         blob = data_blob_const(pData, pcbNeeded);
660
661         torture_assert_int_equal(tctx, pType, REG_SZ, "pType");
662         torture_assert(tctx, pull_reg_sz(tctx, &blob, &s), "");
663         ok = strequal(s, SPOOLSS_ARCHITECTURE_x64) || strequal(s, SPOOLSS_ARCHITECTURE_NT_X86);
664         torture_assert(tctx, ok, "unexpected architecture returned");
665
666         return true;
667 }
668
669 static bool test_AsyncCorePrinterDriverInstalled(struct torture_context *tctx,
670                                                  void *private_data)
671 {
672         struct test_iremotewinspool_context *ctx =
673                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
674
675         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
676         struct dcerpc_binding_handle *b = p->binding_handle;
677
678         struct winspool_AsyncCorePrinterDriverInstalled r;
679         int32_t pbDriverInstalled;
680         struct GUID guid;
681
682         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
683         r.in.pszEnvironment = "";
684         r.in.CoreDriverGUID = GUID_zero();
685         r.in.ftDriverDate = 0;
686         r.in.dwlDriverVersion = 0;
687         r.out.pbDriverInstalled = &pbDriverInstalled;
688
689         torture_assert_ntstatus_ok(tctx,
690                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
691                 "AsyncCorePrinterDriverInstalled failed");
692         torture_assert_werr_equal(tctx,
693                 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
694                 "AsyncCorePrinterDriverInstalled failed");
695
696         r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
697
698         torture_assert_ntstatus_ok(tctx,
699                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
700                 "AsyncCorePrinterDriverInstalled failed");
701         torture_assert_hresult_ok(tctx, r.out.result,
702                 "AsyncCorePrinterDriverInstalled failed");
703         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
704                                 "unexpected driver installed");
705
706         r.in.CoreDriverGUID = GUID_random();
707
708         torture_assert_ntstatus_ok(tctx,
709                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
710                 "AsyncCorePrinterDriverInstalled failed");
711         torture_assert_hresult_ok(tctx, r.out.result,
712                 "AsyncCorePrinterDriverInstalled failed");
713         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
714                                 "unexpected driver installed");
715
716         torture_assert_ntstatus_ok(tctx,
717                 GUID_from_string(SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV, &guid), "");
718
719         r.in.CoreDriverGUID = guid;
720
721         torture_assert_ntstatus_ok(tctx,
722                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
723                 "AsyncCorePrinterDriverInstalled failed");
724         torture_assert_hresult_ok(tctx, r.out.result,
725                 "AsyncCorePrinterDriverInstalled failed");
726         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
727                                 "xps core driver not installed?");
728
729         r.in.dwlDriverVersion = 0xffffffff;
730
731         torture_assert_ntstatus_ok(tctx,
732                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
733                 "AsyncCorePrinterDriverInstalled failed");
734         torture_assert_hresult_ok(tctx, r.out.result,
735                 "AsyncCorePrinterDriverInstalled failed");
736         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
737                                 "xps core driver not installed?");
738
739         r.in.dwlDriverVersion = 1234;
740
741         torture_assert_ntstatus_ok(tctx,
742                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
743                 "AsyncCorePrinterDriverInstalled failed");
744         torture_assert_hresult_ok(tctx, r.out.result,
745                 "AsyncCorePrinterDriverInstalled failed");
746         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
747                                 "xps core driver not installed?");
748
749         r.in.ftDriverDate = unix_timespec_to_nt_time(timespec_current());
750
751         torture_assert_ntstatus_ok(tctx,
752                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
753                 "AsyncCorePrinterDriverInstalled failed");
754         torture_assert_hresult_ok(tctx, r.out.result,
755                 "AsyncCorePrinterDriverInstalled failed");
756         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
757                                 "driver too old ?");
758
759         r.in.dwlDriverVersion = 0;
760
761         torture_assert_ntstatus_ok(tctx,
762                 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
763                 "AsyncCorePrinterDriverInstalled failed");
764         torture_assert_hresult_ok(tctx, r.out.result,
765                 "AsyncCorePrinterDriverInstalled failed");
766         torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
767                                 "unexpected driver installed");
768
769         return true;
770 }
771
772 static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
773                                                     struct dcerpc_pipe *p,
774                                                     const char *architecture,
775                                                     const char *guid_str,
776                                                     const char **package_id)
777 {
778         struct winspool_AsyncGetCorePrinterDrivers r;
779         DATA_BLOB blob;
780         const char **s;
781         struct dcerpc_binding_handle *b = p->binding_handle;
782
783         s = talloc_zero_array(tctx, const char *, 2);
784         s[0] = guid_str;
785
786         torture_assert(tctx,
787                 push_reg_multi_sz(tctx, &blob, s),
788                 "push_reg_multi_sz failed");
789
790         r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
791         r.in.pszEnvironment = architecture;
792         r.in.cchCoreDrivers = blob.length/2;
793         r.in.pszzCoreDriverDependencies = (uint16_t *)blob.data;
794         r.in.cCorePrinterDrivers = 1;
795         r.out.pCorePrinterDrivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.cCorePrinterDrivers);
796
797         torture_assert_ntstatus_ok(tctx,
798                 dcerpc_winspool_AsyncGetCorePrinterDrivers_r(b, tctx, &r),
799                 "winspool_AsyncCorePrinterDrivers failed");
800         torture_assert_hresult_ok(tctx, r.out.result,
801                 "winspool_AsyncCorePrinterDrivers failed");
802
803         if (package_id) {
804                 *package_id = r.out.pCorePrinterDrivers[0].szPackageID;
805         }
806
807         return true;
808 }
809
810 static bool test_AsyncDeletePrintDriverPackage(struct torture_context *tctx,
811                                                void *private_data)
812 {
813         struct test_iremotewinspool_context *ctx =
814                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
815
816         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
817         struct dcerpc_binding_handle *b = p->binding_handle;
818         struct winspool_AsyncDeletePrinterDriverPackage r;
819
820         const char *architectures[] = {
821 /*              SPOOLSS_ARCHITECTURE_NT_X86, */
822                 SPOOLSS_ARCHITECTURE_x64
823         };
824         int i;
825
826         for (i=0; i < ARRAY_SIZE(architectures); i++) {
827
828                 const char *package_id;
829
830                 torture_assert(tctx,
831                         test_get_core_printer_drivers_arch_guid(tctx, p,
832                                                                 architectures[i],
833                                                                 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
834                                                                 &package_id),
835                         "failed to get core printer driver");
836
837                 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
838                 r.in.pszEnvironment = "";
839                 r.in.pszInfPath = "";
840
841                 torture_comment(tctx, "Testing AsyncDeletePrinterDriverPackage(%s, %s, %s)\n",
842                         r.in.pszServer, architectures[i], package_id);
843
844                 torture_assert_ntstatus_ok(tctx,
845                         dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
846                         "AsyncDeletePrinterDriverPackage failed");
847                 torture_assert_werr_equal(tctx,
848                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
849                         "AsyncDeletePrinterDriverPackage failed");
850
851                 r.in.pszInfPath = package_id;
852
853                 torture_assert_ntstatus_ok(tctx,
854                         dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
855                         "AsyncDeletePrinterDriverPackage failed");
856                 torture_assert_werr_equal(tctx,
857                         W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
858                         "AsyncDeletePrinterDriverPackage failed");
859
860                 r.in.pszEnvironment = architectures[i];
861
862                 torture_assert_ntstatus_ok(tctx,
863                         dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
864                         "AsyncDeletePrinterDriverPackage failed");
865                 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_ACCESSDENIED,
866                         "AsyncDeletePrinterDriverPackage failed");
867         }
868
869         return true;
870 }
871
872 static bool test_AsyncGetPrinterDriverDirectory(struct torture_context *tctx,
873                                                 void *private_data)
874 {
875         struct test_iremotewinspool_context *ctx =
876                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
877
878         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
879         struct dcerpc_binding_handle *b = p->binding_handle;
880         struct winspool_AsyncGetPrinterDriverDirectory r;
881         uint32_t pcbNeeded;
882         DATA_BLOB blob;
883         const char *s;
884
885         r.in.pName = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
886         r.in.pEnvironment = ctx->environment;
887         r.in.Level = 1;
888         r.in.cbBuf = 0x200;
889         r.in.pDriverDirectory = talloc_zero_array(tctx, uint8_t, r.in.cbBuf);
890         r.out.pcbNeeded = &pcbNeeded;
891         r.out.pDriverDirectory = r.in.pDriverDirectory;
892
893         torture_comment(tctx, "Testing AsyncGetPrinterDriverDirectory(%s, %s)\n",
894                 r.in.pName, r.in.pEnvironment);
895
896         torture_assert_ntstatus_ok(tctx,
897                 dcerpc_winspool_AsyncGetPrinterDriverDirectory_r(b, tctx, &r),
898                 "AsyncGetPrinterDriverDirectory failed");
899         torture_assert_werr_ok(tctx, r.out.result,
900                 "AsyncGetPrinterDriverDirectory failed");
901
902         blob = data_blob_const(r.out.pDriverDirectory, pcbNeeded);
903
904         torture_assert(tctx,
905                 pull_reg_sz(tctx, &blob, &s),
906                 "failed to pull reg_sz");
907
908         torture_comment(tctx, "got: %s\n", s);
909
910         return true;
911 }
912
913 /*
914  * Test if one can close a printserver handle that has been acquired via
915  * winspool_AsyncOpenPrinter with a spoolss_ClosePrinter operation.
916  */
917
918 static bool test_OpenPrinter(struct torture_context *tctx,
919                              void *private_data)
920 {
921         struct test_iremotewinspool_context *ctx =
922                 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
923
924         struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
925         const char *printer_name;
926         struct policy_handle handle;
927         struct dcerpc_pipe *s;
928         struct dcerpc_binding *binding;
929         struct spoolss_UserLevel1 client_info;
930         struct spoolss_ClosePrinter r;
931
932         torture_assert_ntstatus_ok(tctx,
933                 torture_rpc_binding(tctx, &binding),
934                 "failed to get binding");
935
936         torture_assert_ntstatus_ok(tctx,
937                 dcerpc_binding_set_transport(binding, NCACN_NP),
938                 "failed to set ncacn_np transport");
939
940         torture_assert_ntstatus_ok(tctx,
941                 dcerpc_binding_set_object(binding, GUID_zero()),
942                 "failed to set object uuid to zero");
943
944         torture_assert_ntstatus_ok(tctx,
945                 torture_rpc_connection_with_binding(tctx, binding, &s, &ndr_table_spoolss),
946                 "failed to connect to spoolss");
947
948         printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
949
950         client_info = test_get_client_info(tctx, WIN_2000, 3, SPOOLSS_MINOR_VERSION_0);
951
952         torture_assert(tctx,
953                 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
954                 "failed to open printserver via winspool");
955
956
957         r.in.handle = &handle;
958         r.out.handle = &handle;
959
960         torture_assert_ntstatus_equal(tctx,
961                 dcerpc_spoolss_ClosePrinter_r(s->binding_handle, tctx, &r),
962                 NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
963                 "ClosePrinter failed");
964
965         talloc_free(s);
966
967         return true;
968 }
969
970 struct torture_suite *torture_rpc_iremotewinspool(TALLOC_CTX *mem_ctx)
971 {
972         struct torture_suite *suite = torture_suite_create(mem_ctx, "iremotewinspool");
973         struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
974
975         torture_tcase_set_fixture(tcase,
976                                   torture_rpc_iremotewinspool_setup,
977                                   torture_rpc_iremotewinspool_teardown);
978
979         torture_tcase_add_simple_test(tcase, "AsyncOpenPrinter", test_AsyncOpenPrinter);
980         torture_tcase_add_simple_test(tcase, "SyncRegisterForRemoteNotifications", test_SyncRegisterForRemoteNotifications);
981         torture_tcase_add_simple_test(tcase, "SyncUnRegisterForRemoteNotifications", test_SyncUnRegisterForRemoteNotifications);
982         torture_tcase_add_simple_test(tcase, "AsyncClosePrinter", test_AsyncClosePrinter);
983         torture_tcase_add_simple_test(tcase, "AsyncUploadPrinterDriverPackage", test_AsyncUploadPrinterDriverPackage);
984         torture_tcase_add_simple_test(tcase, "AsyncEnumPrinters", test_AsyncEnumPrinters);
985         torture_tcase_add_simple_test(tcase, "AsyncGetPrinterData", test_AsyncGetPrinterData);
986         torture_tcase_add_simple_test(tcase, "AsyncCorePrinterDriverInstalled", test_AsyncCorePrinterDriverInstalled);
987         torture_tcase_add_simple_test(tcase, "AsyncDeletePrintDriverPackage", test_AsyncDeletePrintDriverPackage);
988         torture_tcase_add_simple_test(tcase, "AsyncGetPrinterDriverDirectory", test_AsyncGetPrinterDriverDirectory);
989
990         tcase = torture_suite_add_tcase(suite, "handles");
991
992         torture_tcase_set_fixture(tcase,
993                                   torture_rpc_iremotewinspool_setup,
994                                   torture_rpc_iremotewinspool_teardown);
995
996         torture_tcase_add_simple_test(tcase, "OpenPrinter", test_OpenPrinter);
997
998         return suite;
999 }