ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / rpc / iremotewinspool.c
blob537af938b5a1f72bc420ad2dfe8895efc80cbf69
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for iremotewinspool rpc operations
5 Copyright (C) Guenther Deschner 2013,2023
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.
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.
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/>.
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 #include "torture/rpc/iremotewinspool_common.h"
30 static bool torture_rpc_iremotewinspool_setup_common(struct torture_context *tctx,
31 struct test_iremotewinspool_context *t)
33 const char *printer_name;
34 struct spoolss_UserLevel1 client_info;
35 struct dcerpc_binding *binding;
37 torture_assert_ntstatus_ok(tctx,
38 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &t->object_uuid),
39 "failed to parse GUID");
41 torture_assert_ntstatus_ok(tctx,
42 torture_rpc_binding(tctx, &binding),
43 "failed to retrieve torture binding");
45 torture_assert_ntstatus_ok(tctx,
46 dcerpc_binding_set_object(binding, t->object_uuid),
47 "failed to set object_uuid");
49 torture_assert_ntstatus_ok(tctx,
50 torture_rpc_connection_with_binding(tctx, binding, &t->iremotewinspool_pipe, &ndr_table_iremotewinspool),
51 "Error connecting to server");
53 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(t->iremotewinspool_pipe));
55 client_info = test_get_client_info(tctx, WIN_7, 6, 1, "testclient_machine", "testclient_user");
57 torture_assert(tctx,
58 test_AsyncOpenPrinter_byprinter(tctx, t,
59 t->iremotewinspool_pipe, printer_name,
60 client_info, &t->server_handle),
61 "failed to open printserver");
62 torture_assert(tctx,
63 test_get_environment(tctx,
64 t->iremotewinspool_pipe->binding_handle,
65 &t->server_handle, &t->environment),
66 "failed to get environment");
68 return true;
71 static bool torture_rpc_iremotewinspool_setup(struct torture_context *tctx,
72 void **data)
74 struct test_iremotewinspool_context *t;
76 *data = t = talloc_zero(tctx, struct test_iremotewinspool_context);
78 return torture_rpc_iremotewinspool_setup_common(tctx, t);
81 static bool torture_rpc_iremotewinspool_teardown_common(struct torture_context *tctx,
82 struct test_iremotewinspool_context *t)
85 test_AsyncClosePrinter_byhandle(tctx, t, t->iremotewinspool_pipe, &t->server_handle);
87 return true;
90 static bool torture_rpc_iremotewinspool_teardown(struct torture_context *tctx,
91 void *data)
93 struct test_iremotewinspool_context *t = talloc_get_type(data, struct test_iremotewinspool_context);
94 bool ret;
96 ret = torture_rpc_iremotewinspool_teardown_common(tctx, t);
97 talloc_free(t);
99 return ret;
102 static bool test_AsyncClosePrinter(struct torture_context *tctx,
103 void *private_data)
105 struct test_iremotewinspool_context *ctx =
106 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
108 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
109 const char *printer_name;
110 struct spoolss_UserLevel1 client_info;
111 struct policy_handle handle;
113 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
115 client_info = test_get_client_info(tctx, WIN_7, 6, 1, "testclient_machine", "testclient_user");
117 torture_assert(tctx,
118 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
119 "failed to test AsyncOpenPrinter");
121 torture_assert(tctx,
122 test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle),
123 "failed to test AsyncClosePrinter");
125 return true;
128 static bool test_AsyncOpenPrinter(struct torture_context *tctx,
129 void *private_data)
131 struct test_iremotewinspool_context *ctx =
132 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
134 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
135 const char *printer_name;
136 struct spoolss_UserLevel1 client_info;
137 struct policy_handle handle;
139 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
141 client_info = test_get_client_info(tctx, WIN_7, 6, 1, "testclient_machine", "testclient_user");
143 torture_assert(tctx,
144 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
145 "failed to test AsyncOpenPrinter");
147 test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle);
149 return true;
153 * Validate the result of AsyncOpenPrinter calls based on client info
154 * build number. Windows Server 2016 rejects an advertised build
155 * number less than 6000(Windows Vista and Windows Server 2008, or older)
157 static bool test_AsyncOpenPrinterValidateBuildNumber(struct torture_context *tctx,
158 void *private_data)
160 struct test_iremotewinspool_context *ctx =
161 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
163 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
164 const char *printer_name;
165 struct spoolss_UserLevel1 client_info;
166 struct policy_handle handle;
167 struct dcerpc_binding_handle *b = p->binding_handle;
168 struct spoolss_DevmodeContainer devmode_ctr;
169 struct spoolss_UserLevelCtr client_info_ctr = {
170 .level = 1,
172 uint32_t access_mask = SERVER_ALL_ACCESS;
173 struct winspool_AsyncOpenPrinter r;
174 NTSTATUS status;
175 bool ok = false;
177 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
178 torture_assert_not_null(tctx, printer_name, "Cannot allocate memory");
180 /* fail with Windows 2000 build number */
181 client_info = test_get_client_info(tctx, WIN_2000, 3, SPOOLSS_MINOR_VERSION_0,
182 "testclient_machine", "testclient_user");
184 ZERO_STRUCT(devmode_ctr);
186 client_info_ctr.user_info.level1 = &client_info;
188 r.in.pPrinterName = printer_name;
189 r.in.pDatatype = NULL;
190 r.in.pDevModeContainer = &devmode_ctr;
191 r.in.AccessRequired = access_mask;
192 r.in.pClientInfo = &client_info_ctr;
193 r.out.pHandle = &handle;
195 status = dcerpc_winspool_AsyncOpenPrinter_r(b, tctx, &r);
196 torture_assert_ntstatus_ok(tctx, status, "AsyncOpenPrinter failed");
197 torture_assert_werr_equal(tctx, r.out.result, WERR_ACCESS_DENIED,
198 "AsyncOpenPrinter should have failed");
200 /* succeed with Windows 7 build number */
201 client_info = test_get_client_info(tctx, WIN_7, 6, 1,
202 "testclient_machine", "testclient_user");
203 client_info_ctr.user_info.level1 = &client_info;
204 r.in.pClientInfo = &client_info_ctr;
206 status = dcerpc_winspool_AsyncOpenPrinter_r(b, tctx, &r);
207 torture_assert_ntstatus_ok(tctx, status, "AsyncOpenPrinter failed");
208 torture_assert_werr_ok(tctx, r.out.result,
209 "AsyncOpenPrinter failed");
211 ok = test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle);
212 torture_assert(tctx, ok, "failed to AsyncClosePrinter handle");
214 return true;
218 static struct spoolss_NotifyOption *setup_printserver_NotifyOption(struct torture_context *tctx)
220 struct spoolss_NotifyOption *o;
222 o = talloc_zero(tctx, struct spoolss_NotifyOption);
223 if (o == NULL) {
224 return NULL;
227 o->version = 2;
228 o->flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
230 o->count = 2;
231 o->types = talloc_zero_array(o, struct spoolss_NotifyOptionType, o->count);
232 if (o->types == NULL) {
233 talloc_free(o);
234 return NULL;
237 o->types[0].type = PRINTER_NOTIFY_TYPE;
238 o->types[0].count = 1;
239 o->types[0].fields = talloc_array(o->types, union spoolss_Field, o->types[0].count);
240 if (o->types[0].fields == NULL) {
241 talloc_free(o);
242 return NULL;
244 o->types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
246 o->types[1].type = JOB_NOTIFY_TYPE;
247 o->types[1].count = 1;
248 o->types[1].fields = talloc_array(o->types, union spoolss_Field, o->types[1].count);
249 if (o->types[1].fields == NULL) {
250 talloc_free(o);
251 return NULL;
253 o->types[1].fields[0].field = JOB_NOTIFY_FIELD_MACHINE_NAME;
255 return o;
258 static bool test_SyncUnRegisterForRemoteNotifications_args(struct torture_context *tctx,
259 struct dcerpc_pipe *p,
260 struct policy_handle *notify_handle)
262 struct winspool_SyncUnRegisterForRemoteNotifications r;
263 struct dcerpc_binding_handle *b = p->binding_handle;
265 r.in.phRpcHandle = notify_handle;
266 r.out.phRpcHandle = notify_handle;
268 torture_assert_ntstatus_ok(tctx,
269 dcerpc_winspool_SyncUnRegisterForRemoteNotifications_r(b, tctx, &r),
270 "SyncUnRegisterForRemoteNotifications failed");
271 torture_assert_hresult_ok(tctx, r.out.result,
272 "SyncUnRegisterForRemoteNotifications failed");
274 return true;
277 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
278 struct dcerpc_pipe *p,
279 struct policy_handle *server_handle,
280 struct policy_handle *notify_handle);
282 static bool test_SyncUnRegisterForRemoteNotifications(struct torture_context *tctx,
283 void *private_data)
285 struct test_iremotewinspool_context *ctx =
286 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
287 struct policy_handle notify_handle;
289 torture_assert(tctx,
290 test_SyncRegisterForRemoteNotifications_args(tctx,
291 ctx->iremotewinspool_pipe,
292 &ctx->server_handle,
293 &notify_handle),
294 "failed to test SyncRegisterForRemoteNotifications");
296 torture_assert(tctx,
297 test_SyncUnRegisterForRemoteNotifications_args(tctx,
298 ctx->iremotewinspool_pipe,
299 &notify_handle),
300 "failed to test UnSyncRegisterForRemoteNotifications");
302 return true;
305 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
306 struct dcerpc_pipe *p,
307 struct policy_handle *server_handle,
308 struct policy_handle *notify_handle)
310 struct dcerpc_binding_handle *b = p->binding_handle;
312 struct winspool_SyncRegisterForRemoteNotifications r;
313 struct winspool_PrintPropertiesCollection NotifyFilter;
314 struct winspool_PrintNamedProperty *c;
315 struct spoolss_NotifyOption *options;
317 ZERO_STRUCT(NotifyFilter);
319 options = setup_printserver_NotifyOption(tctx);
320 torture_assert(tctx, options, "out of memory");
322 c = talloc_zero_array(tctx, struct winspool_PrintNamedProperty, 4);
323 torture_assert(tctx, c, "out of memory");
325 c[0].propertyName = "RemoteNotifyFilter Flags";
326 c[0].propertyValue.PropertyType = winspool_PropertyTypeInt32;
327 c[0].propertyValue.value.propertyInt32 = 0xff;
329 c[1].propertyName = "RemoteNotifyFilter Options";
330 c[1].propertyValue.PropertyType = winspool_PropertyTypeInt32;
331 c[1].propertyValue.value.propertyInt32 = 0;
333 c[2].propertyName = "RemoteNotifyFilter Color";
334 c[2].propertyValue.PropertyType = winspool_PropertyTypeInt32;
335 c[2].propertyValue.value.propertyInt32 = 0;
337 c[3].propertyName = "RemoteNotifyFilter NotifyOptions";
338 c[3].propertyValue.PropertyType = winspool_PropertyTypeNotificationOptions;
339 c[3].propertyValue.value.propertyOptionsContainer.pOptions = options;
341 NotifyFilter.numberOfProperties = 4;
342 NotifyFilter.propertiesCollection = c;
344 r.in.hPrinter = *server_handle;
345 r.in.pNotifyFilter = &NotifyFilter;
346 r.out.phRpcHandle = notify_handle;
348 torture_assert_ntstatus_ok(tctx,
349 dcerpc_winspool_SyncRegisterForRemoteNotifications_r(b, tctx, &r),
350 "SyncRegisterForRemoteNotifications failed");
351 torture_assert_hresult_ok(tctx, r.out.result,
352 "SyncRegisterForRemoteNotifications failed");
354 return true;
357 static bool test_SyncRegisterForRemoteNotifications(struct torture_context *tctx,
358 void *private_data)
360 struct test_iremotewinspool_context *ctx =
361 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
362 struct policy_handle notify_handle;
364 torture_assert(tctx,
365 test_SyncRegisterForRemoteNotifications_args(tctx,
366 ctx->iremotewinspool_pipe,
367 &ctx->server_handle,
368 &notify_handle),
369 "failed to test SyncRegisterForRemoteNotifications");
371 test_SyncUnRegisterForRemoteNotifications_args(tctx, ctx->iremotewinspool_pipe, &notify_handle);
373 return true;
376 static bool test_AsyncUploadPrinterDriverPackage(struct torture_context *tctx,
377 void *private_data)
379 struct test_iremotewinspool_context *ctx =
380 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
382 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
383 struct dcerpc_binding_handle *b = p->binding_handle;
385 struct winspool_AsyncUploadPrinterDriverPackage r;
386 uint32_t pcchDestInfPath = 0;
388 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
389 r.in.pszInfPath = "";
390 r.in.pszEnvironment = "";
391 r.in.dwFlags = 0;
392 r.in.pszDestInfPath = NULL;
393 r.in.pcchDestInfPath = &pcchDestInfPath;
394 r.out.pszDestInfPath = NULL;
395 r.out.pcchDestInfPath = &pcchDestInfPath;
397 torture_assert_ntstatus_ok(tctx,
398 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
399 "AsyncUploadPrinterDriverPackage failed");
400 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
401 "AsyncUploadPrinterDriverPackage failed");
403 pcchDestInfPath = 260;
404 r.in.pszDestInfPath = talloc_zero(tctx, const char);
405 r.out.pszDestInfPath = talloc_zero(tctx, const char);
407 torture_assert_ntstatus_ok(tctx,
408 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
409 "AsyncUploadPrinterDriverPackage failed");
410 torture_assert_werr_equal(tctx,
411 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
412 "AsyncUploadPrinterDriverPackage failed");
414 r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
416 torture_assert_ntstatus_ok(tctx,
417 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
418 "AsyncUploadPrinterDriverPackage failed");
419 torture_assert_werr_equal(tctx,
420 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
421 "AsyncUploadPrinterDriverPackage failed");
423 r.in.pszInfPath = "\\\\mthelena\\print$\\x64\\{BD443844-ED00-4D96-8CAE-95E49492312A}\\prnbrcl1.inf";
425 torture_assert_ntstatus_ok(tctx,
426 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
427 "AsyncUploadPrinterDriverPackage failed");
428 torture_assert_werr_equal(tctx,
429 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
430 "AsyncUploadPrinterDriverPackage failed");
432 return true;
435 static bool test_AsyncEnumPrinters(struct torture_context *tctx,
436 void *private_data)
438 struct test_iremotewinspool_context *ctx =
439 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
441 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
442 struct dcerpc_binding_handle *b = p->binding_handle;
444 struct winspool_AsyncEnumPrinters r;
445 uint32_t levels[] = { 1, 2, /*3,*/ 4, 5 };
446 int i;
448 uint32_t needed;
449 uint32_t returned;
451 for (i = 0; i < ARRAY_SIZE(levels); i++) {
453 r.in.Flags = PRINTER_ENUM_LOCAL;
454 r.in.pName = NULL;
455 r.in.Level = levels[i];
456 r.in.cbBuf = 0;
457 r.in.pPrinterEnum = NULL;
458 r.out.pcbNeeded = &needed;
459 r.out.pcReturned = &returned;
460 r.out.pPrinterEnum = NULL;
462 torture_assert_ntstatus_ok(tctx,
463 dcerpc_winspool_AsyncEnumPrinters_r(b, tctx, &r),
464 "AsyncEnumPrinters failed");
465 torture_assert_werr_equal(tctx, r.out.result, WERR_INSUFFICIENT_BUFFER,
466 "AsyncEnumPrinters failed");
468 r.in.cbBuf = needed;
469 r.in.pPrinterEnum = talloc_zero_array(tctx, uint8_t, r.in.cbBuf);
470 r.out.pPrinterEnum = r.in.pPrinterEnum;
472 torture_assert_ntstatus_ok(tctx,
473 dcerpc_winspool_AsyncEnumPrinters_r(b, tctx, &r),
474 "AsyncEnumPrinters failed");
475 torture_assert_werr_ok(tctx, r.out.result,
476 "AsyncEnumPrinters failed");
479 return true;
482 static bool test_AsyncGetPrinterData(struct torture_context *tctx,
483 void *private_data)
485 struct test_iremotewinspool_context *ctx =
486 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
488 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
489 struct dcerpc_binding_handle *b = p->binding_handle;
490 DATA_BLOB blob;
491 const char *s;
492 bool ok;
494 uint32_t pType;
495 uint32_t pcbNeeded;
496 uint8_t *pData;
498 torture_assert(tctx,
499 test_AsyncGetPrinterData_args(tctx, b, &ctx->server_handle,
500 "MajorVersion",
501 &pType, &pData, &pcbNeeded),
502 "failed to check for MajorVersion");
504 torture_assert_int_equal(tctx, pcbNeeded, 4, "pcbNeeded");
505 torture_assert_int_equal(tctx, pType, REG_DWORD, "pType");
506 torture_assert_int_equal(tctx, IVAL(pData, 0), 3, "pData");
508 torture_assert(tctx,
509 test_AsyncGetPrinterData_args(tctx, b, &ctx->server_handle,
510 "Architecture",
511 &pType, &pData, &pcbNeeded),
512 "failed to check for Architecture");
514 blob = data_blob_const(pData, pcbNeeded);
516 torture_assert_int_equal(tctx, pType, REG_SZ, "pType");
517 torture_assert(tctx, pull_reg_sz(tctx, &blob, &s), "");
518 ok = strequal(s, SPOOLSS_ARCHITECTURE_x64) || strequal(s, SPOOLSS_ARCHITECTURE_NT_X86);
519 torture_assert(tctx, ok, "unexpected architecture returned");
521 return true;
524 static bool test_AsyncCorePrinterDriverInstalled(struct torture_context *tctx,
525 void *private_data)
527 struct test_iremotewinspool_context *ctx =
528 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
530 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
531 struct dcerpc_binding_handle *b = p->binding_handle;
533 struct winspool_AsyncCorePrinterDriverInstalled r;
534 int32_t pbDriverInstalled;
535 struct GUID guid;
537 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
538 r.in.pszEnvironment = "";
539 r.in.CoreDriverGUID = GUID_zero();
540 r.in.ftDriverDate = 0;
541 r.in.dwlDriverVersion = 0;
542 r.out.pbDriverInstalled = &pbDriverInstalled;
544 torture_assert_ntstatus_ok(tctx,
545 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
546 "AsyncCorePrinterDriverInstalled failed");
547 torture_assert_werr_equal(tctx,
548 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
549 "AsyncCorePrinterDriverInstalled failed");
551 r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
553 torture_assert_ntstatus_ok(tctx,
554 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
555 "AsyncCorePrinterDriverInstalled failed");
556 torture_assert_hresult_ok(tctx, r.out.result,
557 "AsyncCorePrinterDriverInstalled failed");
558 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
559 "unexpected driver installed");
561 r.in.CoreDriverGUID = GUID_random();
563 torture_assert_ntstatus_ok(tctx,
564 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
565 "AsyncCorePrinterDriverInstalled failed");
566 torture_assert_hresult_ok(tctx, r.out.result,
567 "AsyncCorePrinterDriverInstalled failed");
568 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
569 "unexpected driver installed");
571 torture_assert_ntstatus_ok(tctx,
572 GUID_from_string(SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV, &guid), "");
574 r.in.CoreDriverGUID = guid;
576 torture_assert_ntstatus_ok(tctx,
577 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
578 "AsyncCorePrinterDriverInstalled failed");
579 torture_assert_hresult_ok(tctx, r.out.result,
580 "AsyncCorePrinterDriverInstalled failed");
581 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
582 "xps core driver not installed?");
584 r.in.dwlDriverVersion = 0xffffffff;
586 torture_assert_ntstatus_ok(tctx,
587 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
588 "AsyncCorePrinterDriverInstalled failed");
589 torture_assert_hresult_ok(tctx, r.out.result,
590 "AsyncCorePrinterDriverInstalled failed");
591 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
592 "xps core driver not installed?");
594 r.in.dwlDriverVersion = 1234;
596 torture_assert_ntstatus_ok(tctx,
597 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
598 "AsyncCorePrinterDriverInstalled failed");
599 torture_assert_hresult_ok(tctx, r.out.result,
600 "AsyncCorePrinterDriverInstalled failed");
601 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, true,
602 "xps core driver not installed?");
604 r.in.ftDriverDate = unix_timespec_to_nt_time(timespec_current());
606 torture_assert_ntstatus_ok(tctx,
607 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
608 "AsyncCorePrinterDriverInstalled failed");
609 torture_assert_hresult_ok(tctx, r.out.result,
610 "AsyncCorePrinterDriverInstalled failed");
611 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
612 "driver too old ?");
614 r.in.dwlDriverVersion = 0;
616 torture_assert_ntstatus_ok(tctx,
617 dcerpc_winspool_AsyncCorePrinterDriverInstalled_r(b, tctx, &r),
618 "AsyncCorePrinterDriverInstalled failed");
619 torture_assert_hresult_ok(tctx, r.out.result,
620 "AsyncCorePrinterDriverInstalled failed");
621 torture_assert_int_equal(tctx, *r.out.pbDriverInstalled, false,
622 "unexpected driver installed");
624 return true;
627 static bool test_get_core_printer_drivers_arch_guid(struct torture_context *tctx,
628 struct dcerpc_pipe *p,
629 const char *architecture,
630 const char *guid_str,
631 const char **package_id)
633 struct winspool_AsyncGetCorePrinterDrivers r;
634 DATA_BLOB blob;
635 const char **s;
636 struct dcerpc_binding_handle *b = p->binding_handle;
638 s = talloc_zero_array(tctx, const char *, 2);
639 s[0] = guid_str;
641 torture_assert(tctx,
642 push_reg_multi_sz(tctx, &blob, s),
643 "push_reg_multi_sz failed");
645 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
646 r.in.pszEnvironment = architecture;
647 r.in.cchCoreDrivers = blob.length/2;
648 r.in.pszzCoreDriverDependencies = (uint16_t *)blob.data;
649 r.in.cCorePrinterDrivers = 1;
650 r.out.pCorePrinterDrivers = talloc_zero_array(tctx, struct spoolss_CorePrinterDriver, r.in.cCorePrinterDrivers);
652 torture_assert_ntstatus_ok(tctx,
653 dcerpc_winspool_AsyncGetCorePrinterDrivers_r(b, tctx, &r),
654 "winspool_AsyncCorePrinterDrivers failed");
655 torture_assert_hresult_ok(tctx, r.out.result,
656 "winspool_AsyncCorePrinterDrivers failed");
658 if (package_id) {
659 *package_id = r.out.pCorePrinterDrivers[0].szPackageID;
662 return true;
665 static bool test_AsyncDeletePrintDriverPackage(struct torture_context *tctx,
666 void *private_data)
668 struct test_iremotewinspool_context *ctx =
669 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
671 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
672 struct dcerpc_binding_handle *b = p->binding_handle;
673 struct winspool_AsyncDeletePrinterDriverPackage r;
675 const char *architectures[] = {
676 /* SPOOLSS_ARCHITECTURE_NT_X86, */
677 SPOOLSS_ARCHITECTURE_x64
679 int i;
681 for (i=0; i < ARRAY_SIZE(architectures); i++) {
683 const char *package_id;
685 torture_assert(tctx,
686 test_get_core_printer_drivers_arch_guid(tctx, p,
687 architectures[i],
688 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV,
689 &package_id),
690 "failed to get core printer driver");
692 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
693 r.in.pszEnvironment = "";
694 r.in.pszInfPath = "";
696 torture_comment(tctx, "Testing AsyncDeletePrinterDriverPackage(%s, %s, %s)\n",
697 r.in.pszServer, architectures[i], package_id);
699 torture_assert_ntstatus_ok(tctx,
700 dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
701 "AsyncDeletePrinterDriverPackage failed");
702 torture_assert_werr_equal(tctx,
703 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_NOT_FOUND,
704 "AsyncDeletePrinterDriverPackage failed");
706 r.in.pszInfPath = package_id;
708 torture_assert_ntstatus_ok(tctx,
709 dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
710 "AsyncDeletePrinterDriverPackage failed");
711 torture_assert_werr_equal(tctx,
712 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
713 "AsyncDeletePrinterDriverPackage failed");
715 r.in.pszEnvironment = architectures[i];
717 torture_assert_ntstatus_ok(tctx,
718 dcerpc_winspool_AsyncDeletePrinterDriverPackage_r(b, tctx, &r),
719 "AsyncDeletePrinterDriverPackage failed");
720 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_ACCESSDENIED,
721 "AsyncDeletePrinterDriverPackage failed");
724 return true;
727 static bool test_AsyncGetPrinterDriverDirectory(struct torture_context *tctx,
728 void *private_data)
730 struct test_iremotewinspool_context *ctx =
731 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
733 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
734 struct dcerpc_binding_handle *b = p->binding_handle;
735 struct winspool_AsyncGetPrinterDriverDirectory r;
736 uint32_t pcbNeeded;
737 DATA_BLOB blob;
738 const char *s;
740 r.in.pName = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
741 r.in.pEnvironment = ctx->environment;
742 r.in.Level = 1;
743 r.in.cbBuf = 0x200;
744 r.in.pDriverDirectory = talloc_zero_array(tctx, uint8_t, r.in.cbBuf);
745 r.out.pcbNeeded = &pcbNeeded;
746 r.out.pDriverDirectory = r.in.pDriverDirectory;
748 torture_comment(tctx, "Testing AsyncGetPrinterDriverDirectory(%s, %s)\n",
749 r.in.pName, r.in.pEnvironment);
751 torture_assert_ntstatus_ok(tctx,
752 dcerpc_winspool_AsyncGetPrinterDriverDirectory_r(b, tctx, &r),
753 "AsyncGetPrinterDriverDirectory failed");
754 torture_assert_werr_ok(tctx, r.out.result,
755 "AsyncGetPrinterDriverDirectory failed");
757 blob = data_blob_const(r.out.pDriverDirectory, pcbNeeded);
759 torture_assert(tctx,
760 pull_reg_sz(tctx, &blob, &s),
761 "failed to pull reg_sz");
763 torture_comment(tctx, "got: %s\n", s);
765 return true;
769 * Test if one can close a printserver handle that has been acquired via
770 * winspool_AsyncOpenPrinter with a spoolss_ClosePrinter operation.
773 static bool test_OpenPrinter(struct torture_context *tctx,
774 void *private_data)
776 struct test_iremotewinspool_context *ctx =
777 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
779 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
780 const char *printer_name;
781 struct policy_handle handle;
782 struct dcerpc_pipe *s;
783 struct dcerpc_binding *binding;
784 struct spoolss_UserLevel1 client_info;
785 struct spoolss_ClosePrinter r;
787 torture_assert_ntstatus_ok(tctx,
788 torture_rpc_binding(tctx, &binding),
789 "failed to get binding");
791 torture_assert_ntstatus_ok(tctx,
792 dcerpc_binding_set_transport(binding, NCACN_NP),
793 "failed to set ncacn_np transport");
795 torture_assert_ntstatus_ok(tctx,
796 dcerpc_binding_set_object(binding, GUID_zero()),
797 "failed to set object uuid to zero");
799 torture_assert_ntstatus_ok(tctx,
800 torture_rpc_connection_with_binding(tctx, binding, &s, &ndr_table_spoolss),
801 "failed to connect to spoolss");
803 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
805 client_info = test_get_client_info(tctx, WIN_7, 6, 1, "testclient_machine", "testclient_user");
807 torture_assert(tctx,
808 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, client_info, &handle),
809 "failed to open printserver via winspool");
812 r.in.handle = &handle;
813 r.out.handle = &handle;
815 torture_assert_ntstatus_equal(tctx,
816 dcerpc_spoolss_ClosePrinter_r(s->binding_handle, tctx, &r),
817 NT_STATUS_RPC_SS_CONTEXT_MISMATCH,
818 "ClosePrinter failed");
820 talloc_free(s);
822 return true;
825 static bool test_object_one_uuid(struct torture_context *tctx,
826 const struct GUID *object_uuid,
827 NTSTATUS expected_status)
829 const char *printer_name;
830 struct spoolss_UserLevel1 client_info;
831 struct dcerpc_binding *binding;
832 struct dcerpc_pipe *p;
833 struct policy_handle server_handle;
835 torture_comment(tctx, "Testing with object_uuid: %s\n",
836 GUID_string(tctx, object_uuid));
838 torture_assert_ntstatus_ok(tctx,
839 torture_rpc_binding(tctx, &binding),
840 "failed to retrieve torture binding");
842 if (object_uuid) {
843 torture_assert_ntstatus_ok(tctx,
844 dcerpc_binding_set_object(binding, *object_uuid),
845 "failed to set object_uuid");
848 torture_assert_ntstatus_ok(tctx,
849 torture_rpc_connection_with_binding(tctx, binding, &p,
850 &ndr_table_iremotewinspool),
851 "Error connecting to server");
853 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
854 torture_assert(tctx, printer_name, "out of memory");
856 client_info = test_get_client_info(tctx,
857 WIN_7, 6, 1, "testclient_machine", "testclient_user");
859 torture_assert(tctx,
860 test_AsyncOpenPrinter_byprinter_expect(tctx, NULL,
862 printer_name,
863 SEC_FLAG_MAXIMUM_ALLOWED,
864 client_info,
865 expected_status,
866 WERR_OK,
867 &server_handle),
868 "failed to open printserver");
869 if (NT_STATUS_IS_OK(expected_status)) {
870 test_AsyncClosePrinter_byhandle(tctx, NULL, p, &server_handle);
873 talloc_free(p);
875 return true;
878 static bool test_object_uuid(struct torture_context *tctx,
879 void *private_data)
881 struct GUID object_uuid;
883 torture_assert(tctx,
884 test_object_one_uuid(tctx, NULL,
885 NT_STATUS_RPC_UNSUPPORTED_TYPE),
886 "failed to test NULL object uuid");
888 object_uuid = GUID_zero();
889 torture_assert(tctx,
890 test_object_one_uuid(tctx, &object_uuid,
891 NT_STATUS_RPC_UNSUPPORTED_TYPE),
892 "failed to test zeroed object uuid");
894 object_uuid = GUID_random();
895 torture_assert(tctx,
896 test_object_one_uuid(tctx, &object_uuid,
897 NT_STATUS_RPC_UNSUPPORTED_TYPE),
898 "failed to test random object uuid");
900 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &object_uuid);
901 torture_assert(tctx,
902 test_object_one_uuid(tctx, &object_uuid,
903 NT_STATUS_OK),
904 "failed to test IREMOTEWINSPOOL_OBJECT_GUID");
906 torture_assert(tctx,
907 test_object_one_uuid(tctx, &ndr_table_spoolss.syntax_id.uuid,
908 NT_STATUS_RPC_UNSUPPORTED_TYPE),
909 "failed to test spoolss interface uuid");
911 torture_assert(tctx,
912 test_object_one_uuid(tctx, &ndr_table_iremotewinspool.syntax_id.uuid,
913 NT_STATUS_RPC_UNSUPPORTED_TYPE),
914 "failed to test iremotewinspool interface uuid");
916 return true;
919 static bool test_setup_binding_handle(struct torture_context *tctx,
920 struct GUID object_uuid,
921 enum dcerpc_transport_t transport,
922 const struct ndr_interface_table *table,
923 struct dcerpc_pipe **p)
925 struct dcerpc_binding *binding;
927 torture_assert_ntstatus_ok(tctx,
928 torture_rpc_binding(tctx, &binding),
929 "failed to retrieve torture binding");
931 torture_assert_ntstatus_ok(tctx,
932 dcerpc_binding_set_object(binding, object_uuid),
933 "failed to set object_uuid");
935 torture_assert_ntstatus_ok(tctx,
936 dcerpc_binding_set_transport(binding, transport),
937 "failed to set transport");
939 torture_assert_ntstatus_ok(tctx,
940 torture_rpc_connection_with_binding(tctx, binding, p, table),
941 "Error connecting to server");
943 return true;
946 static enum ndr_err_code ndr_push_inout_blob(DATA_BLOB *blob,
947 TALLOC_CTX *mem_ctx,
948 ndr_flags_type flags,
949 const void *p,
950 ndr_push_flags_fn_t fn)
952 struct ndr_push *ndr;
953 ndr = ndr_push_init_ctx(mem_ctx);
954 NDR_ERR_HAVE_NO_MEMORY(ndr);
956 NDR_CHECK_FREE(fn(ndr, flags, p));
958 *blob = ndr_push_blob(ndr);
959 talloc_steal(mem_ctx, blob->data);
960 talloc_free(ndr);
962 return NDR_ERR_SUCCESS;
965 static bool test_compare_spoolss(struct torture_context *tctx,
966 void *private_data)
968 DATA_BLOB reply_iremotewinspool, reply_spoolss, request_spoolss;
969 struct dcerpc_pipe *iremotewinspool_pipe, *spoolss_pipe;
970 struct GUID object_uuid;
971 uint32_t out_flags;
972 NTSTATUS status;
973 struct spoolss_EnumPrinters r;
974 DATA_BLOB blob;
976 /* setup two dcerpc pipes */
978 torture_assert_ntstatus_ok(tctx,
979 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &object_uuid),
980 "failed to parse GUID");
982 torture_assert(tctx,
983 test_setup_binding_handle(tctx, object_uuid, NCACN_IP_TCP,
984 &ndr_table_iremotewinspool, &iremotewinspool_pipe),
985 "failed to setup binding handle");
987 torture_assert(tctx,
988 test_setup_binding_handle(tctx, GUID_zero(), NCACN_NP,
989 &ndr_table_spoolss, &spoolss_pipe),
990 "failed to setup binding handle");
993 /* create a spoolss enumprinters request */
995 ZERO_STRUCT(r);
997 blob = data_blob_talloc_zero(tctx, 0x1000);
999 r.in.flags = PRINTER_ENUM_LOCAL;
1000 r.in.server = talloc_asprintf(tctx, "\\\\%s",
1001 dcerpc_server_name(spoolss_pipe));
1002 r.in.level = 1;
1003 r.in.buffer = &blob;
1004 r.in.offered = blob.length;
1006 torture_assert_ndr_success(tctx,
1007 ndr_push_inout_blob(&request_spoolss, tctx, NDR_IN | NDR_SET_VALUES, &r,
1008 (ndr_push_flags_fn_t)ndr_push_spoolss_EnumPrinters),
1009 "failed to push EnumPrinters request");
1011 /* send same request to both endpoints */
1013 status = dcerpc_binding_handle_raw_call(iremotewinspool_pipe->binding_handle,
1014 NULL,
1015 NDR_WINSPOOL_ASYNCENUMPRINTERS,
1016 0, /* in_flags */
1017 request_spoolss.data,
1018 request_spoolss.length,
1019 tctx,
1020 &reply_iremotewinspool.data,
1021 &reply_iremotewinspool.length,
1022 &out_flags);
1023 torture_assert_ntstatus_ok(tctx, status, "dcerpc_binding_handle_raw_call failed");
1025 status = dcerpc_binding_handle_raw_call(spoolss_pipe->binding_handle,
1026 NULL,
1027 NDR_SPOOLSS_ENUMPRINTERS,
1028 0, /* in_flags */
1029 request_spoolss.data,
1030 request_spoolss.length,
1031 tctx,
1032 &reply_spoolss.data,
1033 &reply_spoolss.length,
1034 &out_flags);
1035 torture_assert_ntstatus_ok(tctx, status, "dcerpc_binding_handle_raw_call failed");
1037 torture_assert_data_blob_equal(tctx,
1038 reply_iremotewinspool,
1039 reply_spoolss,
1040 "unexpected difference in replies from spoolss and iremotewinspool servers");
1042 talloc_free(iremotewinspool_pipe);
1043 talloc_free(spoolss_pipe);
1045 return true;
1048 struct torture_suite *torture_rpc_iremotewinspool(TALLOC_CTX *mem_ctx)
1050 struct torture_suite *suite = torture_suite_create(mem_ctx, "iremotewinspool");
1051 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
1053 torture_tcase_set_fixture(tcase,
1054 torture_rpc_iremotewinspool_setup,
1055 torture_rpc_iremotewinspool_teardown);
1057 torture_tcase_add_simple_test(tcase, "AsyncOpenPrinter", test_AsyncOpenPrinter);
1058 torture_tcase_add_simple_test(tcase, "SyncRegisterForRemoteNotifications", test_SyncRegisterForRemoteNotifications);
1059 torture_tcase_add_simple_test(tcase, "SyncUnRegisterForRemoteNotifications", test_SyncUnRegisterForRemoteNotifications);
1060 torture_tcase_add_simple_test(tcase, "AsyncClosePrinter", test_AsyncClosePrinter);
1061 torture_tcase_add_simple_test(tcase, "AsyncUploadPrinterDriverPackage", test_AsyncUploadPrinterDriverPackage);
1062 torture_tcase_add_simple_test(tcase, "AsyncEnumPrinters", test_AsyncEnumPrinters);
1063 torture_tcase_add_simple_test(tcase, "AsyncGetPrinterData", test_AsyncGetPrinterData);
1064 torture_tcase_add_simple_test(tcase, "AsyncCorePrinterDriverInstalled", test_AsyncCorePrinterDriverInstalled);
1065 torture_tcase_add_simple_test(tcase, "AsyncDeletePrintDriverPackage", test_AsyncDeletePrintDriverPackage);
1066 torture_tcase_add_simple_test(tcase, "AsyncGetPrinterDriverDirectory", test_AsyncGetPrinterDriverDirectory);
1067 torture_tcase_add_simple_test(tcase, "AsyncOpenPrinterValidateBuildNumber", test_AsyncOpenPrinterValidateBuildNumber);
1069 tcase = torture_suite_add_tcase(suite, "handles");
1071 torture_tcase_set_fixture(tcase,
1072 torture_rpc_iremotewinspool_setup,
1073 torture_rpc_iremotewinspool_teardown);
1075 torture_tcase_add_simple_test(tcase, "OpenPrinter", test_OpenPrinter);
1077 tcase = torture_suite_add_tcase(suite, "protocol");
1078 torture_tcase_add_simple_test(tcase, "object_uuid", test_object_uuid);
1079 torture_tcase_add_simple_test(tcase, "compare_spoolss", test_compare_spoolss);
1081 return suite;