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:
parent
b5bc8aa0f6
commit
3603cd4947
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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_ */
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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));
|
||||||
|
223
source/libsmb/cli_spoolss_notify.c
Normal file
223
source/libsmb/cli_spoolss_notify.c
Normal 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,
|
||||||
|
¬ify_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
230
source/printing/notify.c
Normal 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)
|
||||||
|
{
|
||||||
|
}
|
@ -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,8 +57,8 @@ 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;
|
||||||
}
|
}
|
||||||
local_pid = sys_getpid();
|
local_pid = sys_getpid();
|
||||||
@ -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) {
|
||||||
@ -733,7 +806,7 @@ BOOL print_job_delete(struct current_user *user, int jobid, WERROR *errcode)
|
|||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!print_job_delete1(jobid))
|
if (!print_job_delete1(jobid))
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
/* force update the database and say the delete failed if the
|
/* force update the database and say the delete failed if the
|
||||||
@ -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,12 +825,11 @@ 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;
|
||||||
|
|
||||||
if (!pjob->spooled || pjob->sysjob == -1)
|
if (!pjob->spooled || pjob->sysjob == -1)
|
||||||
return False;
|
return False;
|
||||||
|
|
||||||
snum = print_job_snum(jobid);
|
snum = print_job_snum(jobid);
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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, ¬ify_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, ¬ify_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;
|
|
||||||
}
|
|
||||||
|
|
@ -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
@ -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);
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MSG_SMB_FORCE_TDIS:
|
case MSG_SMB_FORCE_TDIS:
|
||||||
if (!strequal(dest, "smbd")) {
|
if (!strequal(dest, "smbd")) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user