/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Printing and Spooling RPC service.
*/
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <fcntl.h>
#include <errno.h>
#include <smbsrv/libmlrpc.h>
#include <smbsrv/libmlsvc.h>
#include <mlsvc.h>
#ifdef HAVE_CUPS
typedef struct smb_spool {
int sp_cnt;
int sp_initialized;
} smb_spool_t;
typedef struct smb_spooldoc {
int sd_spool_num;
typedef struct {
char *name;
typedef struct {
} spoolss_sd_t;
static int spoolss_getservername(char *, size_t);
static int spoolss_find_document(ndr_hdid_t *);
static int spoolss_s_OpenPrinter(void *, ndr_xa_t *);
static int spoolss_s_ClosePrinter(void *, ndr_xa_t *);
static int spoolss_s_AbortPrinter(void *, ndr_xa_t *);
static int spoolss_s_ResetPrinter(void *, ndr_xa_t *);
static int spoolss_s_GetPrinter(void *, ndr_xa_t *);
static int spoolss_s_GetPrinterData(void *, ndr_xa_t *);
static int spoolss_s_AddJob(void *, ndr_xa_t *);
static int spoolss_s_GetJob(void *, ndr_xa_t *);
static int spoolss_s_EnumJobs(void *, ndr_xa_t *);
static int spoolss_s_ScheduleJob(void *, ndr_xa_t *);
static int spoolss_s_StartDocPrinter(void *, ndr_xa_t *);
static int spoolss_s_EndDocPrinter(void *, ndr_xa_t *);
static int spoolss_s_StartPagePrinter(void *, ndr_xa_t *);
static int spoolss_s_EndPagePrinter(void *, ndr_xa_t *);
static int spoolss_s_rfnpcnex(void *, ndr_xa_t *);
static int spoolss_s_WritePrinter(void *, ndr_xa_t *);
static int spoolss_s_AddForm(void *, ndr_xa_t *);
static int spoolss_s_DeleteForm(void *, ndr_xa_t *);
static int spoolss_s_EnumForms(void *, ndr_xa_t *);
static int spoolss_s_AddMonitor(void *, ndr_xa_t *);
static int spoolss_s_DeleteMonitor(void *, ndr_xa_t *);
static int spoolss_s_DeletePort(void *, ndr_xa_t *);
static int spoolss_s_AddPortEx(void *, ndr_xa_t *);
static int spoolss_s_SetPort(void *, ndr_xa_t *);
static int spoolss_s_stub(void *, ndr_xa_t *);
{0}
};
"SPOOLSS", /* name */
"Print Spool Service", /* desc */
"\\spoolss", /* endpoint */
PIPE_SPOOLSS, /* sec_addr_port */
"12345678-1234-abcd-ef00-0123456789ab", 1, /* abstract */
0, /* no bind_instance_size */
0, /* no bind_req() */
0, /* no unbind_and_close() */
0, /* use generic_call_stub() */
spoolss_stub_table /* stub_table */
};
void
spoolss_initialize(void)
{
if (!spoolss_splist.sp_initialized) {
sizeof (smb_spooldoc_t),
}
(void) ndr_svc_register(&spoolss_service);
}
void
spoolss_finalize(void)
{
}
/*
* Register a copyfile callback that the spoolss service can use to
* copy files to the spool directory.
*
* Set a null pointer to disable the copying of files to the spool
* directory.
*/
void
{
}
static void
char *docname)
{
if (spoolss_copyfile_callback != NULL)
}
static int
{
return (NDR_DRC_OK);
}
}
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*
* Windows XP and 2000 use this mechanism to write spool files.
* Create a spool file fd to be used by spoolss_s_WritePrinter
* and add it to the tail of the spool list.
*/
static int
{
int rc;
int fd;
smb_tracef("spoolss_s_StartDocPrinter: invalid handle");
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
smb_tracef("spoolss_s_StartDocPrinter: %s error=%d",
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
else
else
/*
* write temporary spool file to print$
*/
if (fd == -1) {
smb_tracef("spoolss_s_StartDocPrinter: %s: %s",
} else {
/*
* Add the document to the spool list.
*/
/*
* JobId isn't used now, but if printQ management is added
* this will have to be incremented per job submitted.
*/
}
return (NDR_DRC_OK);
}
/*
* Windows XP and 2000 use this mechanism to write spool files
* Search the spooldoc list for a matching RPC handle and pass
* the spool the file for printing.
*/
static int
{
smb_tracef("spoolss_s_EndDocPrinter: invalid handle");
return (NDR_DRC_OK);
}
break;
}
}
smb_tracef("spoolss_s_EndDocPrinter: document not found");
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
static int
{
}
return (NDR_DRC_OK);
}
static int
{
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
static int
{
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
static int
{
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
case 1:
case 2:
case 3:
case 4:
default:
break;
}
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
else
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_OK);
}
/*
* Use the RPC context handle to find the fd and write the document content.
*/
static int
{
int written = 0;
int spfd;
smb_tracef("spoolss_s_WritePrinter: invalid handle");
return (NDR_DRC_OK);
}
smb_tracef("spoolss_s_WritePrinter: document not found");
return (NDR_DRC_OK);
}
smb_tracef("spoolss_s_WritePrinter: write failed");
return (NDR_DRC_OK);
}
return (NDR_DRC_OK);
}
/*
* Find a document by RPC handle in the spool list and return the fd.
*/
static int
{
}
}
return (-1);
}
/*
* GetPrinterData is used t obtain values from the registry for a
* printer or a print server. See [MS-RPRN] for value descriptions.
* The registry returns ERROR_FILE_NOT_FOUND for unknown keys.
*/
static int
{
{ "ChangeId", 0x0050acf2 },
{ "W3SvcInstalled", 0x00000000 },
{ "BeepEnabled", 0x00000000 },
{ "EventLog", 0x0000001f },
{ "NetPopup", 0x00000000 },
{ "NetPopupToComputer", 0x00000000 },
{ "MajorVersion", 0x00000003 },
{ "MinorVersion", 0x00000000 },
{ "DsPresent", 0x00000000 }
};
int wcslen;
int i;
goto report_error;
}
continue;
goto need_more_data;
}
goto report_error;
}
value = 0x00000001;
return (NDR_DRC_OK);
}
goto need_more_data;
}
goto report_error;
}
return (NDR_DRC_OK);
}
buf[0] = '\0';
goto encode_string;
}
buf[0] = '\0';
goto report_error;
}
goto encode_string;
}
else
goto encode_string;
}
return (NDR_DRC_OK);
goto need_more_data;
}
goto report_error;
}
return (NDR_DRC_OK);
return (NDR_DRC_OK);
}
void
{
int nwchars;
int bytes;
/*LINTED E_BAD_PTR_CAST_ALIGN*/
}
int
{
char *wname;
goto error_out;
}
goto error_out;
}
switch (param->switch_value) {
case 0:
case 1:
break;
case 2:
break;
default:
goto error_out;
}
return (NDR_DRC_OK);
}
goto error_out;
}
switch (param->switch_value) {
case 0:
/*LINTED E_BAD_PTR_CAST_ALIGN*/
pinfo0->c_setprinter = 0;
break;
case 1:
/*LINTED E_BAD_PTR_CAST_ALIGN*/
break;
case 2:
/*LINTED E_BAD_PTR_CAST_ALIGN*/
offset -= sizeof (struct spoolss_DeviceMode);
/*LINTED E_BAD_PTR_CAST_ALIGN*/
&pinfo2->printprocessor);
if (status == ERROR_SUCCESS) {
}
pinfo2->averageppm = 0;
pinfo2->defaultpriority = 0;
/*LINTED E_BAD_PTR_CAST_ALIGN*/
printer, 32);
devmode2->driverextra_length = 0;
devmode2->paperlength = 0;
devmode2->paperwidth = 0;
/*LINTED E_BAD_PTR_CAST_ALIGN*/
"Letter", 32);
devmode2->bitsperpel = 0;
devmode2->pelsheight = 0;
devmode2->displayflags = 0;
devmode2->displayfrequency = 0;
devmode2->dithertype = 0;
devmode2->panningwidth = 0;
devmode2->panningheight = 0;
break;
default:
break;
}
return (NDR_DRC_OK);
return (NDR_DRC_OK);
}
static int
{
struct hostent *h;
const char *p;
int error;
smb_tracef("spoolss_s_GetPrinter: gethostname failed");
return (-1);
}
smb_tracef("spoolss_s_GetPrinter: gethostbyname failed: %d",
error);
return (-1);
}
freehostent(h);
if (p == NULL) {
smb_tracef("spoolss_s_GetPrinter: inet_ntop failed");
return (-1);
}
return (0);
}
static uint32_t
{
return (status);
return (ERROR_NOT_ENOUGH_MEMORY);
smb_sd_term(&sd);
return (status);
}
static uint32_t
{
smb_tracef("spoolss_format_sd: NOT_ENOUGH_MEMORY");
return (ERROR_NOT_ENOUGH_MEMORY);
}
if (status != NT_STATUS_SUCCESS) {
}
return (status);
}
/*ARGSUSED*/
static int
{
return (NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED);
}
void
{
unsigned short size1 = 0;
unsigned short size2 = 0;
unsigned short size3 = 0;
case TABLE_STRING:
size1 = sizeof (struct STRING_CONTAINER);
break;
case TABLE_DWORD:
break;
case TABLE_TIME:
size1 = sizeof (struct SYSTEMTIME_CONTAINER);
break;
case TABLE_DEVMODE:
size1 = sizeof (struct spoolssDevmodeContainer);
break;
size1 = sizeof (struct SECURITY_CONTAINER);
break;
default:
return;
}
}
void
{
unsigned short size1 = 0;
unsigned short size2 = 0;
unsigned short size3 = 0;
switch (val->switch_value) {
default:
return;
};
}
#else /* HAVE_CUPS */
/*
* If not HAVE_CUPS, just provide a few "stubs".
*/
void
spoolss_initialize(void)
{
}
void
spoolss_finalize(void)
{
}
/*ARGSUSED*/
void
{
}
#endif /* HAVE_CUPS */