s4-torture: add test for winspool_AsyncUploadPrinterDriverPackage
[Samba.git] / source4 / torture / rpc / iremotewinspool.c
blobbcc37f9c7349219eed7fdaebd6c06bbc117a4874
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for iremotewinspool rpc operations
5 Copyright (C) Guenther Deschner 2013
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 "torture/rpc/torture_rpc.h"
26 #include "libcli/registry/util_reg.h"
28 struct test_iremotewinspool_context {
29 struct GUID object_uuid;
30 struct dcerpc_pipe *iremotewinspool_pipe;
31 struct policy_handle server_handle;
32 const char *environment;
35 static bool test_AsyncOpenPrinter_byprinter(struct torture_context *tctx,
36 struct test_iremotewinspool_context *ctx,
37 struct dcerpc_pipe *p,
38 const char *printer_name,
39 struct policy_handle *handle)
41 struct dcerpc_binding_handle *b = p->binding_handle;
42 struct spoolss_DevmodeContainer devmode_ctr;
43 struct spoolss_UserLevelCtr client_info_ctr;
44 struct spoolss_UserLevel1 level1;
45 uint32_t access_mask = SERVER_ALL_ACCESS;
46 struct winspool_AsyncOpenPrinter r;
48 ZERO_STRUCT(devmode_ctr);
50 level1.size = 28;
51 level1.client = talloc_asprintf(tctx, "\\\\%s", "mthelena");
52 level1.user = "GD";
53 level1.build = 1381;
54 level1.major = 3;
55 level1.minor = 0;
56 level1.processor = PROCESSOR_ARCHITECTURE_AMD64;
58 client_info_ctr.level = 1;
59 client_info_ctr.user_info.level1 = &level1;
61 r.in.pPrinterName = printer_name;
62 r.in.pDatatype = NULL;
63 r.in.pDevModeContainer = &devmode_ctr;
64 r.in.AccessRequired = access_mask;
65 r.in.pClientInfo = &client_info_ctr;
66 r.out.pHandle = handle;
68 torture_assert_ntstatus_ok(tctx,
69 dcerpc_winspool_AsyncOpenPrinter_r(b, tctx, &r),
70 "AsyncOpenPrinter failed");
71 torture_assert_werr_ok(tctx, r.out.result,
72 "AsyncOpenPrinter failed");
74 return true;
77 static bool test_AsyncClosePrinter_byhandle(struct torture_context *tctx,
78 struct test_iremotewinspool_context *ctx,
79 struct dcerpc_pipe *p,
80 struct policy_handle *handle)
82 struct dcerpc_binding_handle *b = p->binding_handle;
84 struct winspool_AsyncClosePrinter r;
86 r.in.phPrinter = handle;
87 r.out.phPrinter = handle;
89 torture_assert_ntstatus_ok(tctx,
90 dcerpc_winspool_AsyncClosePrinter_r(b, tctx, &r),
91 "AsyncClosePrinter failed");
92 torture_assert_werr_ok(tctx, r.out.result,
93 "AsyncClosePrinter failed");
95 return true;
98 static bool test_AsyncGetPrinterData_checktype(struct torture_context *tctx,
99 struct dcerpc_binding_handle *b,
100 struct policy_handle *handle,
101 const char *value_name,
102 enum winreg_Type *expected_type,
103 enum winreg_Type *type_p,
104 uint8_t **data_p,
105 uint32_t *needed_p)
107 struct winspool_AsyncGetPrinterData r;
108 enum winreg_Type type;
109 uint32_t needed;
111 r.in.hPrinter = *handle;
112 r.in.pValueName = value_name;
113 r.in.nSize = 0;
114 r.out.pType = &type;
115 r.out.pData = talloc_zero_array(tctx, uint8_t, r.in.nSize);
116 r.out.pcbNeeded = &needed;
118 torture_comment(tctx, "Testing AsyncGetPrinterData(%s)\n",
119 r.in.pValueName);
121 torture_assert_ntstatus_ok(tctx,
122 dcerpc_winspool_AsyncGetPrinterData_r(b, tctx, &r),
123 "AsyncGetPrinterData failed");
125 if (W_ERROR_EQUAL(r.out.result, WERR_MORE_DATA)) {
126 if (expected_type) {
127 torture_assert_int_equal(tctx, type, *expected_type, "unexpected type");
129 r.in.nSize = needed;
130 r.out.pData = talloc_zero_array(tctx, uint8_t, r.in.nSize);
132 torture_assert_ntstatus_ok(tctx,
133 dcerpc_winspool_AsyncGetPrinterData_r(b, tctx, &r),
134 "AsyncGetPrinterData failed");
137 torture_assert_werr_ok(tctx, r.out.result,
138 "AsyncGetPrinterData failed");
140 if (type_p) {
141 *type_p = type;
144 if (data_p) {
145 *data_p = r.out.pData;
148 if (needed_p) {
149 *needed_p = needed;
152 return true;
155 static bool test_AsyncGetPrinterData(struct torture_context *tctx,
156 struct dcerpc_binding_handle *b,
157 struct policy_handle *handle,
158 const char *value_name,
159 enum winreg_Type *type_p,
160 uint8_t **data_p,
161 uint32_t *needed_p)
163 return test_AsyncGetPrinterData_checktype(tctx, b, handle,
164 value_name,
165 NULL,
166 type_p, data_p, needed_p);
169 static bool test_get_environment(struct torture_context *tctx,
170 struct dcerpc_binding_handle *b,
171 struct policy_handle *handle,
172 const char **architecture)
174 DATA_BLOB blob;
175 enum winreg_Type type;
176 uint8_t *data;
177 uint32_t needed;
179 torture_assert(tctx,
180 test_AsyncGetPrinterData(tctx, b, handle, "Architecture", &type, &data, &needed),
181 "failed to get Architecture");
183 torture_assert_int_equal(tctx, type, REG_SZ, "unexpected type");
185 blob = data_blob_const(data, needed);
187 torture_assert(tctx,
188 pull_reg_sz(tctx, &blob, architecture),
189 "failed to pull environment");
191 return true;
194 static bool torture_rpc_iremotewinspool_setup_common(struct torture_context *tctx,
195 struct test_iremotewinspool_context *t)
197 const char *printer_name;
198 struct dcerpc_binding *binding;
200 torture_assert_ntstatus_ok(tctx,
201 GUID_from_string(IREMOTEWINSPOOL_OBJECT_GUID, &t->object_uuid),
202 "failed to parse GUID");
204 torture_assert_ntstatus_ok(tctx,
205 torture_rpc_binding(tctx, &binding),
206 "failed to retrieve torture binding");
208 torture_assert_ntstatus_ok(tctx,
209 dcerpc_binding_set_object(binding, t->object_uuid),
210 "failed to set object_uuid");
212 torture_assert_ntstatus_ok(tctx,
213 torture_rpc_connection_with_binding(tctx, binding, &t->iremotewinspool_pipe, &ndr_table_iremotewinspool),
214 "Error connecting to server");
216 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(t->iremotewinspool_pipe));
218 torture_assert(tctx,
219 test_AsyncOpenPrinter_byprinter(tctx, t,
220 t->iremotewinspool_pipe, printer_name,
221 &t->server_handle),
222 "failed to open printserver");
223 torture_assert(tctx,
224 test_get_environment(tctx,
225 t->iremotewinspool_pipe->binding_handle,
226 &t->server_handle, &t->environment),
227 "failed to get environment");
229 return true;
232 static bool torture_rpc_iremotewinspool_setup(struct torture_context *tctx,
233 void **data)
235 struct test_iremotewinspool_context *t;
237 *data = t = talloc_zero(tctx, struct test_iremotewinspool_context);
239 return torture_rpc_iremotewinspool_setup_common(tctx, t);
242 static bool torture_rpc_iremotewinspool_teardown_common(struct torture_context *tctx,
243 struct test_iremotewinspool_context *t)
246 test_AsyncClosePrinter_byhandle(tctx, t, t->iremotewinspool_pipe, &t->server_handle);
248 return true;
251 static bool torture_rpc_iremotewinspool_teardown(struct torture_context *tctx,
252 void *data)
254 struct test_iremotewinspool_context *t = talloc_get_type(data, struct test_iremotewinspool_context);
255 bool ret;
257 ret = torture_rpc_iremotewinspool_teardown_common(tctx, t);
258 talloc_free(t);
260 return ret;
263 static bool test_AsyncClosePrinter(struct torture_context *tctx,
264 void *private_data)
266 struct test_iremotewinspool_context *ctx =
267 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
269 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
270 const char *printer_name;
271 struct policy_handle handle;
273 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
275 torture_assert(tctx,
276 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, &handle),
277 "failed to test AsyncOpenPrinter");
279 torture_assert(tctx,
280 test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle),
281 "failed to test AsyncClosePrinter");
283 return true;
286 static bool test_AsyncOpenPrinter(struct torture_context *tctx,
287 void *private_data)
289 struct test_iremotewinspool_context *ctx =
290 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
292 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
293 const char *printer_name;
294 struct policy_handle handle;
296 printer_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
298 torture_assert(tctx,
299 test_AsyncOpenPrinter_byprinter(tctx, ctx, p, printer_name, &handle),
300 "failed to test AsyncOpenPrinter");
302 test_AsyncClosePrinter_byhandle(tctx, ctx, p, &handle);
304 return true;
307 static struct spoolss_NotifyOption *setup_printserver_NotifyOption(struct torture_context *tctx)
309 struct spoolss_NotifyOption *o;
311 o = talloc_zero(tctx, struct spoolss_NotifyOption);
312 if (o == NULL) {
313 return NULL;
316 o->version = 2;
317 o->flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
319 o->count = 2;
320 o->types = talloc_zero_array(o, struct spoolss_NotifyOptionType, o->count);
321 if (o->types == NULL) {
322 talloc_free(o);
323 return NULL;
326 o->types[0].type = PRINTER_NOTIFY_TYPE;
327 o->types[0].count = 1;
328 o->types[0].fields = talloc_array(o->types, union spoolss_Field, o->types[0].count);
329 if (o->types[0].fields == NULL) {
330 talloc_free(o);
331 return NULL;
333 o->types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
335 o->types[1].type = JOB_NOTIFY_TYPE;
336 o->types[1].count = 1;
337 o->types[1].fields = talloc_array(o->types, union spoolss_Field, o->types[1].count);
338 if (o->types[1].fields == NULL) {
339 talloc_free(o);
340 return NULL;
342 o->types[1].fields[0].field = JOB_NOTIFY_FIELD_MACHINE_NAME;
344 return o;
347 static bool test_SyncUnRegisterForRemoteNotifications_args(struct torture_context *tctx,
348 struct dcerpc_pipe *p,
349 struct policy_handle *notify_handle)
351 struct winspool_SyncUnRegisterForRemoteNotifications r;
352 struct dcerpc_binding_handle *b = p->binding_handle;
354 r.in.phRpcHandle = notify_handle;
355 r.out.phRpcHandle = notify_handle;
357 torture_assert_ntstatus_ok(tctx,
358 dcerpc_winspool_SyncUnRegisterForRemoteNotifications_r(b, tctx, &r),
359 "SyncUnRegisterForRemoteNotifications failed");
360 torture_assert_hresult_ok(tctx, r.out.result,
361 "SyncUnRegisterForRemoteNotifications failed");
363 return true;
366 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
367 struct dcerpc_pipe *p,
368 struct policy_handle *server_handle,
369 struct policy_handle *notify_handle);
371 static bool test_SyncUnRegisterForRemoteNotifications(struct torture_context *tctx,
372 void *private_data)
374 struct test_iremotewinspool_context *ctx =
375 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
376 struct policy_handle notify_handle;
378 torture_assert(tctx,
379 test_SyncRegisterForRemoteNotifications_args(tctx,
380 ctx->iremotewinspool_pipe,
381 &ctx->server_handle,
382 &notify_handle),
383 "failed to test SyncRegisterForRemoteNotifications");
385 torture_assert(tctx,
386 test_SyncUnRegisterForRemoteNotifications_args(tctx,
387 ctx->iremotewinspool_pipe,
388 &notify_handle),
389 "failed to test UnSyncRegisterForRemoteNotifications");
391 return true;
394 static bool test_SyncRegisterForRemoteNotifications_args(struct torture_context *tctx,
395 struct dcerpc_pipe *p,
396 struct policy_handle *server_handle,
397 struct policy_handle *notify_handle)
399 struct dcerpc_binding_handle *b = p->binding_handle;
401 struct winspool_SyncRegisterForRemoteNotifications r;
402 struct winspool_PrintPropertiesCollection NotifyFilter;
403 struct winspool_PrintNamedProperty *c;
404 struct spoolss_NotifyOption *options;
406 ZERO_STRUCT(NotifyFilter);
408 options = setup_printserver_NotifyOption(tctx);
409 torture_assert(tctx, options, "out of memory");
411 c = talloc_zero_array(tctx, struct winspool_PrintNamedProperty, 4);
412 torture_assert(tctx, c, "out of memory");
414 c[0].propertyName = "RemoteNotifyFilter Flags";
415 c[0].propertyValue.PropertyType = winspool_PropertyTypeInt32;
416 c[0].propertyValue.value.propertyInt32 = 0xff;
418 c[1].propertyName = "RemoteNotifyFilter Options";
419 c[1].propertyValue.PropertyType = winspool_PropertyTypeInt32;
420 c[1].propertyValue.value.propertyInt32 = 0;
422 c[2].propertyName = "RemoteNotifyFilter Color";
423 c[2].propertyValue.PropertyType = winspool_PropertyTypeInt32;
424 c[2].propertyValue.value.propertyInt32 = 0;
426 c[3].propertyName = "RemoteNotifyFilter NotifyOptions";
427 c[3].propertyValue.PropertyType = winspool_PropertyTypeNotificationOptions;
428 c[3].propertyValue.value.propertyOptionsContainer.pOptions = options;
430 NotifyFilter.numberOfProperties = 4;
431 NotifyFilter.propertiesCollection = c;
433 r.in.hPrinter = *server_handle;
434 r.in.pNotifyFilter = &NotifyFilter;
435 r.out.phRpcHandle = notify_handle;
437 torture_assert_ntstatus_ok(tctx,
438 dcerpc_winspool_SyncRegisterForRemoteNotifications_r(b, tctx, &r),
439 "SyncRegisterForRemoteNotifications failed");
440 torture_assert_hresult_ok(tctx, r.out.result,
441 "SyncRegisterForRemoteNotifications failed");
443 return true;
446 static bool test_SyncRegisterForRemoteNotifications(struct torture_context *tctx,
447 void *private_data)
449 struct test_iremotewinspool_context *ctx =
450 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
451 struct policy_handle notify_handle;
453 torture_assert(tctx,
454 test_SyncRegisterForRemoteNotifications_args(tctx,
455 ctx->iremotewinspool_pipe,
456 &ctx->server_handle,
457 &notify_handle),
458 "failed to test SyncRegisterForRemoteNotifications");
460 test_SyncUnRegisterForRemoteNotifications_args(tctx, ctx->iremotewinspool_pipe, &notify_handle);
462 return true;
465 static bool test_AsyncUploadPrinterDriverPackage(struct torture_context *tctx,
466 void *private_data)
468 struct test_iremotewinspool_context *ctx =
469 talloc_get_type_abort(private_data, struct test_iremotewinspool_context);
471 struct dcerpc_pipe *p = ctx->iremotewinspool_pipe;
472 struct dcerpc_binding_handle *b = p->binding_handle;
474 struct winspool_AsyncUploadPrinterDriverPackage r;
475 uint32_t pcchDestInfPath = 0;
477 r.in.pszServer = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
478 r.in.pszInfPath = "";
479 r.in.pszEnvironment = "";
480 r.in.dwFlags = 0;
481 r.in.pszDestInfPath = NULL;
482 r.in.pcchDestInfPath = &pcchDestInfPath;
483 r.out.pszDestInfPath = NULL;
484 r.out.pcchDestInfPath = &pcchDestInfPath;
486 torture_assert_ntstatus_ok(tctx,
487 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
488 "AsyncUploadPrinterDriverPackage failed");
489 torture_assert_hresult_equal(tctx, r.out.result, HRES_E_INVALIDARG,
490 "AsyncUploadPrinterDriverPackage failed");
492 pcchDestInfPath = 260;
493 r.in.pszDestInfPath = talloc_zero_array(tctx, uint16_t, pcchDestInfPath);
494 r.out.pszDestInfPath = talloc_zero_array(tctx, uint16_t, pcchDestInfPath);
496 torture_assert_ntstatus_ok(tctx,
497 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
498 "AsyncUploadPrinterDriverPackage failed");
499 torture_assert_werr_equal(tctx,
500 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_INVALID_ENVIRONMENT,
501 "AsyncUploadPrinterDriverPackage failed");
503 r.in.pszEnvironment = SPOOLSS_ARCHITECTURE_x64;
505 torture_assert_ntstatus_ok(tctx,
506 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
507 "AsyncUploadPrinterDriverPackage failed");
508 torture_assert_werr_equal(tctx,
509 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
510 "AsyncUploadPrinterDriverPackage failed");
512 r.in.pszInfPath = "\\\\mthelena\\print$\\x64\\{BD443844-ED00-4D96-8CAE-95E49492312A}\\prnbrcl1.inf";
514 torture_assert_ntstatus_ok(tctx,
515 dcerpc_winspool_AsyncUploadPrinterDriverPackage_r(b, tctx, &r),
516 "AsyncUploadPrinterDriverPackage failed");
517 torture_assert_werr_equal(tctx,
518 W_ERROR(WIN32_FROM_HRESULT(r.out.result)), WERR_FILE_NOT_FOUND,
519 "AsyncUploadPrinterDriverPackage failed");
521 return true;
524 struct torture_suite *torture_rpc_iremotewinspool(TALLOC_CTX *mem_ctx)
526 struct torture_suite *suite = torture_suite_create(mem_ctx, "iremotewinspool");
527 struct torture_tcase *tcase = torture_suite_add_tcase(suite, "printserver");
529 torture_tcase_set_fixture(tcase,
530 torture_rpc_iremotewinspool_setup,
531 torture_rpc_iremotewinspool_teardown);
533 torture_tcase_add_simple_test(tcase, "AsyncOpenPrinter", test_AsyncOpenPrinter);
534 torture_tcase_add_simple_test(tcase, "SyncRegisterForRemoteNotifications", test_SyncRegisterForRemoteNotifications);
535 torture_tcase_add_simple_test(tcase, "SyncUnRegisterForRemoteNotifications", test_SyncUnRegisterForRemoteNotifications);
536 torture_tcase_add_simple_test(tcase, "AsyncClosePrinter", test_AsyncClosePrinter);
537 torture_tcase_add_simple_test(tcase, "AsyncUploadPrinterDriverPackage", test_AsyncUploadPrinterDriverPackage);
539 return suite;