2 Unix SMB/CIFS implementation.
3 test suite for spoolss rpc operations as performed by various win versions
5 Copyright (C) Kai Blin 2007
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/rpc/rpc.h"
23 #include "librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "librpc/gen_ndr/ndr_misc.h"
25 #include "ntvfs/ntvfs.h"
26 #include "param/param.h"
28 struct test_spoolss_win_context
{
30 uint32_t printer_count
;
31 union spoolss_PrinterInfo
*printer_info
;
32 union spoolss_PrinterInfo
*current_info
;
35 const char **printer_keys
;
37 bool printer_has_driver
;
40 /* This is a convenience function for all OpenPrinterEx calls */
41 static bool test_OpenPrinterEx(struct torture_context
*tctx
,
42 struct dcerpc_binding_handle
*b
,
43 struct policy_handle
*handle
,
44 const char *printer_name
,
48 struct spoolss_OpenPrinterEx op
;
49 struct spoolss_UserLevel1 ul_1
;
51 torture_comment(tctx
, "Opening printer '%s'\n", printer_name
);
53 op
.in
.printername
= talloc_strdup(tctx
, printer_name
);
54 op
.in
.datatype
= NULL
;
55 op
.in
.devmode_ctr
.devmode
= NULL
;
56 op
.in
.access_mask
= access_mask
;
58 op
.in
.userlevel
.level1
= &ul_1
;
59 op
.out
.handle
= handle
;
62 ul_1
.client
= "\\clientname";
63 ul_1
.user
= "username";
67 ul_1
.processor
= 4567;
69 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &op
);
70 torture_assert_ntstatus_ok(tctx
, status
, "OpenPrinterEx failed");
71 torture_assert_werr_ok(tctx
, op
.out
.result
, "OpenPrinterEx failed");
76 static bool test_OpenPrinterAsAdmin(struct torture_context
*tctx
,
77 struct dcerpc_binding_handle
*b
,
78 const char *printername
)
81 struct spoolss_OpenPrinterEx op
;
82 struct spoolss_ClosePrinter cp
;
83 struct spoolss_UserLevel1 ul_1
;
84 struct policy_handle handle
;
87 ul_1
.client
= "\\clientname";
88 ul_1
.user
= "username";
92 ul_1
.processor
= 4567;
94 op
.in
.printername
= talloc_strdup(tctx
, printername
);
95 op
.in
.datatype
= NULL
;
96 op
.in
.devmode_ctr
.devmode
= NULL
;
97 op
.in
.access_mask
= SERVER_ALL_ACCESS
;
99 op
.in
.userlevel
.level1
= &ul_1
;
100 op
.out
.handle
= &handle
;
102 cp
.in
.handle
= &handle
;
103 cp
.out
.handle
= &handle
;
105 torture_comment(tctx
, "Testing OpenPrinterEx(%s) with admin rights\n",
108 status
= dcerpc_spoolss_OpenPrinterEx_r(b
, tctx
, &op
);
110 if (NT_STATUS_IS_OK(status
) && W_ERROR_IS_OK(op
.out
.result
)) {
111 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &cp
);
112 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
119 static bool test_ClosePrinter(struct torture_context
*tctx
,
120 struct dcerpc_binding_handle
*b
,
121 struct policy_handle
*handle
);
123 /* This replicates the opening sequence of OpenPrinterEx calls XP does */
124 static bool test_OpenPrinterSequence(struct torture_context
*tctx
,
125 struct dcerpc_pipe
*p
,
126 struct policy_handle
*handle
)
129 char *printername
= talloc_asprintf(tctx
, "\\\\%s",
130 dcerpc_server_name(p
));
131 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
133 /* First, see if we can open the printer read_only */
134 ret
= test_OpenPrinterEx(tctx
, b
, handle
, printername
, 0);
135 torture_assert(tctx
, ret
== true, "OpenPrinterEx failed.");
137 ret
= test_ClosePrinter(tctx
, b
, handle
);
138 torture_assert(tctx
, ret
, "ClosePrinter failed");
140 /* Now let's see if we have admin rights to it. */
141 ret
= test_OpenPrinterAsAdmin(tctx
, b
, printername
);
142 torture_assert(tctx
, ret
== true,
143 "OpenPrinterEx as admin failed unexpectedly.");
145 ret
= test_OpenPrinterEx(tctx
, b
, handle
, printername
, SERVER_EXECUTE
);
146 torture_assert(tctx
, ret
== true, "OpenPrinterEx failed.");
151 static bool test_GetPrinterData(struct torture_context
*tctx
,
152 struct dcerpc_binding_handle
*b
,
153 struct policy_handle
*handle
,
154 const char *value_name
,
155 WERROR expected_werr
,
156 uint32_t expected_value
)
159 struct spoolss_GetPrinterData gpd
;
161 enum winreg_Type type
;
162 uint8_t *data
= talloc_zero_array(tctx
, uint8_t, 4);
164 torture_comment(tctx
, "Testing GetPrinterData(%s).\n", value_name
);
165 gpd
.in
.handle
= handle
;
166 gpd
.in
.value_name
= value_name
;
168 gpd
.out
.needed
= &needed
;
169 gpd
.out
.type
= &type
;
172 status
= dcerpc_spoolss_GetPrinterData_r(b
, tctx
, &gpd
);
173 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterData failed.");
174 torture_assert_werr_equal(tctx
, gpd
.out
.result
, expected_werr
,
175 "GetPrinterData did not return expected error value.");
177 if (W_ERROR_IS_OK(expected_werr
)) {
178 uint32_t value
= IVAL(data
, 0);
179 torture_assert_int_equal(tctx
, value
,
181 talloc_asprintf(tctx
, "GetPrinterData for %s did not return expected value.", value_name
));
186 static bool test_EnumPrinters(struct torture_context
*tctx
,
187 struct dcerpc_pipe
*p
,
188 struct test_spoolss_win_context
*ctx
,
189 uint32_t initial_blob_size
)
192 struct spoolss_EnumPrinters ep
;
193 DATA_BLOB blob
= data_blob_talloc_zero(ctx
, initial_blob_size
);
196 union spoolss_PrinterInfo
*info
;
197 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
199 ep
.in
.flags
= PRINTER_ENUM_NAME
;
200 ep
.in
.server
= talloc_asprintf(tctx
, "\\\\%s", dcerpc_server_name(p
));
202 ep
.in
.buffer
= &blob
;
203 ep
.in
.offered
= initial_blob_size
;
204 ep
.out
.needed
= &needed
;
205 ep
.out
.count
= &count
;
208 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &ep
);
209 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinters failed.");
211 if (W_ERROR_EQUAL(ep
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
212 blob
= data_blob_talloc_zero(ctx
, needed
);
213 ep
.in
.buffer
= &blob
;
214 ep
.in
.offered
= needed
;
215 status
= dcerpc_spoolss_EnumPrinters_r(b
, ctx
, &ep
);
216 torture_assert_ntstatus_ok(tctx
, status
,"EnumPrinters failed.");
219 torture_assert_werr_ok(tctx
, ep
.out
.result
, "EnumPrinters failed.");
221 ctx
->printer_count
= count
;
222 ctx
->printer_info
= info
;
224 torture_comment(tctx
, "Found %d printer(s).\n", ctx
->printer_count
);
229 static bool test_GetPrinter(struct torture_context
*tctx
,
230 struct dcerpc_binding_handle
*b
,
231 struct policy_handle
*handle
,
232 struct test_spoolss_win_context
*ctx
,
234 uint32_t initial_blob_size
)
237 struct spoolss_GetPrinter gp
;
238 DATA_BLOB blob
= data_blob_talloc_zero(ctx
, initial_blob_size
);
241 torture_comment(tctx
, "Test GetPrinter level %d\n", level
);
243 gp
.in
.handle
= handle
;
245 gp
.in
.buffer
= (initial_blob_size
== 0)?NULL
:&blob
;
246 gp
.in
.offered
= initial_blob_size
;
247 gp
.out
.needed
= &needed
;
249 status
= dcerpc_spoolss_GetPrinter_r(b
, tctx
, &gp
);
250 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
252 if (W_ERROR_EQUAL(gp
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
253 blob
= data_blob_talloc_zero(ctx
, needed
);
254 gp
.in
.buffer
= &blob
;
255 gp
.in
.offered
= needed
;
256 status
= dcerpc_spoolss_GetPrinter_r(b
, tctx
, &gp
);
257 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinter failed");
260 torture_assert_werr_ok(tctx
, gp
.out
.result
, "GetPrinter failed");
262 ctx
->current_info
= gp
.out
.info
;
264 if (level
== 2 && gp
.out
.info
) {
265 ctx
->printer_has_driver
= gp
.out
.info
->info2
.drivername
&&
266 strlen(gp
.out
.info
->info2
.drivername
);
272 static bool test_EnumJobs(struct torture_context
*tctx
,
273 struct dcerpc_binding_handle
*b
,
274 struct policy_handle
*handle
)
277 struct spoolss_EnumJobs ej
;
278 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 1024);
281 union spoolss_JobInfo
*info
;
283 torture_comment(tctx
, "Test EnumJobs\n");
285 ej
.in
.handle
= handle
;
287 ej
.in
.buffer
= &blob
;
288 ej
.in
.offered
= 1024;
289 ej
.out
.needed
= &needed
;
290 ej
.out
.count
= &count
;
293 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &ej
);
294 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
295 if (W_ERROR_EQUAL(ej
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
296 blob
= data_blob_talloc_zero(tctx
, needed
);
297 ej
.in
.offered
= needed
;
298 ej
.in
.buffer
= &blob
;
299 status
= dcerpc_spoolss_EnumJobs_r(b
, tctx
, &ej
);
300 torture_assert_ntstatus_ok(tctx
, status
, "EnumJobs failed");
302 torture_assert_werr_ok(tctx
, ej
.out
.result
, "EnumJobs failed");
307 static bool test_GetPrinterDriver2(struct torture_context
*tctx
,
308 struct dcerpc_binding_handle
*b
,
309 struct test_spoolss_win_context
*ctx
,
310 struct policy_handle
*handle
)
313 struct spoolss_GetPrinterDriver2 gpd2
;
314 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, 87424);
316 uint32_t server_major_version
;
317 uint32_t server_minor_version
;
319 torture_comment(tctx
, "Testing GetPrinterDriver2\n");
321 gpd2
.in
.handle
= handle
;
322 gpd2
.in
.architecture
= "Windows NT x86";
324 gpd2
.in
.buffer
= &blob
;
325 gpd2
.in
.offered
= 87424;
326 gpd2
.in
.client_major_version
= 3;
327 gpd2
.in
.client_minor_version
= 0;
328 gpd2
.out
.needed
= &needed
;
329 gpd2
.out
.server_major_version
= &server_major_version
;
330 gpd2
.out
.server_minor_version
= &server_minor_version
;
332 status
= dcerpc_spoolss_GetPrinterDriver2_r(b
, tctx
, &gpd2
);
333 torture_assert_ntstatus_ok(tctx
, status
, "GetPrinterDriver2 failed");
335 if (ctx
->printer_has_driver
) {
336 torture_assert_werr_ok(tctx
, gpd2
.out
.result
,
337 "GetPrinterDriver2 failed.");
343 static bool test_EnumForms(struct torture_context
*tctx
,
344 struct dcerpc_binding_handle
*b
,
345 struct policy_handle
*handle
,
346 uint32_t initial_blob_size
)
349 struct spoolss_EnumForms ef
;
350 DATA_BLOB blob
= data_blob_talloc_zero(tctx
, initial_blob_size
);
353 union spoolss_FormInfo
*info
;
355 torture_comment(tctx
, "Testing EnumForms\n");
357 ef
.in
.handle
= handle
;
359 ef
.in
.buffer
= (initial_blob_size
== 0)?NULL
:&blob
;
360 ef
.in
.offered
= initial_blob_size
;
361 ef
.out
.needed
= &needed
;
362 ef
.out
.count
= &count
;
365 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &ef
);
366 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
368 if (W_ERROR_EQUAL(ef
.out
.result
, WERR_INSUFFICIENT_BUFFER
)) {
369 blob
= data_blob_talloc_zero(tctx
, needed
);
370 ef
.in
.buffer
= &blob
;
371 ef
.in
.offered
= needed
;
372 status
= dcerpc_spoolss_EnumForms_r(b
, tctx
, &ef
);
373 torture_assert_ntstatus_ok(tctx
, status
, "EnumForms failed");
376 torture_assert_werr_ok(tctx
, ef
.out
.result
, "EnumForms failed");
381 static bool test_EnumPrinterKey(struct torture_context
*tctx
,
382 struct dcerpc_binding_handle
*b
,
383 struct policy_handle
*handle
,
385 struct test_spoolss_win_context
*ctx
)
388 struct spoolss_EnumPrinterKey epk
;
390 union spoolss_KeyNames key_buffer
;
393 torture_comment(tctx
, "Testing EnumPrinterKey(%s)\n", key
);
395 epk
.in
.handle
= handle
;
396 epk
.in
.key_name
= talloc_strdup(tctx
, key
);
398 epk
.out
.needed
= &needed
;
399 epk
.out
.key_buffer
= &key_buffer
;
400 epk
.out
._ndr_size
= &_ndr_size
;
402 status
= dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &epk
);
403 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterKey failed");
405 if (W_ERROR_EQUAL(epk
.out
.result
, WERR_MORE_DATA
)) {
406 epk
.in
.offered
= needed
;
407 status
= dcerpc_spoolss_EnumPrinterKey_r(b
, tctx
, &epk
);
408 torture_assert_ntstatus_ok(tctx
, status
,
409 "EnumPrinterKey failed");
412 torture_assert_werr_ok(tctx
, epk
.out
.result
, "EnumPrinterKey failed");
414 ctx
->printer_keys
= key_buffer
.string_array
;
419 static bool test_EnumPrinterDataEx(struct torture_context
*tctx
,
420 struct dcerpc_binding_handle
*b
,
421 struct policy_handle
*handle
,
423 uint32_t initial_blob_size
,
424 WERROR expected_error
)
427 struct spoolss_EnumPrinterDataEx epde
;
428 struct spoolss_PrinterEnumValues
*info
;
432 torture_comment(tctx
, "Testing EnumPrinterDataEx(%s)\n", key
);
434 epde
.in
.handle
= handle
;
435 epde
.in
.key_name
= talloc_strdup(tctx
, key
);
437 epde
.out
.needed
= &needed
;
438 epde
.out
.count
= &count
;
439 epde
.out
.info
= &info
;
441 status
= dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &epde
);
442 torture_assert_ntstatus_ok(tctx
, status
, "EnumPrinterDataEx failed.");
443 if (W_ERROR_EQUAL(epde
.out
.result
, WERR_MORE_DATA
)) {
444 epde
.in
.offered
= needed
;
445 status
= dcerpc_spoolss_EnumPrinterDataEx_r(b
, tctx
, &epde
);
446 torture_assert_ntstatus_ok(tctx
, status
,
447 "EnumPrinterDataEx failed.");
450 torture_assert_werr_equal(tctx
, epde
.out
.result
, expected_error
,
451 "EnumPrinterDataEx failed.");
456 static bool test_ClosePrinter(struct torture_context
*tctx
,
457 struct dcerpc_binding_handle
*b
,
458 struct policy_handle
*handle
)
461 struct spoolss_ClosePrinter cp
;
463 cp
.in
.handle
= handle
;
464 cp
.out
.handle
= handle
;
466 status
= dcerpc_spoolss_ClosePrinter_r(b
, tctx
, &cp
);
467 torture_assert_ntstatus_ok(tctx
, status
, "ClosePrinter failed");
472 static bool test_WinXP(struct torture_context
*tctx
, struct dcerpc_pipe
*p
)
475 struct test_spoolss_win_context
*ctx
, *tmp_ctx
;
476 struct policy_handle handle01
, handle02
, handle03
, handle04
;
477 /* Sometimes a handle stays unused. In order to make this clear in the
478 * code, the unused_handle structures are used for that. */
479 struct policy_handle unused_handle1
, unused_handle2
;
482 struct dcerpc_binding_handle
*b
= p
->binding_handle
;
484 ntvfs_init(tctx
->lp_ctx
);
486 ctx
= talloc_zero(tctx
, struct test_spoolss_win_context
);
487 tmp_ctx
= talloc_zero(tctx
, struct test_spoolss_win_context
);
489 ret
&= test_OpenPrinterSequence(tctx
, p
, &handle01
);
490 ret
&= test_GetPrinterData(tctx
, b
, &handle01
,"UISingleJobStatusString",
491 WERR_INVALID_PARAM
, 0);
492 torture_comment(tctx
, "Skip RemoteFindNextPrinterChangeNotifyEx test\n");
494 server_name
= talloc_asprintf(ctx
, "\\\\%s", dcerpc_server_name(p
));
495 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle1
, server_name
, 0);
497 ret
&= test_EnumPrinters(tctx
, p
, ctx
, 1024);
499 ret
&= test_OpenPrinterEx(tctx
, b
, &handle02
, server_name
, 0);
500 ret
&= test_GetPrinterData(tctx
, b
, &handle02
, "MajorVersion", WERR_OK
,
502 ret
&= test_ClosePrinter(tctx
, b
, &handle02
);
504 /* If no printers were found, skip all tests that need a printer */
505 if (ctx
->printer_count
== 0) {
509 ret
&= test_OpenPrinterEx(tctx
, b
, &handle02
,
510 ctx
->printer_info
[0].info2
.printername
,
512 ret
&= test_GetPrinter(tctx
, b
, &handle02
, ctx
, 2, 0);
514 torture_assert_str_equal(tctx
, ctx
->current_info
->info2
.printername
,
515 ctx
->printer_info
[0].info2
.printername
,
516 "GetPrinter returned unexpected printername");
517 /*FIXME: Test more components of the PrinterInfo2 struct */
519 ret
&= test_OpenPrinterEx(tctx
, b
, &handle03
,
520 ctx
->printer_info
[0].info2
.printername
, 0);
521 ret
&= test_GetPrinter(tctx
, b
, &handle03
, ctx
, 0, 1164);
522 ret
&= test_GetPrinter(tctx
, b
, &handle03
, ctx
, 2, 0);
524 ret
&= test_OpenPrinterEx(tctx
, b
, &handle04
,
525 ctx
->printer_info
[0].info2
.printername
, 0);
526 ret
&= test_GetPrinter(tctx
, b
, &handle04
, ctx
, 2, 0);
527 ret
&= test_ClosePrinter(tctx
, b
, &handle04
);
529 ret
&= test_OpenPrinterEx(tctx
, b
, &handle04
,
530 ctx
->printer_info
[0].info2
.printername
, 0);
531 ret
&= test_GetPrinter(tctx
, b
, &handle04
, ctx
, 2, 4096);
532 ret
&= test_ClosePrinter(tctx
, b
, &handle04
);
534 ret
&= test_OpenPrinterAsAdmin(tctx
, b
,
535 ctx
->printer_info
[0].info2
.printername
);
537 ret
&= test_OpenPrinterEx(tctx
, b
, &handle04
,
538 ctx
->printer_info
[0].info2
.printername
, PRINTER_READ
);
539 ret
&= test_GetPrinterData(tctx
, b
, &handle04
,"UISingleJobStatusString",
541 torture_comment(tctx
, "Skip RemoteFindNextPrinterChangeNotifyEx test\n");
543 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
544 ctx
->printer_info
[0].info2
.printername
, 0);
546 ret
&= test_EnumJobs(tctx
, b
, &handle04
);
547 ret
&= test_GetPrinter(tctx
, b
, &handle04
, ctx
, 2, 4096);
549 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
550 ret
&= test_ClosePrinter(tctx
, b
, &handle04
);
552 ret
&= test_EnumPrinters(tctx
, p
, ctx
, 1556);
553 ret
&= test_GetPrinterDriver2(tctx
, b
, ctx
, &handle03
);
554 ret
&= test_EnumForms(tctx
, b
, &handle03
, 0);
556 ret
&= test_EnumPrinterKey(tctx
, b
, &handle03
, "", ctx
);
558 for (i
=0; ctx
->printer_keys
&& ctx
->printer_keys
[i
] != NULL
; i
++) {
560 ret
&= test_EnumPrinterKey(tctx
, b
, &handle03
,
561 ctx
->printer_keys
[i
],
563 ret
&= test_EnumPrinterDataEx(tctx
, b
, &handle03
,
564 ctx
->printer_keys
[i
], 0,
568 ret
&= test_EnumPrinterDataEx(tctx
, b
, &handle03
, "", 0,
571 ret
&= test_GetPrinter(tctx
, b
, &handle03
, tmp_ctx
, 2, 0);
573 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
574 ctx
->printer_info
[0].info2
.printername
, 0);
575 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
577 ret
&= test_GetPrinter(tctx
, b
, &handle03
, tmp_ctx
, 2, 2556);
579 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
580 ctx
->printer_info
[0].info2
.printername
, 0);
581 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
583 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
584 ctx
->printer_info
[0].info2
.printername
, 0);
585 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
587 ret
&= test_GetPrinter(tctx
, b
, &handle03
, tmp_ctx
, 7, 0);
589 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
590 ctx
->printer_info
[0].info2
.printername
, 0);
591 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
593 ret
&= test_ClosePrinter(tctx
, b
, &handle03
);
595 ret
&= test_OpenPrinterEx(tctx
, b
, &unused_handle2
,
596 ctx
->printer_info
[0].info2
.printername
, 0);
597 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle2
);
599 ret
&= test_OpenPrinterEx(tctx
, b
, &handle03
, server_name
, 0);
600 ret
&= test_GetPrinterData(tctx
, b
, &handle03
, "W3SvcInstalled",
602 ret
&= test_ClosePrinter(tctx
, b
, &handle03
);
604 ret
&= test_ClosePrinter(tctx
, b
, &unused_handle1
);
605 ret
&= test_ClosePrinter(tctx
, b
, &handle02
);
607 ret
&= test_OpenPrinterEx(tctx
, b
, &handle02
,
608 ctx
->printer_info
[0].info2
.sharename
, 0);
609 ret
&= test_GetPrinter(tctx
, b
, &handle02
, tmp_ctx
, 2, 0);
610 ret
&= test_ClosePrinter(tctx
, b
, &handle02
);
613 ret
&= test_ClosePrinter(tctx
, b
, &handle01
);
615 talloc_free(tmp_ctx
);
620 struct torture_suite
*torture_rpc_spoolss_win(TALLOC_CTX
*mem_ctx
)
622 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "SPOOLSS-WIN");
624 struct torture_rpc_tcase
*tcase
= torture_suite_add_rpc_iface_tcase(suite
,
625 "win", &ndr_table_spoolss
);
627 torture_rpc_tcase_add_test(tcase
, "testWinXP", test_WinXP
);