1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /*
26 * Printing and Spooling RPC service.
27 */
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <sys/utsname.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <strings.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 #include <smbsrv/libsmb.h>
37 #include <smbsrv/libmlrpc.h>
38 #include <smbsrv/libmlsvc.h>
39 #include <smbsrv/smb.h>
40 #include <smbsrv/ndl/spoolss.ndl>
41 #include <smbsrv/ndl/winreg.ndl>
42 #include <smb/nterror.h>
43 #include <smbsrv/smbinfo.h>
44 #include <smbsrv/nmpipes.h>
45 #include <mlsvc.h>
46
47 #define SPOOLSS_PRINTER "Postscript"
48
49 typedef struct smb_spool {
50 list_t sp_list;
51 int sp_cnt;
52 rwlock_t sp_rwl;
53 int sp_initialized;
54 } smb_spool_t;
55
56 typedef struct smb_spooldoc {
57 uint32_t sd_magic;
58 list_node_t sd_lnd;
59 smb_inaddr_t sd_ipaddr;
60 int sd_spool_num;
61 char sd_username[MAXNAMELEN];
62 char sd_path[MAXPATHLEN];
63 char sd_doc_name[MAXNAMELEN];
64 char sd_printer_name[MAXPATHLEN];
65 int32_t sd_fd;
66 ndr_hdid_t sd_handle;
67 } smb_spooldoc_t;
68
69 typedef struct {
70 char *name;
71 uint32_t value;
72 } spoolss_winreg_t;
73
74 typedef struct {
75 uint8_t *sd_buf;
76 uint32_t sd_size;
77 } spoolss_sd_t;
78
79 static uint32_t spoolss_cnt;
80 static smb_spool_t spoolss_splist;
81
82 void (*spoolss_copyfile_callback)(smb_inaddr_t *, char *, char *, char *);
83
84 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result_u);
85 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result);
86 DECL_FIXUP_STRUCT(spoolss_GetPrinter);
87
88 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA);
89 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA);
90 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO);
91 DECL_FIXUP_STRUCT(spoolss_RFNPCNEX);
92
93 uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
94 static int spoolss_getservername(char *, size_t);
95 static uint32_t spoolss_make_sd(ndr_xa_t *, spoolss_sd_t *);
96 static uint32_t spoolss_format_sd(smb_sd_t *);
97 static int spoolss_find_document(ndr_hdid_t *);
98
99 static int spoolss_s_OpenPrinter(void *, ndr_xa_t *);
100 static int spoolss_s_ClosePrinter(void *, ndr_xa_t *);
101 static int spoolss_s_AbortPrinter(void *, ndr_xa_t *);
102 static int spoolss_s_ResetPrinter(void *, ndr_xa_t *);
103 static int spoolss_s_GetPrinter(void *, ndr_xa_t *);
104 static int spoolss_s_GetPrinterData(void *, ndr_xa_t *);
105 static int spoolss_s_AddJob(void *, ndr_xa_t *);
106 static int spoolss_s_GetJob(void *, ndr_xa_t *);
107 static int spoolss_s_EnumJobs(void *, ndr_xa_t *);
108 static int spoolss_s_ScheduleJob(void *, ndr_xa_t *);
109 static int spoolss_s_StartDocPrinter(void *, ndr_xa_t *);
110 static int spoolss_s_EndDocPrinter(void *, ndr_xa_t *);
111 static int spoolss_s_StartPagePrinter(void *, ndr_xa_t *);
112 static int spoolss_s_EndPagePrinter(void *, ndr_xa_t *);
113 static int spoolss_s_rfnpcnex(void *, ndr_xa_t *);
114 static int spoolss_s_WritePrinter(void *, ndr_xa_t *);
115 static int spoolss_s_AddForm(void *, ndr_xa_t *);
116 static int spoolss_s_DeleteForm(void *, ndr_xa_t *);
117 static int spoolss_s_EnumForms(void *, ndr_xa_t *);
118 static int spoolss_s_AddMonitor(void *, ndr_xa_t *);
119 static int spoolss_s_DeleteMonitor(void *, ndr_xa_t *);
120 static int spoolss_s_DeletePort(void *, ndr_xa_t *);
121 static int spoolss_s_AddPortEx(void *, ndr_xa_t *);
122 static int spoolss_s_SetPort(void *, ndr_xa_t *);
123 static int spoolss_s_stub(void *, ndr_xa_t *);
124
125 static ndr_stub_table_t spoolss_stub_table[] = {
126 { spoolss_s_GetJob, SPOOLSS_OPNUM_GetJob },
127 { spoolss_s_EnumJobs, SPOOLSS_OPNUM_EnumJobs },
128 { spoolss_s_stub, SPOOLSS_OPNUM_DeletePrinter },
129 { spoolss_s_GetPrinter, SPOOLSS_OPNUM_GetPrinter },
130 { spoolss_s_stub, SPOOLSS_OPNUM_GetPrinterDriver },
131 { spoolss_s_stub, SPOOLSS_OPNUM_DeletePrinterDriver },
132 { spoolss_s_OpenPrinter, SPOOLSS_OPNUM_OpenPrinter },
133 { spoolss_s_StartDocPrinter, SPOOLSS_OPNUM_StartDocPrinter },
134 { spoolss_s_WritePrinter, SPOOLSS_OPNUM_WritePrinter },
135 { spoolss_s_EndDocPrinter, SPOOLSS_OPNUM_EndDocPrinter },
136 { spoolss_s_StartPagePrinter, SPOOLSS_OPNUM_StartPagePrinter },
137 { spoolss_s_EndPagePrinter, SPOOLSS_OPNUM_EndPagePrinter },
138 { spoolss_s_AbortPrinter, SPOOLSS_OPNUM_AbortPrinter },
139 { spoolss_s_ResetPrinter, SPOOLSS_OPNUM_ResetPrinter },
140 { spoolss_s_AddJob, SPOOLSS_OPNUM_AddJob },
141 { spoolss_s_ScheduleJob, SPOOLSS_OPNUM_ScheduleJob },
142 { spoolss_s_GetPrinterData, SPOOLSS_OPNUM_GetPrinterData },
143 { spoolss_s_ClosePrinter, SPOOLSS_OPNUM_ClosePrinter },
144 { spoolss_s_AddForm, SPOOLSS_OPNUM_AddForm },
145 { spoolss_s_DeleteForm, SPOOLSS_OPNUM_DeleteForm },
146 { spoolss_s_EnumForms, SPOOLSS_OPNUM_EnumForms },
147 { spoolss_s_AddMonitor, SPOOLSS_OPNUM_AddMonitor },
148 { spoolss_s_DeleteMonitor, SPOOLSS_OPNUM_DeleteMonitor },
149 { spoolss_s_DeletePort, SPOOLSS_OPNUM_DeletePort },
150 { spoolss_s_AddPortEx, SPOOLSS_OPNUM_AddPortEx },
151 { spoolss_s_SetPort, SPOOLSS_OPNUM_SetPort },
152 { spoolss_s_stub, SPOOLSS_OPNUM_GetPrinterDriver2 },
153 { spoolss_s_stub, SPOOLSS_OPNUM_FCPN },
154 { spoolss_s_stub, SPOOLSS_OPNUM_ReplyOpenPrinter },
155 { spoolss_s_stub, SPOOLSS_OPNUM_ReplyClosePrinter },
156 { spoolss_s_stub, SPOOLSS_OPNUM_RFFPCNEX },
157 { spoolss_s_rfnpcnex, SPOOLSS_OPNUM_RFNPCNEX },
158 { spoolss_s_stub, SPOOLSS_OPNUM_RRPCN },
159 { spoolss_s_OpenPrinter, SPOOLSS_OPNUM_OpenPrinterEx },
160 { spoolss_s_stub, SPOOLSS_OPNUM_EnumPrinterData },
161 { spoolss_s_stub, SPOOLSS_OPNUM_EnumPrinterDataEx },
162 { spoolss_s_stub, SPOOLSS_OPNUM_EnumPrinterKey },
163 {0}
164 };
165
166 static ndr_service_t spoolss_service = {
167 "SPOOLSS", /* name */
168 "Print Spool Service", /* desc */
169 "\\spoolss", /* endpoint */
170 PIPE_SPOOLSS, /* sec_addr_port */
171 "12345678-1234-abcd-ef00-0123456789ab", 1, /* abstract */
172 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */
173 0, /* no bind_instance_size */
174 0, /* no bind_req() */
175 0, /* no unbind_and_close() */
176 0, /* use generic_call_stub() */
177 &TYPEINFO(spoolss_interface), /* interface ti */
178 spoolss_stub_table /* stub_table */
179 };
180
181 void
spoolss_initialize(void)182 spoolss_initialize(void)
183 {
184 if (!spoolss_splist.sp_initialized) {
185 list_create(&spoolss_splist.sp_list,
186 sizeof (smb_spooldoc_t),
187 offsetof(smb_spooldoc_t, sd_lnd));
188 spoolss_splist.sp_initialized = 1;
189 }
190
191 spoolss_copyfile_callback = NULL;
192
193 (void) ndr_svc_register(&spoolss_service);
194 }
195
196 void
spoolss_finalize(void)197 spoolss_finalize(void)
198 {
199 spoolss_copyfile_callback = NULL;
200 }
201
202 /*
203 * Register a copyfile callback that the spoolss service can use to
204 * copy files to the spool directory.
205 *
206 * Set a null pointer to disable the copying of files to the spool
207 * directory.
208 */
209 void
spoolss_register_copyfile(spoolss_copyfile_t copyfile)210 spoolss_register_copyfile(spoolss_copyfile_t copyfile)
211 {
212 spoolss_copyfile_callback = copyfile;
213 }
214
215 static void
spoolss_copyfile(smb_inaddr_t * ipaddr,char * username,char * path,char * docname)216 spoolss_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
217 char *docname)
218 {
219 if (spoolss_copyfile_callback != NULL)
220 (*spoolss_copyfile_callback)(ipaddr, username, path, docname);
221 }
222
223 static int
spoolss_s_OpenPrinter(void * arg,ndr_xa_t * mxa)224 spoolss_s_OpenPrinter(void *arg, ndr_xa_t *mxa)
225 {
226 struct spoolss_OpenPrinter *param = arg;
227 char *name = (char *)param->printer_name;
228 ndr_hdid_t *id;
229
230 if (name != NULL && *name != '\0') {
231 if (strspn(name, "\\") > 2) {
232 bzero(¶m->handle, sizeof (spoolss_handle_t));
233 param->status = ERROR_INVALID_PRINTER_NAME;
234 return (NDR_DRC_OK);
235 }
236
237 smb_tracef("spoolss_s_OpenPrinter: %s", name);
238 }
239
240 if ((id = ndr_hdalloc(mxa, NULL)) == NULL) {
241 bzero(¶m->handle, sizeof (spoolss_handle_t));
242 param->status = ERROR_NOT_ENOUGH_MEMORY;
243 return (NDR_DRC_OK);
244 }
245
246 bcopy(id, ¶m->handle, sizeof (spoolss_handle_t));
247 param->status = 0;
248 return (NDR_DRC_OK);
249 }
250
251 /*ARGSUSED*/
252 static int
spoolss_s_StartPagePrinter(void * arg,ndr_xa_t * mxa)253 spoolss_s_StartPagePrinter(void *arg, ndr_xa_t *mxa)
254 {
255 struct spoolss_StartPagePrinter *param = arg;
256
257 param->status = ERROR_SUCCESS;
258
259 return (NDR_DRC_OK);
260 }
261
262 /*ARGSUSED*/
263 static int
spoolss_s_EndPagePrinter(void * arg,ndr_xa_t * mxa)264 spoolss_s_EndPagePrinter(void *arg, ndr_xa_t *mxa)
265 {
266 struct spoolss_EndPagePrinter *param = arg;
267
268 param->status = ERROR_SUCCESS;
269
270 return (NDR_DRC_OK);
271 }
272
273 /*
274 * Windows XP and 2000 use this mechanism to write spool files.
275 * Create a spool file fd to be used by spoolss_s_WritePrinter
276 * and add it to the tail of the spool list.
277 */
278 static int
spoolss_s_StartDocPrinter(void * arg,ndr_xa_t * mxa)279 spoolss_s_StartDocPrinter(void *arg, ndr_xa_t *mxa)
280 {
281 struct spoolss_StartDocPrinter *param = arg;
282 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
283 smb_spooldoc_t *spfile;
284 spoolss_DocInfo_t *docinfo;
285 char g_path[MAXPATHLEN];
286 smb_share_t si;
287 int rc;
288 int fd;
289
290 if (ndr_hdlookup(mxa, id) == NULL) {
291 smb_tracef("spoolss_s_StartDocPrinter: invalid handle");
292 param->status = ERROR_INVALID_HANDLE;
293 return (NDR_DRC_OK);
294 }
295
296 if ((docinfo = param->dinfo.DocInfoContainer) == NULL) {
297 param->status = ERROR_INVALID_PARAMETER;
298 return (NDR_DRC_OK);
299 }
300
301 if ((rc = smb_shr_get(SMB_SHARE_PRINT, &si)) != NERR_Success) {
302 smb_tracef("spoolss_s_StartDocPrinter: %s error=%d",
303 SMB_SHARE_PRINT, rc);
304 param->status = rc;
305 return (NDR_DRC_OK);
306 }
307
308 if ((spfile = calloc(1, sizeof (smb_spooldoc_t))) == NULL) {
309 param->status = ERROR_NOT_ENOUGH_MEMORY;
310 return (NDR_DRC_OK);
311 }
312
313 if (docinfo->doc_name != NULL)
314 (void) strlcpy(spfile->sd_doc_name,
315 (char *)docinfo->doc_name, MAXNAMELEN);
316 else
317 (void) strlcpy(spfile->sd_doc_name, "document", MAXNAMELEN);
318
319 if (docinfo->printer_name != NULL)
320 (void) strlcpy(spfile->sd_printer_name,
321 (char *)docinfo->printer_name, MAXPATHLEN);
322 else
323 (void) strlcpy(spfile->sd_printer_name, "printer", MAXPATHLEN);
324
325 spfile->sd_ipaddr = mxa->pipe->np_user.ui_ipaddr;
326 (void) strlcpy((char *)spfile->sd_username,
327 mxa->pipe->np_user.ui_account, MAXNAMELEN);
328 (void) memcpy(&spfile->sd_handle, ¶m->handle, sizeof (ndr_hdid_t));
329
330 /*
331 * write temporary spool file to print$
332 */
333 (void) snprintf(g_path, MAXPATHLEN, "%s/%s%d", si.shr_path,
334 spfile->sd_username, spoolss_cnt);
335 atomic_inc_32(&spoolss_cnt);
336
337 fd = open(g_path, O_CREAT | O_RDWR, 0600);
338 if (fd == -1) {
339 smb_tracef("spoolss_s_StartDocPrinter: %s: %s",
340 g_path, strerror(errno));
341 param->status = ERROR_OPEN_FAILED;
342 free(spfile);
343 } else {
344 (void) strlcpy((char *)spfile->sd_path, g_path, MAXPATHLEN);
345 spfile->sd_fd = (uint16_t)fd;
346
347 /*
348 * Add the document to the spool list.
349 */
350 (void) rw_wrlock(&spoolss_splist.sp_rwl);
351 list_insert_tail(&spoolss_splist.sp_list, spfile);
352 spoolss_splist.sp_cnt++;
353 (void) rw_unlock(&spoolss_splist.sp_rwl);
354
355 /*
356 * JobId isn't used now, but if printQ management is added
357 * this will have to be incremented per job submitted.
358 */
359 param->JobId = 46;
360 param->status = ERROR_SUCCESS;
361 }
362 return (NDR_DRC_OK);
363 }
364
365 /*
366 * Windows XP and 2000 use this mechanism to write spool files
367 * Search the spooldoc list for a matching RPC handle and pass
368 * the spool the file for printing.
369 */
370 static int
spoolss_s_EndDocPrinter(void * arg,ndr_xa_t * mxa)371 spoolss_s_EndDocPrinter(void *arg, ndr_xa_t *mxa)
372 {
373 struct spoolss_EndDocPrinter *param = arg;
374 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
375 smb_spooldoc_t *sp;
376
377 if (ndr_hdlookup(mxa, id) == NULL) {
378 smb_tracef("spoolss_s_EndDocPrinter: invalid handle");
379 param->status = ERROR_INVALID_HANDLE;
380 return (NDR_DRC_OK);
381 }
382
383 param->status = ERROR_INVALID_HANDLE;
384 (void) rw_wrlock(&spoolss_splist.sp_rwl);
385
386 sp = list_head(&spoolss_splist.sp_list);
387 while (sp != NULL) {
388 if (!memcmp(id, &(sp->sd_handle), sizeof (ndr_hdid_t))) {
389 spoolss_copyfile(&sp->sd_ipaddr,
390 sp->sd_username, sp->sd_path, sp->sd_doc_name);
391 (void) close(sp->sd_fd);
392 list_remove(&spoolss_splist.sp_list, sp);
393 free(sp);
394 param->status = ERROR_SUCCESS;
395 break;
396 }
397
398 sp = list_next(&spoolss_splist.sp_list, sp);
399 }
400
401 (void) rw_unlock(&spoolss_splist.sp_rwl);
402
403 if (param->status != ERROR_SUCCESS)
404 smb_tracef("spoolss_s_EndDocPrinter: document not found");
405 return (NDR_DRC_OK);
406 }
407
408 /*ARGSUSED*/
409 static int
spoolss_s_AbortPrinter(void * arg,ndr_xa_t * mxa)410 spoolss_s_AbortPrinter(void *arg, ndr_xa_t *mxa)
411 {
412 struct spoolss_AbortPrinter *param = arg;
413
414 param->status = ERROR_SUCCESS;
415 return (NDR_DRC_OK);
416 }
417
418 /*ARGSUSED*/
419 static int
spoolss_s_ResetPrinter(void * arg,ndr_xa_t * mxa)420 spoolss_s_ResetPrinter(void *arg, ndr_xa_t *mxa)
421 {
422 struct spoolss_AbortPrinter *param = arg;
423
424 param->status = ERROR_SUCCESS;
425 return (NDR_DRC_OK);
426 }
427
428 static int
spoolss_s_ClosePrinter(void * arg,ndr_xa_t * mxa)429 spoolss_s_ClosePrinter(void *arg, ndr_xa_t *mxa)
430 {
431 struct spoolss_ClosePrinter *param = arg;
432 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
433 ndr_handle_t *hd;
434
435 if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
436 free(hd->nh_data);
437 hd->nh_data = NULL;
438 }
439
440 ndr_hdfree(mxa, id);
441 bzero(¶m->result_handle, sizeof (spoolss_handle_t));
442 param->status = ERROR_SUCCESS;
443 return (NDR_DRC_OK);
444 }
445
446 static int
spoolss_s_AddForm(void * arg,ndr_xa_t * mxa)447 spoolss_s_AddForm(void *arg, ndr_xa_t *mxa)
448 {
449 struct spoolss_AddForm *param = arg;
450 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
451
452 if (ndr_hdlookup(mxa, id) == NULL) {
453 bzero(param, sizeof (struct spoolss_AddForm));
454 param->status = ERROR_INVALID_HANDLE;
455 return (NDR_DRC_OK);
456 }
457
458 bzero(param, sizeof (struct spoolss_AddForm));
459 param->status = ERROR_SUCCESS;
460 return (NDR_DRC_OK);
461 }
462
463 static int
spoolss_s_DeleteForm(void * arg,ndr_xa_t * mxa)464 spoolss_s_DeleteForm(void *arg, ndr_xa_t *mxa)
465 {
466 struct spoolss_DeleteForm *param = arg;
467 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
468
469 if (ndr_hdlookup(mxa, id) == NULL) {
470 bzero(param, sizeof (struct spoolss_DeleteForm));
471 param->status = ERROR_INVALID_HANDLE;
472 return (NDR_DRC_OK);
473 }
474
475 bzero(param, sizeof (struct spoolss_DeleteForm));
476 param->status = ERROR_SUCCESS;
477 return (NDR_DRC_OK);
478 }
479
480 static int
spoolss_s_EnumForms(void * arg,ndr_xa_t * mxa)481 spoolss_s_EnumForms(void *arg, ndr_xa_t *mxa)
482 {
483 struct spoolss_EnumForms *param = arg;
484 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
485
486 if (ndr_hdlookup(mxa, id) == NULL) {
487 bzero(param, sizeof (struct spoolss_EnumForms));
488 param->status = ERROR_INVALID_HANDLE;
489 return (NDR_DRC_OK);
490 }
491
492 bzero(param, sizeof (struct spoolss_EnumForms));
493 param->status = ERROR_SUCCESS;
494 param->needed = 0;
495 return (NDR_DRC_OK);
496 }
497
498 /*ARGSUSED*/
499 static int
spoolss_s_AddMonitor(void * arg,ndr_xa_t * mxa)500 spoolss_s_AddMonitor(void *arg, ndr_xa_t *mxa)
501 {
502 struct spoolss_AddMonitor *param = arg;
503
504 param->status = ERROR_SUCCESS;
505 return (NDR_DRC_OK);
506 }
507
508 /*ARGSUSED*/
509 static int
spoolss_s_DeleteMonitor(void * arg,ndr_xa_t * mxa)510 spoolss_s_DeleteMonitor(void *arg, ndr_xa_t *mxa)
511 {
512 struct spoolss_DeleteMonitor *param = arg;
513
514 param->status = ERROR_SUCCESS;
515 return (NDR_DRC_OK);
516 }
517
518 /*ARGSUSED*/
519 static int
spoolss_s_DeletePort(void * arg,ndr_xa_t * mxa)520 spoolss_s_DeletePort(void *arg, ndr_xa_t *mxa)
521 {
522 struct spoolss_DeletePort *param = arg;
523
524 param->status = ERROR_SUCCESS;
525 return (NDR_DRC_OK);
526 }
527
528 /*ARGSUSED*/
529 static int
spoolss_s_AddPortEx(void * arg,ndr_xa_t * mxa)530 spoolss_s_AddPortEx(void *arg, ndr_xa_t *mxa)
531 {
532 struct spoolss_AddPortEx *param = arg;
533
534 param->status = ERROR_SUCCESS;
535 return (NDR_DRC_OK);
536 }
537
538 /*ARGSUSED*/
539 static int
spoolss_s_SetPort(void * arg,ndr_xa_t * mxa)540 spoolss_s_SetPort(void *arg, ndr_xa_t *mxa)
541 {
542 struct spoolss_SetPort *param = arg;
543
544 param->status = ERROR_SUCCESS;
545 return (NDR_DRC_OK);
546 }
547
548 /*ARGSUSED*/
549 static int
spoolss_s_EnumJobs(void * arg,ndr_xa_t * mxa)550 spoolss_s_EnumJobs(void *arg, ndr_xa_t *mxa)
551 {
552 struct spoolss_EnumJobs *param = arg;
553 DWORD status = ERROR_SUCCESS;
554
555 switch (param->level) {
556 case 1:
557 case 2:
558 case 3:
559 case 4:
560 default:
561 break;
562 }
563
564 param->status = status;
565 param->needed = 0;
566 param->needed2 = 0;
567 return (NDR_DRC_OK);
568 }
569
570
571 /*ARGSUSED*/
572 static int
spoolss_s_GetJob(void * arg,ndr_xa_t * mxa)573 spoolss_s_GetJob(void *arg, ndr_xa_t *mxa)
574 {
575 struct spoolss_GetJob *param = arg;
576 DWORD status = ERROR_SUCCESS;
577
578 if (param->BufCount == 0)
579 param->status = ERROR_INSUFFICIENT_BUFFER;
580 else
581 param->status = status;
582 param->needed = 0;
583 return (NDR_DRC_OK);
584 }
585
586
587 /*ARGSUSED*/
588 static int
spoolss_s_ScheduleJob(void * arg,ndr_xa_t * mxa)589 spoolss_s_ScheduleJob(void *arg, ndr_xa_t *mxa)
590 {
591 struct spoolss_ScheduleJob *param = arg;
592 DWORD status = ERROR_SPL_NO_ADDJOB;
593
594 param->status = status;
595 return (NDR_DRC_OK);
596 }
597
598 /*ARGSUSED*/
599 static int
spoolss_s_AddJob(void * arg,ndr_xa_t * mxa)600 spoolss_s_AddJob(void *arg, ndr_xa_t *mxa)
601 {
602 struct spoolss_AddJob *param = arg;
603
604 param->status = ERROR_SUCCESS;
605 param->needed = 0;
606 return (NDR_DRC_OK);
607 }
608
609 /*ARGSUSED*/
610 static int
spoolss_s_rfnpcnex(void * arg,ndr_xa_t * mxa)611 spoolss_s_rfnpcnex(void *arg, ndr_xa_t *mxa)
612 {
613 struct spoolss_RFNPCNEX *param = arg;
614
615 param->ppinfo = 0;
616 param->status = ERROR_SUCCESS;
617 return (NDR_DRC_OK);
618 }
619
620 /*
621 * Use the RPC context handle to find the fd and write the document content.
622 */
623 static int
spoolss_s_WritePrinter(void * arg,ndr_xa_t * mxa)624 spoolss_s_WritePrinter(void *arg, ndr_xa_t *mxa)
625 {
626 struct spoolss_WritePrinter *param = arg;
627 int written = 0;
628 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
629 int spfd;
630
631 if (ndr_hdlookup(mxa, id) == NULL) {
632 param->written = 0;
633 param->status = ERROR_INVALID_HANDLE;
634 smb_tracef("spoolss_s_WritePrinter: invalid handle");
635 return (NDR_DRC_OK);
636 }
637
638 if ((spfd = spoolss_find_document(id)) < 0) {
639 param->written = 0;
640 param->status = ERROR_INVALID_HANDLE;
641 smb_tracef("spoolss_s_WritePrinter: document not found");
642 return (NDR_DRC_OK);
643 }
644
645 written = write(spfd, param->pBuf, param->BufCount);
646 if (written < param->BufCount) {
647 smb_tracef("spoolss_s_WritePrinter: write failed");
648 param->written = 0;
649 param->status = ERROR_CANTWRITE;
650 return (NDR_DRC_OK);
651 }
652
653 param->written = written;
654 param->status = ERROR_SUCCESS;
655 return (NDR_DRC_OK);
656 }
657
658 /*
659 * Find a document by RPC handle in the spool list and return the fd.
660 */
661 static int
spoolss_find_document(ndr_hdid_t * handle)662 spoolss_find_document(ndr_hdid_t *handle)
663 {
664 smb_spooldoc_t *sp;
665
666 (void) rw_rdlock(&spoolss_splist.sp_rwl);
667
668 sp = list_head(&spoolss_splist.sp_list);
669 while (sp != NULL) {
670 if (!memcmp(handle, &(sp->sd_handle), sizeof (ndr_hdid_t))) {
671 (void) rw_unlock(&spoolss_splist.sp_rwl);
672 return (sp->sd_fd);
673 }
674 sp = list_next(&spoolss_splist.sp_list, sp);
675 }
676
677 (void) rw_unlock(&spoolss_splist.sp_rwl);
678 return (-1);
679 }
680
681 /*
682 * GetPrinterData is used t obtain values from the registry for a
683 * printer or a print server. See [MS-RPRN] for value descriptions.
684 * The registry returns ERROR_FILE_NOT_FOUND for unknown keys.
685 */
686 static int
spoolss_s_GetPrinterData(void * arg,ndr_xa_t * mxa)687 spoolss_s_GetPrinterData(void *arg, ndr_xa_t *mxa)
688 {
689 static spoolss_winreg_t reg[] = {
690 { "ChangeId", 0x0050acf2 },
691 { "W3SvcInstalled", 0x00000000 },
692 { "BeepEnabled", 0x00000000 },
693 { "EventLog", 0x0000001f },
694 { "NetPopup", 0x00000000 },
695 { "NetPopupToComputer", 0x00000000 },
696 { "MajorVersion", 0x00000003 },
697 { "MinorVersion", 0x00000000 },
698 { "DsPresent", 0x00000000 }
699 };
700
701 struct spoolss_GetPrinterData *param = arg;
702 char *name = (char *)param->pValueName;
703 char buf[MAXPATHLEN];
704 static uint8_t reserved_buf[4];
705 spoolss_winreg_t *rp;
706 smb_share_t si;
707 smb_version_t *osversion;
708 struct utsname sysname;
709 smb_wchar_t *wcs;
710 uint32_t value;
711 uint32_t status;
712 int wcslen;
713 int i;
714
715 if (name == NULL || *name == '\0') {
716 status = ERROR_FILE_NOT_FOUND;
717 goto report_error;
718 }
719
720 for (i = 0; i < sizeof (reg) / sizeof (reg[0]); ++i) {
721 param->pType = WINREG_DWORD;
722 param->Needed = sizeof (uint32_t);
723 rp = ®[i];
724
725 if (strcasecmp(name, rp->name) != 0)
726 continue;
727
728 if (param->Size < sizeof (uint32_t)) {
729 param->Size = 0;
730 goto need_more_data;
731 }
732
733 if ((param->Buf = NDR_NEW(mxa, uint32_t)) == NULL) {
734 status = ERROR_NOT_ENOUGH_MEMORY;
735 goto report_error;
736 }
737
738 value = rp->value;
739
740 if ((strcasecmp(name, "DsPresent") == 0) &&
741 (smb_config_get_secmode() == SMB_SECMODE_DOMAIN))
742 value = 0x00000001;
743
744 bcopy(&value, param->Buf, sizeof (uint32_t));
745 param->Size = sizeof (uint32_t);
746 param->status = ERROR_SUCCESS;
747 return (NDR_DRC_OK);
748 }
749
750 if (strcasecmp(name, "OSVersion") == 0) {
751 param->pType = WINREG_BINARY;
752 param->Needed = sizeof (smb_version_t);
753
754 if (param->Size < sizeof (smb_version_t)) {
755 param->Size = sizeof (smb_version_t);
756 goto need_more_data;
757 }
758
759 if ((osversion = NDR_NEW(mxa, smb_version_t)) == NULL) {
760 status = ERROR_NOT_ENOUGH_MEMORY;
761 goto report_error;
762 }
763
764 smb_config_get_version(osversion);
765 param->Buf = (uint8_t *)osversion;
766 param->status = ERROR_SUCCESS;
767 return (NDR_DRC_OK);
768 }
769
770 if (strcasecmp(name, "DNSMachineName") == 0) {
771 param->pType = WINREG_SZ;
772 buf[0] = '\0';
773 (void) smb_getfqhostname(buf, MAXHOSTNAMELEN);
774 goto encode_string;
775 }
776
777 if (strcasecmp(name, "DefaultSpoolDirectory") == 0) {
778 param->pType = WINREG_SZ;
779 buf[0] = '\0';
780
781 if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) {
782 status = ERROR_FILE_NOT_FOUND;
783 goto report_error;
784 }
785
786 (void) snprintf(buf, MAXPATHLEN, "C:/%s", si.shr_path);
787 (void) strcanon(buf, "/\\");
788 (void) strsubst(buf, '/', '\\');
789 goto encode_string;
790 }
791
792 if (strcasecmp(name, "Architecture") == 0) {
793 param->pType = WINREG_SZ;
794
795 if (uname(&sysname) < 0)
796 (void) strlcpy(buf, "Solaris", MAXPATHLEN);
797 else
798 (void) snprintf(buf, MAXPATHLEN, "%s %s",
799 sysname.sysname, sysname.machine);
800
801 goto encode_string;
802 }
803
804 status = ERROR_FILE_NOT_FOUND;
805
806 report_error:
807 bzero(param, sizeof (struct spoolss_GetPrinterData));
808 param->Buf = reserved_buf;
809 param->status = status;
810 return (NDR_DRC_OK);
811
812 encode_string:
813 wcslen = smb_wcequiv_strlen(buf) + sizeof (smb_wchar_t);
814 if (param->Size < wcslen) {
815 param->Needed = wcslen;
816 goto need_more_data;
817 }
818
819 if ((wcs = NDR_MALLOC(mxa, wcslen)) == NULL) {
820 status = ERROR_NOT_ENOUGH_MEMORY;
821 goto report_error;
822 }
823
824 (void) ndr_mbstowcs(NULL, wcs, buf, wcslen);
825 param->Buf = (uint8_t *)wcs;
826 param->Needed = wcslen;
827 param->status = ERROR_SUCCESS;
828 return (NDR_DRC_OK);
829
830 need_more_data:
831 param->Size = 0;
832 param->Buf = reserved_buf;
833 param->status = ERROR_MORE_DATA;
834 return (NDR_DRC_OK);
835 }
836
837 void
smb_rpc_off(char * dst,char * src,uint32_t * offset,uint32_t * outoffset)838 smb_rpc_off(char *dst, char *src, uint32_t *offset, uint32_t *outoffset)
839 {
840 int nwchars;
841 int bytes;
842
843 bytes = smb_wcequiv_strlen(src) + 2;
844 nwchars = strlen(src) + 1;
845 *offset -= bytes;
846 *outoffset = *offset;
847 /*LINTED E_BAD_PTR_CAST_ALIGN*/
848 (void) smb_mbstowcs(((smb_wchar_t *)(dst + *offset)), src, nwchars);
849 }
850
851 int
spoolss_s_GetPrinter(void * arg,ndr_xa_t * mxa)852 spoolss_s_GetPrinter(void *arg, ndr_xa_t *mxa)
853 {
854 struct spoolss_GetPrinter *param = arg;
855 struct spoolss_GetPrinter0 *pinfo0;
856 struct spoolss_GetPrinter1 *pinfo1;
857 struct spoolss_GetPrinter2 *pinfo2;
858 struct spoolss_DeviceMode *devmode2;
859 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
860 spoolss_sd_t secdesc;
861 char server[MAXNAMELEN];
862 char printer[MAXNAMELEN];
863 DWORD status = ERROR_SUCCESS;
864 char *wname;
865 uint32_t offset;
866 uint8_t *tmpbuf;
867
868 if (ndr_hdlookup(mxa, id) == NULL) {
869 status = ERROR_INVALID_HANDLE;
870 goto error_out;
871 }
872
873 if (spoolss_getservername(server, MAXNAMELEN) != 0) {
874 status = ERROR_INTERNAL_ERROR;
875 goto error_out;
876 }
877
878 (void) snprintf(printer, MAXNAMELEN, "%s\\%s", server, SPOOLSS_PRINTER);
879
880 switch (param->switch_value) {
881 case 0:
882 case 1:
883 param->needed = 460;
884 break;
885 case 2:
886 param->needed = 712;
887 break;
888 default:
889 status = ERROR_INVALID_LEVEL;
890 goto error_out;
891 }
892
893 if (param->BufCount < param->needed) {
894 param->BufCount = 0;
895 param->Buf = NULL;
896 param->status = ERROR_INSUFFICIENT_BUFFER;
897 return (NDR_DRC_OK);
898 }
899
900 if ((param->Buf = NDR_MALLOC(mxa, param->BufCount)) == NULL) {
901 status = ERROR_NOT_ENOUGH_MEMORY;
902 goto error_out;
903 }
904
905 bzero(param->Buf, param->BufCount);
906 wname = (char *)param->Buf;
907 offset = param->needed;
908
909 switch (param->switch_value) {
910 case 0:
911 /*LINTED E_BAD_PTR_CAST_ALIGN*/
912 pinfo0 = (struct spoolss_GetPrinter0 *)param->Buf;
913
914 smb_rpc_off(wname, server, &offset, &pinfo0->servername);
915 smb_rpc_off(wname, printer, &offset, &pinfo0->printername);
916 pinfo0->cjobs = 0;
917 pinfo0->total_jobs = 6;
918 pinfo0->total_bytes = 1040771;
919 pinfo0->time0 = 0;
920 pinfo0->time1 = 0;
921 pinfo0->time2 = 3;
922 pinfo0->time3 = 0;
923 pinfo0->global_counter = 2162710;
924 pinfo0->total_pages = 21495865;
925 pinfo0->version = 10;
926 pinfo0->session_counter = 1;
927 pinfo0->job_error = 0x6;
928 pinfo0->change_id = 0x1;
929 pinfo0->status = 0;
930 pinfo0->c_setprinter = 0;
931 break;
932 case 1:
933 /*LINTED E_BAD_PTR_CAST_ALIGN*/
934 pinfo1 = (struct spoolss_GetPrinter1 *)param->Buf;
935
936 pinfo1->flags = PRINTER_ENUM_ICON8;
937 smb_rpc_off(wname, printer, &offset, &pinfo1->flags);
938 smb_rpc_off(wname, printer, &offset, &pinfo1->description);
939 smb_rpc_off(wname, printer, &offset, &pinfo1->comment);
940 break;
941 case 2:
942 /*LINTED E_BAD_PTR_CAST_ALIGN*/
943 pinfo2 = (struct spoolss_GetPrinter2 *)param->Buf;
944
945 smb_rpc_off(wname, server, &offset, &pinfo2->servername);
946 smb_rpc_off(wname, printer, &offset, &pinfo2->printername);
947 smb_rpc_off(wname, SPOOLSS_PRINTER, &offset,
948 &pinfo2->sharename);
949 smb_rpc_off(wname, "CIFS Printer Port", &offset,
950 &pinfo2->portname);
951 smb_rpc_off(wname, "", &offset, &pinfo2->drivername);
952 smb_rpc_off(wname, SPOOLSS_PRINTER, &offset,
953 &pinfo2->comment);
954 smb_rpc_off(wname, "farside", &offset, &pinfo2->location);
955
956 offset -= sizeof (struct spoolss_DeviceMode);
957 pinfo2->devmode = offset;
958 /*LINTED E_BAD_PTR_CAST_ALIGN*/
959 devmode2 = (struct spoolss_DeviceMode *)(param->Buf + offset);
960
961 smb_rpc_off(wname, "farside", &offset, &pinfo2->sepfile);
962 smb_rpc_off(wname, "winprint", &offset,
963 &pinfo2->printprocessor);
964 smb_rpc_off(wname, "RAW", &offset, &pinfo2->datatype);
965 smb_rpc_off(wname, "", &offset, &pinfo2->parameters);
966
967 status = spoolss_make_sd(mxa, &secdesc);
968 if (status == ERROR_SUCCESS) {
969 offset -= secdesc.sd_size;
970 pinfo2->secdesc = offset;
971 tmpbuf = (uint8_t *)(param->Buf + offset);
972 bcopy(secdesc.sd_buf, tmpbuf, secdesc.sd_size);
973 }
974
975 pinfo2->attributes = 0x00001048;
976 pinfo2->status = 0x00000000;
977 pinfo2->starttime = 0;
978 pinfo2->untiltime = 0;
979 pinfo2->cjobs = 0;
980 pinfo2->averageppm = 0;
981 pinfo2->defaultpriority = 0;
982
983 /*LINTED E_BAD_PTR_CAST_ALIGN*/
984 (void) smb_mbstowcs((smb_wchar_t *)devmode2->devicename,
985 printer, 32);
986 devmode2->specversion = 0x0401;
987 devmode2->driverversion = 1024;
988 devmode2->size = 220;
989 devmode2->driverextra_length = 0;
990 devmode2->fields = 0x00014713;
991 devmode2->orientation = 1;
992 devmode2->papersize = 1;
993 devmode2->paperlength = 0;
994 devmode2->paperwidth = 0;
995 devmode2->scale = 100;
996 devmode2->copies = 1;
997 devmode2->defaultsource = 15;
998 devmode2->printquality = 65532;
999 devmode2->color = 1;
1000 devmode2->duplex = 1;
1001 devmode2->yresolution = 1;
1002 devmode2->ttoption = 1;
1003 devmode2->collate = 0;
1004 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1005 (void) smb_mbstowcs((smb_wchar_t *)devmode2->formname,
1006 "Letter", 32);
1007 devmode2->logpixels = 0;
1008 devmode2->bitsperpel = 0;
1009 devmode2->pelswidth = 0;
1010 devmode2->pelsheight = 0;
1011 devmode2->displayflags = 0;
1012 devmode2->displayfrequency = 0;
1013 devmode2->icmmethod = 0;
1014 devmode2->icmintent = 0;
1015 devmode2->mediatype = 0;
1016 devmode2->dithertype = 0;
1017 devmode2->reserved1 = 0;
1018 devmode2->reserved2 = 0;
1019 devmode2->panningwidth = 0;
1020 devmode2->panningheight = 0;
1021 break;
1022
1023 default:
1024 break;
1025 }
1026
1027 param->status = status;
1028 return (NDR_DRC_OK);
1029
1030 error_out:
1031 smb_tracef("spoolss_s_GetPrinter: error %u", status);
1032 bzero(param, sizeof (struct spoolss_GetPrinter));
1033 param->status = status;
1034 return (NDR_DRC_OK);
1035 }
1036
1037 static int
spoolss_getservername(char * name,size_t namelen)1038 spoolss_getservername(char *name, size_t namelen)
1039 {
1040 char hostname[MAXHOSTNAMELEN];
1041 char ipstr[INET6_ADDRSTRLEN];
1042 smb_inaddr_t ipaddr;
1043 struct hostent *h;
1044 const char *p;
1045 int error;
1046
1047 if (smb_gethostname(hostname, MAXHOSTNAMELEN, 0) != 0) {
1048 smb_tracef("spoolss_s_GetPrinter: gethostname failed");
1049 return (-1);
1050 }
1051
1052 if ((h = smb_gethostbyname(hostname, &error)) == NULL) {
1053 smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d",
1054 error);
1055 return (-1);
1056 }
1057
1058 bcopy(h->h_addr, &ipaddr, h->h_length);
1059 ipaddr.a_family = h->h_addrtype;
1060 freehostent(h);
1061
1062 p = smb_inet_ntop(&ipaddr, ipstr, SMB_IPSTRLEN(ipaddr.a_family));
1063 if (p == NULL) {
1064 smb_tracef("spoolss_s_GetPrinter: inet_ntop failed");
1065 return (-1);
1066 }
1067
1068 (void) snprintf(name, namelen, "\\\\%s", ipstr);
1069 return (0);
1070 }
1071
1072 static uint32_t
spoolss_make_sd(ndr_xa_t * mxa,spoolss_sd_t * secdesc)1073 spoolss_make_sd(ndr_xa_t *mxa, spoolss_sd_t *secdesc)
1074 {
1075 smb_sd_t sd;
1076 uint8_t *sd_buf;
1077 uint32_t sd_len;
1078 uint32_t status;
1079
1080 bzero(&sd, sizeof (smb_sd_t));
1081
1082 if ((status = spoolss_format_sd(&sd)) != ERROR_SUCCESS)
1083 return (status);
1084
1085 sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO);
1086
1087 if ((sd_buf = NDR_MALLOC(mxa, sd_len)) == NULL)
1088 return (ERROR_NOT_ENOUGH_MEMORY);
1089
1090 secdesc->sd_buf = sd_buf;
1091 secdesc->sd_size = sd_len;
1092
1093 status = srvsvc_sd_set_relative(&sd, sd_buf);
1094 smb_sd_term(&sd);
1095 return (status);
1096 }
1097
1098 static uint32_t
spoolss_format_sd(smb_sd_t * sd)1099 spoolss_format_sd(smb_sd_t *sd)
1100 {
1101 smb_fssd_t fs_sd;
1102 acl_t *acl;
1103 uint32_t status = ERROR_SUCCESS;
1104
1105 if (acl_fromtext("everyone@:full_set::allow", &acl) != 0) {
1106 smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY");
1107 return (ERROR_NOT_ENOUGH_MEMORY);
1108 }
1109 smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
1110 fs_sd.sd_uid = 0;
1111 fs_sd.sd_gid = 0;
1112 fs_sd.sd_zdacl = acl;
1113 fs_sd.sd_zsacl = NULL;
1114
1115 status = smb_sd_fromfs(&fs_sd, sd);
1116 if (status != NT_STATUS_SUCCESS) {
1117 smb_tracef("spoolss_format_sd: %u", status);
1118 status = ERROR_ACCESS_DENIED;
1119 }
1120 smb_fssd_term(&fs_sd);
1121 return (status);
1122 }
1123
1124 /*ARGSUSED*/
1125 static int
spoolss_s_stub(void * arg,ndr_xa_t * mxa)1126 spoolss_s_stub(void *arg, ndr_xa_t *mxa)
1127 {
1128 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
1129 }
1130
1131 void
fixup_spoolss_RFNPCNEX(struct spoolss_RFNPCNEX * val)1132 fixup_spoolss_RFNPCNEX(struct spoolss_RFNPCNEX *val)
1133 {
1134 unsigned short size1 = 0;
1135 unsigned short size2 = 0;
1136 unsigned short size3 = 0;
1137 struct spoolss_RPC_V2_NOTIFY_INFO *pinfo;
1138
1139 pinfo = val->ppinfo->pinfo;
1140 switch (pinfo->aData->Reserved) {
1141 case TABLE_STRING:
1142 size1 = sizeof (struct STRING_CONTAINER);
1143 break;
1144 case TABLE_DWORD:
1145 size1 = sizeof (DWORD) * 2;
1146 break;
1147 case TABLE_TIME:
1148 size1 = sizeof (struct SYSTEMTIME_CONTAINER);
1149 break;
1150 case TABLE_DEVMODE:
1151 size1 = sizeof (struct spoolssDevmodeContainer);
1152 break;
1153 case TABLE_SECURITY_DESCRIPTOR:
1154 size1 = sizeof (struct SECURITY_CONTAINER);
1155 break;
1156 default:
1157 return;
1158 }
1159 size2 = size1 + (2 * sizeof (DWORD));
1160 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1161
1162 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA, size1);
1163 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA, size2);
1164 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO, size3);
1165 FIXUP_PDU_SIZE(spoolss_RFNPCNEX, size3);
1166 }
1167
1168 void
fixup_spoolss_GetPrinter(struct spoolss_GetPrinter * val)1169 fixup_spoolss_GetPrinter(struct spoolss_GetPrinter *val)
1170 {
1171 unsigned short size1 = 0;
1172 unsigned short size2 = 0;
1173 unsigned short size3 = 0;
1174
1175 switch (val->switch_value) {
1176 CASE_INFO_ENT(spoolss_GetPrinter, 0);
1177 CASE_INFO_ENT(spoolss_GetPrinter, 1);
1178 CASE_INFO_ENT(spoolss_GetPrinter, 2);
1179 CASE_INFO_ENT(spoolss_GetPrinter, 3);
1180 CASE_INFO_ENT(spoolss_GetPrinter, 4);
1181 CASE_INFO_ENT(spoolss_GetPrinter, 5);
1182 CASE_INFO_ENT(spoolss_GetPrinter, 6);
1183 CASE_INFO_ENT(spoolss_GetPrinter, 7);
1184 CASE_INFO_ENT(spoolss_GetPrinter, 8);
1185
1186 default:
1187 return;
1188 };
1189
1190 size2 = size1 + (2 * sizeof (DWORD));
1191 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1192
1193 FIXUP_PDU_SIZE(spoolss_GetPrinter_result_u, size1);
1194 FIXUP_PDU_SIZE(spoolss_GetPrinter_result, size2);
1195 FIXUP_PDU_SIZE(spoolss_GetPrinter, size3);
1196 }
1197