• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/torture/rpc/
1/*
2   Unix SMB/CIFS implementation.
3   test suite for spoolss rpc operations as performed by various win versions
4
5   Copyright (C) Kai Blin 2007
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 "torture/rpc/rpc.h"
24#include "librpc/gen_ndr/ndr_spoolss_c.h"
25#include "rpc_server/dcerpc_server.h"
26#include "librpc/gen_ndr/ndr_misc.h"
27#include "ntvfs/ntvfs.h"
28#include "param/param.h"
29
30struct test_spoolss_win_context {
31	/* EnumPrinters */
32	uint32_t printer_count;
33	union spoolss_PrinterInfo *printer_info;
34	union spoolss_PrinterInfo *current_info;
35
36	/* EnumPrinterKeys */
37	const char **printer_keys;
38
39	bool printer_has_driver;
40};
41
42/* This is a convenience function for all OpenPrinterEx calls */
43static bool test_OpenPrinterEx(struct torture_context *tctx,
44				struct dcerpc_pipe *p,
45				struct policy_handle *handle,
46				const char *printer_name,
47				uint32_t access_mask)
48{
49	NTSTATUS status;
50	struct spoolss_OpenPrinterEx op;
51	struct spoolss_UserLevel1 ul_1;
52
53	torture_comment(tctx, "Opening printer '%s'\n", printer_name);
54
55	op.in.printername		= talloc_strdup(tctx, printer_name);
56	op.in.datatype			= NULL;
57	op.in.devmode_ctr.devmode	= NULL;
58	op.in.access_mask		= access_mask;
59	op.in.level			= 1;
60	op.in.userlevel.level1		= &ul_1;
61	op.out.handle			= handle;
62
63	ul_1.size 			= 1234;
64	ul_1.client			= "\\clientname";
65	ul_1.user			= "username";
66	ul_1.build			= 1;
67	ul_1.major			= 2;
68	ul_1.minor			= 3;
69	ul_1.processor			= 4567;
70
71	status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &op);
72	torture_assert_ntstatus_ok(tctx, status, "OpenPrinterEx failed");
73	torture_assert_werr_ok(tctx, op.out.result, "OpenPrinterEx failed");
74
75	return true;
76}
77
78static bool test_OpenPrinterAsAdmin(struct torture_context *tctx,
79					struct dcerpc_pipe *p,
80					const char *printername)
81{
82	NTSTATUS status;
83	struct spoolss_OpenPrinterEx op;
84	struct spoolss_ClosePrinter cp;
85	struct spoolss_UserLevel1 ul_1;
86	struct policy_handle handle;
87
88	ul_1.size 			= 1234;
89	ul_1.client			= "\\clientname";
90	ul_1.user			= "username";
91	ul_1.build			= 1;
92	ul_1.major			= 2;
93	ul_1.minor			= 3;
94	ul_1.processor			= 4567;
95
96	op.in.printername		= talloc_strdup(tctx, printername);
97	op.in.datatype			= NULL;
98	op.in.devmode_ctr.devmode	= NULL;
99	op.in.access_mask		= SERVER_ALL_ACCESS;
100	op.in.level			= 1;
101	op.in.userlevel.level1		= &ul_1;
102	op.out.handle			= &handle;
103
104	cp.in.handle			= &handle;
105	cp.out.handle			= &handle;
106
107	torture_comment(tctx, "Testing OpenPrinterEx(%s) with admin rights\n",
108			op.in.printername);
109
110	status = dcerpc_spoolss_OpenPrinterEx(p, tctx, &op);
111
112	if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(op.out.result)) {
113		status = dcerpc_spoolss_ClosePrinter(p, tctx, &cp);
114		torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
115	}
116
117	return true;
118}
119
120
121static bool test_ClosePrinter(struct torture_context *tctx,
122				struct dcerpc_pipe *p,
123				struct policy_handle *handle);
124
125/* This replicates the opening sequence of OpenPrinterEx calls XP does */
126static bool test_OpenPrinterSequence(struct torture_context *tctx,
127					struct dcerpc_pipe *p,
128					struct policy_handle *handle)
129{
130	bool ret;
131	char *printername = talloc_asprintf(tctx, "\\\\%s",
132			dcerpc_server_name(p));
133
134	/* First, see if we can open the printer read_only */
135	ret = test_OpenPrinterEx(tctx, p, handle, printername, 0);
136	torture_assert(tctx, ret == true, "OpenPrinterEx failed.");
137
138	ret = test_ClosePrinter(tctx, p, handle);
139	torture_assert(tctx, ret, "ClosePrinter failed");
140
141	/* Now let's see if we have admin rights to it. */
142	ret = test_OpenPrinterAsAdmin(tctx, p, printername);
143	torture_assert(tctx, ret == true,
144			"OpenPrinterEx as admin failed unexpectedly.");
145
146	ret = test_OpenPrinterEx(tctx, p, handle, printername, SERVER_EXECUTE);
147	torture_assert(tctx, ret == true, "OpenPrinterEx failed.");
148
149	return true;
150}
151
152static bool test_GetPrinterData(struct torture_context *tctx,
153				struct dcerpc_pipe *p,
154				struct policy_handle *handle,
155				const char *value_name,
156				WERROR expected_werr,
157				uint32_t expected_value)
158{
159	NTSTATUS status;
160	struct spoolss_GetPrinterData gpd;
161	uint32_t needed;
162	enum winreg_Type type;
163	uint8_t *data = talloc_zero_array(tctx, uint8_t, 4);
164
165	torture_comment(tctx, "Testing GetPrinterData(%s).\n", value_name);
166	gpd.in.handle = handle;
167	gpd.in.value_name = value_name;
168	gpd.in.offered = 4;
169	gpd.out.needed = &needed;
170	gpd.out.type = &type;
171	gpd.out.data = data;
172
173	status = dcerpc_spoolss_GetPrinterData(p, tctx, &gpd);
174	torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed.");
175	torture_assert_werr_equal(tctx, gpd.out.result, expected_werr,
176			"GetPrinterData did not return expected error value.");
177
178	if (W_ERROR_IS_OK(expected_werr)) {
179		uint32_t value = IVAL(data, 0);
180		torture_assert_int_equal(tctx, value,
181			expected_value,
182			talloc_asprintf(tctx, "GetPrinterData for %s did not return expected value.", value_name));
183	}
184	return true;
185}
186
187static bool test_EnumPrinters(struct torture_context *tctx,
188				struct dcerpc_pipe *p,
189				struct test_spoolss_win_context *ctx,
190				uint32_t initial_blob_size)
191{
192	NTSTATUS status;
193	struct spoolss_EnumPrinters ep;
194	DATA_BLOB blob = data_blob_talloc_zero(ctx, initial_blob_size);
195	uint32_t needed;
196	uint32_t count;
197	union spoolss_PrinterInfo *info;
198
199	ep.in.flags = PRINTER_ENUM_NAME;
200	ep.in.server = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
201	ep.in.level = 2;
202	ep.in.buffer = &blob;
203	ep.in.offered = initial_blob_size;
204	ep.out.needed = &needed;
205	ep.out.count = &count;
206	ep.out.info = &info;
207
208	status = dcerpc_spoolss_EnumPrinters(p, ctx, &ep);
209	torture_assert_ntstatus_ok(tctx, status, "EnumPrinters failed.");
210
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(p, ctx, &ep);
216		torture_assert_ntstatus_ok(tctx, status,"EnumPrinters failed.");
217	}
218
219	torture_assert_werr_ok(tctx, ep.out.result, "EnumPrinters failed.");
220
221	ctx->printer_count = count;
222	ctx->printer_info = info;
223
224	torture_comment(tctx, "Found %d printer(s).\n", ctx->printer_count);
225
226	return true;
227}
228
229static bool test_GetPrinter(struct torture_context *tctx,
230				struct dcerpc_pipe *p,
231				struct policy_handle *handle,
232				struct test_spoolss_win_context *ctx,
233				uint32_t level,
234				uint32_t initial_blob_size)
235{
236	NTSTATUS status;
237	struct spoolss_GetPrinter gp;
238	DATA_BLOB blob = data_blob_talloc_zero(ctx, initial_blob_size);
239	uint32_t needed;
240
241	torture_comment(tctx, "Test GetPrinter level %d\n", level);
242
243	gp.in.handle = handle;
244	gp.in.level = level;
245	gp.in.buffer = (initial_blob_size == 0)?NULL:&blob;
246	gp.in.offered = initial_blob_size;
247	gp.out.needed = &needed;
248
249	status = dcerpc_spoolss_GetPrinter(p, tctx, &gp);
250	torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
251
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(p, tctx, &gp);
257		torture_assert_ntstatus_ok(tctx, status, "GetPrinter failed");
258	}
259
260	torture_assert_werr_ok(tctx, gp.out.result, "GetPrinter failed");
261
262	ctx->current_info = gp.out.info;
263
264	if (level == 2 && gp.out.info) {
265		ctx->printer_has_driver = gp.out.info->info2.drivername &&
266					  strlen(gp.out.info->info2.drivername);
267	}
268
269	return true;
270}
271
272static bool test_EnumJobs(struct torture_context *tctx,
273				struct dcerpc_pipe *p,
274				struct policy_handle *handle)
275{
276	NTSTATUS status;
277	struct spoolss_EnumJobs ej;
278	DATA_BLOB blob = data_blob_talloc_zero(tctx, 1024);
279	uint32_t needed;
280	uint32_t count;
281	union spoolss_JobInfo *info;
282
283	torture_comment(tctx, "Test EnumJobs\n");
284
285	ej.in.handle = handle;
286	ej.in.level = 2;
287	ej.in.buffer = &blob;
288	ej.in.offered = 1024;
289	ej.out.needed = &needed;
290	ej.out.count = &count;
291	ej.out.info = &info;
292
293	status = dcerpc_spoolss_EnumJobs(p, 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(p, tctx, &ej);
300		torture_assert_ntstatus_ok(tctx, status, "EnumJobs failed");
301	}
302	torture_assert_werr_ok(tctx, ej.out.result, "EnumJobs failed");
303
304	return true;
305}
306
307static bool test_GetPrinterDriver2(struct torture_context *tctx,
308					struct dcerpc_pipe *p,
309					struct test_spoolss_win_context *ctx,
310					struct policy_handle *handle)
311{
312	NTSTATUS status;
313	struct spoolss_GetPrinterDriver2 gpd2;
314	DATA_BLOB blob = data_blob_talloc_zero(tctx, 87424);
315	uint32_t needed;
316	uint32_t server_major_version;
317	uint32_t server_minor_version;
318
319	torture_comment(tctx, "Testing GetPrinterDriver2\n");
320
321	gpd2.in.handle = handle;
322	gpd2.in.architecture = "Windows NT x86";
323	gpd2.in.level = 101;
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;
331
332	status = dcerpc_spoolss_GetPrinterDriver2(p, tctx, &gpd2);
333	torture_assert_ntstatus_ok(tctx, status, "GetPrinterDriver2 failed");
334
335	if (ctx->printer_has_driver) {
336		torture_assert_werr_ok(tctx, gpd2.out.result,
337				"GetPrinterDriver2 failed.");
338	}
339
340	return true;
341}
342
343static bool test_EnumForms(struct torture_context *tctx,
344				struct dcerpc_pipe *p,
345				struct policy_handle *handle,
346				uint32_t initial_blob_size)
347{
348	NTSTATUS status;
349	struct spoolss_EnumForms ef;
350	DATA_BLOB blob = data_blob_talloc_zero(tctx, initial_blob_size);
351	uint32_t needed;
352	uint32_t count;
353	union spoolss_FormInfo *info;
354
355	torture_comment(tctx, "Testing EnumForms\n");
356
357	ef.in.handle = handle;
358	ef.in.level = 1;
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;
363	ef.out.info = &info;
364
365	status = dcerpc_spoolss_EnumForms(p, tctx, &ef);
366	torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
367
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(p, tctx, &ef);
373		torture_assert_ntstatus_ok(tctx, status, "EnumForms failed");
374	}
375
376	torture_assert_werr_ok(tctx, ef.out.result, "EnumForms failed");
377
378	return true;
379}
380
381static bool test_EnumPrinterKey(struct torture_context *tctx,
382				struct dcerpc_pipe *p,
383				struct policy_handle *handle,
384				const char* key,
385				struct test_spoolss_win_context *ctx)
386{
387	NTSTATUS status;
388	struct spoolss_EnumPrinterKey epk;
389	uint32_t needed = 0;
390	union spoolss_KeyNames key_buffer;
391	uint32_t _ndr_size;
392
393	torture_comment(tctx, "Testing EnumPrinterKey(%s)\n", key);
394
395	epk.in.handle = handle;
396	epk.in.key_name = talloc_strdup(tctx, key);
397	epk.in.offered = 0;
398	epk.out.needed = &needed;
399	epk.out.key_buffer = &key_buffer;
400	epk.out._ndr_size = &_ndr_size;
401
402	status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk);
403	torture_assert_ntstatus_ok(tctx, status, "EnumPrinterKey failed");
404
405	if (W_ERROR_EQUAL(epk.out.result, WERR_MORE_DATA)) {
406		epk.in.offered = needed;
407		status = dcerpc_spoolss_EnumPrinterKey(p, tctx, &epk);
408		torture_assert_ntstatus_ok(tctx, status,
409				"EnumPrinterKey failed");
410	}
411
412	torture_assert_werr_ok(tctx, epk.out.result, "EnumPrinterKey failed");
413
414	ctx->printer_keys = key_buffer.string_array;
415
416	return true;
417}
418
419static bool test_EnumPrinterDataEx(struct torture_context *tctx,
420					struct dcerpc_pipe *p,
421					struct policy_handle *handle,
422					const char *key,
423					uint32_t initial_blob_size,
424					WERROR expected_error)
425{
426	NTSTATUS status;
427	struct spoolss_EnumPrinterDataEx epde;
428	struct spoolss_PrinterEnumValues *info;
429	uint32_t needed;
430	uint32_t count;
431
432	torture_comment(tctx, "Testing EnumPrinterDataEx(%s)\n", key);
433
434	epde.in.handle = handle;
435	epde.in.key_name = talloc_strdup(tctx, key);
436	epde.in.offered = 0;
437	epde.out.needed = &needed;
438	epde.out.count = &count;
439	epde.out.info = &info;
440
441	status = dcerpc_spoolss_EnumPrinterDataEx(p, 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(p, tctx, &epde);
446		torture_assert_ntstatus_ok(tctx, status,
447				"EnumPrinterDataEx failed.");
448	}
449
450	torture_assert_werr_equal(tctx, epde.out.result, expected_error,
451			"EnumPrinterDataEx failed.");
452
453	return true;
454}
455
456static bool test_ClosePrinter(struct torture_context *tctx,
457				struct dcerpc_pipe *p,
458				struct policy_handle *handle)
459{
460	NTSTATUS status;
461	struct spoolss_ClosePrinter cp;
462
463	cp.in.handle  = handle;
464	cp.out.handle = handle;
465
466	status = dcerpc_spoolss_ClosePrinter(p, tctx, &cp);
467	torture_assert_ntstatus_ok(tctx, status, "ClosePrinter failed");
468
469	return true;
470}
471
472static bool test_WinXP(struct torture_context *tctx, struct dcerpc_pipe *p)
473{
474	bool ret = true;
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;
480	char *server_name;
481	uint32_t i;
482
483	ntvfs_init(tctx->lp_ctx);
484
485	ctx = talloc_zero(tctx, struct test_spoolss_win_context);
486	tmp_ctx = talloc_zero(tctx, struct test_spoolss_win_context);
487
488	ret &= test_OpenPrinterSequence(tctx, p, &handle01);
489	ret &= test_GetPrinterData(tctx, p, &handle01,"UISingleJobStatusString",
490			WERR_INVALID_PARAM, 0);
491	torture_comment(tctx, "Skip RemoteFindNextPrinterChangeNotifyEx test\n");
492
493	server_name = talloc_asprintf(ctx, "\\\\%s", dcerpc_server_name(p));
494	ret &= test_OpenPrinterEx(tctx, p, &unused_handle1, server_name, 0);
495
496	ret &= test_EnumPrinters(tctx, p, ctx, 1024);
497
498	ret &= test_OpenPrinterEx(tctx, p, &handle02, server_name, 0);
499	ret &= test_GetPrinterData(tctx, p, &handle02, "MajorVersion", WERR_OK,
500			3);
501	ret &= test_ClosePrinter(tctx, p, &handle02);
502
503	/* If no printers were found, skip all tests that need a printer */
504	if (ctx->printer_count == 0) {
505		goto end_testWinXP;
506	}
507
508	ret &= test_OpenPrinterEx(tctx, p, &handle02,
509			ctx->printer_info[0].info2.printername,
510			PRINTER_ACCESS_USE);
511	ret &= test_GetPrinter(tctx, p, &handle02, ctx, 2, 0);
512
513	torture_assert_str_equal(tctx, ctx->current_info->info2.printername,
514			ctx->printer_info[0].info2.printername,
515			"GetPrinter returned unexpected printername");
516	/*FIXME: Test more components of the PrinterInfo2 struct */
517
518	ret &= test_OpenPrinterEx(tctx, p, &handle03,
519			ctx->printer_info[0].info2.printername, 0);
520	ret &= test_GetPrinter(tctx, p, &handle03, ctx, 0, 1164);
521	ret &= test_GetPrinter(tctx, p, &handle03, ctx, 2, 0);
522
523	ret &= test_OpenPrinterEx(tctx, p, &handle04,
524			ctx->printer_info[0].info2.printername, 0);
525	ret &= test_GetPrinter(tctx, p, &handle04, ctx, 2, 0);
526	ret &= test_ClosePrinter(tctx, p, &handle04);
527
528	ret &= test_OpenPrinterEx(tctx, p, &handle04,
529			ctx->printer_info[0].info2.printername, 0);
530	ret &= test_GetPrinter(tctx, p, &handle04, ctx, 2, 4096);
531	ret &= test_ClosePrinter(tctx, p, &handle04);
532
533	ret &= test_OpenPrinterAsAdmin(tctx, p,
534			ctx->printer_info[0].info2.printername);
535
536	ret &= test_OpenPrinterEx(tctx, p, &handle04,
537			ctx->printer_info[0].info2.printername, PRINTER_READ);
538	ret &= test_GetPrinterData(tctx, p, &handle04,"UISingleJobStatusString",
539			WERR_BADFILE, 0);
540	torture_comment(tctx, "Skip RemoteFindNextPrinterChangeNotifyEx test\n");
541
542	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
543			ctx->printer_info[0].info2.printername, 0);
544
545	ret &= test_EnumJobs(tctx, p, &handle04);
546	ret &= test_GetPrinter(tctx, p, &handle04, ctx, 2, 4096);
547
548	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
549	ret &= test_ClosePrinter(tctx, p, &handle04);
550
551	ret &= test_EnumPrinters(tctx, p, ctx, 1556);
552	ret &= test_GetPrinterDriver2(tctx, p, ctx, &handle03);
553	ret &= test_EnumForms(tctx, p, &handle03, 0);
554
555	ret &= test_EnumPrinterKey(tctx, p, &handle03, "", ctx);
556
557	for (i=0; ctx->printer_keys && ctx->printer_keys[i] != NULL; i++) {
558
559		ret &= test_EnumPrinterKey(tctx, p, &handle03,
560					   ctx->printer_keys[i],
561					   tmp_ctx);
562		ret &= test_EnumPrinterDataEx(tctx, p, &handle03,
563					      ctx->printer_keys[i], 0,
564					      WERR_OK);
565	}
566
567	ret &= test_EnumPrinterDataEx(tctx, p, &handle03, "", 0,
568			WERR_INVALID_PARAM);
569
570	ret &= test_GetPrinter(tctx, p, &handle03, tmp_ctx, 2, 0);
571
572	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
573			ctx->printer_info[0].info2.printername, 0);
574	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
575
576	ret &= test_GetPrinter(tctx, p, &handle03, tmp_ctx, 2, 2556);
577
578	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
579			ctx->printer_info[0].info2.printername, 0);
580	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
581
582	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
583			ctx->printer_info[0].info2.printername, 0);
584	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
585
586	ret &= test_GetPrinter(tctx, p, &handle03, tmp_ctx, 7, 0);
587
588	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
589			ctx->printer_info[0].info2.printername, 0);
590	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
591
592	ret &= test_ClosePrinter(tctx, p, &handle03);
593
594	ret &= test_OpenPrinterEx(tctx, p, &unused_handle2,
595			ctx->printer_info[0].info2.printername, 0);
596	ret &= test_ClosePrinter(tctx, p, &unused_handle2);
597
598	ret &= test_OpenPrinterEx(tctx, p, &handle03, server_name, 0);
599	ret &= test_GetPrinterData(tctx, p, &handle03, "W3SvcInstalled",
600			WERR_OK, 0);
601	ret &= test_ClosePrinter(tctx, p, &handle03);
602
603	ret &= test_ClosePrinter(tctx, p, &unused_handle1);
604	ret &= test_ClosePrinter(tctx, p, &handle02);
605
606	ret &= test_OpenPrinterEx(tctx, p, &handle02,
607			ctx->printer_info[0].info2.sharename, 0);
608	ret &= test_GetPrinter(tctx, p, &handle02, tmp_ctx, 2, 0);
609	ret &= test_ClosePrinter(tctx, p, &handle02);
610
611end_testWinXP:
612	ret &= test_ClosePrinter(tctx, p, &handle01);
613
614	talloc_free(tmp_ctx);
615	talloc_free(ctx);
616	return ret;
617}
618
619struct torture_suite *torture_rpc_spoolss_win(TALLOC_CTX *mem_ctx)
620{
621	struct torture_suite *suite = torture_suite_create(mem_ctx, "SPOOLSS-WIN");
622
623	struct torture_rpc_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite,
624							"win", &ndr_table_spoolss);
625
626	torture_rpc_tcase_add_test(tcase, "testWinXP", test_WinXP);
627
628	return suite;
629}
630
631