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/>.
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");
58 test_AsyncOpenPrinter_byprinter(tctx
, t
,
59 t
->iremotewinspool_pipe
, printer_name
,
60 client_info
, &t
->server_handle
),
61 "failed to open printserver");
63 test_get_environment(tctx
,
64 t
->iremotewinspool_pipe
->binding_handle
,
65 &t
->server_handle
, &t
->environment
),
66 "failed to get environment");
71 static bool torture_rpc_iremotewinspool_setup(struct torture_context
*tctx
,
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
);
90 static bool torture_rpc_iremotewinspool_teardown(struct torture_context
*tctx
,
93 struct test_iremotewinspool_context
*t
= talloc_get_type(data
, struct test_iremotewinspool_context
);
96 ret
= torture_rpc_iremotewinspool_teardown_common(tctx
, t
);
102 static bool test_AsyncClosePrinter(struct torture_context
*tctx
,
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");
118 test_AsyncOpenPrinter_byprinter(tctx
, ctx
, p
, printer_name
, client_info
, &handle
),
119 "failed to test AsyncOpenPrinter");
122 test_AsyncClosePrinter_byhandle(tctx
, ctx
, p
, &handle
),
123 "failed to test AsyncClosePrinter");
128 static bool test_AsyncOpenPrinter(struct torture_context
*tctx
,
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");
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
);
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
,
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
= {
172 uint32_t access_mask
= SERVER_ALL_ACCESS
;
173 struct winspool_AsyncOpenPrinter r
;
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");
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
);
228 o
->flags
= PRINTER_NOTIFY_OPTIONS_REFRESH
;
231 o
->types
= talloc_zero_array(o
, struct spoolss_NotifyOptionType
, o
->count
);
232 if (o
->types
== 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
) {
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
) {
253 o
->types
[1].fields
[0].field
= JOB_NOTIFY_FIELD_MACHINE_NAME
;
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");
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
,
285 struct test_iremotewinspool_context
*ctx
=
286 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
287 struct policy_handle notify_handle
;
290 test_SyncRegisterForRemoteNotifications_args(tctx
,
291 ctx
->iremotewinspool_pipe
,
294 "failed to test SyncRegisterForRemoteNotifications");
297 test_SyncUnRegisterForRemoteNotifications_args(tctx
,
298 ctx
->iremotewinspool_pipe
,
300 "failed to test UnSyncRegisterForRemoteNotifications");
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");
357 static bool test_SyncRegisterForRemoteNotifications(struct torture_context
*tctx
,
360 struct test_iremotewinspool_context
*ctx
=
361 talloc_get_type_abort(private_data
, struct test_iremotewinspool_context
);
362 struct policy_handle notify_handle
;
365 test_SyncRegisterForRemoteNotifications_args(tctx
,
366 ctx
->iremotewinspool_pipe
,
369 "failed to test SyncRegisterForRemoteNotifications");
371 test_SyncUnRegisterForRemoteNotifications_args(tctx
, ctx
->iremotewinspool_pipe
, ¬ify_handle
);
376 static bool test_AsyncUploadPrinterDriverPackage(struct torture_context
*tctx
,
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
= "";
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");
435 static bool test_AsyncEnumPrinters(struct torture_context
*tctx
,
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 };
451 for (i
= 0; i
< ARRAY_SIZE(levels
); i
++) {
453 r
.in
.Flags
= PRINTER_ENUM_LOCAL
;
455 r
.in
.Level
= levels
[i
];
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");
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");
482 static bool test_AsyncGetPrinterData(struct torture_context
*tctx
,
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
;
499 test_AsyncGetPrinterData_args(tctx
, b
, &ctx
->server_handle
,
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");
509 test_AsyncGetPrinterData_args(tctx
, b
, &ctx
->server_handle
,
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");
524 static bool test_AsyncCorePrinterDriverInstalled(struct torture_context
*tctx
,
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
;
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,
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");
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
;
636 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
638 s
= talloc_zero_array(tctx
, const char *, 2);
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");
659 *package_id
= r
.out
.pCorePrinterDrivers
[0].szPackageID
;
665 static bool test_AsyncDeletePrintDriverPackage(struct torture_context
*tctx
,
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
681 for (i
=0; i
< ARRAY_SIZE(architectures
); i
++) {
683 const char *package_id
;
686 test_get_core_printer_drivers_arch_guid(tctx
, p
,
688 SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV
,
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");
727 static bool test_AsyncGetPrinterDriverDirectory(struct torture_context
*tctx
,
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
;
740 r
.in
.pName
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
741 r
.in
.pEnvironment
= ctx
->environment
;
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
);
760 pull_reg_sz(tctx
, &blob
, &s
),
761 "failed to pull reg_sz");
763 torture_comment(tctx
, "got: %s\n", s
);
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
,
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");
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");
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");
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");
860 test_AsyncOpenPrinter_byprinter_expect(tctx
, NULL
,
863 SEC_FLAG_MAXIMUM_ALLOWED
,
868 "failed to open printserver");
869 if (NT_STATUS_IS_OK(expected_status
)) {
870 test_AsyncClosePrinter_byhandle(tctx
, NULL
, p
, &server_handle
);
878 static bool test_object_uuid(struct torture_context
*tctx
,
881 struct GUID object_uuid
;
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();
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();
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
);
902 test_object_one_uuid(tctx
, &object_uuid
,
904 "failed to test IREMOTEWINSPOOL_OBJECT_GUID");
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");
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");
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");
946 static enum ndr_err_code
ndr_push_inout_blob(DATA_BLOB
*blob
,
948 ndr_flags_type flags
,
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
);
962 return NDR_ERR_SUCCESS
;
965 static bool test_compare_spoolss(struct torture_context
*tctx
,
968 DATA_BLOB reply_iremotewinspool
, reply_spoolss
, request_spoolss
;
969 struct dcerpc_pipe
*iremotewinspool_pipe
, *spoolss_pipe
;
970 struct GUID object_uuid
;
973 struct spoolss_EnumPrinters r
;
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");
983 test_setup_binding_handle(tctx
, object_uuid
, NCACN_IP_TCP
,
984 &ndr_table_iremotewinspool
, &iremotewinspool_pipe
),
985 "failed to setup binding handle");
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 */
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
));
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
,
1015 NDR_WINSPOOL_ASYNCENUMPRINTERS
,
1017 request_spoolss
.data
,
1018 request_spoolss
.length
,
1020 &reply_iremotewinspool
.data
,
1021 &reply_iremotewinspool
.length
,
1023 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_binding_handle_raw_call failed");
1025 status
= dcerpc_binding_handle_raw_call(spoolss_pipe
->binding_handle
,
1027 NDR_SPOOLSS_ENUMPRINTERS
,
1029 request_spoolss
.data
,
1030 request_spoolss
.length
,
1032 &reply_spoolss
.data
,
1033 &reply_spoolss
.length
,
1035 torture_assert_ntstatus_ok(tctx
, status
, "dcerpc_binding_handle_raw_call failed");
1037 torture_assert_data_blob_equal(tctx
,
1038 reply_iremotewinspool
,
1040 "unexpected difference in replies from spoolss and iremotewinspool servers");
1042 talloc_free(iremotewinspool_pipe
);
1043 talloc_free(spoolss_pipe
);
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
);