1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-09 08:58:35 +03:00

Proper merge of all the working printing stuff from APPLIANCE_HEAD.

Now let's keep this in sync !
Jeremy.
This commit is contained in:
Jeremy Allison -
parent b5bc8aa0f6
commit 3603cd4947
14 changed files with 1489 additions and 1067 deletions

View File

@ -171,7 +171,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
LIBMSRPC_OBJ = libsmb/cli_lsarpc.o libsmb/cli_samr.o libsmb/cli_spoolss.o \ LIBMSRPC_OBJ = libsmb/cli_lsarpc.o libsmb/cli_samr.o libsmb/cli_spoolss.o \
libsmb/cli_netlogon.o libsmb/cli_srvsvc.o libsmb/cli_wkssvc.o \ libsmb/cli_netlogon.o libsmb/cli_srvsvc.o libsmb/cli_wkssvc.o \
libsmb/cli_dfs.o libsmb/cli_reg.o libsmb/trust_passwd.o\ libsmb/cli_dfs.o libsmb/cli_reg.o libsmb/trust_passwd.o\
rpc_client/cli_pipe.o rpc_client/cli_pipe.o libsmb/cli_spoolss_notify.o
LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po) LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po)
@ -196,8 +196,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o
RPC_CLIENT_OBJ = rpc_client/cli_pipe.o \ RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
rpc_client/cli_spoolss_notify.o
LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o LOCKING_OBJ = locking/locking.o locking/brlock.o locking/posix.o
@ -242,7 +241,6 @@ SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \ printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \
smbd/build_options.o \ smbd/build_options.o \
smbd/change_trust_pw.o \ smbd/change_trust_pw.o \
rpc_client/cli_spoolss_notify.o \
$(MANGLE_OBJ) $(MANGLE_OBJ)
@ -250,7 +248,7 @@ PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
printing/print_cups.o printing/print_generic.o \ printing/print_cups.o printing/print_generic.o \
printing/lpq_parse.o printing/load.o printing/lpq_parse.o printing/load.o
PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o printing/notify.o
MSDFS_OBJ = msdfs/msdfs.o MSDFS_OBJ = msdfs/msdfs.o
@ -301,7 +299,7 @@ STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ)
SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) printing/notify.o
SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \ SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \
$(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ)

View File

@ -167,6 +167,7 @@
#define WERR_INVALID_OWNER W_ERROR(1307) #define WERR_INVALID_OWNER W_ERROR(1307)
#define WERR_CAN_NOT_COMPLETE W_ERROR(1003) #define WERR_CAN_NOT_COMPLETE W_ERROR(1003)
#define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338) #define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
#define WERR_SERVER_UNAVAILABLE W_ERROR(1722)
#define WERR_UNKNOWN_PRINTER_DRIVER W_ERROR(1797) #define WERR_UNKNOWN_PRINTER_DRIVER W_ERROR(1797)
#define WERR_INVALID_PRINTER_NAME W_ERROR(1801) #define WERR_INVALID_PRINTER_NAME W_ERROR(1801)
#define WERR_PRINTER_ALREADY_EXISTS W_ERROR(1802) #define WERR_PRINTER_ALREADY_EXISTS W_ERROR(1802)

View File

@ -47,10 +47,10 @@
#define MSG_FORCE_ELECTION 1001 #define MSG_FORCE_ELECTION 1001
#define MSG_WINS_NEW_ENTRY 1002 #define MSG_WINS_NEW_ENTRY 1002
/* rpc messages */ /* printing messages */
#define MSG_PRINTER_NOTIFY 2001 /* #define MSG_PRINTER_NOTIFY 2001*/ /* Obsolete */
#define MSG_PRINTER_DRVUPGRADE 2002 #define MSG_PRINTER_DRVUPGRADE 2002
#define MSG_PRINTER_UPDATE 2003 #define MSG_PRINTER_NOTIFY2 2003
/* smbd messages */ /* smbd messages */
#define MSG_SMB_CONF_UPDATED 3001 #define MSG_SMB_CONF_UPDATED 3001

View File

@ -1,5 +1,6 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-2000, Copyright (C) Andrew Tridgell 1992-2000,
Copyright (C) Jean Francois Micouleau 1998-2000. Copyright (C) Jean Francois Micouleau 1998-2000.
@ -331,4 +332,23 @@ typedef struct _form
#define VS_VERSION_INFO_SIZE (sizeof(VS_SIGNATURE)+4+VS_MINOR_OFFSET+4) /* not true size! */ #define VS_VERSION_INFO_SIZE (sizeof(VS_SIGNATURE)+4+VS_MINOR_OFFSET+4) /* not true size! */
#define VS_NE_BUF_SIZE 4096 /* Must be > 2*VS_VERSION_INFO_SIZE */ #define VS_NE_BUF_SIZE 4096 /* Must be > 2*VS_VERSION_INFO_SIZE */
/* Notify spoolss clients that something has changed. The
notification data is either stored in two uint32 values or a
variable length array. */
#define SPOOLSS_NOTIFY_MSG_UNIX_JOBID 0x0001 /* Job id is unix */
struct spoolss_notify_msg {
fstring printer; /* Name of printer notified */
uint32 type; /* Printer or job notify */
uint32 field; /* Notify field changed */
uint32 id; /* Job id */
uint32 len; /* Length of data, 0 for two uint32 value */
uint32 flags;
union {
uint32 value[2];
char *data;
} notify;
};
#endif /* NT_PRINTING_H_ */ #endif /* NT_PRINTING_H_ */

View File

@ -1,5 +1,6 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-2000, Copyright (C) Andrew Tridgell 1992-2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-2000, Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
@ -117,6 +118,7 @@
#define PRINTER_CONTROL_PURGE 0x00000003 #define PRINTER_CONTROL_PURGE 0x00000003
#define PRINTER_CONTROL_SET_STATUS 0x00000004 #define PRINTER_CONTROL_SET_STATUS 0x00000004
#define PRINTER_STATUS_OK 0x00000000
#define PRINTER_STATUS_PAUSED 0x00000001 #define PRINTER_STATUS_PAUSED 0x00000001
#define PRINTER_STATUS_ERROR 0x00000002 #define PRINTER_STATUS_ERROR 0x00000002
#define PRINTER_STATUS_PENDING_DELETION 0x00000004 #define PRINTER_STATUS_PENDING_DELETION 0x00000004
@ -157,17 +159,18 @@
/* JOB status codes. */ /* JOB status codes. */
#define JOB_STATUS_PAUSED 0x001 #define JOB_STATUS_QUEUED 0x0000
#define JOB_STATUS_ERROR 0x002 #define JOB_STATUS_PAUSED 0x0001
#define JOB_STATUS_DELETING 0x004 #define JOB_STATUS_ERROR 0x0002
#define JOB_STATUS_SPOOLING 0x008 #define JOB_STATUS_DELETING 0x0004
#define JOB_STATUS_PRINTING 0x010 #define JOB_STATUS_SPOOLING 0x0008
#define JOB_STATUS_OFFLINE 0x020 #define JOB_STATUS_PRINTING 0x0010
#define JOB_STATUS_PAPEROUT 0x040 #define JOB_STATUS_OFFLINE 0x0020
#define JOB_STATUS_PRINTED 0x080 #define JOB_STATUS_PAPEROUT 0x0040
#define JOB_STATUS_DELETED 0x100 #define JOB_STATUS_PRINTED 0x0080
#define JOB_STATUS_BLOCKED 0x200 #define JOB_STATUS_DELETED 0x0100
#define JOB_STATUS_USER_INTERVENTION 0x400 #define JOB_STATUS_BLOCKED 0x0200
#define JOB_STATUS_USER_INTERVENTION 0x0400
/* ACE masks for the various print permissions */ /* ACE masks for the various print permissions */
@ -194,11 +197,12 @@
#define JOB_WRITE STANDARD_RIGHTS_WRITE_ACCESS|JOB_ACCESS_ADMINISTER #define JOB_WRITE STANDARD_RIGHTS_WRITE_ACCESS|JOB_ACCESS_ADMINISTER
#define JOB_EXECUTE STANDARD_RIGHTS_EXECUTE_ACCESS|JOB_ACCESS_ADMINISTER #define JOB_EXECUTE STANDARD_RIGHTS_EXECUTE_ACCESS|JOB_ACCESS_ADMINISTER
/* Print notification constants */ /* Notify field types */
#define ONE_VALUE 1 #define ONE_VALUE 1 /* Notify data is stored in value1 */
#define TWO_VALUE 2 #define TWO_VALUE 2 /* Notify data is stored in value2 */
#define POINTER 3 #define POINTER 3 /* Data is a pointer to a buffer */
#define STRING 4 /* Data is a pointer to a buffer w/length */
#define PRINTER_NOTIFY_TYPE 0x00 #define PRINTER_NOTIFY_TYPE 0x00
#define JOB_NOTIFY_TYPE 0x01 #define JOB_NOTIFY_TYPE 0x01
@ -315,8 +319,6 @@
#define PRINTER_NOTIFY_INFO_DISCARDED 0x1 #define PRINTER_NOTIFY_INFO_DISCARDED 0x1
#define PRINTER_NOTIFY_VERSION 0x2
/* /*
* Set of macros for flagging what changed in the PRINTER_INFO_2 struct * Set of macros for flagging what changed in the PRINTER_INFO_2 struct
* when sending messages to other smbd's * when sending messages to other smbd's
@ -1203,8 +1205,8 @@ typedef struct job_info_ctr_info
{ {
union union
{ {
JOB_INFO_1 *job_info_1; JOB_INFO_1 **job_info_1;
JOB_INFO_2 *job_info_2; JOB_INFO_2 **job_info_2;
void *info; void *info;
} job; } job;
@ -2118,3 +2120,4 @@ SPOOL_R_GETPRINTPROCESSORDIRECTORY;
#define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86" #define PRINTER_DRIVER_ARCHITECTURE "Windows NT x86"
#endif /* _RPC_SPOOLSS_H */ #endif /* _RPC_SPOOLSS_H */

View File

@ -1556,11 +1556,11 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
switch(level) { switch(level) {
case 1: case 1:
decode_jobs_1(mem_ctx, r.buffer, r.returned, decode_jobs_1(mem_ctx, r.buffer, r.returned,
&ctr->job.job_info_1); ctr->job.job_info_1);
break; break;
case 2: case 2:
decode_jobs_2(mem_ctx, r.buffer, r.returned, decode_jobs_2(mem_ctx, r.buffer, r.returned,
&ctr->job.job_info_2); ctr->job.job_info_2);
break; break;
default: default:
DEBUG(3, ("unsupported info level %d", level)); DEBUG(3, ("unsupported info level %d", level));
@ -1669,10 +1669,10 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
switch(level) { switch(level) {
case 1: case 1:
decode_jobs_1(mem_ctx, r.buffer, 1, &ctr->job.job_info_1); decode_jobs_1(mem_ctx, r.buffer, 1, ctr->job.job_info_1);
break; break;
case 2: case 2:
decode_jobs_2(mem_ctx, r.buffer, 1, &ctr->job.job_info_2); decode_jobs_2(mem_ctx, r.buffer, 1, ctr->job.job_info_2);
break; break;
default: default:
DEBUG(3, ("unsupported info level %d", level)); DEBUG(3, ("unsupported info level %d", level));

View File

@ -0,0 +1,223 @@
/*
Unix SMB/CIFS implementation.
RPC pipe client
Copyright (C) Gerald Carter 2001-2002,
Copyright (C) Tim Potter 2000-2002,
Copyright (C) Andrew Tridgell 1994-2000,
Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
Copyright (C) Jean-Francois Micouleau 1999-2000.
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/*
* SPOOLSS Client RPC's used by servers as the notification
* back channel.
*/
/* Send a ReplyOpenPrinter request. This rpc is made by the printer
server to the printer client in response to a rffpcnex request.
The rrfpcnex request names a printer and a handle (the printerlocal
value) and this rpc establishes a back-channel over which printer
notifications are performed. */
WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
char *printer, uint32 printerlocal, uint32 type,
POLICY_HND *handle)
{
prs_struct qbuf, rbuf;
SPOOL_Q_REPLYOPENPRINTER q;
SPOOL_R_REPLYOPENPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
/* Initialise input parameters */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
/* Marshall data and send request */
if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0))
goto done;
/* Return result */
memcpy(handle, &r.handle, sizeof(r.handle));
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/* Close a back-channel notification connection */
WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *handle)
{
prs_struct qbuf, rbuf;
SPOOL_Q_REPLYCLOSEPRINTER q;
SPOOL_R_REPLYCLOSEPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
/* Initialise input parameters */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
make_spoolss_q_reply_closeprinter(&q, handle);
/* Marshall data and send request */
if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0))
goto done;
/* Return result */
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/*********************************************************************
This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
notification event when the registration **did not** use
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor.
Also see cli_spolss_reply_rrpcn()
*********************************************************************/
WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 condition, uint32 change_id)
{
prs_struct qbuf, rbuf;
SPOOL_Q_ROUTERREPLYPRINTER q;
SPOOL_R_ROUTERREPLYPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
/* Initialise input parameters */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
/* Marshall data and send request */
if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) ||
!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0))
goto done;
/* Return output parameters */
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/*********************************************************************
This SPOOLSS_REPLY_RRPCN function is used to send a change
notification event when the registration **did** use
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
Also see cli_spoolss_routereplyprinter()
*********************************************************************/
WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 notify_data_len,
SPOOL_NOTIFY_INFO_DATA *notify_data,
uint32 change_low, uint32 change_high)
{
prs_struct qbuf, rbuf;
SPOOL_Q_REPLY_RRPCN q;
SPOOL_R_REPLY_RRPCN r;
WERROR result = W_ERROR(ERRgeneral);
SPOOL_NOTIFY_INFO notify_info;
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise parse structures */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
ZERO_STRUCT(notify_info);
/* Initialise input parameters */
notify_info.version = 0x2;
notify_info.flags = 0x00020000; /* ?? */
notify_info.count = notify_data_len;
notify_info.data = notify_data;
/* create and send a MSRPC command with api */
/* store the parameters */
make_spoolss_q_reply_rrpcn(&q, pol, change_low, change_high,
&notify_info);
/* Marshall data and send request */
if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) ||
!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0))
goto done;
if (r.unknown0 == 0x00080000)
DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}

230
source/printing/notify.c Normal file
View File

@ -0,0 +1,230 @@
/*
Unix SMB/Netbios implementation.
Version 2.2
printing backend routines
Copyright (C) Tim Potter, 2002
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "printing.h"
/*
* Print notification routines
*/
static void send_spoolss_notify2_msg(struct spoolss_notify_msg *msg)
{
char *buf = NULL;
int buflen = 0, len;
TDB_CONTEXT *tdb;
/* Let's not waste any time with this */
if (lp_disable_spoolss())
return;
/* Flatten data into a message */
again:
len = 0;
/* Pack header */
len += tdb_pack(buf + len, buflen - len, "f", msg->printer);
len += tdb_pack(buf + len, buflen - len, "ddddd",
msg->type, msg->field, msg->id, msg->len, msg->flags);
/* Pack data */
if (msg->len == 0)
len += tdb_pack(buf + len, buflen - len, "dd",
msg->notify.value[0], msg->notify.value[1]);
else
len += tdb_pack(buf + len, buflen - len, "B",
msg->len, msg->notify.data);
if (buflen != len) {
buf = Realloc(buf, len);
buflen = len;
goto again;
}
/* Send message */
tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_DEFAULT, O_RDONLY, 0);
if (!tdb) {
DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n"));
return;
}
message_send_all(tdb, MSG_PRINTER_NOTIFY2, buf,
buflen, False, NULL);
SAFE_FREE(buf);
tdb_close(tdb);
}
static void send_notify_field_values(const char *printer_name, uint32 type,
uint32 field, uint32 id, uint32 value1,
uint32 value2, uint32 flags)
{
struct spoolss_notify_msg msg;
ZERO_STRUCT(msg);
fstrcpy(msg.printer, printer_name);
msg.type = type;
msg.field = field;
msg.id = id;
msg.notify.value[0] = value1;
msg.notify.value[1] = value2;
msg.flags = flags;
send_spoolss_notify2_msg(&msg);
}
static void send_notify_field_buffer(const char *printer_name, uint32 type,
uint32 field, uint32 id, uint32 len,
char *buffer)
{
struct spoolss_notify_msg msg;
ZERO_STRUCT(msg);
fstrcpy(msg.printer, printer_name);
msg.type = type;
msg.field = field;
msg.id = id;
msg.len = len;
msg.notify.data = buffer;
send_spoolss_notify2_msg(&msg);
}
/* Send a message that the printer status has changed */
void notify_printer_status_byname(char *printer_name, uint32 status)
{
/* Printer status stored in value1 */
send_notify_field_values(printer_name, PRINTER_NOTIFY_TYPE,
PRINTER_NOTIFY_STATUS, 0,
status, 0, 0);
}
void notify_printer_status(int snum, uint32 status)
{
char *printer_name = PRINTERNAME(snum);
if (printer_name)
notify_printer_status_byname(printer_name, status);
}
void notify_job_status_byname(char *printer_name, uint32 jobid, uint32 status,
uint32 flags)
{
/* Job id stored in id field, status in value1 */
send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
JOB_NOTIFY_STATUS, jobid,
status, 0, flags);
}
void notify_job_status(int snum, uint32 jobid, uint32 status)
{
char *printer_name = PRINTERNAME(snum);
notify_job_status_byname(printer_name, jobid, status, 0);
}
void notify_job_total_bytes(int snum, uint32 jobid, uint32 size)
{
char *printer_name = PRINTERNAME(snum);
/* Job id stored in id field, status in value1 */
send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
JOB_NOTIFY_TOTAL_BYTES, jobid,
size, 0, 0);
}
void notify_job_total_pages(int snum, uint32 jobid, uint32 pages)
{
char *printer_name = PRINTERNAME(snum);
/* Job id stored in id field, status in value1 */
send_notify_field_values(printer_name, JOB_NOTIFY_TYPE,
JOB_NOTIFY_TOTAL_PAGES, jobid,
pages, 0, 0);
}
void notify_job_username(int snum, uint32 jobid, char *name)
{
char *printer_name = PRINTERNAME(snum);
send_notify_field_buffer(
printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME,
jobid, strlen(name) + 1, name);
}
void notify_job_name(int snum, uint32 jobid, char *name)
{
char *printer_name = PRINTERNAME(snum);
send_notify_field_buffer(
printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT,
jobid, strlen(name) + 1, name);
}
void notify_job_submitted(int snum, uint32 jobid, time_t submitted)
{
char *printer_name = PRINTERNAME(snum);
send_notify_field_buffer(
printer_name, JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED,
jobid, sizeof(submitted), (char *)&submitted);
}
void notify_printer_delete(char *printer_name)
{
}
void notify_printer_add(char *printer_name)
{
}
void notify_printer_driver(int num, char *driver_name)
{
}
void notify_printer_comment(int num, char *comment)
{
}
void notify_printer_sharename(int num, char *share_name)
{
}
void notify_printer_port(int num, char *port_name)
{
}
void notify_printer_location(int num, char *location)
{
}

View File

@ -1,5 +1,6 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/Netbios implementation.
Version 3.0
printing backend routines printing backend routines
Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Andrew Tridgell 1992-2000
@ -56,7 +57,7 @@ BOOL print_backend_init(void)
return True; return True;
tdb = tdb_open_log(lock_path("printing.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); tdb = tdb_open_log(lock_path("printing.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
if (!tdb) { if (!tdb) {
DEBUG(0,("print_backend_init: Failed to open printing backend database %s\n", DEBUG(0,("print_backend_init: Failed to open printing backend database %s.\n",
lock_path("printing.tdb") )); lock_path("printing.tdb") ));
return False; return False;
} }
@ -113,21 +114,178 @@ static struct printjob *print_job_find(int jobid)
return &pjob; return &pjob;
} }
/* Convert a unix jobid to a smb jobid */
static int sysjob_to_jobid_value;
static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
TDB_DATA data, void *state)
{
struct printjob *pjob = (struct printjob *)data.dptr;
int *sysjob = (int *)state;
if (key.dsize != sizeof(int))
return 0;
if (*sysjob == pjob->sysjob) {
int *jobid = (int *)key.dptr;
sysjob_to_jobid_value = *jobid;
return 1;
}
return 0;
}
int sysjob_to_jobid(int unix_jobid)
{
sysjob_to_jobid_value = -1;
tdb_traverse(tdb, unixjob_traverse_fn, &unix_jobid);
return sysjob_to_jobid_value;
}
/****************************************************************************
send notifications based on what has changed after a pjob_store
****************************************************************************/
static struct {
uint32 lpq_status;
uint32 spoolss_status;
} lpq_to_spoolss_status_map[] = {
{ LPQ_QUEUED, JOB_STATUS_QUEUED },
{ LPQ_PAUSED, JOB_STATUS_PAUSED },
{ LPQ_SPOOLING, JOB_STATUS_SPOOLING },
{ LPQ_PRINTING, JOB_STATUS_PRINTING },
{ LPQ_DELETING, JOB_STATUS_DELETING },
{ LPQ_OFFLINE, JOB_STATUS_OFFLINE },
{ LPQ_PAPEROUT, JOB_STATUS_PAPEROUT },
{ LPQ_PRINTED, JOB_STATUS_PRINTED },
{ LPQ_DELETED, JOB_STATUS_DELETED },
{ LPQ_BLOCKED, JOB_STATUS_BLOCKED },
{ LPQ_USER_INTERVENTION, JOB_STATUS_USER_INTERVENTION },
{ -1, 0 }
};
/* Convert a lpq status value stored in printing.tdb into the
appropriate win32 API constant. */
static uint32 map_to_spoolss_status(uint32 lpq_status)
{
int i = 0;
while (lpq_to_spoolss_status_map[i].lpq_status != -1) {
if (lpq_to_spoolss_status_map[i].lpq_status == lpq_status)
return lpq_to_spoolss_status_map[i].spoolss_status;
i++;
}
return 0;
}
static void pjob_store_notify(int jobid, struct printjob *old_data,
struct printjob *new_data)
{
BOOL new_job = False;
int snum = print_job_snum(jobid);
if (snum == -1)
return;
if (!old_data)
new_job = True;
/* Notify the job name first */
if (new_job || !strequal(old_data->jobname, new_data->jobname))
notify_job_name(snum, jobid, new_data->jobname);
/* Job attributes that can't be changed. We only send
notification for these on a new job. */
if (new_job) {
notify_job_submitted(snum, jobid, new_data->starttime);
notify_job_username(snum, jobid, new_data->user);
}
/* Job attributes of a new job or attributes that can be
modified. */
if (new_job || old_data->status != new_data->status)
notify_job_status(snum, jobid, map_to_spoolss_status(new_data->status));
if (new_job || old_data->size != new_data->size)
notify_job_total_bytes(snum, jobid, new_data->size);
if (new_job || old_data->page_count != new_data->page_count)
notify_job_total_pages(snum, jobid, new_data->page_count);
}
/**************************************************************************** /****************************************************************************
Store a job structure back to the database. Store a job structure back to the database.
****************************************************************************/ ****************************************************************************/
static BOOL print_job_store(int jobid, struct printjob *pjob) static BOOL pjob_store(int jobid, struct printjob *pjob)
{ {
TDB_DATA d; TDB_DATA old_data, new_data;
BOOL ret; BOOL ret;
d.dptr = (void *)pjob; /* Get old data */
d.dsize = sizeof(*pjob);
ret = (tdb_store(tdb, print_key(jobid), d, TDB_REPLACE) == 0); old_data = tdb_fetch(tdb, print_key(jobid));
/* Store new data */
new_data.dptr = (void *)pjob;
new_data.dsize = sizeof(*pjob);
ret = (tdb_store(tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
/* Send notify updates for what has changed */
if (ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob))) {
pjob_store_notify(
jobid, (struct printjob *)old_data.dptr,
(struct printjob *)new_data.dptr);
free(old_data.dptr);
}
return ret; return ret;
} }
/****************************************************************************
remove a job structure from the database
****************************************************************************/
static void pjob_delete(int jobid)
{
int snum;
struct printjob *pjob = print_job_find(jobid);
uint32 job_status = 0;
if (!pjob) {
DEBUG(5, ("pjob_delete(): we were asked to delete nonexistent job %d\n", jobid));
return;
}
/* Send a notification that a job has been deleted */
job_status = map_to_spoolss_status(pjob->status);
/* We must cycle through JOB_STATUS_DELETING and
JOB_STATUS_DELETED for the port monitor to delete the job
properly. */
snum = print_job_snum(jobid);
job_status |= JOB_STATUS_DELETING;
notify_job_status(snum, jobid, job_status);
job_status |= JOB_STATUS_DELETED;
notify_job_status(snum, jobid, job_status);
/* Remove from printing.tdb */
tdb_delete(tdb, print_key(jobid));
}
/**************************************************************************** /****************************************************************************
Parse a file name from the system spooler to generate a jobid. Parse a file name from the system spooler to generate a jobid.
****************************************************************************/ ****************************************************************************/
@ -175,7 +333,7 @@ static void print_unix_job(int snum, print_queue_struct *q)
fstrcpy(pj.user, q->fs_user); fstrcpy(pj.user, q->fs_user);
fstrcpy(pj.queuename, lp_servicename(snum)); fstrcpy(pj.queuename, lp_servicename(snum));
print_job_store(jobid, &pj); pjob_store(jobid, &pj);
} }
@ -213,7 +371,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
break; break;
} }
if (i == ts->qcount) if (i == ts->qcount)
tdb_delete(tdb, key); pjob_delete(jobid);
else else
ts->total_jobs++; ts->total_jobs++;
return 0; return 0;
@ -225,7 +383,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
exist then kill it. This cleans up after smbd exist then kill it. This cleans up after smbd
deaths */ deaths */
if (!process_exists(pjob.pid)) if (!process_exists(pjob.pid))
tdb_delete(tdb, key); pjob_delete(jobid);
else else
ts->total_jobs++; ts->total_jobs++;
return 0; return 0;
@ -252,7 +410,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
submitted less than lp_lpqcachetime() seconds ago. */ submitted less than lp_lpqcachetime() seconds ago. */
if ((cur_t - pjob.starttime) > lp_lpqcachetime()) if ((cur_t - pjob.starttime) > lp_lpqcachetime())
tdb_delete(t, key); pjob_delete(jobid);
else else
ts->total_jobs++; ts->total_jobs++;
} }
@ -328,24 +486,10 @@ static void set_updating_pid(fstring printer_name, BOOL delete)
} }
/**************************************************************************** /****************************************************************************
Send a message saying the queue changed. update the internal database from the system print queue for a queue
****************************************************************************/ ****************************************************************************/
static void send_queue_message(const char *printer_name, uint32 high, uint32 low) static void print_queue_update(int snum)
{
char msg[8 + sizeof(fstring)];
SIVAL(msg,0,low);
SIVAL(msg,4,high);
fstrcpy(&msg[8], printer_name);
message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, 8 + strlen(printer_name) + 1, False, NULL);
}
/****************************************************************************
Update the internal database from the system print queue for a queue in the background
****************************************************************************/
static void print_queue_update_background(int snum)
{ {
int i, qcount; int i, qcount;
print_queue_struct *queue = NULL; print_queue_struct *queue = NULL;
@ -356,6 +500,8 @@ static void print_queue_update_background(int snum)
fstring keystr, printer_name, cachestr; fstring keystr, printer_name, cachestr;
TDB_DATA data, key; TDB_DATA data, key;
/* Convert printer name (i.e. share name) to unix-codepage for all of the
* following tdb key generation */
fstrcpy(printer_name, lp_servicename(snum)); fstrcpy(printer_name, lp_servicename(snum));
/* /*
@ -448,7 +594,7 @@ static void print_queue_update_background(int snum)
pjob->sysjob = queue[i].job; pjob->sysjob = queue[i].job;
pjob->status = queue[i].status; pjob->status = queue[i].status;
print_job_store(jobid, pjob); pjob_store(jobid, pjob);
} }
/* now delete any queued entries that don't appear in the /* now delete any queued entries that don't appear in the
@ -460,21 +606,12 @@ static void print_queue_update_background(int snum)
tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct); tdb_traverse(tdb, traverse_fn_delete, (void *)&tstruct);
safe_free(tstruct.queue); SAFE_FREE(tstruct.queue);
tdb_store_int32(tdb, "INFO/total_jobs", tstruct.total_jobs); tdb_store_int32(tdb, "INFO/total_jobs", tstruct.total_jobs);
/* if( qcount != get_queue_status(snum, &old_status))
* Get the old print status. We will use this to compare the DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n", old_status.qcount, qcount, printer_name ));
* number of jobs. If they have changed we need to send a
* "changed" message to the smbds.
*/
if( qcount != get_queue_status(snum, &old_status)) {
DEBUG(10,("print_queue_update: queue status change %d jobs -> %d jobs for printer %s\n",
old_status.qcount, qcount, printer_name ));
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
}
/* store the new queue status structure */ /* store the new queue status structure */
slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printer_name); slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", printer_name);
@ -492,74 +629,12 @@ static void print_queue_update_background(int snum)
*/ */
slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", printer_name); slprintf(keystr, sizeof(keystr)-1, "CACHE/%s", printer_name);
tdb_store_int32(tdb, keystr, (int)time(NULL)); tdb_store_int32(tdb, keystr, (int32)time(NULL));
/* Delete our pid from the db. */ /* Delete our pid from the db. */
set_updating_pid(printer_name, True); set_updating_pid(printer_name, True);
} }
/****************************************************************************
This is the receive function of the background lpq updater.
****************************************************************************/
static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t len)
{
int snum;
snum=*((int *)buf);
print_queue_update_background(snum);
}
static pid_t background_lpq_updater_pid;
/****************************************************************************
Main thread of the background lpq updater.
****************************************************************************/
void start_background_queue(void)
{
DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
background_lpq_updater_pid = sys_fork();
if (background_lpq_updater_pid == -1) {
DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
exit(1);
}
if(background_lpq_updater_pid == 0) {
/* Child. */
DEBUG(5,("start_background_queue: background LPQ thread started\n"));
claim_connection(NULL,"smbd lpq backend",0,False);
if (!locking_init(0))
exit(1);
if (!print_backend_init())
exit(1);
message_register(MSG_PRINTER_UPDATE, print_queue_receive);
DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
while (1) {
pause();
DEBUG(10,("start_background_queue: background LPQ thread got a message\n"));
message_dispatch();
}
}
}
/****************************************************************************
Update the internal database from the system print queue for a queue.
****************************************************************************/
static void print_queue_update(int snum)
{
if (background_lpq_updater_pid > 0) {
message_send_pid(background_lpq_updater_pid, MSG_PRINTER_UPDATE,
&snum, sizeof(snum), False);
}
}
/**************************************************************************** /****************************************************************************
Check if a jobid is valid. It is valid if it exists in the database. Check if a jobid is valid. It is valid if it exists in the database.
****************************************************************************/ ****************************************************************************/
@ -634,7 +709,7 @@ BOOL print_job_set_name(int jobid, char *name)
return False; return False;
fstrcpy(pjob->jobname, name); fstrcpy(pjob->jobname, name);
return print_job_store(jobid, pjob); return pjob_store(jobid, pjob);
} }
/**************************************************************************** /****************************************************************************
@ -672,7 +747,7 @@ static BOOL print_job_delete1(int jobid)
/* Set the tdb entry to be deleting. */ /* Set the tdb entry to be deleting. */
pjob->status = LPQ_DELETING; pjob->status = LPQ_DELETING;
print_job_store(jobid, pjob); pjob_store(jobid, pjob);
if (pjob->spooled && pjob->sysjob != -1) if (pjob->spooled && pjob->sysjob != -1)
result = (*(current_printif->job_delete))(snum, pjob); result = (*(current_printif->job_delete))(snum, pjob);
@ -680,9 +755,8 @@ static BOOL print_job_delete1(int jobid)
/* Delete the tdb entry if the delete suceeded or the job hasn't /* Delete the tdb entry if the delete suceeded or the job hasn't
been spooled. */ been spooled. */
if (result == 0) { if (result == 0)
tdb_delete(tdb, print_key(jobid)); pjob_delete(jobid);
}
return (result == 0); return (result == 0);
} }
@ -713,7 +787,6 @@ static BOOL is_owner(struct current_user *user, int jobid)
BOOL print_job_delete(struct current_user *user, int jobid, WERROR *errcode) BOOL print_job_delete(struct current_user *user, int jobid, WERROR *errcode)
{ {
int snum = print_job_snum(jobid); int snum = print_job_snum(jobid);
char *printer_name;
BOOL owner; BOOL owner;
if (snum == -1) { if (snum == -1) {
@ -741,12 +814,6 @@ BOOL print_job_delete(struct current_user *user, int jobid, WERROR *errcode)
print_queue_update(snum); print_queue_update(snum);
/* Send a printer notify message */
printer_name = PRINTERNAME(snum);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
return !print_job_exists(jobid); return !print_job_exists(jobid);
} }
@ -758,7 +825,6 @@ BOOL print_job_pause(struct current_user *user, int jobid, WERROR *errcode)
{ {
struct printjob *pjob = print_job_find(jobid); struct printjob *pjob = print_job_find(jobid);
int snum, ret = -1; int snum, ret = -1;
char *printer_name;
if (!pjob || !user) if (!pjob || !user)
return False; return False;
@ -771,10 +837,6 @@ BOOL print_job_pause(struct current_user *user, int jobid, WERROR *errcode)
DEBUG(5,("print_job_pause: unknown service number for jobid %d\n", jobid)); DEBUG(5,("print_job_pause: unknown service number for jobid %d\n", jobid));
return False; return False;
} }
if (snum == -1) {
DEBUG(5,("print_job_resume: unknown service number for jobid %d\n", jobid));
return False;
}
if (!is_owner(user, jobid) && if (!is_owner(user, jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
@ -796,9 +858,7 @@ BOOL print_job_pause(struct current_user *user, int jobid, WERROR *errcode)
/* Send a printer notify message */ /* Send a printer notify message */
printer_name = PRINTERNAME(snum); notify_job_status(snum, jobid, JOB_STATUS_PAUSED);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
/* how do we tell if this succeeded? */ /* how do we tell if this succeeded? */
@ -812,7 +872,6 @@ BOOL print_job_pause(struct current_user *user, int jobid, WERROR *errcode)
BOOL print_job_resume(struct current_user *user, int jobid, WERROR *errcode) BOOL print_job_resume(struct current_user *user, int jobid, WERROR *errcode)
{ {
struct printjob *pjob = print_job_find(jobid); struct printjob *pjob = print_job_find(jobid);
char *printer_name;
int snum, ret; int snum, ret;
if (!pjob || !user) if (!pjob || !user)
@ -822,6 +881,10 @@ BOOL print_job_resume(struct current_user *user, int jobid, WERROR *errcode)
return False; return False;
snum = print_job_snum(jobid); snum = print_job_snum(jobid);
if (snum == -1) {
DEBUG(5,("print_job_resume: unknown service number for jobid %d\n", jobid));
return False;
}
if (!is_owner(user, jobid) && if (!is_owner(user, jobid) &&
!print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) { !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
@ -842,9 +905,7 @@ BOOL print_job_resume(struct current_user *user, int jobid, WERROR *errcode)
/* Send a printer notify message */ /* Send a printer notify message */
printer_name = PRINTERNAME(snum); notify_job_status(snum, jobid, JOB_STATUS_QUEUED);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
return True; return True;
} }
@ -867,7 +928,7 @@ int print_job_write(int jobid, const char *buf, int size)
return_code = write(pjob->fd, buf, size); return_code = write(pjob->fd, buf, size);
if (return_code>0) { if (return_code>0) {
pjob->size += size; pjob->size += size;
print_job_store(jobid, pjob); pjob_store(jobid, pjob);
} }
return return_code; return return_code;
} }
@ -1060,8 +1121,8 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
if (!print_job_exists(jobid)) if (!print_job_exists(jobid))
break; break;
} }
if (jobid == next_jobid || !print_job_store(jobid, &pjob)) { if (jobid == next_jobid || !pjob_store(jobid, &pjob)) {
DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or print_job_store failed.\n", DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or pjob_store failed.\n",
jobid, next_jobid )); jobid, next_jobid ));
jobid = -1; jobid = -1;
goto fail; goto fail;
@ -1087,7 +1148,7 @@ to open spool file %s.\n", pjob.filename));
goto fail; goto fail;
} }
print_job_store(jobid, &pjob); pjob_store(jobid, &pjob);
tdb_unlock_bystring(tdb, "INFO/nextjob"); tdb_unlock_bystring(tdb, "INFO/nextjob");
@ -1105,9 +1166,8 @@ to open spool file %s.\n", pjob.filename));
return jobid; return jobid;
fail: fail:
if (jobid != -1) { if (jobid != -1)
tdb_delete(tdb, print_key(jobid)); pjob_delete(jobid);
}
tdb_unlock_bystring(tdb, "INFO/nextjob"); tdb_unlock_bystring(tdb, "INFO/nextjob");
@ -1129,7 +1189,7 @@ void print_job_endpage(int jobid)
return; return;
pjob->page_count++; pjob->page_count++;
print_job_store(jobid, pjob); pjob_store(jobid, pjob);
} }
/**************************************************************************** /****************************************************************************
@ -1180,7 +1240,7 @@ BOOL print_job_end(int jobid, BOOL normal_close)
DEBUG(5,("print_job_end: canceling spool of %s (%s)\n", DEBUG(5,("print_job_end: canceling spool of %s (%s)\n",
pjob->filename, pjob->size ? "deleted" : "zero length" )); pjob->filename, pjob->size ? "deleted" : "zero length" ));
unlink(pjob->filename); unlink(pjob->filename);
tdb_delete(tdb, print_key(jobid)); pjob_delete(jobid);
return True; return True;
} }
@ -1193,7 +1253,7 @@ BOOL print_job_end(int jobid, BOOL normal_close)
pjob->spooled = True; pjob->spooled = True;
pjob->status = LPQ_QUEUED; pjob->status = LPQ_QUEUED;
print_job_store(jobid, pjob); pjob_store(jobid, pjob);
/* make sure the database is up to date */ /* make sure the database is up to date */
if (print_cache_expired(snum)) if (print_cache_expired(snum))
@ -1206,7 +1266,7 @@ fail:
/* The print job was not succesfully started. Cleanup */ /* The print job was not succesfully started. Cleanup */
/* Still need to add proper error return propagation! 010122:JRR */ /* Still need to add proper error return propagation! 010122:JRR */
unlink(pjob->filename); unlink(pjob->filename);
tdb_delete(tdb, print_key(jobid)); pjob_delete(jobid);
return False; return False;
} }
@ -1389,7 +1449,6 @@ int print_queue_snum(char *qname)
BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode) BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
{ {
char *printer_name;
int ret; int ret;
if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
@ -1409,9 +1468,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
/* Send a printer notify message */ /* Send a printer notify message */
printer_name = PRINTERNAME(snum); notify_printer_status(snum, PRINTER_STATUS_PAUSED);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
return True; return True;
} }
@ -1422,7 +1479,6 @@ BOOL print_queue_pause(struct current_user *user, int snum, WERROR *errcode)
BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode) BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
{ {
char *printer_name;
int ret; int ret;
if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) { if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
@ -1442,9 +1498,7 @@ BOOL print_queue_resume(struct current_user *user, int snum, WERROR *errcode)
/* Send a printer notify message */ /* Send a printer notify message */
printer_name = PRINTERNAME(snum); notify_printer_status(snum, PRINTER_STATUS_OK);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
return True; return True;
} }
@ -1457,7 +1511,6 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
{ {
print_queue_struct *queue; print_queue_struct *queue;
print_status_struct status; print_status_struct status;
char *printer_name;
int njobs, i; int njobs, i;
BOOL can_job_admin; BOOL can_job_admin;
@ -1475,13 +1528,7 @@ BOOL print_queue_purge(struct current_user *user, int snum, WERROR *errcode)
} }
} }
safe_free(queue); SAFE_FREE(queue);
/* Send a printer notify message */
printer_name = PRINTERNAME(snum);
send_queue_message(printer_name, 0, PRINTER_CHANGE_JOB);
return True; return True;
} }

View File

@ -1,451 +0,0 @@
/*
* Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Jean Francois Micouleau 1998-2000,
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
#if 0
#include "rpc_parse.h"
#include "nterr.h"
#endif
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_CLI
extern pstring global_myname;
struct msg_info_table {
uint32 msg;
uint32 field;
char* name;
void (*construct_fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
print_queue_struct *queue,
NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
};
struct msg_info_table msg_table[] = {
{ PRINTER_MESSAGE_DRIVER, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_MESSAGE_DRIVER", spoolss_notify_driver_name },
{ PRINTER_MESSAGE_ATTRIBUTES, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_MESSAGE_ATTRIBUTES", spoolss_notify_attributes },
{ PRINTER_MESSAGE_COMMENT, PRINTER_NOTIFY_COMMENT, "PRINTER_MESSAGE_COMMENT", spoolss_notify_comment },
{ PRINTER_MESSAGE_LOCATION, PRINTER_NOTIFY_LOCATION, "PRINTER_MESSAGE_LOCATION", spoolss_notify_location },
{ PRINTER_MESSAGE_PRINTERNAME, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_MESSAGE_PRINTERNAME", spoolss_notify_printer_name },
{ PRINTER_MESSAGE_SHARENAME, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_MESSAGE_SHARENAME", spoolss_notify_share_name },
{ PRINTER_MESSAGE_PORT, PRINTER_NOTIFY_PORT_NAME, "PRINTER_MESSAGE_PORT", spoolss_notify_port_name },
{ PRINTER_MESSAGE_CJOBS, PRINTER_NOTIFY_CJOBS, "PRINTER_MESSAGE_CJOBS", spoolss_notify_cjobs },
{ PRINTER_MESSAGE_SEPFILE, PRINTER_NOTIFY_SEPFILE, "PRINTER_MESSAGE_SEPFILE", spoolss_notify_sepfile },
{ PRINTER_MESSAGE_PARAMS, PRINTER_NOTIFY_PARAMETERS, "PRINTER_MESSAGE_PARAMETERS", spoolss_notify_parameters },
{ PRINTER_MESSAGE_DATATYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_MESSAGE_DATATYPE", spoolss_notify_datatype },
{ PRINTER_MESSAGE_NULL, 0x0, "", NULL },
};
/*********************************************************
Disconnect from the client machine.
**********************************************************/
BOOL spoolss_disconnect_from_client( struct cli_state *cli)
{
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return True;
}
/*********************************************************
Connect to the client machine.
**********************************************************/
BOOL spoolss_connect_to_client( struct cli_state *cli, char *remote_machine)
{
ZERO_STRUCTP(cli);
if(cli_initialise(cli) == NULL) {
DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
return False;
}
if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (ismyip(cli->dest_ip)) {
DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
remote_machine));
return False;
}
cli->protocol = PROTOCOL_NT1;
if (!cli_negprot(cli)) {
DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (cli->protocol != PROTOCOL_NT1) {
DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
cli_shutdown(cli);
return False;
}
/*
* Do an anonymous session setup.
*/
if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
cli_shutdown(cli);
return False;
}
if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
cli_shutdown(cli);
return False;
}
/*
* Ok - we have an anonymous connection to the IPC$ share.
* Now start the NT Domain stuff :-).
*/
if(cli_nt_session_open(cli, PIPE_SPOOLSS) == False) {
DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli)));
cli_nt_session_close(cli);
cli_ulogoff(cli);
cli_shutdown(cli);
return False;
}
return True;
}
/*
* SPOOLSS Client RPC's used by servers as the notification
* back channel
*/
/***************************************************************************
do a reply open printer
****************************************************************************/
WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
char *printer, uint32 localprinter, uint32 type,
POLICY_HND *handle)
{
WERROR result = W_ERROR(ERRgeneral);
prs_struct rbuf;
prs_struct buf;
SPOOL_Q_REPLYOPENPRINTER q_s;
SPOOL_R_REPLYOPENPRINTER r_s;
prs_init(&buf, 1024, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
/* create and send a MSRPC command with api SPOOLSS_REPLYOPENPRINTER */
/* store the parameters */
make_spoolss_q_replyopenprinter(&q_s, printer, localprinter, type);
/* turn parameters into data stream */
if(!spoolss_io_q_replyopenprinter("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to marshall SPOOL_Q_REPLYOPENPRINTER struct.\n"));
goto done;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYOPENPRINTER, &buf, &rbuf))
goto done;
/* turn data stream into parameters*/
if(!spoolss_io_r_replyopenprinter("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to unmarshall SPOOL_R_REPLYOPENPRINTER struct.\n"));
goto done;
}
memcpy(handle, &r_s.handle, sizeof(r_s.handle));
result = r_s.status;
done:
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return result;
}
/***************************************************************************
do a reply open printer
****************************************************************************/
WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *handle)
{
WERROR result = W_ERROR(ERRgeneral);
prs_struct rbuf;
prs_struct buf;
SPOOL_Q_REPLYCLOSEPRINTER q_s;
SPOOL_R_REPLYCLOSEPRINTER r_s;
prs_init(&buf, 1024, cli->mem_ctx, MARSHALL);
prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
/* create and send a MSRPC command with api */
/* store the parameters */
make_spoolss_q_reply_closeprinter(&q_s, handle);
/* turn parameters into data stream */
if(!spoolss_io_q_replycloseprinter("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_Q_REPLY_CLOSEPRINTER struct.\n"));
goto done;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYCLOSEPRINTER, &buf, &rbuf))
goto done;
/* turn data stream into parameters*/
if(!spoolss_io_r_replycloseprinter("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_R_REPLY_CLOSEPRINTER struct.\n"));
goto done;
}
result = r_s.status;
done:
prs_mem_free(&buf);
prs_mem_free(&rbuf);
return result;
}
/*********************************************************************
This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
notification event when the registration **did not** use
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor.
Also see cli_spolss_reply_rrpcn()
*********************************************************************/
WERROR cli_spoolss_routerreplyprinter (struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 condition, uint32 changd_id)
{
prs_struct qbuf, rbuf;
SPOOL_Q_ROUTERREPLYPRINTER q;
SPOOL_R_ROUTERREPLYPRINTER r;
WERROR result = W_ERROR(ERRgeneral);
ZERO_STRUCT(q);
ZERO_STRUCT(r);
/* Initialise input parameters */
prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
/* write the request */
make_spoolss_q_routerreplyprinter(&q, pol, condition, changd_id);
/* Marshall data and send request */
if (!spoolss_io_q_routerreplyprinter ("", &q, &qbuf, 0)) {
DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to marshall SPOOL_Q_ROUTERREPLYPRINTER!\n"));
goto done;
}
if (!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf))
goto done;
/* Unmarshall response */
if (!spoolss_io_r_routerreplyprinter ("", &r, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to unmarshall SPOOL_R_ROUTERREPLYPRINTER!\n"));
goto done;
}
/* Return output parameters */
result = r.status;
done:
prs_mem_free(&qbuf);
prs_mem_free(&rbuf);
return result;
}
/**********************************************************************************
Build the SPOOL_NOTIFY_INFO_DATA entries based upon the flags which have been set
*********************************************************************************/
static int build_notify_data (TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, uint32 flags,
SPOOL_NOTIFY_INFO_DATA **notify_data)
{
SPOOL_NOTIFY_INFO_DATA *data;
uint32 idx = 0;
int i = 0;
while ((msg_table[i].msg != PRINTER_MESSAGE_NULL) && flags)
{
if (flags & msg_table[i].msg)
{
DEBUG(10,("build_notify_data: %s set on [%s][%d]\n", msg_table[i].name,
printer->info_2->printername, idx));
if ((data=Realloc(*notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
DEBUG(0,("build_notify_data: Realloc() failed with size [%d]!\n",
(idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA)));
return -1;
}
*notify_data = data;
/* clear memory */
memset(*notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA));
/*
* 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE
* See PRINTER_NOTIFY_INFO_DATA entries in MSDN
* --jerry
*/
construct_info_data(*notify_data+idx, PRINTER_NOTIFY_TYPE, msg_table[i].field, 0x00);
msg_table[i].construct_fn(-1, *notify_data+idx, NULL, printer, ctx);
idx++;
}
i++;
}
return idx;
}
/*********************************************************************
This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
notification event when the registration **did** use
SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
Also see cli_spoolss_routereplyprinter()
*********************************************************************/
WERROR cli_spoolss_reply_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *handle, PRINTER_MESSAGE_INFO *info,
NT_PRINTER_INFO_LEVEL *printer)
{
prs_struct rbuf;
prs_struct buf;
SPOOL_NOTIFY_INFO notify_info;
SPOOL_NOTIFY_INFO_DATA *notify_data = NULL;
uint32 data_len;
WERROR result = W_ERROR(ERRgeneral);
SPOOL_Q_REPLY_RRPCN q_s;
SPOOL_R_REPLY_RRPCN r_s;
if (!info) {
DEBUG(5,("cli_spoolss_reply_rrpcn: NULL printer message info pointer!\n"));
goto done;
}
prs_init(&buf, 1024, mem_ctx, MARSHALL);
prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
ZERO_STRUCT(notify_info);
/*
* See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX
* events. --jerry
*/
DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_MESSAGE flags = 0x%8x\n", info->flags));
data_len = build_notify_data(mem_ctx, printer, info->flags, &notify_data);
if (info->flags && (data_len == -1)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Failed to build SPOOL_NOTIFY_INFO_DATA [flags == 0x%x] for printer [%s]\n",
info->flags, info->printer_name));
result = WERR_NOMEM;
goto done;
}
notify_info.version = 0x2;
notify_info.flags = 0x00020000; /* ?? */
notify_info.count = data_len;
notify_info.data = notify_data;
/* create and send a MSRPC command with api */
/* store the parameters */
make_spoolss_q_reply_rrpcn(&q_s, handle, info->low, info->high, &notify_info);
/* turn parameters into data stream */
if(!spoolss_io_q_reply_rrpcn("", &q_s, &buf, 0)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n"));
goto done;
}
/* send the data on \PIPE\ */
if (!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &buf, &rbuf))
goto done;
/* turn data stream into parameters*/
if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) {
DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n"));
goto done;
}
if (r_s.unknown0 == 0x00080000) {
DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
}
result = r_s.status;
done:
prs_mem_free(&buf);
prs_mem_free(&rbuf);
/*
* The memory allocated in this array is talloc'd so we only need
* free the array here. JRA.
*/
SAFE_FREE(notify_data);
return result;
}

View File

@ -48,7 +48,7 @@ static uint32 str_len_uni(UNISTR *source)
This should be moved in a more generic lib. This should be moved in a more generic lib.
********************************************************************/ ********************************************************************/
static BOOL spoolss_io_system_time(char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime) BOOL spoolss_io_system_time(char *desc, prs_struct *ps, int depth, SYSTEMTIME *systime)
{ {
if(!prs_uint16("year", ps, depth, &systime->year)) if(!prs_uint16("year", ps, depth, &systime->year))
return False; return False;
@ -124,7 +124,7 @@ reads or writes an DOC_INFO structure.
static BOOL smb_io_doc_info(char *desc, DOC_INFO *info, prs_struct *ps, int depth) static BOOL smb_io_doc_info(char *desc, DOC_INFO *info, prs_struct *ps, int depth)
{ {
uint32 useless_ptr=1; uint32 useless_ptr=0;
if (info == NULL) return False; if (info == NULL) return False;
@ -324,53 +324,64 @@ static BOOL smb_io_notify_info_data(char *desc,SPOOL_NOTIFY_INFO_DATA *data, prs
{ {
uint32 useless_ptr=0xADDE0FF0; uint32 useless_ptr=0xADDE0FF0;
uint32 how_many_words;
BOOL isvalue;
uint32 x;
prs_debug(ps, depth, desc, "smb_io_notify_info_data"); prs_debug(ps, depth, desc, "smb_io_notify_info_data");
depth++; depth++;
how_many_words=data->size;
if (how_many_words==POINTER) {
how_many_words=TWO_VALUE;
}
isvalue=data->enc_type;
if(!prs_align(ps)) if(!prs_align(ps))
return False; return False;
if(!prs_uint16("type", ps, depth, &data->type)) if(!prs_uint16("type", ps, depth, &data->type))
return False; return False;
if(!prs_uint16("field", ps, depth, &data->field)) if(!prs_uint16("field", ps, depth, &data->field))
return False; return False;
/*prs_align(ps);*/
if(!prs_uint32("how many words", ps, depth, &how_many_words)) if(!prs_uint32("how many words", ps, depth, &data->size))
return False; return False;
if(!prs_uint32("id", ps, depth, &data->id)) if(!prs_uint32("id", ps, depth, &data->id))
return False; return False;
if(!prs_uint32("how many words", ps, depth, &how_many_words)) if(!prs_uint32("how many words", ps, depth, &data->size))
return False; return False;
switch (data->enc_type) {
/*prs_align(ps);*/ /* One and two value data has two uint32 values */
case ONE_VALUE:
case TWO_VALUE:
if (isvalue==True) {
if(!prs_uint32("value[0]", ps, depth, &data->notify_data.value[0])) if(!prs_uint32("value[0]", ps, depth, &data->notify_data.value[0]))
return False; return False;
if(!prs_uint32("value[1]", ps, depth, &data->notify_data.value[1])) if(!prs_uint32("value[1]", ps, depth, &data->notify_data.value[1]))
return False; return False;
/*prs_align(ps);*/ break;
} else {
/* it's a string */ /* Pointers and strings have a string length and a
/* length in ascii including \0 */ pointer. For a string the length is expressed as
x=2*(data->notify_data.data.length+1); the number of uint16 characters plus a trailing
if(!prs_uint32("string length", ps, depth, &x )) \0\0. */
case POINTER:
if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length ))
return False; return False;
if(!prs_uint32("pointer", ps, depth, &useless_ptr)) if(!prs_uint32("pointer", ps, depth, &useless_ptr))
return False; return False;
/*prs_align(ps);*/
break;
case STRING:
if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
return False;
if(!prs_uint32("pointer", ps, depth, &useless_ptr))
return False;
break;
default:
DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data\n",
data->enc_type));
break;
} }
return True; return True;
@ -383,22 +394,79 @@ reads or writes an NOTIFY INFO DATA structure.
BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data, BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
prs_struct *ps, int depth) prs_struct *ps, int depth)
{ {
uint32 x;
BOOL isvalue;
prs_debug(ps, depth, desc, "smb_io_notify_info_data_strings"); prs_debug(ps, depth, desc, "smb_io_notify_info_data_strings");
depth++; depth++;
if(!prs_align(ps)) if(!prs_align(ps))
return False; return False;
isvalue=data->enc_type; switch(data->enc_type) {
/* No data for values */
case ONE_VALUE:
case TWO_VALUE:
break;
/* Strings start with a length in uint16s */
case STRING:
if (UNMARSHALLING(ps)) {
data->notify_data.data.string =
(uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
if (!data->notify_data.data.string)
return False;
}
if (MARSHALLING(ps))
data->notify_data.data.length /= 2;
if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
return False;
if (!prs_uint16uni(True, "string", ps, depth, data->notify_data.data.string,
data->notify_data.data.length))
return False;
if (MARSHALLING(ps))
data->notify_data.data.length *= 2;
break;
case POINTER:
if (UNMARSHALLING(ps)) {
data->notify_data.data.string =
(uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
if (!data->notify_data.data.string)
return False;
}
if(!prs_uint8s(True,"buffer",ps,depth,(uint8*)data->notify_data.data.string,data->notify_data.data.length))
return False;
break;
default:
DEBUG(3, ("invalid enc_type %d for smb_io_notify_info_data_strings\n",
data->enc_type));
break;
}
#if 0
if (isvalue==False) { if (isvalue==False) {
/* length of string in unicode include \0 */ /* length of string in unicode include \0 */
x=data->notify_data.data.length+1; x=data->notify_data.data.length+1;
if (data->field != 16)
if(!prs_uint32("string length", ps, depth, &x )) if(!prs_uint32("string length", ps, depth, &x ))
return False; return False;
if (MARSHALLING(ps)) { if (MARSHALLING(ps)) {
/* These are already in little endian format. Don't byte swap. */ /* These are already in little endian format. Don't byte swap. */
if (x == 1) { if (x == 1) {
@ -412,6 +480,10 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
if(!prs_uint8s(True,"string",ps,depth, (uint8 *)&data->notify_data.data.length,x*2)) if(!prs_uint8s(True,"string",ps,depth, (uint8 *)&data->notify_data.data.length,x*2))
return False; return False;
} else { } else {
if (data->field == 16)
x /= 2;
if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x)) if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x))
return False; return False;
} }
@ -427,10 +499,11 @@ BOOL smb_io_notify_info_data_strings(char *desc,SPOOL_NOTIFY_INFO_DATA *data,
return False; return False;
} }
} }
#endif
#if 0 /* JERRY */ #if 0 /* JERRY */
/* Win2k does not seem to put this parse align here */ /* Win2k does not seem to put this parse align here */
if(!prs_align(ps)) if(!prs_align(ps))
return False; return False;
#endif #endif
@ -959,6 +1032,7 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
return True; return True;
} }
/******************************************************************* /*******************************************************************
* read a structure. * read a structure.
* called from spoolss_q_open_printer_ex (srv_spoolss.c) * called from spoolss_q_open_printer_ex (srv_spoolss.c)
@ -1209,8 +1283,11 @@ BOOL spoolss_io_r_getprinterdata(char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_st
if (!prs_uint32("size", ps, depth, &r_u->size)) if (!prs_uint32("size", ps, depth, &r_u->size))
return False; return False;
if (UNMARSHALLING(ps)) if (UNMARSHALLING(ps) && r_u->size) {
r_u->data = prs_alloc_mem(ps, r_u->size); r_u->data = prs_alloc_mem(ps, r_u->size);
if(r_u->data)
return False;
}
if (!prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size)) if (!prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size))
return False; return False;
@ -5748,9 +5825,7 @@ BOOL spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_
return False; return False;
if (UNMARSHALLING(ps) && r_u->valuesize) { if (UNMARSHALLING(ps) && r_u->valuesize) {
r_u->value = (uint16 *)prs_alloc_mem(ps, r_u->valuesize * 2); r_u->value = (uint16 *)prs_alloc_mem(ps, r_u->valuesize * 2);
if (!r_u->value) { if (!r_u->value) {
DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata value\n")); DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata value\n"));
return False; return False;
@ -5773,10 +5848,8 @@ BOOL spoolss_io_r_enumprinterdata(char *desc, SPOOL_R_ENUMPRINTERDATA *r_u, prs_
return False; return False;
if (UNMARSHALLING(ps) && r_u->datasize) { if (UNMARSHALLING(ps) && r_u->datasize) {
r_u->data = (uint8 *)prs_alloc_mem(ps, r_u->datasize); r_u->data = (uint8 *)prs_alloc_mem(ps, r_u->datasize);
if (!r_u->data) {
if (!r_u->value) {
DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata data\n")); DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata data\n"));
return False; return False;
} }

File diff suppressed because it is too large Load Diff

View File

@ -1778,10 +1778,10 @@ static NTSTATUS cmd_spoolss_enum_jobs(struct cli_state *cli,
for (i = 0; i < num_jobs; i++) { for (i = 0; i < num_jobs; i++) {
switch(level) { switch(level) {
case 1: case 1:
display_job_info_1(&ctr.job.job_info_1[i]); display_job_info_1(ctr.job.job_info_1[i]);
break; break;
case 2: case 2:
display_job_info_2(&ctr.job.job_info_2[i]); display_job_info_2(ctr.job.job_info_2[i]);
break; break;
default: default:
d_printf("unknown info level %d\n", level); d_printf("unknown info level %d\n", level);

View File

@ -34,7 +34,7 @@ static struct {
{"profile", MSG_PROFILE}, {"profile", MSG_PROFILE},
{"profilelevel", MSG_REQ_PROFILELEVEL}, {"profilelevel", MSG_REQ_PROFILELEVEL},
{"debuglevel", MSG_REQ_DEBUGLEVEL}, {"debuglevel", MSG_REQ_DEBUGLEVEL},
{"printer-notify", MSG_PRINTER_NOTIFY}, {"printnotify", MSG_PRINTER_NOTIFY2 },
{"close-share", MSG_SMB_FORCE_TDIS}, {"close-share", MSG_SMB_FORCE_TDIS},
{"samsync", MSG_SMB_SAM_SYNC}, {"samsync", MSG_SMB_SAM_SYNC},
{"samrepl", MSG_SMB_SAM_REPL}, {"samrepl", MSG_SMB_SAM_REPL},
@ -341,24 +341,106 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
} }
break; break;
case MSG_PRINTER_NOTIFY: /* Send a notification message to a printer */
if (!strequal(dest, "smbd")) {
fprintf(stderr,"printer-notify can only be sent to smbd\n");
return(False);
}
if (!params || !params[0]) {
fprintf(stderr, "printer-notify needs a printer name\n");
return (False);
}
{
char msg[8 + sizeof(fstring)];
SIVAL(msg,0,PRINTER_CHANGE_ALL);
SIVAL(msg,4,0);
fstrcpy(&msg[8], params[0]);
retval = send_message(dest, MSG_PRINTER_NOTIFY, msg, 8 + strlen(params[0]) + 1, False); case MSG_PRINTER_NOTIFY2: {
char *cmd;
/* Read subcommand */
if (!params || !params[0]) {
fprintf(stderr, "Must specify subcommand:\n");
fprintf(stderr, "\tqueuepause <printername>\n");
fprintf(stderr, "\tqueueresume <printername>\n");
return False;
} }
cmd = params[0];
/* Pause a print queue */
if (strequal(cmd, "queuepause")) {
if (!params[1]) {
fprintf(stderr, "queuepause command requires a printer name\n");
return False;
}
notify_printer_status_byname(params[1], PRINTER_STATUS_PAUSED);
break; break;
}
/* Resume a print queue */
if (strequal(cmd, "queueresume")) {
if (!params[1]) {
fprintf(stderr, "queueresume command requires a printer name\n");
return False;
}
notify_printer_status_byname(params[1], PRINTER_STATUS_OK);
break;
}
/* Pause a print job */
if (strequal(cmd, "jobpause")) {
int jobid;
if (!params[1] || !params[2]) {
fprintf(stderr, "jobpause command requires a printer name and a jobid\n");
return False;
}
jobid = atoi(params[2]);
notify_job_status_byname(
params[1], jobid, JOB_STATUS_PAUSED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
}
/* Resume a print job */
if (strequal(cmd, "jobresume")) {
int jobid;
if (!params[1] || !params[2]) {
fprintf(stderr, "jobresume command requires a printer name and a jobid\n");
return False;
}
jobid = atoi(params[2]);
notify_job_status_byname(
params[1], jobid, JOB_STATUS_QUEUED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
}
/* Delete a print job */
if (strequal(cmd, "jobdelete")) {
int jobid;
if (!params[1] || !params[2]) {
fprintf(stderr, "jobdelete command requires a printer name and a jobid\n");
return False;
}
jobid = atoi(params[2]);
notify_job_status_byname(
params[1], jobid, JOB_STATUS_DELETING,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
notify_job_status_byname(
params[1], jobid, JOB_STATUS_DELETING|
JOB_STATUS_DELETED,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID);
}
break;
}
case MSG_SMB_FORCE_TDIS: case MSG_SMB_FORCE_TDIS:
if (!strequal(dest, "smbd")) { if (!strequal(dest, "smbd")) {