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.
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.
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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 * Printing and Spooling RPC service.
29 #include <sys/types.h>
31 #include <sys/utsname.h>
32 #include <sys/atomic.h>
38 #include <libmlrpc/libmlrpc.h>
39 #include <sys/cfgparam.h>
40 #include <smbsrv/libsmb.h>
41 #include <smbsrv/libmlsvc.h>
42 #include <smbsrv/smb.h>
43 #include <smbsrv/ndl/spoolss.ndl>
44 #include <smbsrv/ndl/winreg.ndl>
45 #include <smb/nterror.h>
46 #include <smbsrv/smbinfo.h>
47 #include <smbsrv/nmpipes.h>
50 #ifdef CONFIG_SMB_PRINTING
52 #define SPOOLSS_PRINTER "Postscript"
54 typedef struct smb_spool
{
61 typedef struct smb_spooldoc
{
64 smb_inaddr_t sd_ipaddr
;
66 char sd_username
[MAXNAMELEN
];
67 char sd_path
[MAXPATHLEN
];
68 char sd_doc_name
[MAXNAMELEN
];
69 char sd_printer_name
[MAXPATHLEN
];
84 static uint32_t spoolss_cnt
;
85 static smb_spool_t spoolss_splist
;
87 void (*spoolss_copyfile_callback
)(smb_inaddr_t
*, char *, char *, char *);
89 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result_u
);
90 DECL_FIXUP_STRUCT(spoolss_GetPrinter_result
);
91 DECL_FIXUP_STRUCT(spoolss_GetPrinter
);
93 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA
);
94 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO_DATA
);
95 DECL_FIXUP_STRUCT(spoolss_RPC_V2_NOTIFY_INFO
);
96 DECL_FIXUP_STRUCT(spoolss_RFNPCNEX
);
98 uint32_t srvsvc_sd_set_relative(smb_sd_t
*, uint8_t *);
99 static int spoolss_getservername(char *, size_t);
100 static uint32_t spoolss_make_sd(ndr_xa_t
*, spoolss_sd_t
*);
101 static uint32_t spoolss_format_sd(smb_sd_t
*);
102 static int spoolss_find_document(ndr_hdid_t
*);
104 static int spoolss_s_OpenPrinter(void *, ndr_xa_t
*);
105 static int spoolss_s_ClosePrinter(void *, ndr_xa_t
*);
106 static int spoolss_s_AbortPrinter(void *, ndr_xa_t
*);
107 static int spoolss_s_ResetPrinter(void *, ndr_xa_t
*);
108 static int spoolss_s_GetPrinter(void *, ndr_xa_t
*);
109 static int spoolss_s_GetPrinterData(void *, ndr_xa_t
*);
110 static int spoolss_s_AddJob(void *, ndr_xa_t
*);
111 static int spoolss_s_GetJob(void *, ndr_xa_t
*);
112 static int spoolss_s_EnumJobs(void *, ndr_xa_t
*);
113 static int spoolss_s_ScheduleJob(void *, ndr_xa_t
*);
114 static int spoolss_s_StartDocPrinter(void *, ndr_xa_t
*);
115 static int spoolss_s_EndDocPrinter(void *, ndr_xa_t
*);
116 static int spoolss_s_StartPagePrinter(void *, ndr_xa_t
*);
117 static int spoolss_s_EndPagePrinter(void *, ndr_xa_t
*);
118 static int spoolss_s_rfnpcnex(void *, ndr_xa_t
*);
119 static int spoolss_s_WritePrinter(void *, ndr_xa_t
*);
120 static int spoolss_s_AddForm(void *, ndr_xa_t
*);
121 static int spoolss_s_DeleteForm(void *, ndr_xa_t
*);
122 static int spoolss_s_EnumForms(void *, ndr_xa_t
*);
123 static int spoolss_s_AddMonitor(void *, ndr_xa_t
*);
124 static int spoolss_s_DeleteMonitor(void *, ndr_xa_t
*);
125 static int spoolss_s_DeletePort(void *, ndr_xa_t
*);
126 static int spoolss_s_AddPortEx(void *, ndr_xa_t
*);
127 static int spoolss_s_SetPort(void *, ndr_xa_t
*);
128 static int spoolss_s_stub(void *, ndr_xa_t
*);
130 static ndr_stub_table_t spoolss_stub_table
[] = {
131 { spoolss_s_GetJob
, SPOOLSS_OPNUM_GetJob
},
132 { spoolss_s_EnumJobs
, SPOOLSS_OPNUM_EnumJobs
},
133 { spoolss_s_stub
, SPOOLSS_OPNUM_DeletePrinter
},
134 { spoolss_s_GetPrinter
, SPOOLSS_OPNUM_GetPrinter
},
135 { spoolss_s_stub
, SPOOLSS_OPNUM_GetPrinterDriver
},
136 { spoolss_s_stub
, SPOOLSS_OPNUM_DeletePrinterDriver
},
137 { spoolss_s_OpenPrinter
, SPOOLSS_OPNUM_OpenPrinter
},
138 { spoolss_s_StartDocPrinter
, SPOOLSS_OPNUM_StartDocPrinter
},
139 { spoolss_s_WritePrinter
, SPOOLSS_OPNUM_WritePrinter
},
140 { spoolss_s_EndDocPrinter
, SPOOLSS_OPNUM_EndDocPrinter
},
141 { spoolss_s_StartPagePrinter
, SPOOLSS_OPNUM_StartPagePrinter
},
142 { spoolss_s_EndPagePrinter
, SPOOLSS_OPNUM_EndPagePrinter
},
143 { spoolss_s_AbortPrinter
, SPOOLSS_OPNUM_AbortPrinter
},
144 { spoolss_s_ResetPrinter
, SPOOLSS_OPNUM_ResetPrinter
},
145 { spoolss_s_AddJob
, SPOOLSS_OPNUM_AddJob
},
146 { spoolss_s_ScheduleJob
, SPOOLSS_OPNUM_ScheduleJob
},
147 { spoolss_s_GetPrinterData
, SPOOLSS_OPNUM_GetPrinterData
},
148 { spoolss_s_ClosePrinter
, SPOOLSS_OPNUM_ClosePrinter
},
149 { spoolss_s_AddForm
, SPOOLSS_OPNUM_AddForm
},
150 { spoolss_s_DeleteForm
, SPOOLSS_OPNUM_DeleteForm
},
151 { spoolss_s_EnumForms
, SPOOLSS_OPNUM_EnumForms
},
152 { spoolss_s_AddMonitor
, SPOOLSS_OPNUM_AddMonitor
},
153 { spoolss_s_DeleteMonitor
, SPOOLSS_OPNUM_DeleteMonitor
},
154 { spoolss_s_DeletePort
, SPOOLSS_OPNUM_DeletePort
},
155 { spoolss_s_AddPortEx
, SPOOLSS_OPNUM_AddPortEx
},
156 { spoolss_s_SetPort
, SPOOLSS_OPNUM_SetPort
},
157 { spoolss_s_stub
, SPOOLSS_OPNUM_GetPrinterDriver2
},
158 { spoolss_s_stub
, SPOOLSS_OPNUM_FCPN
},
159 { spoolss_s_stub
, SPOOLSS_OPNUM_ReplyOpenPrinter
},
160 { spoolss_s_stub
, SPOOLSS_OPNUM_ReplyClosePrinter
},
161 { spoolss_s_stub
, SPOOLSS_OPNUM_RFFPCNEX
},
162 { spoolss_s_rfnpcnex
, SPOOLSS_OPNUM_RFNPCNEX
},
163 { spoolss_s_stub
, SPOOLSS_OPNUM_RRPCN
},
164 { spoolss_s_OpenPrinter
, SPOOLSS_OPNUM_OpenPrinterEx
},
165 { spoolss_s_stub
, SPOOLSS_OPNUM_EnumPrinterData
},
166 { spoolss_s_stub
, SPOOLSS_OPNUM_EnumPrinterDataEx
},
167 { spoolss_s_stub
, SPOOLSS_OPNUM_EnumPrinterKey
},
171 static ndr_service_t spoolss_service
= {
172 "SPOOLSS", /* name */
173 "Print Spool Service", /* desc */
174 "\\spoolss", /* endpoint */
175 PIPE_SPOOLSS
, /* sec_addr_port */
176 "12345678-1234-abcd-ef00-0123456789ab", 1, /* abstract */
177 NDR_TRANSFER_SYNTAX_UUID
, 2, /* transfer */
178 0, /* no bind_instance_size */
179 0, /* no bind_req() */
180 0, /* no unbind_and_close() */
181 0, /* use generic_call_stub() */
182 &TYPEINFO(spoolss_interface
), /* interface ti */
183 spoolss_stub_table
/* stub_table */
187 spoolss_initialize(void)
189 if (!spoolss_splist
.sp_initialized
) {
190 list_create(&spoolss_splist
.sp_list
,
191 sizeof (smb_spooldoc_t
),
192 offsetof(smb_spooldoc_t
, sd_lnd
));
193 spoolss_splist
.sp_initialized
= 1;
196 spoolss_copyfile_callback
= NULL
;
198 (void) ndr_svc_register(&spoolss_service
);
202 spoolss_finalize(void)
204 spoolss_copyfile_callback
= NULL
;
208 * Register a copyfile callback that the spoolss service can use to
209 * copy files to the spool directory.
211 * Set a null pointer to disable the copying of files to the spool
215 spoolss_register_copyfile(spoolss_copyfile_t copyfile
)
217 spoolss_copyfile_callback
= copyfile
;
221 spoolss_copyfile(smb_inaddr_t
*ipaddr
, char *username
, char *path
,
224 if (spoolss_copyfile_callback
!= NULL
)
225 (*spoolss_copyfile_callback
)(ipaddr
, username
, path
, docname
);
229 spoolss_s_OpenPrinter(void *arg
, ndr_xa_t
*mxa
)
231 struct spoolss_OpenPrinter
*param
= arg
;
232 char *name
= (char *)param
->printer_name
;
235 if (name
!= NULL
&& *name
!= '\0') {
236 if (strspn(name
, "\\") > 2) {
237 bzero(¶m
->handle
, sizeof (spoolss_handle_t
));
238 param
->status
= ERROR_INVALID_PRINTER_NAME
;
242 smb_tracef("spoolss_s_OpenPrinter: %s", name
);
245 if ((id
= ndr_hdalloc(mxa
, NULL
)) == NULL
) {
246 bzero(¶m
->handle
, sizeof (spoolss_handle_t
));
247 param
->status
= ERROR_NOT_ENOUGH_MEMORY
;
251 bcopy(id
, ¶m
->handle
, sizeof (spoolss_handle_t
));
258 spoolss_s_StartPagePrinter(void *arg
, ndr_xa_t
*mxa
)
260 struct spoolss_StartPagePrinter
*param
= arg
;
262 param
->status
= ERROR_SUCCESS
;
269 spoolss_s_EndPagePrinter(void *arg
, ndr_xa_t
*mxa
)
271 struct spoolss_EndPagePrinter
*param
= arg
;
273 param
->status
= ERROR_SUCCESS
;
279 * Windows XP and 2000 use this mechanism to write spool files.
280 * Create a spool file fd to be used by spoolss_s_WritePrinter
281 * and add it to the tail of the spool list.
284 spoolss_s_StartDocPrinter(void *arg
, ndr_xa_t
*mxa
)
286 struct spoolss_StartDocPrinter
*param
= arg
;
287 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
288 smb_spooldoc_t
*spfile
;
289 spoolss_DocInfo_t
*docinfo
;
290 char g_path
[MAXPATHLEN
];
295 if (ndr_hdlookup(mxa
, id
) == NULL
) {
296 smb_tracef("spoolss_s_StartDocPrinter: invalid handle");
297 param
->status
= ERROR_INVALID_HANDLE
;
301 if ((docinfo
= param
->dinfo
.DocInfoContainer
) == NULL
) {
302 param
->status
= ERROR_INVALID_PARAMETER
;
306 if ((rc
= smb_shr_get(SMB_SHARE_PRINT
, &si
)) != NERR_Success
) {
307 smb_tracef("spoolss_s_StartDocPrinter: %s error=%d",
308 SMB_SHARE_PRINT
, rc
);
313 if ((spfile
= calloc(1, sizeof (smb_spooldoc_t
))) == NULL
) {
314 param
->status
= ERROR_NOT_ENOUGH_MEMORY
;
318 if (docinfo
->doc_name
!= NULL
)
319 (void) strlcpy(spfile
->sd_doc_name
,
320 (char *)docinfo
->doc_name
, MAXNAMELEN
);
322 (void) strlcpy(spfile
->sd_doc_name
, "document", MAXNAMELEN
);
324 if (docinfo
->printer_name
!= NULL
)
325 (void) strlcpy(spfile
->sd_printer_name
,
326 (char *)docinfo
->printer_name
, MAXPATHLEN
);
328 (void) strlcpy(spfile
->sd_printer_name
, "printer", MAXPATHLEN
);
330 spfile
->sd_ipaddr
= mxa
->pipe
->np_user
->ui_ipaddr
;
331 (void) strlcpy((char *)spfile
->sd_username
,
332 mxa
->pipe
->np_user
->ui_account
, MAXNAMELEN
);
333 (void) memcpy(&spfile
->sd_handle
, ¶m
->handle
, sizeof (ndr_hdid_t
));
336 * write temporary spool file to print$
338 (void) snprintf(g_path
, MAXPATHLEN
, "%s/%s%d", si
.shr_path
,
339 spfile
->sd_username
, spoolss_cnt
);
340 atomic_inc_32(&spoolss_cnt
);
342 fd
= open(g_path
, O_CREAT
| O_RDWR
, 0600);
344 smb_tracef("spoolss_s_StartDocPrinter: %s: %s",
345 g_path
, strerror(errno
));
346 param
->status
= ERROR_OPEN_FAILED
;
349 (void) strlcpy((char *)spfile
->sd_path
, g_path
, MAXPATHLEN
);
350 spfile
->sd_fd
= (uint16_t)fd
;
353 * Add the document to the spool list.
355 (void) rw_wrlock(&spoolss_splist
.sp_rwl
);
356 list_insert_tail(&spoolss_splist
.sp_list
, spfile
);
357 spoolss_splist
.sp_cnt
++;
358 (void) rw_unlock(&spoolss_splist
.sp_rwl
);
361 * JobId isn't used now, but if printQ management is added
362 * this will have to be incremented per job submitted.
365 param
->status
= ERROR_SUCCESS
;
371 * Windows XP and 2000 use this mechanism to write spool files
372 * Search the spooldoc list for a matching RPC handle and pass
373 * the spool the file for printing.
376 spoolss_s_EndDocPrinter(void *arg
, ndr_xa_t
*mxa
)
378 struct spoolss_EndDocPrinter
*param
= arg
;
379 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
382 if (ndr_hdlookup(mxa
, id
) == NULL
) {
383 smb_tracef("spoolss_s_EndDocPrinter: invalid handle");
384 param
->status
= ERROR_INVALID_HANDLE
;
388 param
->status
= ERROR_INVALID_HANDLE
;
389 (void) rw_wrlock(&spoolss_splist
.sp_rwl
);
391 sp
= list_head(&spoolss_splist
.sp_list
);
393 if (!memcmp(id
, &(sp
->sd_handle
), sizeof (ndr_hdid_t
))) {
394 spoolss_copyfile(&sp
->sd_ipaddr
,
395 sp
->sd_username
, sp
->sd_path
, sp
->sd_doc_name
);
396 (void) close(sp
->sd_fd
);
397 list_remove(&spoolss_splist
.sp_list
, sp
);
399 param
->status
= ERROR_SUCCESS
;
403 sp
= list_next(&spoolss_splist
.sp_list
, sp
);
406 (void) rw_unlock(&spoolss_splist
.sp_rwl
);
408 if (param
->status
!= ERROR_SUCCESS
)
409 smb_tracef("spoolss_s_EndDocPrinter: document not found");
415 spoolss_s_AbortPrinter(void *arg
, ndr_xa_t
*mxa
)
417 struct spoolss_AbortPrinter
*param
= arg
;
419 param
->status
= ERROR_SUCCESS
;
425 spoolss_s_ResetPrinter(void *arg
, ndr_xa_t
*mxa
)
427 struct spoolss_AbortPrinter
*param
= arg
;
429 param
->status
= ERROR_SUCCESS
;
434 spoolss_s_ClosePrinter(void *arg
, ndr_xa_t
*mxa
)
436 struct spoolss_ClosePrinter
*param
= arg
;
437 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
440 if ((hd
= ndr_hdlookup(mxa
, id
)) != NULL
) {
446 bzero(¶m
->result_handle
, sizeof (spoolss_handle_t
));
447 param
->status
= ERROR_SUCCESS
;
452 spoolss_s_AddForm(void *arg
, ndr_xa_t
*mxa
)
454 struct spoolss_AddForm
*param
= arg
;
455 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
457 if (ndr_hdlookup(mxa
, id
) == NULL
) {
458 bzero(param
, sizeof (struct spoolss_AddForm
));
459 param
->status
= ERROR_INVALID_HANDLE
;
463 bzero(param
, sizeof (struct spoolss_AddForm
));
464 param
->status
= ERROR_SUCCESS
;
469 spoolss_s_DeleteForm(void *arg
, ndr_xa_t
*mxa
)
471 struct spoolss_DeleteForm
*param
= arg
;
472 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
474 if (ndr_hdlookup(mxa
, id
) == NULL
) {
475 bzero(param
, sizeof (struct spoolss_DeleteForm
));
476 param
->status
= ERROR_INVALID_HANDLE
;
480 bzero(param
, sizeof (struct spoolss_DeleteForm
));
481 param
->status
= ERROR_SUCCESS
;
486 spoolss_s_EnumForms(void *arg
, ndr_xa_t
*mxa
)
488 struct spoolss_EnumForms
*param
= arg
;
489 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
491 if (ndr_hdlookup(mxa
, id
) == NULL
) {
492 bzero(param
, sizeof (struct spoolss_EnumForms
));
493 param
->status
= ERROR_INVALID_HANDLE
;
497 bzero(param
, sizeof (struct spoolss_EnumForms
));
498 param
->status
= ERROR_SUCCESS
;
505 spoolss_s_AddMonitor(void *arg
, ndr_xa_t
*mxa
)
507 struct spoolss_AddMonitor
*param
= arg
;
509 param
->status
= ERROR_SUCCESS
;
515 spoolss_s_DeleteMonitor(void *arg
, ndr_xa_t
*mxa
)
517 struct spoolss_DeleteMonitor
*param
= arg
;
519 param
->status
= ERROR_SUCCESS
;
525 spoolss_s_DeletePort(void *arg
, ndr_xa_t
*mxa
)
527 struct spoolss_DeletePort
*param
= arg
;
529 param
->status
= ERROR_SUCCESS
;
535 spoolss_s_AddPortEx(void *arg
, ndr_xa_t
*mxa
)
537 struct spoolss_AddPortEx
*param
= arg
;
539 param
->status
= ERROR_SUCCESS
;
545 spoolss_s_SetPort(void *arg
, ndr_xa_t
*mxa
)
547 struct spoolss_SetPort
*param
= arg
;
549 param
->status
= ERROR_SUCCESS
;
555 spoolss_s_EnumJobs(void *arg
, ndr_xa_t
*mxa
)
557 struct spoolss_EnumJobs
*param
= arg
;
558 DWORD status
= ERROR_SUCCESS
;
560 switch (param
->level
) {
569 param
->status
= status
;
578 spoolss_s_GetJob(void *arg
, ndr_xa_t
*mxa
)
580 struct spoolss_GetJob
*param
= arg
;
581 DWORD status
= ERROR_SUCCESS
;
583 if (param
->BufCount
== 0)
584 param
->status
= ERROR_INSUFFICIENT_BUFFER
;
586 param
->status
= status
;
594 spoolss_s_ScheduleJob(void *arg
, ndr_xa_t
*mxa
)
596 struct spoolss_ScheduleJob
*param
= arg
;
597 DWORD status
= ERROR_SPL_NO_ADDJOB
;
599 param
->status
= status
;
605 spoolss_s_AddJob(void *arg
, ndr_xa_t
*mxa
)
607 struct spoolss_AddJob
*param
= arg
;
609 param
->status
= ERROR_SUCCESS
;
616 spoolss_s_rfnpcnex(void *arg
, ndr_xa_t
*mxa
)
618 struct spoolss_RFNPCNEX
*param
= arg
;
621 param
->status
= ERROR_SUCCESS
;
626 * Use the RPC context handle to find the fd and write the document content.
629 spoolss_s_WritePrinter(void *arg
, ndr_xa_t
*mxa
)
631 struct spoolss_WritePrinter
*param
= arg
;
633 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
636 if (ndr_hdlookup(mxa
, id
) == NULL
) {
638 param
->status
= ERROR_INVALID_HANDLE
;
639 smb_tracef("spoolss_s_WritePrinter: invalid handle");
643 if ((spfd
= spoolss_find_document(id
)) < 0) {
645 param
->status
= ERROR_INVALID_HANDLE
;
646 smb_tracef("spoolss_s_WritePrinter: document not found");
650 written
= write(spfd
, param
->pBuf
, param
->BufCount
);
651 if (written
< param
->BufCount
) {
652 smb_tracef("spoolss_s_WritePrinter: write failed");
654 param
->status
= ERROR_CANTWRITE
;
658 param
->written
= written
;
659 param
->status
= ERROR_SUCCESS
;
664 * Find a document by RPC handle in the spool list and return the fd.
667 spoolss_find_document(ndr_hdid_t
*handle
)
671 (void) rw_rdlock(&spoolss_splist
.sp_rwl
);
673 sp
= list_head(&spoolss_splist
.sp_list
);
675 if (!memcmp(handle
, &(sp
->sd_handle
), sizeof (ndr_hdid_t
))) {
676 (void) rw_unlock(&spoolss_splist
.sp_rwl
);
679 sp
= list_next(&spoolss_splist
.sp_list
, sp
);
682 (void) rw_unlock(&spoolss_splist
.sp_rwl
);
687 * GetPrinterData is used t obtain values from the registry for a
688 * printer or a print server. See [MS-RPRN] for value descriptions.
689 * The registry returns ERROR_FILE_NOT_FOUND for unknown keys.
692 spoolss_s_GetPrinterData(void *arg
, ndr_xa_t
*mxa
)
694 static spoolss_winreg_t reg
[] = {
695 { "ChangeId", 0x0050acf2 },
696 { "W3SvcInstalled", 0x00000000 },
697 { "BeepEnabled", 0x00000000 },
698 { "EventLog", 0x0000001f },
699 { "NetPopup", 0x00000000 },
700 { "NetPopupToComputer", 0x00000000 },
701 { "MajorVersion", 0x00000003 },
702 { "MinorVersion", 0x00000000 },
703 { "DsPresent", 0x00000000 }
706 struct spoolss_GetPrinterData
*param
= arg
;
707 char *name
= (char *)param
->pValueName
;
708 char buf
[MAXPATHLEN
];
709 static uint8_t reserved_buf
[4];
710 spoolss_winreg_t
*rp
;
712 smb_version_t
*osversion
;
713 struct utsname sysname
;
720 if (name
== NULL
|| *name
== '\0') {
721 status
= ERROR_FILE_NOT_FOUND
;
725 for (i
= 0; i
< sizeof (reg
) / sizeof (reg
[0]); ++i
) {
726 param
->pType
= WINREG_DWORD
;
727 param
->Needed
= sizeof (uint32_t);
730 if (strcasecmp(name
, rp
->name
) != 0)
733 if (param
->Size
< sizeof (uint32_t)) {
738 if ((param
->Buf
= NDR_NEW(mxa
, uint32_t)) == NULL
) {
739 status
= ERROR_NOT_ENOUGH_MEMORY
;
745 if ((strcasecmp(name
, "DsPresent") == 0) &&
746 (smb_config_get_secmode() == SMB_SECMODE_DOMAIN
))
749 bcopy(&value
, param
->Buf
, sizeof (uint32_t));
750 param
->Size
= sizeof (uint32_t);
751 param
->status
= ERROR_SUCCESS
;
755 if (strcasecmp(name
, "OSVersion") == 0) {
756 param
->pType
= WINREG_BINARY
;
757 param
->Needed
= sizeof (smb_version_t
);
759 if (param
->Size
< sizeof (smb_version_t
)) {
760 param
->Size
= sizeof (smb_version_t
);
764 if ((osversion
= NDR_NEW(mxa
, smb_version_t
)) == NULL
) {
765 status
= ERROR_NOT_ENOUGH_MEMORY
;
769 smb_config_get_version(osversion
);
770 param
->Buf
= (uint8_t *)osversion
;
771 param
->status
= ERROR_SUCCESS
;
775 if (strcasecmp(name
, "DNSMachineName") == 0) {
776 param
->pType
= WINREG_SZ
;
778 (void) smb_getfqhostname(buf
, MAXHOSTNAMELEN
);
782 if (strcasecmp(name
, "DefaultSpoolDirectory") == 0) {
783 param
->pType
= WINREG_SZ
;
786 if (smb_shr_get(SMB_SHARE_PRINT
, &si
) != NERR_Success
) {
787 status
= ERROR_FILE_NOT_FOUND
;
791 (void) snprintf(buf
, MAXPATHLEN
, "C:/%s", si
.shr_path
);
792 (void) strcanon(buf
, "/\\");
793 (void) strsubst(buf
, '/', '\\');
797 if (strcasecmp(name
, "Architecture") == 0) {
798 param
->pType
= WINREG_SZ
;
800 if (uname(&sysname
) < 0)
801 (void) strlcpy(buf
, "Solaris", MAXPATHLEN
);
803 (void) snprintf(buf
, MAXPATHLEN
, "%s %s",
804 sysname
.sysname
, sysname
.machine
);
809 status
= ERROR_FILE_NOT_FOUND
;
812 bzero(param
, sizeof (struct spoolss_GetPrinterData
));
813 param
->Buf
= reserved_buf
;
814 param
->status
= status
;
818 wcslen
= smb_wcequiv_strlen(buf
) + sizeof (smb_wchar_t
);
819 if (param
->Size
< wcslen
) {
820 param
->Needed
= wcslen
;
824 if ((wcs
= NDR_MALLOC(mxa
, wcslen
)) == NULL
) {
825 status
= ERROR_NOT_ENOUGH_MEMORY
;
829 (void) ndr_mbstowcs(NULL
, wcs
, buf
, wcslen
);
830 param
->Buf
= (uint8_t *)wcs
;
831 param
->Needed
= wcslen
;
832 param
->status
= ERROR_SUCCESS
;
837 param
->Buf
= reserved_buf
;
838 param
->status
= ERROR_MORE_DATA
;
843 smb_rpc_off(char *dst
, char *src
, uint32_t *offset
, uint32_t *outoffset
)
848 bytes
= smb_wcequiv_strlen(src
) + 2;
849 nwchars
= strlen(src
) + 1;
851 *outoffset
= *offset
;
852 /*LINTED E_BAD_PTR_CAST_ALIGN*/
853 (void) smb_mbstowcs(((smb_wchar_t
*)(dst
+ *offset
)), src
, nwchars
);
857 spoolss_s_GetPrinter(void *arg
, ndr_xa_t
*mxa
)
859 struct spoolss_GetPrinter
*param
= arg
;
860 struct spoolss_GetPrinter0
*pinfo0
;
861 struct spoolss_GetPrinter1
*pinfo1
;
862 struct spoolss_GetPrinter2
*pinfo2
;
863 struct spoolss_DeviceMode
*devmode2
;
864 ndr_hdid_t
*id
= (ndr_hdid_t
*)¶m
->handle
;
865 spoolss_sd_t secdesc
;
866 char server
[MAXNAMELEN
];
867 char printer
[MAXNAMELEN
];
868 DWORD status
= ERROR_SUCCESS
;
873 if (ndr_hdlookup(mxa
, id
) == NULL
) {
874 status
= ERROR_INVALID_HANDLE
;
878 if (spoolss_getservername(server
, MAXNAMELEN
) != 0) {
879 status
= ERROR_INTERNAL_ERROR
;
883 (void) snprintf(printer
, MAXNAMELEN
, "%s\\%s", server
, SPOOLSS_PRINTER
);
885 switch (param
->switch_value
) {
894 status
= ERROR_INVALID_LEVEL
;
898 if (param
->BufCount
< param
->needed
) {
901 param
->status
= ERROR_INSUFFICIENT_BUFFER
;
905 if ((param
->Buf
= NDR_MALLOC(mxa
, param
->BufCount
)) == NULL
) {
906 status
= ERROR_NOT_ENOUGH_MEMORY
;
910 bzero(param
->Buf
, param
->BufCount
);
911 wname
= (char *)param
->Buf
;
912 offset
= param
->needed
;
914 switch (param
->switch_value
) {
916 /*LINTED E_BAD_PTR_CAST_ALIGN*/
917 pinfo0
= (struct spoolss_GetPrinter0
*)param
->Buf
;
919 smb_rpc_off(wname
, server
, &offset
, &pinfo0
->servername
);
920 smb_rpc_off(wname
, printer
, &offset
, &pinfo0
->printername
);
922 pinfo0
->total_jobs
= 6;
923 pinfo0
->total_bytes
= 1040771;
928 pinfo0
->global_counter
= 2162710;
929 pinfo0
->total_pages
= 21495865;
930 pinfo0
->version
= 10;
931 pinfo0
->session_counter
= 1;
932 pinfo0
->job_error
= 0x6;
933 pinfo0
->change_id
= 0x1;
935 pinfo0
->c_setprinter
= 0;
938 /*LINTED E_BAD_PTR_CAST_ALIGN*/
939 pinfo1
= (struct spoolss_GetPrinter1
*)param
->Buf
;
941 pinfo1
->flags
= PRINTER_ENUM_ICON8
;
942 smb_rpc_off(wname
, printer
, &offset
, &pinfo1
->flags
);
943 smb_rpc_off(wname
, printer
, &offset
, &pinfo1
->description
);
944 smb_rpc_off(wname
, printer
, &offset
, &pinfo1
->comment
);
947 /*LINTED E_BAD_PTR_CAST_ALIGN*/
948 pinfo2
= (struct spoolss_GetPrinter2
*)param
->Buf
;
950 smb_rpc_off(wname
, server
, &offset
, &pinfo2
->servername
);
951 smb_rpc_off(wname
, printer
, &offset
, &pinfo2
->printername
);
952 smb_rpc_off(wname
, SPOOLSS_PRINTER
, &offset
,
954 smb_rpc_off(wname
, "CIFS Printer Port", &offset
,
956 smb_rpc_off(wname
, "", &offset
, &pinfo2
->drivername
);
957 smb_rpc_off(wname
, SPOOLSS_PRINTER
, &offset
,
959 smb_rpc_off(wname
, "farside", &offset
, &pinfo2
->location
);
961 offset
-= sizeof (struct spoolss_DeviceMode
);
962 pinfo2
->devmode
= offset
;
963 /*LINTED E_BAD_PTR_CAST_ALIGN*/
964 devmode2
= (struct spoolss_DeviceMode
*)(param
->Buf
+ offset
);
966 smb_rpc_off(wname
, "farside", &offset
, &pinfo2
->sepfile
);
967 smb_rpc_off(wname
, "winprint", &offset
,
968 &pinfo2
->printprocessor
);
969 smb_rpc_off(wname
, "RAW", &offset
, &pinfo2
->datatype
);
970 smb_rpc_off(wname
, "", &offset
, &pinfo2
->parameters
);
972 status
= spoolss_make_sd(mxa
, &secdesc
);
973 if (status
== ERROR_SUCCESS
) {
974 offset
-= secdesc
.sd_size
;
975 pinfo2
->secdesc
= offset
;
976 tmpbuf
= (uint8_t *)(param
->Buf
+ offset
);
977 bcopy(secdesc
.sd_buf
, tmpbuf
, secdesc
.sd_size
);
980 pinfo2
->attributes
= 0x00001048;
981 pinfo2
->status
= 0x00000000;
982 pinfo2
->starttime
= 0;
983 pinfo2
->untiltime
= 0;
985 pinfo2
->averageppm
= 0;
986 pinfo2
->defaultpriority
= 0;
988 /*LINTED E_BAD_PTR_CAST_ALIGN*/
989 (void) smb_mbstowcs((smb_wchar_t
*)devmode2
->devicename
,
991 devmode2
->specversion
= 0x0401;
992 devmode2
->driverversion
= 1024;
993 devmode2
->size
= 220;
994 devmode2
->driverextra_length
= 0;
995 devmode2
->fields
= 0x00014713;
996 devmode2
->orientation
= 1;
997 devmode2
->papersize
= 1;
998 devmode2
->paperlength
= 0;
999 devmode2
->paperwidth
= 0;
1000 devmode2
->scale
= 100;
1001 devmode2
->copies
= 1;
1002 devmode2
->defaultsource
= 15;
1003 devmode2
->printquality
= 65532;
1004 devmode2
->color
= 1;
1005 devmode2
->duplex
= 1;
1006 devmode2
->yresolution
= 1;
1007 devmode2
->ttoption
= 1;
1008 devmode2
->collate
= 0;
1009 /*LINTED E_BAD_PTR_CAST_ALIGN*/
1010 (void) smb_mbstowcs((smb_wchar_t
*)devmode2
->formname
,
1012 devmode2
->logpixels
= 0;
1013 devmode2
->bitsperpel
= 0;
1014 devmode2
->pelswidth
= 0;
1015 devmode2
->pelsheight
= 0;
1016 devmode2
->displayflags
= 0;
1017 devmode2
->displayfrequency
= 0;
1018 devmode2
->icmmethod
= 0;
1019 devmode2
->icmintent
= 0;
1020 devmode2
->mediatype
= 0;
1021 devmode2
->dithertype
= 0;
1022 devmode2
->reserved1
= 0;
1023 devmode2
->reserved2
= 0;
1024 devmode2
->panningwidth
= 0;
1025 devmode2
->panningheight
= 0;
1032 param
->status
= status
;
1033 return (NDR_DRC_OK
);
1036 smb_tracef("spoolss_s_GetPrinter: error %u", status
);
1037 bzero(param
, sizeof (struct spoolss_GetPrinter
));
1038 param
->status
= status
;
1039 return (NDR_DRC_OK
);
1043 spoolss_getservername(char *name
, size_t namelen
)
1045 char hostname
[MAXHOSTNAMELEN
];
1046 char ipstr
[INET6_ADDRSTRLEN
];
1047 smb_inaddr_t ipaddr
;
1052 if (smb_gethostname(hostname
, MAXHOSTNAMELEN
, 0) != 0) {
1053 smb_tracef("spoolss_s_GetPrinter: gethostname failed");
1057 if ((h
= smb_gethostbyname(hostname
, &error
)) == NULL
) {
1058 smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d",
1063 bcopy(h
->h_addr
, &ipaddr
, h
->h_length
);
1064 ipaddr
.a_family
= h
->h_addrtype
;
1067 p
= smb_inet_ntop(&ipaddr
, ipstr
, SMB_IPSTRLEN(ipaddr
.a_family
));
1069 smb_tracef("spoolss_s_GetPrinter: inet_ntop failed");
1073 (void) snprintf(name
, namelen
, "\\\\%s", ipstr
);
1078 spoolss_make_sd(ndr_xa_t
*mxa
, spoolss_sd_t
*secdesc
)
1085 bzero(&sd
, sizeof (smb_sd_t
));
1087 if ((status
= spoolss_format_sd(&sd
)) != ERROR_SUCCESS
)
1090 sd_len
= smb_sd_len(&sd
, SMB_ALL_SECINFO
);
1092 if ((sd_buf
= NDR_MALLOC(mxa
, sd_len
)) == NULL
)
1093 return (ERROR_NOT_ENOUGH_MEMORY
);
1095 secdesc
->sd_buf
= sd_buf
;
1096 secdesc
->sd_size
= sd_len
;
1098 status
= srvsvc_sd_set_relative(&sd
, sd_buf
);
1104 spoolss_format_sd(smb_sd_t
*sd
)
1108 uint32_t status
= ERROR_SUCCESS
;
1110 if (acl_fromtext("everyone@:full_set::allow", &acl
) != 0) {
1111 smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY");
1112 return (ERROR_NOT_ENOUGH_MEMORY
);
1114 smb_fssd_init(&fs_sd
, SMB_ALL_SECINFO
, SMB_FSSD_FLAGS_DIR
);
1117 fs_sd
.sd_zdacl
= acl
;
1118 fs_sd
.sd_zsacl
= NULL
;
1120 status
= smb_sd_fromfs(&fs_sd
, sd
);
1121 if (status
!= NT_STATUS_SUCCESS
) {
1122 smb_tracef("spoolss_format_sd: %u", status
);
1123 status
= ERROR_ACCESS_DENIED
;
1125 smb_fssd_term(&fs_sd
);
1131 spoolss_s_stub(void *arg
, ndr_xa_t
*mxa
)
1133 return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED
);
1137 fixup_spoolss_RFNPCNEX(struct spoolss_RFNPCNEX
*val
)
1139 unsigned short size1
= 0;
1140 unsigned short size2
= 0;
1141 unsigned short size3
= 0;
1142 struct spoolss_RPC_V2_NOTIFY_INFO
*pinfo
;
1144 pinfo
= val
->ppinfo
->pinfo
;
1145 switch (pinfo
->aData
->Reserved
) {
1147 size1
= sizeof (struct STRING_CONTAINER
);
1150 size1
= sizeof (DWORD
) * 2;
1153 size1
= sizeof (struct SYSTEMTIME_CONTAINER
);
1156 size1
= sizeof (struct spoolssDevmodeContainer
);
1158 case TABLE_SECURITY_DESCRIPTOR
:
1159 size1
= sizeof (struct SECURITY_CONTAINER
);
1164 size2
= size1
+ (2 * sizeof (DWORD
));
1165 size3
= size2
+ sizeof (ndr_request_hdr_t
) + sizeof (DWORD
);
1167 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA_DATA
, size1
);
1168 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO_DATA
, size2
);
1169 FIXUP_PDU_SIZE(spoolss_RPC_V2_NOTIFY_INFO
, size3
);
1170 FIXUP_PDU_SIZE(spoolss_RFNPCNEX
, size3
);
1174 fixup_spoolss_GetPrinter(struct spoolss_GetPrinter
*val
)
1176 unsigned short size1
= 0;
1177 unsigned short size2
= 0;
1178 unsigned short size3
= 0;
1180 switch (val
->switch_value
) {
1181 CASE_INFO_ENT(spoolss_GetPrinter
, 0);
1182 CASE_INFO_ENT(spoolss_GetPrinter
, 1);
1183 CASE_INFO_ENT(spoolss_GetPrinter
, 2);
1184 CASE_INFO_ENT(spoolss_GetPrinter
, 3);
1185 CASE_INFO_ENT(spoolss_GetPrinter
, 4);
1186 CASE_INFO_ENT(spoolss_GetPrinter
, 5);
1187 CASE_INFO_ENT(spoolss_GetPrinter
, 6);
1188 CASE_INFO_ENT(spoolss_GetPrinter
, 7);
1189 CASE_INFO_ENT(spoolss_GetPrinter
, 8);
1195 size2
= size1
+ (2 * sizeof (DWORD
));
1196 size3
= size2
+ sizeof (ndr_request_hdr_t
) + sizeof (DWORD
);
1198 FIXUP_PDU_SIZE(spoolss_GetPrinter_result_u
, size1
);
1199 FIXUP_PDU_SIZE(spoolss_GetPrinter_result
, size2
);
1200 FIXUP_PDU_SIZE(spoolss_GetPrinter
, size3
);
1203 #else /* CONFIG_SMB_PRINTING */
1206 * If not CONFIG_SMB_PRINTING, just provide a few "stubs".
1210 spoolss_initialize(void)
1215 spoolss_finalize(void)
1221 spoolss_register_copyfile(spoolss_copyfile_t copyfile
)
1225 #endif /* CONFIG_SMB_PRINTING */