summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2006-03-03 16:44:30 +0000
committerGerald Carter <jerry@samba.org>2006-03-03 16:44:30 +0000
commit3e7f8c6b63d692e33ff019ce193db58040821bb5 (patch)
tree2f44bd0bee70cbf70d56dc793da994732fe47e2f
parent2a4978ffbdfc49aa0dd6bf4955a8d42a256a7a08 (diff)
downloadsamba-3e7f8c6b63d692e33ff019ce193db58040821bb5.tar.gz
samba-3e7f8c6b63d692e33ff019ce193db58040821bb5.tar.xz
samba-3e7f8c6b63d692e33ff019ce193db58040821bb5.zip
r13815: "Into the blind world let us now descend,"
Began the poet, his face as pale as death. "I will go first, and you will follow me." --- Adding XcvDataPort() to the spoolss code for remotely add ports. The design is to allow an intuitive means of creating a new CUPS print queue from the Windows 2000/XP APW without hacks like specifying the deviceURI in the location field of the printer properties dialog. Also set 'default devmode = yes' as the new default since it causes no harm and only is executed when you have a NULL devmode anyways.
-rw-r--r--source/include/nt_printing.h1
-rwxr-xr-xsource/include/rpc_spoolss.h28
-rw-r--r--source/param/loadparm.c2
-rw-r--r--source/rpc_parse/parse_spoolss.c64
-rwxr-xr-xsource/rpc_server/srv_spoolss.c55
-rw-r--r--source/rpc_server/srv_spoolss_nt.c149
6 files changed, 161 insertions, 138 deletions
diff --git a/source/include/nt_printing.h b/source/include/nt_printing.h
index f0d50878ce4..7e3bd320032 100644
--- a/source/include/nt_printing.h
+++ b/source/include/nt_printing.h
@@ -423,6 +423,7 @@ typedef struct {
#define PRINTER_HANDLE_IS_PRINTER 0
#define PRINTER_HANDLE_IS_PRINTSERVER 1
+#define PRINTER_HANDLE_IS_TCPMON 2
/* structure to store the printer handles */
/* and a reference to what it's pointing to */
diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h
index 3b88f76588b..347aca0e08e 100755
--- a/source/include/rpc_spoolss.h
+++ b/source/include/rpc_spoolss.h
@@ -4,7 +4,7 @@
Copyright (C) Andrew Tridgell 1992-2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
Copyright (C) Jean Francois Micouleau 1998-2000.
- Copyright (C) Gerald Carter 2001-2005.
+ Copyright (C) Gerald Carter 2001-2006.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -107,8 +107,16 @@
#define SPOOLSS_DELETEPRINTERDATAEX 0x51
#define SPOOLSS_DELETEPRINTERKEY 0x52
#define SPOOLSS_DELETEPRINTERDRIVEREX 0x54
+#define SPOOLSS_XCVDATAPORT 0x58
#define SPOOLSS_ADDPRINTERDRIVEREX 0x59
+/*
+ * Special strings for the OpenPrinter() call. See the MSDN DDK
+ * docs on the XcvDataPort() for more details.
+ */
+
+#define SPL_XCV_MONITOR_TCPMON ",XcvMonitor Standard TCP/IP Port"
+
#define PRINTER_CONTROL_UNPAUSE 0x00000000
#define PRINTER_CONTROL_PAUSE 0x00000001
@@ -2161,6 +2169,24 @@ typedef struct spool_r_getprintprocessordirectory
}
SPOOL_R_GETPRINTPROCESSORDIRECTORY;
+/**************************************/
+
+typedef struct spool_q_xcvdataport {
+ POLICY_HND handle;
+ UNISTR2 dataname;
+ RPC_BUFFER indata;
+ uint32 indata_len;
+ uint32 offered;
+ uint32 unknown;
+} SPOOL_Q_XCVDATAPORT;
+
+typedef struct spool_r_xcvdataport {
+ RPC_BUFFER outdata;
+ uint32 *unknown1;
+ uint32 *unknown2;
+ WERROR status;
+} SPOOL_R_XCVDATAPORT;
+
#define PRINTER_DRIVER_VERSION 2
#define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86"
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index 6d0eb46f23f..ce4bef8d27b 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -574,7 +574,7 @@ static service sDefault = {
False, /* bInheritOwner */
True, /* bMSDfsRoot */
False, /* bUseClientDriver */
- False, /* bDefaultDevmode */
+ True, /* bDefaultDevmode */
False, /* bForcePrintername */
True, /* bNTAclSupport */
False, /* bForceUnknownAclUser */
diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c
index 45b683e9c60..6f3245243d6 100644
--- a/source/rpc_parse/parse_spoolss.c
+++ b/source/rpc_parse/parse_spoolss.c
@@ -7406,3 +7406,67 @@ BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
return True;
}
+
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL spoolss_io_q_xcvdataport(const char *desc, SPOOL_Q_XCVDATAPORT *q_u, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "spoolss_io_q_xcvdataport");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+
+ if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
+ return False;
+
+ if(!smb_io_unistr2("", &q_u->dataname, True, ps, depth))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if(!prs_rpcbuffer("", ps, depth, &q_u->indata))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if (!prs_uint32("indata_len", ps, depth, &q_u->indata_len))
+ return False;
+ if (!prs_uint32("offered", ps, depth, &q_u->offered))
+ return False;
+ if (!prs_uint32("unknown", ps, depth, &q_u->unknown))
+ return False;
+
+ return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+BOOL spoolss_io_r_xcvdataport(const char *desc, SPOOL_R_XCVDATAPORT *r_u, prs_struct *ps, int depth)
+{
+ prs_debug(ps, depth, desc, "spoolss_io_r_xcvdataport");
+ depth++;
+
+ if(!prs_align(ps))
+ return False;
+ if(!prs_rpcbuffer("", ps, depth, &r_u->outdata))
+ return False;
+
+ if (!prs_align(ps))
+ return False;
+
+ if(!prs_pointer("unknown1", ps, depth, (void**)&r_u->unknown1, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_uint32))
+ return False;
+ if(!prs_pointer("unknown2", ps, depth, (void**)&r_u->unknown2, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_uint32))
+ return False;
+ if(!prs_werror("status", ps, depth, &r_u->status))
+ return False;
+
+ return True;
+}
+
diff --git a/source/rpc_server/srv_spoolss.c b/source/rpc_server/srv_spoolss.c
index b3a67dd6cfd..0a43e8ae8ac 100755
--- a/source/rpc_server/srv_spoolss.c
+++ b/source/rpc_server/srv_spoolss.c
@@ -1519,66 +1519,34 @@ static BOOL api_spoolss_deleteprinterdriverex(pipes_struct *p)
return True;
}
-#if 0
-
-/****************************************************************************
-****************************************************************************/
-
-static BOOL api_spoolss_replyopenprinter(pipes_struct *p)
-{
- SPOOL_Q_REPLYOPENPRINTER q_u;
- SPOOL_R_REPLYOPENPRINTER r_u;
- prs_struct *data = &p->in_data.data;
- prs_struct *rdata = &p->out_data.rdata;
-
- ZERO_STRUCT(q_u);
- ZERO_STRUCT(r_u);
-
- if(!spoolss_io_q_replyopenprinter("", &q_u, data, 0)) {
- DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_REPLYOPENPRINTER.\n"));
- return False;
- }
-
- r_u.status = _spoolss_replyopenprinter(p, &q_u, &r_u);
-
- if(!spoolss_io_r_replyopenprinter("", &r_u, rdata, 0)) {
- DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_REPLYOPENPRINTER.\n"));
- return False;
- }
-
- return True;
-}
-
/****************************************************************************
****************************************************************************/
-static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
+static BOOL api_spoolss_xcvdataport(pipes_struct *p)
{
- SPOOL_Q_REPLYCLOSEPRINTER q_u;
- SPOOL_R_REPLYCLOSEPRINTER r_u;
+ SPOOL_Q_XCVDATAPORT q_u;
+ SPOOL_R_XCVDATAPORT r_u;
prs_struct *data = &p->in_data.data;
prs_struct *rdata = &p->out_data.rdata;
ZERO_STRUCT(q_u);
ZERO_STRUCT(r_u);
- if(!spoolss_io_q_replycloseprinter("", &q_u, data, 0)) {
- DEBUG(0,("spoolss_io_q_replycloseprinter: unable to unmarshall SPOOL_Q_REPLYCLOSEPRINTER.\n"));
+ if(!spoolss_io_q_xcvdataport("", &q_u, data, 0)) {
+ DEBUG(0,("spoolss_io_q_replyopenprinter: unable to unmarshall SPOOL_Q_XCVDATAPORT.\n"));
return False;
}
- r_u.status = _spoolss_replycloseprinter(p, &q_u, &r_u);
+ r_u.status = _spoolss_xcvdataport(p, &q_u, &r_u);
- if(!spoolss_io_r_replycloseprinter("", &r_u, rdata, 0)) {
- DEBUG(0,("spoolss_io_r_replycloseprinter: unable to marshall SPOOL_R_REPLYCLOSEPRINTER.\n"));
+ if(!spoolss_io_r_xcvdataport("", &r_u, rdata, 0)) {
+ DEBUG(0,("spoolss_io_r_replyopenprinter: unable to marshall SPOOL_R_XCVDATAPORT.\n"));
return False;
}
return True;
}
-#endif
-
/*******************************************************************
\pipe\spoolss commands
********************************************************************/
@@ -1636,11 +1604,8 @@ static BOOL api_spoolss_replycloseprinter(pipes_struct *p)
{"SPOOLSS_GETPRINTPROCESSORDIRECTORY",SPOOLSS_GETPRINTPROCESSORDIRECTORY,api_spoolss_getprintprocessordirectory},
{"SPOOLSS_ADDPRINTERDRIVEREX", SPOOLSS_ADDPRINTERDRIVEREX, api_spoolss_addprinterdriverex },
{"SPOOLSS_DELETEPRINTERDRIVEREX", SPOOLSS_DELETEPRINTERDRIVEREX, api_spoolss_deleteprinterdriverex },
-#if 0
- {"SPOOLSS_REPLYOPENPRINTER", SPOOLSS_REPLYOPENPRINTER, api_spoolss_replyopenprinter },
- {"SPOOLSS_REPLYCLOSEPRINTER", SPOOLSS_REPLYCLOSEPRINTER, api_spoolss_replycloseprinter }
-#endif
- };
+ {"SPOOLSS_XCVDATAPORT", SPOOLSS_XCVDATAPORT, api_spoolss_xcvdataport },
+};
void spoolss_get_pipe_fns( struct api_struct **fns, int *n_fns )
{
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c
index c767daf88ca..cfa0cc7cba9 100644
--- a/source/rpc_server/srv_spoolss_nt.c
+++ b/source/rpc_server/srv_spoolss_nt.c
@@ -435,7 +435,10 @@ static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename
}
/****************************************************************************
- Set printer handle name.
+ Set printer handle name.. Accept names like \\server, \\server\printer,
+ \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
+ the MSDN docs regarding OpenPrinter() for details on the XcvData() and
+ XcvDataPort() interface.
****************************************************************************/
static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
@@ -477,6 +480,14 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
return False;
DEBUGADD(5, ("searching for [%s]\n", aprinter ));
+
+ /* check for the TCPMON interface */
+
+ if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
+ Printer->printer_type = PRINTER_HANDLE_IS_TCPMON;
+ fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
+ found = True;
+ }
/* Search all sharenames first as this is easier than pulling
the printer_info_2 off of disk. Don't use find_service() since
@@ -1473,60 +1484,6 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
}
/********************************************************************
- * spoolss_open_printer
- *
- * If the openprinterex rpc call contains a devmode,
- * it's a per-user one. This per-user devmode is derivated
- * from the global devmode. Openprinterex() contains a per-user
- * devmode for when you do EMF printing and spooling.
- * In the EMF case, the NT workstation is only doing half the job
- * of rendering the page. The other half is done by running the printer
- * driver on the server.
- * The EMF file doesn't contain the page description (paper size, orientation, ...).
- * The EMF file only contains what is to be printed on the page.
- * So in order for the server to know how to print, the NT client sends
- * a devicemode attached to the openprinterex call.
- * But this devicemode is short lived, it's only valid for the current print job.
- *
- * If Samba would have supported EMF spooling, this devicemode would
- * have been attached to the handle, to sent it to the driver to correctly
- * rasterize the EMF file.
- *
- * As Samba only supports RAW spooling, we only receive a ready-to-print file,
- * we just act as a pass-thru between windows and the printer.
- *
- * In order to know that Samba supports only RAW spooling, NT has to call
- * getprinter() at level 2 (attribute field) or NT has to call startdoc()
- * and until NT sends a RAW job, we refuse it.
- *
- * But to call getprinter() or startdoc(), you first need a valid handle,
- * and to get an handle you have to call openprintex(). Hence why you have
- * a devicemode in the openprinterex() call.
- *
- *
- * Differences between NT4 and NT 2000.
- * NT4:
- * ---
- * On NT4, you only have a global devicemode. This global devicemode can be changed
- * by the administrator (or by a user with enough privs). Everytime a user
- * wants to print, the devicemode is resetted to the default. In Word, everytime
- * you print, the printer's characteristics are always reset to the global devicemode.
- *
- * NT 2000:
- * -------
- * In W2K, there is the notion of per-user devicemode. The first time you use
- * a printer, a per-user devicemode is build from the global devicemode.
- * If you change your per-user devicemode, it is saved in the registry, under the
- * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
- * printer preferences available.
- *
- * To change the per-user devicemode: it's the "Printing Preferences ..." button
- * on the General Tab of the printer properties windows.
- *
- * To change the global devicemode: it's the "Printing Defaults..." button
- * on the Advanced Tab of the printer properties window.
- *
- * JFM.
********************************************************************/
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
@@ -1581,10 +1538,15 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
* Second case: the user is opening a printer:
* NT doesn't let us connect to a printer if the connecting user
* doesn't have print permission.
+ *
+ * Third case: user is opening the TCP/IP port monitor
+ * access checks same as opening a handle to the print server.
*/
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ switch (Printer->printer_type )
{
+ case PRINTER_HANDLE_IS_PRINTSERVER:
+ case PRINTER_HANDLE_IS_TCPMON:
/* Printserver handles use global struct... */
snum = -1;
@@ -1642,10 +1604,9 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
/* We fall through to return WERR_OK */
-
- }
- else
- {
+ break;
+
+ case PRINTER_HANDLE_IS_PRINTER:
/* NT doesn't let us connect to a printer if the connecting user
doesn't have print permission. */
@@ -1702,6 +1663,11 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
+ break;
+
+ default:
+ /* sanity check to prevent programmer error */
+ return WERR_BADFID;
}
Printer->access_granted = printer_default->access_required;
@@ -8496,18 +8462,22 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- PRINTMONITOR_1 *info_1=NULL;
+ PRINTMONITOR_1 *info_1;
WERROR result = WERR_OK;
+ int i;
- if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
+ if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
return WERR_NOMEM;
- (*returned) = 0x1;
+ *returned = 2;
- init_unistr(&info_1->name, "Local Port");
-
- *needed += spoolss_size_printmonitor_info_1(info_1);
+ init_unistr(&(info_1[0].name), "Local Port");
+ init_unistr(&(info_1[1].name), "Standard TCP/IP Port");
+ for ( i=0; i<*returned; i++ ) {
+ *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
+ }
+
if (*needed > offered) {
result = WERR_INSUFFICIENT_BUFFER;
goto out;
@@ -8518,7 +8488,9 @@ static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint
goto out;
}
- smb_io_printmonitor_info_1("", buffer, info_1, 0);
+ for ( i=0; i<*returned; i++ ) {
+ smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
+ }
out:
SAFE_FREE(info_1);
@@ -8535,20 +8507,27 @@ out:
static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
{
- PRINTMONITOR_2 *info_2=NULL;
+ PRINTMONITOR_2 *info_2;
WERROR result = WERR_OK;
+ int i;
- if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
+ if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
return WERR_NOMEM;
- (*returned) = 0x1;
+ *returned = 2;
- init_unistr(&info_2->name, "Local Port");
- init_unistr(&info_2->environment, "Windows NT X86");
- init_unistr(&info_2->dll_name, "localmon.dll");
-
- *needed += spoolss_size_printmonitor_info_2(info_2);
+ init_unistr(&(info_2[0].name), "Local Port");
+ init_unistr(&(info_2[0].environment), "Windows NT X86");
+ init_unistr(&(info_2[0].dll_name), "localmon.dll");
+
+ init_unistr(&(info_2[1].name), "Standard TCP/IP Port");
+ init_unistr(&(info_2[1].environment), "Windows NT X86");
+ init_unistr(&(info_2[1].dll_name), "tcpmon.dll");
+ for ( i=0; i<*returned; i++ ) {
+ *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
+ }
+
if (*needed > offered) {
result = WERR_INSUFFICIENT_BUFFER;
goto out;
@@ -8559,7 +8538,9 @@ static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint
goto out;
}
- smb_io_printmonitor_info_2("", buffer, info_2, 0);
+ for ( i=0; i<*returned; i++ ) {
+ smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
+ }
out:
SAFE_FREE(info_2);
@@ -9398,23 +9379,9 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
return result;
}
-#if 0
-
-WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
- SPOOL_R_REPLYOPENPRINTER *r_u)
+WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
{
- DEBUG(5,("_spoolss_replyopenprinter\n"));
-
- DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
-
return WERR_OK;
}
-WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
- SPOOL_R_REPLYCLOSEPRINTER *r_u)
-{
- DEBUG(5,("_spoolss_replycloseprinter\n"));
- return WERR_OK;
-}
-#endif