2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
33 #include "librpc/gen_ndr/messaging.h"
35 #include "registry/reg_objects.h"
37 /* macros stolen from s4 spoolss server */
38 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
39 ((info)?ndr_size_##fn(info, level, 0):0)
41 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
42 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
44 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
47 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
50 extern userdom_struct current_user_info;
53 #define DBGC_CLASS DBGC_RPC_SRV
55 #ifndef MAX_OPEN_PRINTER_EXS
56 #define MAX_OPEN_PRINTER_EXS 50
59 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
61 static Printer_entry *printers_list;
63 typedef struct _counter_printer_0 {
64 struct _counter_printer_0 *next;
65 struct _counter_printer_0 *prev;
71 static counter_printer_0 *counter_list;
73 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
74 static uint32_t smb_connections = 0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table {
85 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername)
94 const char *pservername = servername;
95 while (*pservername == '\\') {
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v)
108 return JOB_STATUS_PAUSED;
110 return JOB_STATUS_SPOOLING;
112 return JOB_STATUS_PRINTING;
114 return JOB_STATUS_ERROR;
116 return JOB_STATUS_DELETING;
118 return JOB_STATUS_OFFLINE;
120 return JOB_STATUS_PAPEROUT;
122 return JOB_STATUS_PRINTED;
124 return JOB_STATUS_DELETED;
126 return JOB_STATUS_BLOCKED_DEVQ;
127 case LPQ_USER_INTERVENTION:
128 return JOB_STATUS_USER_INTERVENTION;
133 static int nt_printq_status(int v)
137 return PRINTER_STATUS_PAUSED;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
172 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
180 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2, NULL);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 serverid_register_msg_flags(
189 messaging_server_id(smbd_messaging_context()),
190 false, FLAG_MSG_PRINT_NOTIFY);
196 /****************************************************************************
197 Functions to free a printer entry datastruct.
198 ****************************************************************************/
200 static int printer_entry_destructor(Printer_entry *Printer)
202 if (Printer->notify.client_connected == true) {
205 if ( Printer->printer_type == SPLHND_SERVER) {
207 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
208 } else if (Printer->printer_type == SPLHND_PRINTER) {
209 snum = print_queue_snum(Printer->sharename);
211 srv_spoolss_replycloseprinter(snum,
212 &Printer->notify.client_hnd);
216 Printer->notify.flags=0;
217 Printer->notify.options=0;
218 Printer->notify.localmachine[0]='\0';
219 Printer->notify.printerlocal=0;
220 TALLOC_FREE(Printer->notify.option);
221 Printer->notify.client_connected = false;
223 TALLOC_FREE(Printer->devmode);
224 free_a_printer( &Printer->printer_info, 2 );
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list, Printer);
231 /****************************************************************************
232 find printer index by handle
233 ****************************************************************************/
235 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
236 struct policy_handle *hnd)
238 Printer_entry *find_printer = NULL;
240 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
241 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
248 /****************************************************************************
249 Close printer index by handle.
250 ****************************************************************************/
252 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
254 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
257 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
262 close_policy_hnd(p, hnd);
267 /****************************************************************************
268 Delete a printer given a handle.
269 ****************************************************************************/
271 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
273 char *cmd = lp_deleteprinter_cmd();
274 char *command = NULL;
276 SE_PRIV se_printop = SE_PRINT_OPERATOR;
277 bool is_print_op = false;
279 /* can't fail if we don't try */
284 command = talloc_asprintf(ctx,
291 is_print_op = user_has_privileges( token, &se_printop );
293 DEBUG(10,("Running [%s]\n", command));
295 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
300 if ( (ret = smbrun(command, NULL)) == 0 ) {
301 /* Tell everyone we updated smb.conf. */
302 message_send_all(smbd_messaging_context(),
303 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
309 /********** END SePrintOperatorPrivlege BLOCK **********/
311 DEBUGADD(10,("returned [%d]\n", ret));
313 TALLOC_FREE(command);
316 return WERR_BADFID; /* What to return here? */
318 /* go ahead and re-read the services immediately */
320 reload_services(false);
323 if ( lp_servicenumber( sharename ) > 0 )
324 return WERR_ACCESS_DENIED;
329 /****************************************************************************
330 Delete a printer given a handle.
331 ****************************************************************************/
333 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
335 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
338 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
344 * It turns out that Windows allows delete printer on a handle
345 * opened by an admin user, then used on a pipe handle created
346 * by an anonymous user..... but they're working on security.... riiight !
350 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
351 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
352 return WERR_ACCESS_DENIED;
355 /* this does not need a become root since the access check has been
356 done on the handle already */
358 if (del_a_printer( Printer->sharename ) != 0) {
359 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
363 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
364 Printer->sharename );
367 /****************************************************************************
368 Return the snum of a printer corresponding to an handle.
369 ****************************************************************************/
371 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
372 int *number, struct share_params **params)
374 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
377 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
382 switch (Printer->printer_type) {
384 DEBUG(4,("short name:%s\n", Printer->sharename));
385 *number = print_queue_snum(Printer->sharename);
386 return (*number != -1);
394 /****************************************************************************
395 Set printer handle type.
396 Check if it's \\server or \\server\printer
397 ****************************************************************************/
399 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
401 DEBUG(3,("Setting printer type=%s\n", handlename));
403 if ( strlen(handlename) < 3 ) {
404 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
408 /* it's a print server */
409 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
410 DEBUGADD(4,("Printer is a print server\n"));
411 Printer->printer_type = SPLHND_SERVER;
413 /* it's a printer (set_printer_hnd_name() will handle port monitors */
415 DEBUGADD(4,("Printer is a printer\n"));
416 Printer->printer_type = SPLHND_PRINTER;
422 /****************************************************************************
423 Set printer handle name.. Accept names like \\server, \\server\printer,
424 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
425 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
426 XcvDataPort() interface.
427 ****************************************************************************/
429 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
432 int n_services=lp_numservices();
433 char *aprinter, *printername;
434 const char *servername;
437 NT_PRINTER_INFO_LEVEL *printer = NULL;
440 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
441 (unsigned long)strlen(handlename)));
443 aprinter = CONST_DISCARD(char *, handlename);
444 if ( *handlename == '\\' ) {
445 servername = canon_servername(handlename);
446 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
451 servername = global_myname();
454 /* save the servername to fill in replies on this handle */
456 if ( !is_myname_or_ipaddr( servername ) )
459 fstrcpy( Printer->servername, servername );
461 if ( Printer->printer_type == SPLHND_SERVER )
464 if ( Printer->printer_type != SPLHND_PRINTER )
467 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
469 /* check for the Port Monitor Interface */
471 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
472 Printer->printer_type = SPLHND_PORTMON_TCP;
473 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
476 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
477 Printer->printer_type = SPLHND_PORTMON_LOCAL;
478 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
482 /* Search all sharenames first as this is easier than pulling
483 the printer_info_2 off of disk. Don't use find_service() since
484 that calls out to map_username() */
486 /* do another loop to look for printernames */
488 for (snum=0; !found && snum<n_services; snum++) {
490 /* no point going on if this is not a printer */
492 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
495 fstrcpy(sname, lp_servicename(snum));
496 if ( strequal( aprinter, sname ) ) {
501 /* no point looking up the printer object if
502 we aren't allowing printername != sharename */
504 if ( lp_force_printername(snum) )
507 fstrcpy(sname, lp_servicename(snum));
511 /* This call doesn't fill in the location or comment from
512 * a CUPS server for efficiency with large numbers of printers.
516 result = get_a_printer_search( NULL, &printer, 2, sname );
517 if ( !W_ERROR_IS_OK(result) ) {
518 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
519 sname, win_errstr(result)));
523 /* printername is always returned as \\server\printername */
524 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
525 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
526 printer->info_2->printername));
527 free_a_printer( &printer, 2);
533 if ( strequal(printername, aprinter) ) {
534 free_a_printer( &printer, 2);
539 DEBUGADD(10, ("printername: %s\n", printername));
541 free_a_printer( &printer, 2);
544 free_a_printer( &printer, 2);
547 DEBUGADD(4,("Printer not found\n"));
551 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
553 fstrcpy(Printer->sharename, sname);
558 /****************************************************************************
559 Find first available printer slot. creates a printer handle for you.
560 ****************************************************************************/
562 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
563 const char *name, uint32_t access_granted)
565 Printer_entry *new_printer;
567 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
569 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
570 if (new_printer == NULL) {
573 talloc_set_destructor(new_printer, printer_entry_destructor);
575 if (!create_policy_hnd(p, hnd, new_printer)) {
576 TALLOC_FREE(new_printer);
580 /* Add to the internal list. */
581 DLIST_ADD(printers_list, new_printer);
583 new_printer->notify.option=NULL;
585 if (!set_printer_hnd_printertype(new_printer, name)) {
586 close_printer_handle(p, hnd);
590 if (!set_printer_hnd_name(new_printer, name)) {
591 close_printer_handle(p, hnd);
595 new_printer->access_granted = access_granted;
597 DEBUG(5, ("%d printer handles active\n",
598 (int)num_pipe_handles(p)));
603 /***************************************************************************
604 check to see if the client motify handle is monitoring the notification
605 given by (notify_type, notify_field).
606 **************************************************************************/
608 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
609 uint16_t notify_field)
614 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
615 uint16_t notify_field)
617 struct spoolss_NotifyOption *option = p->notify.option;
621 * Flags should always be zero when the change notify
622 * is registered by the client's spooler. A user Win32 app
623 * might use the flags though instead of the NOTIFY_OPTION_INFO
632 return is_monitoring_event_flags(
633 p->notify.flags, notify_type, notify_field);
635 for (i = 0; i < option->count; i++) {
637 /* Check match for notify_type */
639 if (option->types[i].type != notify_type)
642 /* Check match for field */
644 for (j = 0; j < option->types[i].count; j++) {
645 if (option->types[i].fields[j].field == notify_field) {
651 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652 p->servername, p->sharename, notify_type, notify_field));
657 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
658 _data->data.integer[0] = _integer; \
659 _data->data.integer[1] = 0;
662 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
663 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
664 if (!_data->data.string.string) {\
665 _data->data.string.size = 0; \
667 _data->data.string.size = strlen_m_term(_p) * 2;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
670 _data->data.devmode.devmode = _devmode;
672 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
673 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
674 if (!_data->data.sd.sd) { \
675 _data->data.sd.sd_size = 0; \
677 _data->data.sd.sd_size = _size;
679 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
684 struct spoolss_Time st;
688 if (!init_systemtime(&st, t)) {
692 p = talloc_array(mem_ctx, char, len);
698 * Systemtime must be linearized as a set of UINT16's.
699 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
702 SSVAL(p, 0, st.year);
703 SSVAL(p, 2, st.month);
704 SSVAL(p, 4, st.day_of_week);
706 SSVAL(p, 8, st.hour);
707 SSVAL(p, 10, st.minute);
708 SSVAL(p, 12, st.second);
709 SSVAL(p, 14, st.millisecond);
715 /* Convert a notification message to a struct spoolss_Notify */
717 static void notify_one_value(struct spoolss_notify_msg *msg,
718 struct spoolss_Notify *data,
721 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
724 static void notify_string(struct spoolss_notify_msg *msg,
725 struct spoolss_Notify *data,
728 /* The length of the message includes the trailing \0 */
730 data->data.string.size = msg->len * 2;
731 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
732 if (!data->data.string.string) {
733 data->data.string.size = 0;
738 static void notify_system_time(struct spoolss_notify_msg *msg,
739 struct spoolss_Notify *data,
742 data->data.string.string = NULL;
743 data->data.string.size = 0;
745 if (msg->len != sizeof(time_t)) {
746 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
751 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
752 &data->data.string.string,
753 &data->data.string.size);
756 struct notify2_message_table {
758 void (*fn)(struct spoolss_notify_msg *msg,
759 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
762 static struct notify2_message_table printer_notify_table[] = {
763 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
764 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
765 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
766 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
767 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
768 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
769 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
770 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
771 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
772 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
773 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
774 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
775 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
776 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
777 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
778 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
779 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
780 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
781 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
784 static struct notify2_message_table job_notify_table[] = {
785 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
786 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
787 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
788 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
789 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
790 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
791 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
792 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
793 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
794 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
795 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
796 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
797 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
798 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
799 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
800 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
801 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
802 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
803 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
804 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
805 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
806 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
807 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
808 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
812 /***********************************************************************
813 Allocate talloc context for container object
814 **********************************************************************/
816 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
821 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
826 /***********************************************************************
827 release all allocated memory and zero out structure
828 **********************************************************************/
830 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
836 talloc_destroy(ctr->ctx);
843 /***********************************************************************
844 **********************************************************************/
846 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
854 /***********************************************************************
855 **********************************************************************/
857 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
859 if ( !ctr || !ctr->msg_groups )
862 if ( idx >= ctr->num_groups )
865 return &ctr->msg_groups[idx];
869 /***********************************************************************
870 How many groups of change messages do we have ?
871 **********************************************************************/
873 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
878 return ctr->num_groups;
881 /***********************************************************************
882 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
883 **********************************************************************/
885 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
887 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
888 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
889 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
895 /* loop over all groups looking for a matching printer name */
897 for ( i=0; i<ctr->num_groups; i++ ) {
898 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
902 /* add a new group? */
904 if ( i == ctr->num_groups ) {
907 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
911 ctr->msg_groups = groups;
913 /* clear the new entry and set the printer name */
915 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
916 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
919 /* add the change messages; 'i' is the correct index now regardless */
921 msg_grp = &ctr->msg_groups[i];
925 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
926 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
929 msg_grp->msgs = msg_list;
931 new_slot = msg_grp->num_msgs-1;
932 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
934 /* need to allocate own copy of data */
937 msg_grp->msgs[new_slot].notify.data = (char *)
938 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
940 return ctr->num_groups;
943 void construct_info_data(struct spoolss_Notify *info_data,
944 enum spoolss_NotifyType type,
948 /***********************************************************************
949 Send a change notication message on all handles which have a call
951 **********************************************************************/
953 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
956 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
957 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
958 SPOOLSS_NOTIFY_MSG *messages;
959 int sending_msg_count;
962 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
966 messages = msg_group->msgs;
969 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
973 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
975 /* loop over all printers */
977 for (p = printers_list; p; p = p->next) {
978 struct spoolss_Notify *notifies;
983 /* Is there notification on this handle? */
985 if ( !p->notify.client_connected )
988 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
990 /* For this printer? Print servers always receive
993 if ( ( p->printer_type == SPLHND_PRINTER ) &&
994 ( !strequal(msg_group->printername, p->sharename) ) )
997 DEBUG(10,("Our printer\n"));
999 /* allocate the max entries possible */
1001 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1006 /* build the array of change notifications */
1008 sending_msg_count = 0;
1010 for ( i=0; i<msg_group->num_msgs; i++ ) {
1011 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1013 /* Are we monitoring this event? */
1015 if (!is_monitoring_event(p, msg->type, msg->field))
1018 sending_msg_count++;
1021 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1022 msg->type, msg->field, p->sharename));
1025 * if the is a printer notification handle and not a job notification
1026 * type, then set the id to 0. Other wise just use what was specified
1029 * When registering change notification on a print server handle
1030 * we always need to send back the id (snum) matching the printer
1031 * for which the change took place. For change notify registered
1032 * on a printer handle, this does not matter and the id should be 0.
1037 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1043 /* Convert unix jobid to smb jobid */
1045 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1046 id = sysjob_to_jobid(msg->id);
1049 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1054 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1057 case PRINTER_NOTIFY_TYPE:
1058 if ( printer_notify_table[msg->field].fn )
1059 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1062 case JOB_NOTIFY_TYPE:
1063 if ( job_notify_table[msg->field].fn )
1064 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1068 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1075 if ( sending_msg_count ) {
1078 union spoolss_ReplyPrinterInfo info;
1079 struct spoolss_NotifyInfo info0;
1080 uint32_t reply_result;
1082 info0.version = 0x2;
1083 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1084 info0.count = count;
1085 info0.notifies = notifies;
1087 info.info0 = &info0;
1089 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1090 &p->notify.client_hnd,
1091 p->notify.change, /* color */
1094 0, /* reply_type, must be 0 */
1097 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1098 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1099 notify_cli_pipe->srv_name_slash,
1102 switch (reply_result) {
1105 case PRINTER_NOTIFY_INFO_DISCARDED:
1106 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1107 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1116 DEBUG(8,("send_notify2_changes: Exit...\n"));
1120 /***********************************************************************
1121 **********************************************************************/
1123 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1126 uint32_t tv_sec, tv_usec;
1129 /* Unpack message */
1131 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1134 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1136 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1139 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1140 &msg->notify.value[0], &msg->notify.value[1]);
1142 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1143 &msg->len, &msg->notify.data);
1145 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1146 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1148 tv->tv_sec = tv_sec;
1149 tv->tv_usec = tv_usec;
1152 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1153 msg->notify.value[1]));
1155 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1160 /********************************************************************
1161 Receive a notify2 message list
1162 ********************************************************************/
1164 static void receive_notify2_message_list(struct messaging_context *msg,
1167 struct server_id server_id,
1170 size_t msg_count, i;
1171 char *buf = (char *)data->data;
1174 SPOOLSS_NOTIFY_MSG notify;
1175 SPOOLSS_NOTIFY_MSG_CTR messages;
1178 if (data->length < 4) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1183 msg_count = IVAL(buf, 0);
1186 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1188 if (msg_count == 0) {
1189 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1193 /* initialize the container */
1195 ZERO_STRUCT( messages );
1196 notify_msg_ctr_init( &messages );
1199 * build message groups for each printer identified
1200 * in a change_notify msg. Remember that a PCN message
1201 * includes the handle returned for the srv_spoolss_replyopenprinter()
1202 * call. Therefore messages are grouped according to printer handle.
1205 for ( i=0; i<msg_count; i++ ) {
1206 struct timeval msg_tv;
1208 if (msg_ptr + 4 - buf > data->length) {
1209 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1213 msg_len = IVAL(msg_ptr,0);
1216 if (msg_ptr + msg_len - buf > data->length) {
1217 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1221 /* unpack messages */
1223 ZERO_STRUCT( notify );
1224 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1227 /* add to correct list in container */
1229 notify_msg_ctr_addmsg( &messages, ¬ify );
1231 /* free memory that might have been allocated by notify2_unpack_msg() */
1233 if ( notify.len != 0 )
1234 SAFE_FREE( notify.notify.data );
1237 /* process each group of messages */
1239 num_groups = notify_msg_ctr_numgroups( &messages );
1240 for ( i=0; i<num_groups; i++ )
1241 send_notify2_changes( &messages, i );
1246 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1247 (uint32_t)msg_count ));
1249 notify_msg_ctr_destroy( &messages );
1254 /********************************************************************
1255 Send a message to ourself about new driver being installed
1256 so we can upgrade the information for each printer bound to this
1258 ********************************************************************/
1260 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1262 int len = strlen(drivername);
1267 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1270 messaging_send_buf(smbd_messaging_context(),
1271 messaging_server_id(smbd_messaging_context()),
1272 MSG_PRINTER_DRVUPGRADE,
1273 (uint8_t *)drivername, len+1);
1278 /**********************************************************************
1279 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1280 over all printers, upgrading ones as necessary
1281 **********************************************************************/
1283 void do_drv_upgrade_printer(struct messaging_context *msg,
1286 struct server_id server_id,
1291 int n_services = lp_numservices();
1294 len = MIN(data->length,sizeof(drivername)-1);
1295 strncpy(drivername, (const char *)data->data, len);
1297 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1299 /* Iterate the printer list */
1301 for (snum=0; snum<n_services; snum++)
1303 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1306 NT_PRINTER_INFO_LEVEL *printer = NULL;
1308 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1309 if (!W_ERROR_IS_OK(result))
1312 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1314 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1316 /* all we care about currently is the change_id */
1318 result = mod_a_printer(printer, 2);
1319 if (!W_ERROR_IS_OK(result)) {
1320 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1321 win_errstr(result)));
1325 free_a_printer(&printer, 2);
1332 /********************************************************************
1333 Update the cache for all printq's with a registered client
1335 ********************************************************************/
1337 void update_monitored_printq_cache( void )
1339 Printer_entry *printer = printers_list;
1342 /* loop through all printers and update the cache where
1343 client_connected == true */
1346 if ( (printer->printer_type == SPLHND_PRINTER)
1347 && printer->notify.client_connected )
1349 snum = print_queue_snum(printer->sharename);
1350 print_queue_status( snum, NULL, NULL );
1353 printer = printer->next;
1359 /****************************************************************
1360 _spoolss_OpenPrinter
1361 ****************************************************************/
1363 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1364 struct spoolss_OpenPrinter *r)
1366 struct spoolss_OpenPrinterEx e;
1369 ZERO_STRUCT(e.in.userlevel);
1371 e.in.printername = r->in.printername;
1372 e.in.datatype = r->in.datatype;
1373 e.in.devmode_ctr = r->in.devmode_ctr;
1374 e.in.access_mask = r->in.access_mask;
1377 e.out.handle = r->out.handle;
1379 werr = _spoolss_OpenPrinterEx(p, &e);
1381 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1382 /* OpenPrinterEx returns this for a bad
1383 * printer name. We must return WERR_INVALID_PRINTER_NAME
1386 werr = WERR_INVALID_PRINTER_NAME;
1392 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1393 struct spoolss_DeviceMode *orig,
1394 struct spoolss_DeviceMode **dest)
1396 struct spoolss_DeviceMode *dm;
1398 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1403 /* copy all values, then duplicate strings and structs */
1406 dm->devicename = talloc_strdup(dm, orig->devicename);
1407 if (!dm->devicename) {
1410 dm->formname = talloc_strdup(dm, orig->formname);
1411 if (!dm->formname) {
1414 if (orig->driverextra_data.data) {
1415 dm->driverextra_data.data =
1416 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1417 orig->driverextra_data.length);
1418 if (!dm->driverextra_data.data) {
1427 /****************************************************************
1428 _spoolss_OpenPrinterEx
1429 ****************************************************************/
1431 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1432 struct spoolss_OpenPrinterEx *r)
1435 Printer_entry *Printer=NULL;
1437 if (!r->in.printername) {
1438 return WERR_INVALID_PARAM;
1441 /* some sanity check because you can open a printer or a print server */
1442 /* aka: \\server\printer or \\server */
1444 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1446 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1447 ZERO_STRUCTP(r->out.handle);
1448 return WERR_INVALID_PARAM;
1451 Printer = find_printer_index_by_hnd(p, r->out.handle);
1453 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1454 "handle we created for printer %s\n", r->in.printername));
1455 close_printer_handle(p, r->out.handle);
1456 ZERO_STRUCTP(r->out.handle);
1457 return WERR_INVALID_PARAM;
1461 * First case: the user is opening the print server:
1463 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1464 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1466 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1467 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1468 * or if the user is listed in the smb.conf printer admin parameter.
1470 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1471 * client view printer folder, but does not show the MSAPW.
1473 * Note: this test needs code to check access rights here too. Jeremy
1474 * could you look at this?
1476 * Second case: the user is opening a printer:
1477 * NT doesn't let us connect to a printer if the connecting user
1478 * doesn't have print permission.
1480 * Third case: user is opening a Port Monitor
1481 * access checks same as opening a handle to the print server.
1484 switch (Printer->printer_type )
1487 case SPLHND_PORTMON_TCP:
1488 case SPLHND_PORTMON_LOCAL:
1489 /* Printserver handles use global struct... */
1493 /* Map standard access rights to object specific access rights */
1495 se_map_standard(&r->in.access_mask,
1496 &printserver_std_mapping);
1498 /* Deny any object specific bits that don't apply to print
1499 servers (i.e printer and job specific bits) */
1501 r->in.access_mask &= SEC_MASK_SPECIFIC;
1503 if (r->in.access_mask &
1504 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1505 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1506 close_printer_handle(p, r->out.handle);
1507 ZERO_STRUCTP(r->out.handle);
1508 return WERR_ACCESS_DENIED;
1511 /* Allow admin access */
1513 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1515 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1517 if (!lp_ms_add_printer_wizard()) {
1518 close_printer_handle(p, r->out.handle);
1519 ZERO_STRUCTP(r->out.handle);
1520 return WERR_ACCESS_DENIED;
1523 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1524 and not a printer admin, then fail */
1526 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1527 !user_has_privileges(p->server_info->ptok,
1529 !token_contains_name_in_list(
1530 uidtoname(p->server_info->utok.uid),
1531 p->server_info->info3->base.domain.string,
1533 p->server_info->ptok,
1534 lp_printer_admin(snum))) {
1535 close_printer_handle(p, r->out.handle);
1536 ZERO_STRUCTP(r->out.handle);
1537 return WERR_ACCESS_DENIED;
1540 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1544 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1547 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1548 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1550 /* We fall through to return WERR_OK */
1553 case SPLHND_PRINTER:
1554 /* NT doesn't let us connect to a printer if the connecting user
1555 doesn't have print permission. */
1557 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1558 close_printer_handle(p, r->out.handle);
1559 ZERO_STRUCTP(r->out.handle);
1563 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1564 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1567 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1569 /* map an empty access mask to the minimum access mask */
1570 if (r->in.access_mask == 0x0)
1571 r->in.access_mask = PRINTER_ACCESS_USE;
1574 * If we are not serving the printer driver for this printer,
1575 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1576 * will keep NT clients happy --jerry
1579 if (lp_use_client_driver(snum)
1580 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1582 r->in.access_mask = PRINTER_ACCESS_USE;
1585 /* check smb.conf parameters and the the sec_desc */
1587 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1588 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1589 ZERO_STRUCTP(r->out.handle);
1590 return WERR_ACCESS_DENIED;
1593 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1594 p->server_info->ptok, snum) ||
1595 !print_access_check(p->server_info, snum,
1596 r->in.access_mask)) {
1597 DEBUG(3, ("access DENIED for printer open\n"));
1598 close_printer_handle(p, r->out.handle);
1599 ZERO_STRUCTP(r->out.handle);
1600 return WERR_ACCESS_DENIED;
1603 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1604 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1605 close_printer_handle(p, r->out.handle);
1606 ZERO_STRUCTP(r->out.handle);
1607 return WERR_ACCESS_DENIED;
1610 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1611 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1613 r->in.access_mask = PRINTER_ACCESS_USE;
1615 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1616 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1621 /* sanity check to prevent programmer error */
1622 ZERO_STRUCTP(r->out.handle);
1626 Printer->access_granted = r->in.access_mask;
1629 * If the client sent a devmode in the OpenPrinter() call, then
1630 * save it here in case we get a job submission on this handle
1633 if ((Printer->printer_type != SPLHND_SERVER) &&
1634 r->in.devmode_ctr.devmode) {
1635 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1639 #if 0 /* JERRY -- I'm doubtful this is really effective */
1640 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1641 optimization in Windows 2000 clients --jerry */
1643 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1644 && (RA_WIN2K == get_remote_arch()) )
1646 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1647 sys_usleep( 500000 );
1654 /****************************************************************************
1655 ****************************************************************************/
1657 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1658 NT_PRINTER_INFO_LEVEL_2 *d)
1660 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1666 d->attributes = r->attributes;
1667 d->priority = r->priority;
1668 d->default_priority = r->defaultpriority;
1669 d->starttime = r->starttime;
1670 d->untiltime = r->untiltime;
1671 d->status = r->status;
1672 d->cjobs = r->cjobs;
1674 fstrcpy(d->servername, r->servername);
1675 fstrcpy(d->printername, r->printername);
1676 fstrcpy(d->sharename, r->sharename);
1677 fstrcpy(d->portname, r->portname);
1678 fstrcpy(d->drivername, r->drivername);
1679 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1680 fstrcpy(d->location, r->location);
1681 fstrcpy(d->sepfile, r->sepfile);
1682 fstrcpy(d->printprocessor, r->printprocessor);
1683 fstrcpy(d->datatype, r->datatype);
1684 fstrcpy(d->parameters, r->parameters);
1689 /****************************************************************************
1690 ****************************************************************************/
1692 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1693 NT_PRINTER_INFO_LEVEL *printer)
1697 switch (info_ctr->level) {
1699 /* allocate memory if needed. Messy because
1700 convert_printer_info is used to update an existing
1701 printer or build a new one */
1703 if (!printer->info_2) {
1704 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1705 if (!printer->info_2) {
1706 DEBUG(0,("convert_printer_info: "
1707 "talloc() failed!\n"));
1712 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1714 printer->info_2->setuptime = time(NULL);
1721 /****************************************************************
1722 _spoolss_ClosePrinter
1723 ****************************************************************/
1725 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1726 struct spoolss_ClosePrinter *r)
1728 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1730 if (Printer && Printer->document_started) {
1731 struct spoolss_EndDocPrinter e;
1733 e.in.handle = r->in.handle;
1735 _spoolss_EndDocPrinter(p, &e);
1738 if (!close_printer_handle(p, r->in.handle))
1741 /* clear the returned printer handle. Observed behavior
1742 from Win2k server. Don't think this really matters.
1743 Previous code just copied the value of the closed
1746 ZERO_STRUCTP(r->out.handle);
1751 /****************************************************************
1752 _spoolss_DeletePrinter
1753 ****************************************************************/
1755 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1756 struct spoolss_DeletePrinter *r)
1758 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1761 if (Printer && Printer->document_started) {
1762 struct spoolss_EndDocPrinter e;
1764 e.in.handle = r->in.handle;
1766 _spoolss_EndDocPrinter(p, &e);
1769 result = delete_printer_handle(p, r->in.handle);
1771 update_c_setprinter(false);
1776 /*******************************************************************
1777 * static function to lookup the version id corresponding to an
1778 * long architecture string
1779 ******************************************************************/
1781 static const struct print_architecture_table_node archi_table[]= {
1783 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1784 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1785 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1786 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1787 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1788 {"Windows IA64", SPL_ARCH_IA64, 3 },
1789 {"Windows x64", SPL_ARCH_X64, 3 },
1793 static int get_version_id(const char *arch)
1797 for (i=0; archi_table[i].long_archi != NULL; i++)
1799 if (strcmp(arch, archi_table[i].long_archi) == 0)
1800 return (archi_table[i].version);
1806 /****************************************************************
1807 _spoolss_DeletePrinterDriver
1808 ****************************************************************/
1810 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1811 struct spoolss_DeletePrinterDriver *r)
1814 struct spoolss_DriverInfo8 *info = NULL;
1815 struct spoolss_DriverInfo8 *info_win2k = NULL;
1818 WERROR status_win2k = WERR_ACCESS_DENIED;
1819 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1821 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1822 and not a printer admin, then fail */
1824 if ( (p->server_info->utok.uid != sec_initial_uid())
1825 && !user_has_privileges(p->server_info->ptok, &se_printop )
1826 && !token_contains_name_in_list(
1827 uidtoname(p->server_info->utok.uid),
1828 p->server_info->info3->base.domain.string,
1830 p->server_info->ptok,
1831 lp_printer_admin(-1)) )
1833 return WERR_ACCESS_DENIED;
1836 /* check that we have a valid driver name first */
1838 if ((version = get_version_id(r->in.architecture)) == -1)
1839 return WERR_INVALID_ENVIRONMENT;
1841 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1845 /* try for Win2k driver if "Windows NT x86" */
1847 if ( version == 2 ) {
1849 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1854 status = WERR_UNKNOWN_PRINTER_DRIVER;
1858 /* otherwise it was a failure */
1860 status = WERR_UNKNOWN_PRINTER_DRIVER;
1866 if (printer_driver_in_use(info)) {
1867 status = WERR_PRINTER_DRIVER_IN_USE;
1873 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1876 r->in.architecture, 3)))
1878 /* if we get to here, we now have 2 driver info structures to remove */
1879 /* remove the Win2k driver first*/
1881 status_win2k = delete_printer_driver(
1882 p, info_win2k, 3, false);
1883 free_a_printer_driver(info_win2k);
1885 /* this should not have failed---if it did, report to client */
1886 if ( !W_ERROR_IS_OK(status_win2k) )
1888 status = status_win2k;
1894 status = delete_printer_driver(p, info, version, false);
1896 /* if at least one of the deletes succeeded return OK */
1898 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1902 free_a_printer_driver(info);
1907 /****************************************************************
1908 _spoolss_DeletePrinterDriverEx
1909 ****************************************************************/
1911 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1912 struct spoolss_DeletePrinterDriverEx *r)
1914 struct spoolss_DriverInfo8 *info = NULL;
1915 struct spoolss_DriverInfo8 *info_win2k = NULL;
1919 WERROR status_win2k = WERR_ACCESS_DENIED;
1920 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1922 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1923 and not a printer admin, then fail */
1925 if ( (p->server_info->utok.uid != sec_initial_uid())
1926 && !user_has_privileges(p->server_info->ptok, &se_printop )
1927 && !token_contains_name_in_list(
1928 uidtoname(p->server_info->utok.uid),
1929 p->server_info->info3->base.domain.string,
1931 p->server_info->ptok, lp_printer_admin(-1)) )
1933 return WERR_ACCESS_DENIED;
1936 /* check that we have a valid driver name first */
1937 if ((version = get_version_id(r->in.architecture)) == -1) {
1938 /* this is what NT returns */
1939 return WERR_INVALID_ENVIRONMENT;
1942 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1943 version = r->in.version;
1945 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1946 r->in.architecture, version);
1948 if ( !W_ERROR_IS_OK(status) )
1951 * if the client asked for a specific version,
1952 * or this is something other than Windows NT x86,
1956 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1959 /* try for Win2k driver if "Windows NT x86" */
1962 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1965 status = WERR_UNKNOWN_PRINTER_DRIVER;
1970 if (printer_driver_in_use(info)) {
1971 status = WERR_PRINTER_DRIVER_IN_USE;
1976 * we have a couple of cases to consider.
1977 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1978 * then the delete should fail if **any** files overlap with
1980 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1981 * non-overlapping files
1982 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1983 * is set, the do not delete any files
1984 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1987 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1989 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1991 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
1992 /* no idea of the correct error here */
1993 status = WERR_ACCESS_DENIED;
1998 /* also check for W32X86/3 if necessary; maybe we already have? */
2000 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2001 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2003 r->in.architecture, 3)))
2006 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2007 /* no idea of the correct error here */
2008 free_a_printer_driver(info_win2k);
2009 status = WERR_ACCESS_DENIED;
2013 /* if we get to here, we now have 2 driver info structures to remove */
2014 /* remove the Win2k driver first*/
2016 status_win2k = delete_printer_driver(
2017 p, info_win2k, 3, delete_files);
2018 free_a_printer_driver(info_win2k);
2020 /* this should not have failed---if it did, report to client */
2022 if ( !W_ERROR_IS_OK(status_win2k) )
2027 status = delete_printer_driver(p, info, version, delete_files);
2029 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2032 free_a_printer_driver(info);
2038 /****************************************************************************
2039 Internal routine for removing printerdata
2040 ***************************************************************************/
2042 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2044 return delete_printer_data( printer->info_2, key, value );
2047 /****************************************************************************
2048 Internal routine for storing printerdata
2049 ***************************************************************************/
2051 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2052 const char *key, const char *value,
2053 uint32_t type, uint8_t *data, int real_len)
2055 /* the registry objects enforce uniqueness based on value name */
2057 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2060 /********************************************************************
2061 GetPrinterData on a printer server Handle.
2062 ********************************************************************/
2064 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2066 enum winreg_Type *type,
2067 union spoolss_PrinterData *data)
2069 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2071 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2077 if (!StrCaseCmp(value, "BeepEnabled")) {
2083 if (!StrCaseCmp(value, "EventLog")) {
2085 /* formally was 0x1b */
2090 if (!StrCaseCmp(value, "NetPopup")) {
2096 if (!StrCaseCmp(value, "MajorVersion")) {
2099 /* Windows NT 4.0 seems to not allow uploading of drivers
2100 to a server that reports 0x3 as the MajorVersion.
2101 need to investigate more how Win2k gets around this .
2104 if (RA_WINNT == get_remote_arch()) {
2113 if (!StrCaseCmp(value, "MinorVersion")) {
2120 * uint32_t size = 0x114
2121 * uint32_t major = 5
2122 * uint32_t minor = [0|1]
2123 * uint32_t build = [2195|2600]
2124 * extra unicode string = e.g. "Service Pack 3"
2126 if (!StrCaseCmp(value, "OSVersion")) {
2128 enum ndr_err_code ndr_err;
2129 struct spoolss_OSVersion os;
2131 os.major = 5; /* Windows 2000 == 5.0 */
2133 os.build = 2195; /* build */
2134 os.extra_string = ""; /* leave extra string empty */
2136 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2137 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2138 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2139 return WERR_GENERAL_FAILURE;
2143 data->binary = blob;
2149 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2152 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2153 W_ERROR_HAVE_NO_MEMORY(data->string);
2158 if (!StrCaseCmp(value, "Architecture")) {
2160 data->string = talloc_strdup(mem_ctx,
2161 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2162 W_ERROR_HAVE_NO_MEMORY(data->string);
2167 if (!StrCaseCmp(value, "DsPresent")) {
2170 /* only show the publish check box if we are a
2171 member of a AD domain */
2173 if (lp_security() == SEC_ADS) {
2181 if (!StrCaseCmp(value, "DNSMachineName")) {
2182 const char *hostname = get_mydnsfullname();
2185 return WERR_BADFILE;
2189 data->string = talloc_strdup(mem_ctx, hostname);
2190 W_ERROR_HAVE_NO_MEMORY(data->string);
2197 return WERR_INVALID_PARAM;
2200 /****************************************************************
2201 _spoolss_GetPrinterData
2202 ****************************************************************/
2204 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2205 struct spoolss_GetPrinterData *r)
2207 struct spoolss_GetPrinterDataEx r2;
2209 r2.in.handle = r->in.handle;
2210 r2.in.key_name = "PrinterDriverData";
2211 r2.in.value_name = r->in.value_name;
2212 r2.in.offered = r->in.offered;
2213 r2.out.type = r->out.type;
2214 r2.out.data = r->out.data;
2215 r2.out.needed = r->out.needed;
2217 return _spoolss_GetPrinterDataEx(p, &r2);
2220 /*********************************************************
2221 Connect to the client machine.
2222 **********************************************************/
2224 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2225 struct sockaddr_storage *client_ss, const char *remote_machine)
2228 struct cli_state *the_cli;
2229 struct sockaddr_storage rm_addr;
2230 char addr[INET6_ADDRSTRLEN];
2232 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2233 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2235 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2236 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2239 print_sockaddr(addr, sizeof(addr), &rm_addr);
2241 rm_addr = *client_ss;
2242 print_sockaddr(addr, sizeof(addr), &rm_addr);
2243 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2247 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2248 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2253 /* setup the connection */
2254 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2255 &rm_addr, 0, "IPC$", "IPC",
2259 0, lp_client_signing(), NULL );
2261 if ( !NT_STATUS_IS_OK( ret ) ) {
2262 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2267 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2268 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2269 cli_shutdown(the_cli);
2274 * Ok - we have an anonymous connection to the IPC$ share.
2275 * Now start the NT Domain stuff :-).
2278 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2279 if (!NT_STATUS_IS_OK(ret)) {
2280 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2281 remote_machine, nt_errstr(ret)));
2282 cli_shutdown(the_cli);
2289 /***************************************************************************
2290 Connect to the client.
2291 ****************************************************************************/
2293 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2294 uint32_t localprinter, uint32_t type,
2295 struct policy_handle *handle,
2296 struct sockaddr_storage *client_ss)
2302 * If it's the first connection, contact the client
2303 * and connect to the IPC$ share anonymously
2305 if (smb_connections==0) {
2306 fstring unix_printer;
2308 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2310 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2313 messaging_register(smbd_messaging_context(), NULL,
2314 MSG_PRINTER_NOTIFY2,
2315 receive_notify2_message_list);
2316 /* Tell the connections db we're now interested in printer
2317 * notify messages. */
2318 serverid_register_msg_flags(
2319 messaging_server_id(smbd_messaging_context()),
2320 true, FLAG_MSG_PRINT_NOTIFY);
2324 * Tell the specific printing tdb we want messages for this printer
2325 * by registering our PID.
2328 if (!print_notify_register_pid(snum))
2329 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2333 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2341 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2342 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2343 win_errstr(result)));
2345 return (W_ERROR_IS_OK(result));
2348 /****************************************************************
2349 ****************************************************************/
2351 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2352 const struct spoolss_NotifyOption *r)
2354 struct spoolss_NotifyOption *option;
2361 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2368 if (!option->count) {
2372 option->types = talloc_zero_array(option,
2373 struct spoolss_NotifyOptionType, option->count);
2374 if (!option->types) {
2375 talloc_free(option);
2379 for (i=0; i < option->count; i++) {
2380 option->types[i] = r->types[i];
2382 if (option->types[i].count) {
2383 option->types[i].fields = talloc_zero_array(option,
2384 union spoolss_Field, option->types[i].count);
2385 if (!option->types[i].fields) {
2386 talloc_free(option);
2389 for (k=0; k<option->types[i].count; k++) {
2390 option->types[i].fields[k] =
2391 r->types[i].fields[k];
2399 /****************************************************************
2400 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2402 * before replying OK: status=0 a rpc call is made to the workstation
2403 * asking ReplyOpenPrinter
2405 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2406 * called from api_spoolss_rffpcnex
2407 ****************************************************************/
2409 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2410 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2413 struct spoolss_NotifyOption *option = r->in.notify_options;
2414 struct sockaddr_storage client_ss;
2416 /* store the notify value in the printer struct */
2418 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2421 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2422 "Invalid handle (%s:%u:%u).\n",
2423 OUR_HANDLE(r->in.handle)));
2427 Printer->notify.flags = r->in.flags;
2428 Printer->notify.options = r->in.options;
2429 Printer->notify.printerlocal = r->in.printer_local;
2431 TALLOC_FREE(Printer->notify.option);
2432 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2434 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2436 /* Connect to the client machine and send a ReplyOpenPrinter */
2438 if ( Printer->printer_type == SPLHND_SERVER)
2440 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2441 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2444 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2445 "client_address is %s\n", p->client_address));
2447 if (!interpret_string_addr(&client_ss, p->client_address,
2449 return WERR_SERVER_UNAVAILABLE;
2452 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2453 Printer->notify.printerlocal, 1,
2454 &Printer->notify.client_hnd, &client_ss))
2455 return WERR_SERVER_UNAVAILABLE;
2457 Printer->notify.client_connected = true;
2462 /*******************************************************************
2463 * fill a notify_info_data with the servername
2464 ********************************************************************/
2466 static void spoolss_notify_server_name(int snum,
2467 struct spoolss_Notify *data,
2468 print_queue_struct *queue,
2469 NT_PRINTER_INFO_LEVEL *printer,
2470 TALLOC_CTX *mem_ctx)
2472 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2475 /*******************************************************************
2476 * fill a notify_info_data with the printername (not including the servername).
2477 ********************************************************************/
2479 static void spoolss_notify_printer_name(int snum,
2480 struct spoolss_Notify *data,
2481 print_queue_struct *queue,
2482 NT_PRINTER_INFO_LEVEL *printer,
2483 TALLOC_CTX *mem_ctx)
2485 /* the notify name should not contain the \\server\ part */
2486 char *p = strrchr(printer->info_2->printername, '\\');
2489 p = printer->info_2->printername;
2494 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2497 /*******************************************************************
2498 * fill a notify_info_data with the servicename
2499 ********************************************************************/
2501 static void spoolss_notify_share_name(int snum,
2502 struct spoolss_Notify *data,
2503 print_queue_struct *queue,
2504 NT_PRINTER_INFO_LEVEL *printer,
2505 TALLOC_CTX *mem_ctx)
2507 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2510 /*******************************************************************
2511 * fill a notify_info_data with the port name
2512 ********************************************************************/
2514 static void spoolss_notify_port_name(int snum,
2515 struct spoolss_Notify *data,
2516 print_queue_struct *queue,
2517 NT_PRINTER_INFO_LEVEL *printer,
2518 TALLOC_CTX *mem_ctx)
2520 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2523 /*******************************************************************
2524 * fill a notify_info_data with the printername
2525 * but it doesn't exist, have to see what to do
2526 ********************************************************************/
2528 static void spoolss_notify_driver_name(int snum,
2529 struct spoolss_Notify *data,
2530 print_queue_struct *queue,
2531 NT_PRINTER_INFO_LEVEL *printer,
2532 TALLOC_CTX *mem_ctx)
2534 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2537 /*******************************************************************
2538 * fill a notify_info_data with the comment
2539 ********************************************************************/
2541 static void spoolss_notify_comment(int snum,
2542 struct spoolss_Notify *data,
2543 print_queue_struct *queue,
2544 NT_PRINTER_INFO_LEVEL *printer,
2545 TALLOC_CTX *mem_ctx)
2549 if (*printer->info_2->comment == '\0') {
2550 p = lp_comment(snum);
2552 p = printer->info_2->comment;
2555 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2558 /*******************************************************************
2559 * fill a notify_info_data with the comment
2560 * location = "Room 1, floor 2, building 3"
2561 ********************************************************************/
2563 static void spoolss_notify_location(int snum,
2564 struct spoolss_Notify *data,
2565 print_queue_struct *queue,
2566 NT_PRINTER_INFO_LEVEL *printer,
2567 TALLOC_CTX *mem_ctx)
2569 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2572 /*******************************************************************
2573 * fill a notify_info_data with the device mode
2574 * jfm:xxxx don't to it for know but that's a real problem !!!
2575 ********************************************************************/
2577 static void spoolss_notify_devmode(int snum,
2578 struct spoolss_Notify *data,
2579 print_queue_struct *queue,
2580 NT_PRINTER_INFO_LEVEL *printer,
2581 TALLOC_CTX *mem_ctx)
2583 /* for a dummy implementation we have to zero the fields */
2584 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2587 /*******************************************************************
2588 * fill a notify_info_data with the separator file name
2589 ********************************************************************/
2591 static void spoolss_notify_sepfile(int snum,
2592 struct spoolss_Notify *data,
2593 print_queue_struct *queue,
2594 NT_PRINTER_INFO_LEVEL *printer,
2595 TALLOC_CTX *mem_ctx)
2597 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2600 /*******************************************************************
2601 * fill a notify_info_data with the print processor
2602 * jfm:xxxx return always winprint to indicate we don't do anything to it
2603 ********************************************************************/
2605 static void spoolss_notify_print_processor(int snum,
2606 struct spoolss_Notify *data,
2607 print_queue_struct *queue,
2608 NT_PRINTER_INFO_LEVEL *printer,
2609 TALLOC_CTX *mem_ctx)
2611 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2614 /*******************************************************************
2615 * fill a notify_info_data with the print processor options
2616 * jfm:xxxx send an empty string
2617 ********************************************************************/
2619 static void spoolss_notify_parameters(int snum,
2620 struct spoolss_Notify *data,
2621 print_queue_struct *queue,
2622 NT_PRINTER_INFO_LEVEL *printer,
2623 TALLOC_CTX *mem_ctx)
2625 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2628 /*******************************************************************
2629 * fill a notify_info_data with the data type
2630 * jfm:xxxx always send RAW as data type
2631 ********************************************************************/
2633 static void spoolss_notify_datatype(int snum,
2634 struct spoolss_Notify *data,
2635 print_queue_struct *queue,
2636 NT_PRINTER_INFO_LEVEL *printer,
2637 TALLOC_CTX *mem_ctx)
2639 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2642 /*******************************************************************
2643 * fill a notify_info_data with the security descriptor
2644 * jfm:xxxx send an null pointer to say no security desc
2645 * have to implement security before !
2646 ********************************************************************/
2648 static void spoolss_notify_security_desc(int snum,
2649 struct spoolss_Notify *data,
2650 print_queue_struct *queue,
2651 NT_PRINTER_INFO_LEVEL *printer,
2652 TALLOC_CTX *mem_ctx)
2654 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2655 printer->info_2->secdesc_buf->sd_size,
2656 printer->info_2->secdesc_buf->sd);
2659 /*******************************************************************
2660 * fill a notify_info_data with the attributes
2661 * jfm:xxxx a samba printer is always shared
2662 ********************************************************************/
2664 static void spoolss_notify_attributes(int snum,
2665 struct spoolss_Notify *data,
2666 print_queue_struct *queue,
2667 NT_PRINTER_INFO_LEVEL *printer,
2668 TALLOC_CTX *mem_ctx)
2670 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2673 /*******************************************************************
2674 * fill a notify_info_data with the priority
2675 ********************************************************************/
2677 static void spoolss_notify_priority(int snum,
2678 struct spoolss_Notify *data,
2679 print_queue_struct *queue,
2680 NT_PRINTER_INFO_LEVEL *printer,
2681 TALLOC_CTX *mem_ctx)
2683 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2686 /*******************************************************************
2687 * fill a notify_info_data with the default priority
2688 ********************************************************************/
2690 static void spoolss_notify_default_priority(int snum,
2691 struct spoolss_Notify *data,
2692 print_queue_struct *queue,
2693 NT_PRINTER_INFO_LEVEL *printer,
2694 TALLOC_CTX *mem_ctx)
2696 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2699 /*******************************************************************
2700 * fill a notify_info_data with the start time
2701 ********************************************************************/
2703 static void spoolss_notify_start_time(int snum,
2704 struct spoolss_Notify *data,
2705 print_queue_struct *queue,
2706 NT_PRINTER_INFO_LEVEL *printer,
2707 TALLOC_CTX *mem_ctx)
2709 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2712 /*******************************************************************
2713 * fill a notify_info_data with the until time
2714 ********************************************************************/
2716 static void spoolss_notify_until_time(int snum,
2717 struct spoolss_Notify *data,
2718 print_queue_struct *queue,
2719 NT_PRINTER_INFO_LEVEL *printer,
2720 TALLOC_CTX *mem_ctx)
2722 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2725 /*******************************************************************
2726 * fill a notify_info_data with the status
2727 ********************************************************************/
2729 static void spoolss_notify_status(int snum,
2730 struct spoolss_Notify *data,
2731 print_queue_struct *queue,
2732 NT_PRINTER_INFO_LEVEL *printer,
2733 TALLOC_CTX *mem_ctx)
2735 print_status_struct status;
2737 print_queue_length(snum, &status);
2738 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2741 /*******************************************************************
2742 * fill a notify_info_data with the number of jobs queued
2743 ********************************************************************/
2745 static void spoolss_notify_cjobs(int snum,
2746 struct spoolss_Notify *data,
2747 print_queue_struct *queue,
2748 NT_PRINTER_INFO_LEVEL *printer,
2749 TALLOC_CTX *mem_ctx)
2751 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2754 /*******************************************************************
2755 * fill a notify_info_data with the average ppm
2756 ********************************************************************/
2758 static void spoolss_notify_average_ppm(int snum,
2759 struct spoolss_Notify *data,
2760 print_queue_struct *queue,
2761 NT_PRINTER_INFO_LEVEL *printer,
2762 TALLOC_CTX *mem_ctx)
2764 /* always respond 8 pages per minutes */
2765 /* a little hard ! */
2766 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2769 /*******************************************************************
2770 * fill a notify_info_data with username
2771 ********************************************************************/
2773 static void spoolss_notify_username(int snum,
2774 struct spoolss_Notify *data,
2775 print_queue_struct *queue,
2776 NT_PRINTER_INFO_LEVEL *printer,
2777 TALLOC_CTX *mem_ctx)
2779 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2782 /*******************************************************************
2783 * fill a notify_info_data with job status
2784 ********************************************************************/
2786 static void spoolss_notify_job_status(int snum,
2787 struct spoolss_Notify *data,
2788 print_queue_struct *queue,
2789 NT_PRINTER_INFO_LEVEL *printer,
2790 TALLOC_CTX *mem_ctx)
2792 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2795 /*******************************************************************
2796 * fill a notify_info_data with job name
2797 ********************************************************************/
2799 static void spoolss_notify_job_name(int snum,
2800 struct spoolss_Notify *data,
2801 print_queue_struct *queue,
2802 NT_PRINTER_INFO_LEVEL *printer,
2803 TALLOC_CTX *mem_ctx)
2805 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2808 /*******************************************************************
2809 * fill a notify_info_data with job status
2810 ********************************************************************/
2812 static void spoolss_notify_job_status_string(int snum,
2813 struct spoolss_Notify *data,
2814 print_queue_struct *queue,
2815 NT_PRINTER_INFO_LEVEL *printer,
2816 TALLOC_CTX *mem_ctx)
2819 * Now we're returning job status codes we just return a "" here. JRA.
2824 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2827 switch (queue->status) {
2832 p = ""; /* NT provides the paused string */
2841 #endif /* NO LONGER NEEDED. */
2843 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2846 /*******************************************************************
2847 * fill a notify_info_data with job time
2848 ********************************************************************/
2850 static void spoolss_notify_job_time(int snum,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 NT_PRINTER_INFO_LEVEL *printer,
2854 TALLOC_CTX *mem_ctx)
2856 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2859 /*******************************************************************
2860 * fill a notify_info_data with job size
2861 ********************************************************************/
2863 static void spoolss_notify_job_size(int snum,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2869 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2872 /*******************************************************************
2873 * fill a notify_info_data with page info
2874 ********************************************************************/
2875 static void spoolss_notify_total_pages(int snum,
2876 struct spoolss_Notify *data,
2877 print_queue_struct *queue,
2878 NT_PRINTER_INFO_LEVEL *printer,
2879 TALLOC_CTX *mem_ctx)
2881 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2884 /*******************************************************************
2885 * fill a notify_info_data with pages printed info.
2886 ********************************************************************/
2887 static void spoolss_notify_pages_printed(int snum,
2888 struct spoolss_Notify *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2893 /* Add code when back-end tracks this */
2894 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2897 /*******************************************************************
2898 Fill a notify_info_data with job position.
2899 ********************************************************************/
2901 static void spoolss_notify_job_position(int snum,
2902 struct spoolss_Notify *data,
2903 print_queue_struct *queue,
2904 NT_PRINTER_INFO_LEVEL *printer,
2905 TALLOC_CTX *mem_ctx)
2907 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2910 /*******************************************************************
2911 Fill a notify_info_data with submitted time.
2912 ********************************************************************/
2914 static void spoolss_notify_submitted_time(int snum,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 NT_PRINTER_INFO_LEVEL *printer,
2918 TALLOC_CTX *mem_ctx)
2920 data->data.string.string = NULL;
2921 data->data.string.size = 0;
2923 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2924 &data->data.string.string,
2925 &data->data.string.size);
2929 struct s_notify_info_data_table
2931 enum spoolss_NotifyType type;
2934 enum spoolss_NotifyTable variable_type;
2935 void (*fn) (int snum, struct spoolss_Notify *data,
2936 print_queue_struct *queue,
2937 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2940 /* A table describing the various print notification constants and
2941 whether the notification data is a pointer to a variable sized
2942 buffer, a one value uint32_t or a two value uint32_t. */
2944 static const struct s_notify_info_data_table notify_info_data_table[] =
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2950 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2951 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2952 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2953 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2954 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2955 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2956 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2957 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2958 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2959 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2960 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2961 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2962 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2963 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2964 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2965 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2966 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2967 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2968 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
2969 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2970 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
2971 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2972 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2973 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2974 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2975 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2976 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2977 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2978 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2979 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2980 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2981 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2982 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
2983 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
2984 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
2985 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
2986 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2987 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
2988 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
2989 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2990 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2991 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
2992 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
2993 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
2994 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
2997 /*******************************************************************
2998 Return the variable_type of info_data structure.
2999 ********************************************************************/
3001 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3006 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3007 if ( (notify_info_data_table[i].type == type) &&
3008 (notify_info_data_table[i].field == field) ) {
3009 return notify_info_data_table[i].variable_type;
3013 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3018 /****************************************************************************
3019 ****************************************************************************/
3021 static bool search_notify(enum spoolss_NotifyType type,
3027 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3028 if (notify_info_data_table[i].type == type &&
3029 notify_info_data_table[i].field == field &&
3030 notify_info_data_table[i].fn != NULL) {
3039 /****************************************************************************
3040 ****************************************************************************/
3042 void construct_info_data(struct spoolss_Notify *info_data,
3043 enum spoolss_NotifyType type,
3047 info_data->type = type;
3048 info_data->field.field = field;
3049 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3050 info_data->job_id = id;
3053 /*******************************************************************
3055 * fill a notify_info struct with info asked
3057 ********************************************************************/
3059 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3060 struct spoolss_NotifyInfo *info,
3062 const struct spoolss_NotifyOptionType *option_type,
3064 TALLOC_CTX *mem_ctx)
3067 enum spoolss_NotifyType type;
3070 struct spoolss_Notify *current_data;
3071 NT_PRINTER_INFO_LEVEL *printer = NULL;
3072 print_queue_struct *queue=NULL;
3074 type = option_type->type;
3076 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3077 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3078 option_type->count, lp_servicename(snum)));
3080 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3083 for(field_num=0; field_num < option_type->count; field_num++) {
3084 field = option_type->fields[field_num].field;
3086 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3088 if (!search_notify(type, field, &j) )
3091 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3092 struct spoolss_Notify,
3094 if (info->notifies == NULL) {
3095 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3096 free_a_printer(&printer, 2);
3100 current_data = &info->notifies[info->count];
3102 construct_info_data(current_data, type, field, id);
3104 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3105 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3107 notify_info_data_table[j].fn(snum, current_data, queue,
3113 free_a_printer(&printer, 2);
3117 /*******************************************************************
3119 * fill a notify_info struct with info asked
3121 ********************************************************************/
3123 static bool construct_notify_jobs_info(print_queue_struct *queue,
3124 struct spoolss_NotifyInfo *info,
3125 NT_PRINTER_INFO_LEVEL *printer,
3127 const struct spoolss_NotifyOptionType *option_type,
3129 TALLOC_CTX *mem_ctx)
3132 enum spoolss_NotifyType type;
3134 struct spoolss_Notify *current_data;
3136 DEBUG(4,("construct_notify_jobs_info\n"));
3138 type = option_type->type;
3140 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3141 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3142 option_type->count));
3144 for(field_num=0; field_num<option_type->count; field_num++) {
3145 field = option_type->fields[field_num].field;
3147 if (!search_notify(type, field, &j) )
3150 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3151 struct spoolss_Notify,
3153 if (info->notifies == NULL) {
3154 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3158 current_data=&(info->notifies[info->count]);
3160 construct_info_data(current_data, type, field, id);
3161 notify_info_data_table[j].fn(snum, current_data, queue,
3170 * JFM: The enumeration is not that simple, it's even non obvious.
3172 * let's take an example: I want to monitor the PRINTER SERVER for
3173 * the printer's name and the number of jobs currently queued.
3174 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3175 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3177 * I have 3 printers on the back of my server.
3179 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3182 * 1 printer 1 name 1
3183 * 2 printer 1 cjob 1
3184 * 3 printer 2 name 2
3185 * 4 printer 2 cjob 2
3186 * 5 printer 3 name 3
3187 * 6 printer 3 name 3
3189 * that's the print server case, the printer case is even worse.
3192 /*******************************************************************
3194 * enumerate all printers on the printserver
3195 * fill a notify_info struct with info asked
3197 ********************************************************************/
3199 static WERROR printserver_notify_info(pipes_struct *p,
3200 struct policy_handle *hnd,
3201 struct spoolss_NotifyInfo *info,
3202 TALLOC_CTX *mem_ctx)
3205 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3206 int n_services=lp_numservices();
3208 struct spoolss_NotifyOption *option;
3209 struct spoolss_NotifyOptionType option_type;
3211 DEBUG(4,("printserver_notify_info\n"));
3216 option = Printer->notify.option;
3219 info->notifies = NULL;
3222 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3223 sending a ffpcn() request first */
3228 for (i=0; i<option->count; i++) {
3229 option_type = option->types[i];
3231 if (option_type.type != PRINTER_NOTIFY_TYPE)
3234 for (snum=0; snum<n_services; snum++)
3236 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3237 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3243 * Debugging information, don't delete.
3246 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3247 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3248 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3250 for (i=0; i<info->count; i++) {
3251 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3252 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3253 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3260 /*******************************************************************
3262 * fill a notify_info struct with info asked
3264 ********************************************************************/
3266 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3267 struct spoolss_NotifyInfo *info,
3268 TALLOC_CTX *mem_ctx)
3271 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3274 struct spoolss_NotifyOption *option;
3275 struct spoolss_NotifyOptionType option_type;
3277 print_queue_struct *queue=NULL;
3278 print_status_struct status;
3280 DEBUG(4,("printer_notify_info\n"));
3285 option = Printer->notify.option;
3289 info->notifies = NULL;
3292 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3293 sending a ffpcn() request first */
3298 get_printer_snum(p, hnd, &snum, NULL);
3300 for (i=0; i<option->count; i++) {
3301 option_type = option->types[i];
3303 switch (option_type.type) {
3304 case PRINTER_NOTIFY_TYPE:
3305 if(construct_notify_printer_info(Printer, info, snum,
3311 case JOB_NOTIFY_TYPE: {
3312 NT_PRINTER_INFO_LEVEL *printer = NULL;
3314 count = print_queue_status(snum, &queue, &status);
3316 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3319 for (j=0; j<count; j++) {
3320 construct_notify_jobs_info(&queue[j], info,
3327 free_a_printer(&printer, 2);
3337 * Debugging information, don't delete.
3340 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3341 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3342 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3344 for (i=0; i<info->count; i++) {
3345 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3346 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3347 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3353 /****************************************************************
3354 _spoolss_RouterRefreshPrinterChangeNotify
3355 ****************************************************************/
3357 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3358 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3360 struct spoolss_NotifyInfo *info;
3362 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3363 WERROR result = WERR_BADFID;
3365 /* we always have a spoolss_NotifyInfo struct */
3366 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3368 result = WERR_NOMEM;
3372 *r->out.info = info;
3375 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3376 "Invalid handle (%s:%u:%u).\n",
3377 OUR_HANDLE(r->in.handle)));
3381 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3384 * We are now using the change value, and
3385 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3386 * I don't have a global notification system, I'm sending back all the
3387 * informations even when _NOTHING_ has changed.
3390 /* We need to keep track of the change value to send back in
3391 RRPCN replies otherwise our updates are ignored. */
3393 Printer->notify.fnpcn = true;
3395 if (Printer->notify.client_connected) {
3396 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3397 "Saving change value in request [%x]\n",
3399 Printer->notify.change = r->in.change_low;
3402 /* just ignore the spoolss_NotifyOption */
3404 switch (Printer->printer_type) {
3406 result = printserver_notify_info(p, r->in.handle,
3410 case SPLHND_PRINTER:
3411 result = printer_notify_info(p, r->in.handle,
3416 Printer->notify.fnpcn = false;
3422 /********************************************************************
3423 * construct_printer_info_0
3424 * fill a printer_info_0 struct
3425 ********************************************************************/
3427 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3428 const NT_PRINTER_INFO_LEVEL *ntprinter,
3429 struct spoolss_PrinterInfo0 *r,
3433 counter_printer_0 *session_counter;
3435 print_status_struct status;
3437 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3438 W_ERROR_HAVE_NO_MEMORY(r->printername);
3440 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3441 W_ERROR_HAVE_NO_MEMORY(r->servername);
3443 count = print_queue_length(snum, &status);
3445 /* check if we already have a counter for this printer */
3446 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3447 if (session_counter->snum == snum)
3451 /* it's the first time, add it to the list */
3452 if (session_counter == NULL) {
3453 session_counter = SMB_MALLOC_P(counter_printer_0);
3454 W_ERROR_HAVE_NO_MEMORY(session_counter);
3455 ZERO_STRUCTP(session_counter);
3456 session_counter->snum = snum;
3457 session_counter->counter = 0;
3458 DLIST_ADD(counter_list, session_counter);
3462 session_counter->counter++;
3468 setuptime = (time_t)ntprinter->info_2->setuptime;
3470 init_systemtime(&r->time, gmtime(&setuptime));
3473 * the global_counter should be stored in a TDB as it's common to all the clients
3474 * and should be zeroed on samba startup
3476 r->global_counter = session_counter->counter;
3478 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3479 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3480 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3481 r->free_build = SPOOLSS_RELEASE_BUILD;
3483 r->max_spooling = 0;
3484 r->session_counter = session_counter->counter;
3485 r->num_error_out_of_paper = 0x0;
3486 r->num_error_not_ready = 0x0; /* number of print failure */
3488 r->number_of_processors = 0x1;
3489 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3490 r->high_part_total_bytes = 0x0;
3491 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3492 r->last_error = WERR_OK;
3493 r->status = nt_printq_status(status.status);
3494 r->enumerate_network_printers = 0x0;
3495 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3496 r->processor_architecture = 0x0;
3497 r->processor_level = 0x6; /* 6 ???*/
3506 /****************************************************************************
3507 Create a spoolss_DeviceMode struct. Returns talloced memory.
3508 ****************************************************************************/
3510 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3511 const char *servicename)
3513 NT_PRINTER_INFO_LEVEL *printer = NULL;
3514 struct spoolss_DeviceMode *devmode = NULL;
3516 DEBUG(7,("construct_dev_mode\n"));
3518 DEBUGADD(8,("getting printer characteristics\n"));
3520 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3523 if (!printer->info_2->devmode) {
3524 DEBUG(5, ("BONG! There was no device mode!\n"));
3528 devmode = talloc_steal(mem_ctx, printer->info_2->devmode);
3531 free_a_printer(&printer,2);
3536 /********************************************************************
3537 * construct_printer_info1
3538 * fill a spoolss_PrinterInfo1 struct
3539 ********************************************************************/
3541 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3542 const NT_PRINTER_INFO_LEVEL *ntprinter,
3544 struct spoolss_PrinterInfo1 *r,
3549 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3550 ntprinter->info_2->printername,
3551 ntprinter->info_2->drivername,
3552 ntprinter->info_2->location);
3553 W_ERROR_HAVE_NO_MEMORY(r->description);
3555 if (*ntprinter->info_2->comment == '\0') {
3556 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3558 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3560 W_ERROR_HAVE_NO_MEMORY(r->comment);
3562 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3563 W_ERROR_HAVE_NO_MEMORY(r->name);
3568 /********************************************************************
3569 * construct_printer_info2
3570 * fill a spoolss_PrinterInfo2 struct
3571 ********************************************************************/
3573 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3574 const NT_PRINTER_INFO_LEVEL *ntprinter,
3575 struct spoolss_PrinterInfo2 *r,
3580 print_status_struct status;
3582 count = print_queue_length(snum, &status);
3584 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3585 W_ERROR_HAVE_NO_MEMORY(r->servername);
3586 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3587 W_ERROR_HAVE_NO_MEMORY(r->printername);
3588 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3589 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3590 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3591 W_ERROR_HAVE_NO_MEMORY(r->portname);
3592 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3593 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3595 if (*ntprinter->info_2->comment == '\0') {
3596 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3598 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3600 W_ERROR_HAVE_NO_MEMORY(r->comment);
3602 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3603 W_ERROR_HAVE_NO_MEMORY(r->location);
3604 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3605 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3606 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3607 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3608 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3609 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3610 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3611 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3613 r->attributes = ntprinter->info_2->attributes;
3615 r->priority = ntprinter->info_2->priority;
3616 r->defaultpriority = ntprinter->info_2->default_priority;
3617 r->starttime = ntprinter->info_2->starttime;
3618 r->untiltime = ntprinter->info_2->untiltime;
3619 r->status = nt_printq_status(status.status);
3621 r->averageppm = ntprinter->info_2->averageppm;
3623 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3625 DEBUG(8,("Returning NULL Devicemode!\n"));
3630 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3631 /* don't use talloc_steal() here unless you do a deep steal of all
3632 the SEC_DESC members */
3634 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3640 /********************************************************************
3641 * construct_printer_info3
3642 * fill a spoolss_PrinterInfo3 struct
3643 ********************************************************************/
3645 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3646 const NT_PRINTER_INFO_LEVEL *ntprinter,
3647 struct spoolss_PrinterInfo3 *r,
3650 /* These are the components of the SD we are returning. */
3652 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3653 /* don't use talloc_steal() here unless you do a deep steal of all
3654 the SEC_DESC members */
3656 r->secdesc = dup_sec_desc(mem_ctx,
3657 ntprinter->info_2->secdesc_buf->sd);
3658 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3664 /********************************************************************
3665 * construct_printer_info4
3666 * fill a spoolss_PrinterInfo4 struct
3667 ********************************************************************/
3669 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3670 const NT_PRINTER_INFO_LEVEL *ntprinter,
3671 struct spoolss_PrinterInfo4 *r,
3674 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3675 W_ERROR_HAVE_NO_MEMORY(r->printername);
3676 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3677 W_ERROR_HAVE_NO_MEMORY(r->servername);
3679 r->attributes = ntprinter->info_2->attributes;
3684 /********************************************************************
3685 * construct_printer_info5
3686 * fill a spoolss_PrinterInfo5 struct
3687 ********************************************************************/
3689 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3690 const NT_PRINTER_INFO_LEVEL *ntprinter,
3691 struct spoolss_PrinterInfo5 *r,
3694 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3695 W_ERROR_HAVE_NO_MEMORY(r->printername);
3696 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3697 W_ERROR_HAVE_NO_MEMORY(r->portname);
3699 r->attributes = ntprinter->info_2->attributes;
3701 /* these two are not used by NT+ according to MSDN */
3703 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3704 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3709 /********************************************************************
3710 * construct_printer_info_6
3711 * fill a spoolss_PrinterInfo6 struct
3712 ********************************************************************/
3714 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3715 const NT_PRINTER_INFO_LEVEL *ntprinter,
3716 struct spoolss_PrinterInfo6 *r,
3720 print_status_struct status;
3722 count = print_queue_length(snum, &status);
3724 r->status = nt_printq_status(status.status);
3729 /********************************************************************
3730 * construct_printer_info7
3731 * fill a spoolss_PrinterInfo7 struct
3732 ********************************************************************/
3734 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3735 Printer_entry *print_hnd,
3736 struct spoolss_PrinterInfo7 *r,
3741 if (is_printer_published(print_hnd, snum, &guid)) {
3742 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3743 r->action = DSPRINT_PUBLISH;
3745 r->guid = talloc_strdup(mem_ctx, "");
3746 r->action = DSPRINT_UNPUBLISH;
3748 W_ERROR_HAVE_NO_MEMORY(r->guid);
3753 /********************************************************************
3754 * construct_printer_info8
3755 * fill a spoolss_PrinterInfo8 struct
3756 ********************************************************************/
3758 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3759 const NT_PRINTER_INFO_LEVEL *ntprinter,
3760 struct spoolss_DeviceModeInfo *r,
3763 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3765 DEBUG(8,("Returning NULL Devicemode!\n"));
3772 /********************************************************************
3773 ********************************************************************/
3775 static bool snum_is_shared_printer(int snum)
3777 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3780 /********************************************************************
3781 Spoolss_enumprinters.
3782 ********************************************************************/
3784 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3787 union spoolss_PrinterInfo **info_p,
3791 int n_services = lp_numservices();
3792 union spoolss_PrinterInfo *info = NULL;
3794 WERROR result = WERR_OK;
3799 for (snum = 0; snum < n_services; snum++) {
3801 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3803 if (!snum_is_shared_printer(snum)) {
3807 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3808 lp_servicename(snum), snum));
3810 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3811 union spoolss_PrinterInfo,
3814 result = WERR_NOMEM;
3818 result = get_a_printer(NULL, &ntprinter, 2,
3819 lp_const_servicename(snum));
3820 if (!W_ERROR_IS_OK(result)) {
3826 result = construct_printer_info0(info, ntprinter,
3827 &info[count].info0, snum);
3830 result = construct_printer_info1(info, ntprinter, flags,
3831 &info[count].info1, snum);
3834 result = construct_printer_info2(info, ntprinter,
3835 &info[count].info2, snum);
3838 result = construct_printer_info4(info, ntprinter,
3839 &info[count].info4, snum);
3842 result = construct_printer_info5(info, ntprinter,
3843 &info[count].info5, snum);
3847 result = WERR_UNKNOWN_LEVEL;
3848 free_a_printer(&ntprinter, 2);
3852 free_a_printer(&ntprinter, 2);
3853 if (!W_ERROR_IS_OK(result)) {
3864 if (!W_ERROR_IS_OK(result)) {
3874 /********************************************************************
3875 * handle enumeration of printers at level 0
3876 ********************************************************************/
3878 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3880 const char *servername,
3881 union spoolss_PrinterInfo **info,
3884 DEBUG(4,("enum_all_printers_info_0\n"));
3886 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3890 /********************************************************************
3891 ********************************************************************/
3893 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3895 union spoolss_PrinterInfo **info,
3898 DEBUG(4,("enum_all_printers_info_1\n"));
3900 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
3903 /********************************************************************
3904 enum_all_printers_info_1_local.
3905 *********************************************************************/
3907 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3908 union spoolss_PrinterInfo **info,
3911 DEBUG(4,("enum_all_printers_info_1_local\n"));
3913 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3916 /********************************************************************
3917 enum_all_printers_info_1_name.
3918 *********************************************************************/
3920 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3922 union spoolss_PrinterInfo **info,
3925 const char *s = name;
3927 DEBUG(4,("enum_all_printers_info_1_name\n"));
3929 if ((name[0] == '\\') && (name[1] == '\\')) {
3933 if (!is_myname_or_ipaddr(s)) {
3934 return WERR_INVALID_NAME;
3937 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3940 /********************************************************************
3941 enum_all_printers_info_1_network.
3942 *********************************************************************/
3944 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3946 union spoolss_PrinterInfo **info,
3949 const char *s = name;
3951 DEBUG(4,("enum_all_printers_info_1_network\n"));
3953 /* If we respond to a enum_printers level 1 on our name with flags
3954 set to PRINTER_ENUM_REMOTE with a list of printers then these
3955 printers incorrectly appear in the APW browse list.
3956 Specifically the printers for the server appear at the workgroup
3957 level where all the other servers in the domain are
3958 listed. Windows responds to this call with a
3959 WERR_CAN_NOT_COMPLETE so we should do the same. */
3961 if (name[0] == '\\' && name[1] == '\\') {
3965 if (is_myname_or_ipaddr(s)) {
3966 return WERR_CAN_NOT_COMPLETE;
3969 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
3972 /********************************************************************
3973 * api_spoolss_enumprinters
3975 * called from api_spoolss_enumprinters (see this to understand)
3976 ********************************************************************/
3978 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3979 union spoolss_PrinterInfo **info,
3982 DEBUG(4,("enum_all_printers_info_2\n"));
3984 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
3987 /********************************************************************
3988 * handle enumeration of printers at level 1
3989 ********************************************************************/
3991 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3994 union spoolss_PrinterInfo **info,
3997 /* Not all the flags are equals */
3999 if (flags & PRINTER_ENUM_LOCAL) {
4000 return enum_all_printers_info_1_local(mem_ctx, info, count);
4003 if (flags & PRINTER_ENUM_NAME) {
4004 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4007 if (flags & PRINTER_ENUM_NETWORK) {
4008 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4011 return WERR_OK; /* NT4sp5 does that */
4014 /********************************************************************
4015 * handle enumeration of printers at level 2
4016 ********************************************************************/
4018 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4020 const char *servername,
4021 union spoolss_PrinterInfo **info,
4024 if (flags & PRINTER_ENUM_LOCAL) {
4025 return enum_all_printers_info_2(mem_ctx, info, count);
4028 if (flags & PRINTER_ENUM_NAME) {
4029 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4030 return WERR_INVALID_NAME;
4033 return enum_all_printers_info_2(mem_ctx, info, count);
4036 if (flags & PRINTER_ENUM_REMOTE) {
4037 return WERR_UNKNOWN_LEVEL;
4043 /********************************************************************
4044 * handle enumeration of printers at level 4
4045 ********************************************************************/
4047 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4049 const char *servername,
4050 union spoolss_PrinterInfo **info,
4053 DEBUG(4,("enum_all_printers_info_4\n"));
4055 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4059 /********************************************************************
4060 * handle enumeration of printers at level 5
4061 ********************************************************************/
4063 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4065 const char *servername,
4066 union spoolss_PrinterInfo **info,
4069 DEBUG(4,("enum_all_printers_info_5\n"));
4071 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4074 /****************************************************************
4075 _spoolss_EnumPrinters
4076 ****************************************************************/
4078 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4079 struct spoolss_EnumPrinters *r)
4081 const char *name = NULL;
4084 /* that's an [in out] buffer */
4086 if (!r->in.buffer && (r->in.offered != 0)) {
4087 return WERR_INVALID_PARAM;
4090 DEBUG(4,("_spoolss_EnumPrinters\n"));
4094 *r->out.info = NULL;
4098 * flags==PRINTER_ENUM_NAME
4099 * if name=="" then enumerates all printers
4100 * if name!="" then enumerate the printer
4101 * flags==PRINTER_ENUM_REMOTE
4102 * name is NULL, enumerate printers
4103 * Level 2: name!="" enumerates printers, name can't be NULL
4104 * Level 3: doesn't exist
4105 * Level 4: does a local registry lookup
4106 * Level 5: same as Level 2
4110 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4111 W_ERROR_HAVE_NO_MEMORY(name);
4114 switch (r->in.level) {
4116 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4117 r->out.info, r->out.count);
4120 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4121 r->out.info, r->out.count);
4124 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4125 r->out.info, r->out.count);
4128 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4129 r->out.info, r->out.count);
4132 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4133 r->out.info, r->out.count);
4136 return WERR_UNKNOWN_LEVEL;
4139 if (!W_ERROR_IS_OK(result)) {
4143 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4144 spoolss_EnumPrinters,
4145 *r->out.info, r->in.level,
4147 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4148 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4150 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4153 /****************************************************************
4155 ****************************************************************/
4157 WERROR _spoolss_GetPrinter(pipes_struct *p,
4158 struct spoolss_GetPrinter *r)
4160 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4161 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4162 WERROR result = WERR_OK;
4166 /* that's an [in out] buffer */
4168 if (!r->in.buffer && (r->in.offered != 0)) {
4169 return WERR_INVALID_PARAM;
4174 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4178 result = get_a_printer(Printer, &ntprinter, 2,
4179 lp_const_servicename(snum));
4180 if (!W_ERROR_IS_OK(result)) {
4184 switch (r->in.level) {
4186 result = construct_printer_info0(p->mem_ctx, ntprinter,
4187 &r->out.info->info0, snum);
4190 result = construct_printer_info1(p->mem_ctx, ntprinter,
4192 &r->out.info->info1, snum);
4195 result = construct_printer_info2(p->mem_ctx, ntprinter,
4196 &r->out.info->info2, snum);
4199 result = construct_printer_info3(p->mem_ctx, ntprinter,
4200 &r->out.info->info3, snum);
4203 result = construct_printer_info4(p->mem_ctx, ntprinter,
4204 &r->out.info->info4, snum);
4207 result = construct_printer_info5(p->mem_ctx, ntprinter,
4208 &r->out.info->info5, snum);
4211 result = construct_printer_info6(p->mem_ctx, ntprinter,
4212 &r->out.info->info6, snum);
4215 result = construct_printer_info7(p->mem_ctx, Printer,
4216 &r->out.info->info7, snum);
4219 result = construct_printer_info8(p->mem_ctx, ntprinter,
4220 &r->out.info->info8, snum);
4223 result = WERR_UNKNOWN_LEVEL;
4227 free_a_printer(&ntprinter, 2);
4229 if (!W_ERROR_IS_OK(result)) {
4230 TALLOC_FREE(r->out.info);
4234 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4235 r->out.info, r->in.level);
4236 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4238 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4241 /********************************************************************
4242 ********************************************************************/
4244 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4245 const char **string_array,
4246 const char *cservername)
4248 int i, num_strings = 0;
4249 const char **array = NULL;
4251 if (!string_array) {
4255 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4257 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4258 cservername, string_array[i]);
4265 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4272 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4273 &array, &num_strings);
4279 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4281 if (in && strlen(in)) { \
4282 out = talloc_strdup(mem_ctx, in); \
4283 W_ERROR_HAVE_NO_MEMORY(out); \
4289 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4291 if (in && strlen(in)) { \
4292 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4294 out = talloc_strdup(mem_ctx, ""); \
4296 W_ERROR_HAVE_NO_MEMORY(out); \
4299 /********************************************************************
4300 * fill a spoolss_DriverInfo1 struct
4301 ********************************************************************/
4303 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4304 struct spoolss_DriverInfo1 *r,
4305 const struct spoolss_DriverInfo8 *driver,
4306 const char *servername)
4308 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4309 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4314 /********************************************************************
4315 * fill a spoolss_DriverInfo2 struct
4316 ********************************************************************/
4318 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4319 struct spoolss_DriverInfo2 *r,
4320 const struct spoolss_DriverInfo8 *driver,
4321 const char *servername)
4324 const char *cservername = canon_servername(servername);
4326 r->version = driver->version;
4328 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4329 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4330 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4331 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4333 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4334 driver->driver_path,
4337 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4341 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4342 driver->config_file,
4348 /********************************************************************
4349 * fill a spoolss_DriverInfo3 struct
4350 ********************************************************************/
4352 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4353 struct spoolss_DriverInfo3 *r,
4354 const struct spoolss_DriverInfo8 *driver,
4355 const char *servername)
4357 const char *cservername = canon_servername(servername);
4359 r->version = driver->version;
4361 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4362 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4363 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4364 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4366 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4367 driver->driver_path,
4370 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4374 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4375 driver->config_file,
4378 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4382 FILL_DRIVER_STRING(mem_ctx,
4383 driver->monitor_name,
4386 FILL_DRIVER_STRING(mem_ctx,
4387 driver->default_datatype,
4388 r->default_datatype);
4390 r->dependent_files = string_array_from_driver_info(mem_ctx,
4391 driver->dependent_files,
4396 /********************************************************************
4397 * fill a spoolss_DriverInfo4 struct
4398 ********************************************************************/
4400 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4401 struct spoolss_DriverInfo4 *r,
4402 const struct spoolss_DriverInfo8 *driver,
4403 const char *servername)
4405 const char *cservername = canon_servername(servername);
4407 r->version = driver->version;
4409 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4410 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4411 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4412 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4414 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4415 driver->driver_path,
4418 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4422 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4423 driver->config_file,
4426 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4430 r->dependent_files = string_array_from_driver_info(mem_ctx,
4431 driver->dependent_files,
4434 FILL_DRIVER_STRING(mem_ctx,
4435 driver->monitor_name,
4438 FILL_DRIVER_STRING(mem_ctx,
4439 driver->default_datatype,
4440 r->default_datatype);
4442 r->previous_names = string_array_from_driver_info(mem_ctx,
4443 driver->previous_names,
4449 /********************************************************************
4450 * fill a spoolss_DriverInfo5 struct
4451 ********************************************************************/
4453 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4454 struct spoolss_DriverInfo5 *r,
4455 const struct spoolss_DriverInfo8 *driver,
4456 const char *servername)
4458 const char *cservername = canon_servername(servername);
4460 r->version = driver->version;
4462 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4463 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4464 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4465 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4467 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4468 driver->driver_path,
4471 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4475 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4476 driver->config_file,
4479 r->driver_attributes = 0;
4480 r->config_version = 0;
4481 r->driver_version = 0;
4485 /********************************************************************
4486 * fill a spoolss_DriverInfo6 struct
4487 ********************************************************************/
4489 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4490 struct spoolss_DriverInfo6 *r,
4491 const struct spoolss_DriverInfo8 *driver,
4492 const char *servername)
4494 const char *cservername = canon_servername(servername);
4496 r->version = driver->version;
4498 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4499 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4500 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4501 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4503 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4504 driver->driver_path,
4507 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4511 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4512 driver->config_file,
4515 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4519 FILL_DRIVER_STRING(mem_ctx,
4520 driver->monitor_name,
4523 FILL_DRIVER_STRING(mem_ctx,
4524 driver->default_datatype,
4525 r->default_datatype);
4527 r->dependent_files = string_array_from_driver_info(mem_ctx,
4528 driver->dependent_files,
4530 r->previous_names = string_array_from_driver_info(mem_ctx,
4531 driver->previous_names,
4534 r->driver_date = driver->driver_date;
4535 r->driver_version = driver->driver_version;
4537 FILL_DRIVER_STRING(mem_ctx,
4538 driver->manufacturer_name,
4539 r->manufacturer_name);
4540 FILL_DRIVER_STRING(mem_ctx,
4541 driver->manufacturer_url,
4542 r->manufacturer_url);
4543 FILL_DRIVER_STRING(mem_ctx,
4544 driver->hardware_id,
4546 FILL_DRIVER_STRING(mem_ctx,
4553 /********************************************************************
4554 * fill a spoolss_DriverInfo8 struct
4555 ********************************************************************/
4557 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4558 struct spoolss_DriverInfo8 *r,
4559 const struct spoolss_DriverInfo8 *driver,
4560 const char *servername)
4562 const char *cservername = canon_servername(servername);
4564 r->version = driver->version;
4566 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4567 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4568 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4569 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4571 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4572 driver->driver_path,
4575 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4579 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4580 driver->config_file,
4583 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4587 FILL_DRIVER_STRING(mem_ctx,
4588 driver->monitor_name,
4591 FILL_DRIVER_STRING(mem_ctx,
4592 driver->default_datatype,
4593 r->default_datatype);
4595 r->dependent_files = string_array_from_driver_info(mem_ctx,
4596 driver->dependent_files,
4598 r->previous_names = string_array_from_driver_info(mem_ctx,
4599 driver->previous_names,
4602 r->driver_date = driver->driver_date;
4603 r->driver_version = driver->driver_version;
4605 FILL_DRIVER_STRING(mem_ctx,
4606 driver->manufacturer_name,
4607 r->manufacturer_name);
4608 FILL_DRIVER_STRING(mem_ctx,
4609 driver->manufacturer_url,
4610 r->manufacturer_url);
4611 FILL_DRIVER_STRING(mem_ctx,
4612 driver->hardware_id,
4614 FILL_DRIVER_STRING(mem_ctx,
4618 FILL_DRIVER_STRING(mem_ctx,
4619 driver->print_processor,
4620 r->print_processor);
4621 FILL_DRIVER_STRING(mem_ctx,
4622 driver->vendor_setup,
4625 r->color_profiles = string_array_from_driver_info(mem_ctx,
4626 driver->color_profiles,
4629 FILL_DRIVER_STRING(mem_ctx,
4633 r->printer_driver_attributes = driver->printer_driver_attributes;
4635 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4636 driver->core_driver_dependencies,
4639 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4640 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4645 #if 0 /* disabled until marshalling issues are resolved - gd */
4646 /********************************************************************
4647 ********************************************************************/
4649 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4650 struct spoolss_DriverFileInfo *r,
4651 const char *cservername,
4652 const char *file_name,
4653 enum spoolss_DriverFileType file_type,
4654 uint32_t file_version)
4656 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4657 cservername, file_name);
4658 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4659 r->file_type = file_type;
4660 r->file_version = file_version;
4665 /********************************************************************
4666 ********************************************************************/
4668 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4669 const struct spoolss_DriverInfo8 *driver,
4670 const char *cservername,
4671 struct spoolss_DriverFileInfo **info_p,
4674 struct spoolss_DriverFileInfo *info = NULL;
4682 if (strlen(driver->driver_path)) {
4683 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4684 struct spoolss_DriverFileInfo,
4686 W_ERROR_HAVE_NO_MEMORY(info);
4687 result = fill_spoolss_DriverFileInfo(info,
4690 driver->driver_path,
4691 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4693 W_ERROR_NOT_OK_RETURN(result);
4697 if (strlen(driver->config_file)) {
4698 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4699 struct spoolss_DriverFileInfo,
4701 W_ERROR_HAVE_NO_MEMORY(info);
4702 result = fill_spoolss_DriverFileInfo(info,
4705 driver->config_file,
4706 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4708 W_ERROR_NOT_OK_RETURN(result);
4712 if (strlen(driver->data_file)) {
4713 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4714 struct spoolss_DriverFileInfo,
4716 W_ERROR_HAVE_NO_MEMORY(info);
4717 result = fill_spoolss_DriverFileInfo(info,
4721 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4723 W_ERROR_NOT_OK_RETURN(result);
4727 if (strlen(driver->help_file)) {
4728 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4729 struct spoolss_DriverFileInfo,
4731 W_ERROR_HAVE_NO_MEMORY(info);
4732 result = fill_spoolss_DriverFileInfo(info,
4736 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4738 W_ERROR_NOT_OK_RETURN(result);
4742 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4743 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4744 struct spoolss_DriverFileInfo,
4746 W_ERROR_HAVE_NO_MEMORY(info);
4747 result = fill_spoolss_DriverFileInfo(info,
4750 driver->dependent_files[i],
4751 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4753 W_ERROR_NOT_OK_RETURN(result);
4763 /********************************************************************
4764 * fill a spoolss_DriverInfo101 struct
4765 ********************************************************************/
4767 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4768 struct spoolss_DriverInfo101 *r,
4769 const struct spoolss_DriverInfo8 *driver,
4770 const char *servername)
4772 const char *cservername = canon_servername(servername);
4775 r->version = driver->version;
4777 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4778 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4779 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4780 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4782 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4786 if (!W_ERROR_IS_OK(result)) {
4790 FILL_DRIVER_STRING(mem_ctx,
4791 driver->monitor_name,
4794 FILL_DRIVER_STRING(mem_ctx,
4795 driver->default_datatype,
4796 r->default_datatype);
4798 r->previous_names = string_array_from_driver_info(mem_ctx,
4799 driver->previous_names,
4801 r->driver_date = driver->driver_date;
4802 r->driver_version = driver->driver_version;
4804 FILL_DRIVER_STRING(mem_ctx,
4805 driver->manufacturer_name,
4806 r->manufacturer_name);
4807 FILL_DRIVER_STRING(mem_ctx,
4808 driver->manufacturer_url,
4809 r->manufacturer_url);
4810 FILL_DRIVER_STRING(mem_ctx,
4811 driver->hardware_id,
4813 FILL_DRIVER_STRING(mem_ctx,
4820 /********************************************************************
4821 ********************************************************************/
4823 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4825 union spoolss_DriverInfo *r,
4827 const char *servername,
4828 const char *architecture,
4831 NT_PRINTER_INFO_LEVEL *printer = NULL;
4832 struct spoolss_DriverInfo8 *driver;
4835 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4837 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4838 win_errstr(result)));
4840 if (!W_ERROR_IS_OK(result)) {
4841 return WERR_INVALID_PRINTER_NAME;
4844 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4845 architecture, version);
4847 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4848 win_errstr(result)));
4850 if (!W_ERROR_IS_OK(result)) {
4852 * Is this a W2k client ?
4856 free_a_printer(&printer, 2);
4857 return WERR_UNKNOWN_PRINTER_DRIVER;
4860 /* Yes - try again with a WinNT driver. */
4862 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4863 architecture, version);
4864 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4865 win_errstr(result)));
4866 if (!W_ERROR_IS_OK(result)) {
4867 free_a_printer(&printer, 2);
4868 return WERR_UNKNOWN_PRINTER_DRIVER;
4874 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4877 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4880 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4883 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4886 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4889 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4892 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4894 #if 0 /* disabled until marshalling issues are resolved - gd */
4896 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4900 result = WERR_UNKNOWN_LEVEL;
4904 free_a_printer(&printer, 2);
4905 free_a_printer_driver(driver);
4910 /****************************************************************
4911 _spoolss_GetPrinterDriver2
4912 ****************************************************************/
4914 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4915 struct spoolss_GetPrinterDriver2 *r)
4917 Printer_entry *printer;
4920 const char *servername;
4923 /* that's an [in out] buffer */
4925 if (!r->in.buffer && (r->in.offered != 0)) {
4926 return WERR_INVALID_PARAM;
4929 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4931 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4932 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4933 return WERR_INVALID_PRINTER_NAME;
4937 *r->out.server_major_version = 0;
4938 *r->out.server_minor_version = 0;
4940 servername = get_server_name(printer);
4942 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4946 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
4950 r->in.client_major_version);
4951 if (!W_ERROR_IS_OK(result)) {
4952 TALLOC_FREE(r->out.info);
4956 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
4957 r->out.info, r->in.level);
4958 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4960 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4964 /****************************************************************
4965 _spoolss_StartPagePrinter
4966 ****************************************************************/
4968 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4969 struct spoolss_StartPagePrinter *r)
4971 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4974 DEBUG(3,("_spoolss_StartPagePrinter: "
4975 "Error in startpageprinter printer handle\n"));
4979 Printer->page_started = true;
4983 /****************************************************************
4984 _spoolss_EndPagePrinter
4985 ****************************************************************/
4987 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4988 struct spoolss_EndPagePrinter *r)
4992 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4995 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4996 OUR_HANDLE(r->in.handle)));
5000 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5003 Printer->page_started = false;
5004 print_job_endpage(snum, Printer->jobid);
5009 /****************************************************************
5010 _spoolss_StartDocPrinter
5011 ****************************************************************/
5013 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5014 struct spoolss_StartDocPrinter *r)
5016 struct spoolss_DocumentInfo1 *info_1;
5018 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5021 DEBUG(2,("_spoolss_StartDocPrinter: "
5022 "Invalid handle (%s:%u:%u)\n",
5023 OUR_HANDLE(r->in.handle)));
5027 if (r->in.level != 1) {
5028 return WERR_UNKNOWN_LEVEL;
5031 info_1 = r->in.info.info1;
5034 * a nice thing with NT is it doesn't listen to what you tell it.
5035 * when asked to send _only_ RAW datas, it tries to send datas
5038 * So I add checks like in NT Server ...
5041 if (info_1->datatype) {
5042 if (strcmp(info_1->datatype, "RAW") != 0) {
5044 return WERR_INVALID_DATATYPE;
5048 /* get the share number of the printer */
5049 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5053 Printer->jobid = print_job_start(p->server_info, snum,
5054 info_1->document_name,
5057 /* An error occured in print_job_start() so return an appropriate
5060 if (Printer->jobid == -1) {
5061 return map_werror_from_unix(errno);
5064 Printer->document_started = true;
5065 *r->out.job_id = Printer->jobid;
5070 /****************************************************************
5071 _spoolss_EndDocPrinter
5072 ****************************************************************/
5074 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5075 struct spoolss_EndDocPrinter *r)
5077 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5081 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5082 OUR_HANDLE(r->in.handle)));
5086 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5090 Printer->document_started = false;
5091 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5092 /* error codes unhandled so far ... */
5097 /****************************************************************
5098 _spoolss_WritePrinter
5099 ****************************************************************/
5101 WERROR _spoolss_WritePrinter(pipes_struct *p,
5102 struct spoolss_WritePrinter *r)
5104 ssize_t buffer_written;
5106 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5109 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5110 OUR_HANDLE(r->in.handle)));
5111 *r->out.num_written = r->in._data_size;
5115 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5118 buffer_written = print_job_write(snum, Printer->jobid,
5119 (const char *)r->in.data.data,
5121 (size_t)r->in._data_size);
5122 if (buffer_written == (ssize_t)-1) {
5123 *r->out.num_written = 0;
5124 if (errno == ENOSPC)
5125 return WERR_NO_SPOOL_SPACE;
5127 return WERR_ACCESS_DENIED;
5130 *r->out.num_written = r->in._data_size;
5135 /********************************************************************
5136 * api_spoolss_getprinter
5137 * called from the spoolss dispatcher
5139 ********************************************************************/
5141 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5145 WERROR errcode = WERR_BADFUNC;
5146 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5149 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5150 OUR_HANDLE(handle)));
5154 if (!get_printer_snum(p, handle, &snum, NULL))
5158 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5159 errcode = print_queue_pause(p->server_info, snum);
5161 case SPOOLSS_PRINTER_CONTROL_RESUME:
5162 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5163 errcode = print_queue_resume(p->server_info, snum);
5165 case SPOOLSS_PRINTER_CONTROL_PURGE:
5166 errcode = print_queue_purge(p->server_info, snum);
5169 return WERR_UNKNOWN_LEVEL;
5176 /****************************************************************
5177 _spoolss_AbortPrinter
5178 * From MSDN: "Deletes printer's spool file if printer is configured
5180 ****************************************************************/
5182 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5183 struct spoolss_AbortPrinter *r)
5185 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5187 WERROR errcode = WERR_OK;
5190 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5191 OUR_HANDLE(r->in.handle)));
5195 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5198 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5203 /********************************************************************
5204 * called by spoolss_api_setprinter
5205 * when updating a printer description
5206 ********************************************************************/
5208 static WERROR update_printer_sec(struct policy_handle *handle,
5209 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5211 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5215 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5217 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5218 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5219 OUR_HANDLE(handle)));
5221 result = WERR_BADFID;
5226 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5227 result = WERR_INVALID_PARAM;
5231 /* Check the user has permissions to change the security
5232 descriptor. By experimentation with two NT machines, the user
5233 requires Full Access to the printer to change security
5236 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5237 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5238 result = WERR_ACCESS_DENIED;
5242 /* NT seems to like setting the security descriptor even though
5243 nothing may have actually changed. */
5245 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5246 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5247 result = WERR_BADFID;
5251 if (DEBUGLEVEL >= 10) {
5252 struct security_acl *the_acl;
5255 the_acl = old_secdesc_ctr->sd->dacl;
5256 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5257 lp_printername(snum), the_acl->num_aces));
5259 for (i = 0; i < the_acl->num_aces; i++) {
5260 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5261 &the_acl->aces[i].trustee),
5262 the_acl->aces[i].access_mask));
5265 the_acl = secdesc_ctr->sd->dacl;
5268 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5269 lp_printername(snum), the_acl->num_aces));
5271 for (i = 0; i < the_acl->num_aces; i++) {
5272 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5273 &the_acl->aces[i].trustee),
5274 the_acl->aces[i].access_mask));
5277 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5281 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5282 if (!new_secdesc_ctr) {
5283 result = WERR_NOMEM;
5287 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5292 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5299 /********************************************************************
5300 Canonicalize printer info from a client
5302 ATTN: It does not matter what we set the servername to hear
5303 since we do the necessary work in get_a_printer() to set it to
5304 the correct value based on what the client sent in the
5305 _spoolss_open_printer_ex().
5306 ********************************************************************/
5308 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5310 fstring printername;
5313 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5314 "portname=%s drivername=%s comment=%s location=%s\n",
5315 info->servername, info->printername, info->sharename,
5316 info->portname, info->drivername, info->comment, info->location));
5318 /* we force some elements to "correct" values */
5319 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5320 fstrcpy(info->sharename, lp_servicename(snum));
5322 /* check to see if we allow printername != sharename */
5324 if ( lp_force_printername(snum) ) {
5325 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5326 global_myname(), info->sharename );
5329 /* make sure printername is in \\server\printername format */
5331 fstrcpy( printername, info->printername );
5333 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5334 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5338 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5339 global_myname(), p );
5342 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5343 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5350 /****************************************************************************
5351 ****************************************************************************/
5353 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5355 char *cmd = lp_addport_cmd();
5356 char *command = NULL;
5358 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5359 bool is_print_op = false;
5362 return WERR_ACCESS_DENIED;
5365 command = talloc_asprintf(ctx,
5366 "%s \"%s\" \"%s\"", cmd, portname, uri );
5372 is_print_op = user_has_privileges( token, &se_printop );
5374 DEBUG(10,("Running [%s]\n", command));
5376 /********* BEGIN SePrintOperatorPrivilege **********/
5381 ret = smbrun(command, NULL);
5386 /********* END SePrintOperatorPrivilege **********/
5388 DEBUGADD(10,("returned [%d]\n", ret));
5390 TALLOC_FREE(command);
5393 return WERR_ACCESS_DENIED;
5399 /****************************************************************************
5400 ****************************************************************************/
5402 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5404 char *cmd = lp_addprinter_cmd();
5406 char *command = NULL;
5410 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5411 bool is_print_op = false;
5412 char *remote_machine = talloc_strdup(ctx, "%m");
5414 if (!remote_machine) {
5417 remote_machine = talloc_sub_basic(ctx,
5418 current_user_info.smb_name,
5419 current_user_info.domain,
5421 if (!remote_machine) {
5425 command = talloc_asprintf(ctx,
5426 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5427 cmd, printer->info_2->printername, printer->info_2->sharename,
5428 printer->info_2->portname, printer->info_2->drivername,
5429 printer->info_2->location, printer->info_2->comment, remote_machine);
5435 is_print_op = user_has_privileges( token, &se_printop );
5437 DEBUG(10,("Running [%s]\n", command));
5439 /********* BEGIN SePrintOperatorPrivilege **********/
5444 if ( (ret = smbrun(command, &fd)) == 0 ) {
5445 /* Tell everyone we updated smb.conf. */
5446 message_send_all(smbd_messaging_context(),
5447 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5453 /********* END SePrintOperatorPrivilege **********/
5455 DEBUGADD(10,("returned [%d]\n", ret));
5457 TALLOC_FREE(command);
5458 TALLOC_FREE(remote_machine);
5466 /* reload our services immediately */
5468 reload_services(false);
5472 /* Get lines and convert them back to dos-codepage */
5473 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5474 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5477 /* Set the portname to what the script says the portname should be. */
5478 /* but don't require anything to be return from the script exit a good error code */
5481 /* Set the portname to what the script says the portname should be. */
5482 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5483 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5486 TALLOC_FREE(qlines);
5491 /********************************************************************
5492 * Called by spoolss_api_setprinter
5493 * when updating a printer description.
5494 ********************************************************************/
5496 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5497 struct spoolss_SetPrinterInfoCtr *info_ctr,
5498 struct spoolss_DeviceMode *devmode)
5501 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5502 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5507 DEBUG(8,("update_printer\n"));
5512 result = WERR_BADFID;
5516 if (!get_printer_snum(p, handle, &snum, NULL)) {
5517 result = WERR_BADFID;
5521 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5522 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5523 result = WERR_BADFID;
5527 DEBUGADD(8,("Converting info_2 struct\n"));
5530 * convert_printer_info converts the incoming
5531 * info from the client and overwrites the info
5532 * just read from the tdb in the pointer 'printer'.
5535 if (!convert_printer_info(info_ctr, printer)) {
5536 result = WERR_NOMEM;
5541 /* we have a valid devmode
5542 convert it and link it*/
5544 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5545 result = copy_devicemode(printer->info_2, devmode,
5546 &printer->info_2->devmode);
5547 if (!W_ERROR_IS_OK(result)) {
5552 /* Do sanity check on the requested changes for Samba */
5554 if (!check_printer_ok(printer->info_2, snum)) {
5555 result = WERR_INVALID_PARAM;
5559 /* FIXME!!! If the driver has changed we really should verify that
5560 it is installed before doing much else --jerry */
5562 /* Check calling user has permission to update printer description */
5564 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5565 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5566 result = WERR_ACCESS_DENIED;
5570 /* Call addprinter hook */
5571 /* Check changes to see if this is really needed */
5573 if ( *lp_addprinter_cmd()
5574 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5575 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5576 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5577 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5579 /* add_printer_hook() will call reload_services() */
5581 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5583 result = WERR_ACCESS_DENIED;
5589 * When a *new* driver is bound to a printer, the drivername is used to
5590 * lookup previously saved driver initialization info, which is then
5591 * bound to the printer, simulating what happens in the Windows arch.
5593 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5595 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5596 printer->info_2->drivername));
5598 notify_printer_driver(snum, printer->info_2->drivername);
5602 * flag which changes actually occured. This is a small subset of
5603 * all the possible changes. We also have to update things in the
5607 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5608 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5609 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
5610 REG_SZ, buffer.data, buffer.length);
5612 notify_printer_comment(snum, printer->info_2->comment);
5615 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5616 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5617 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
5618 REG_SZ, buffer.data, buffer.length);
5620 notify_printer_sharename(snum, printer->info_2->sharename);
5623 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5626 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5629 pname = printer->info_2->printername;
5632 push_reg_sz(talloc_tos(), &buffer, pname);
5633 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
5634 REG_SZ, buffer.data, buffer.length);
5636 notify_printer_printername( snum, pname );
5639 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5640 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5641 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
5642 REG_SZ, buffer.data, buffer.length);
5644 notify_printer_port(snum, printer->info_2->portname);
5647 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5648 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5649 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
5650 REG_SZ, buffer.data, buffer.length);
5652 notify_printer_location(snum, printer->info_2->location);
5655 /* here we need to update some more DsSpooler keys */
5656 /* uNCName, serverName, shortServerName */
5658 push_reg_sz(talloc_tos(), &buffer, global_myname());
5659 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
5660 REG_SZ, buffer.data, buffer.length);
5661 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
5662 REG_SZ, buffer.data, buffer.length);
5664 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5665 global_myname(), printer->info_2->sharename );
5666 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5667 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
5668 REG_SZ, buffer.data, buffer.length);
5670 /* Update printer info */
5671 result = mod_a_printer(printer, 2);
5674 free_a_printer(&printer, 2);
5675 free_a_printer(&old_printer, 2);
5681 /****************************************************************************
5682 ****************************************************************************/
5683 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5684 struct policy_handle *handle,
5685 struct spoolss_SetPrinterInfo7 *info7)
5689 Printer_entry *Printer;
5691 if ( lp_security() != SEC_ADS ) {
5692 return WERR_UNKNOWN_LEVEL;
5695 Printer = find_printer_index_by_hnd(p, handle);
5697 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5702 if (!get_printer_snum(p, handle, &snum, NULL))
5705 nt_printer_publish(Printer, snum, info7->action);
5709 return WERR_UNKNOWN_LEVEL;
5713 /********************************************************************
5714 ********************************************************************/
5716 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5717 struct spoolss_DeviceMode *devmode)
5720 NT_PRINTER_INFO_LEVEL *printer = NULL;
5721 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5724 DEBUG(8,("update_printer_devmode\n"));
5729 result = WERR_BADFID;
5733 if (!get_printer_snum(p, handle, &snum, NULL)) {
5734 result = WERR_BADFID;
5738 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5739 result = WERR_BADFID;
5744 /* we have a valid devmode, copy it */
5746 DEBUGADD(8, ("update_printer: Copying the devicemode struct\n"));
5747 result = copy_devicemode(printer->info_2, devmode,
5748 &printer->info_2->devmode);
5749 if (!W_ERROR_IS_OK(result)) {
5754 /* Check calling user has permission to update printer description */
5756 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5757 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5758 result = WERR_ACCESS_DENIED;
5763 /* Update printer info */
5764 result = mod_a_printer(printer, 2);
5767 free_a_printer(&printer, 2);
5773 /****************************************************************
5775 ****************************************************************/
5777 WERROR _spoolss_SetPrinter(pipes_struct *p,
5778 struct spoolss_SetPrinter *r)
5782 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5785 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5786 OUR_HANDLE(r->in.handle)));
5790 /* check the level */
5791 switch (r->in.info_ctr->level) {
5793 return control_printer(r->in.handle, r->in.command, p);
5795 result = update_printer(p, r->in.handle,
5797 r->in.devmode_ctr->devmode);
5798 if (!W_ERROR_IS_OK(result))
5800 if (r->in.secdesc_ctr->sd)
5801 result = update_printer_sec(r->in.handle, p,
5805 return update_printer_sec(r->in.handle, p,
5808 return publish_or_unpublish_printer(p, r->in.handle,
5809 r->in.info_ctr->info.info7);
5811 return update_printer_devmode(p, r->in.handle,
5812 r->in.devmode_ctr->devmode);
5814 return WERR_UNKNOWN_LEVEL;
5818 /****************************************************************
5819 _spoolss_FindClosePrinterNotify
5820 ****************************************************************/
5822 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5823 struct spoolss_FindClosePrinterNotify *r)
5825 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5828 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5829 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5833 if (Printer->notify.client_connected == true) {
5836 if ( Printer->printer_type == SPLHND_SERVER)
5838 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5839 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5842 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5845 Printer->notify.flags=0;
5846 Printer->notify.options=0;
5847 Printer->notify.localmachine[0]='\0';
5848 Printer->notify.printerlocal=0;
5849 TALLOC_FREE(Printer->notify.option);
5850 Printer->notify.client_connected = false;
5855 /****************************************************************
5857 ****************************************************************/
5859 WERROR _spoolss_AddJob(pipes_struct *p,
5860 struct spoolss_AddJob *r)
5862 if (!r->in.buffer && (r->in.offered != 0)) {
5863 return WERR_INVALID_PARAM;
5866 /* this is what a NT server returns for AddJob. AddJob must fail on
5867 * non-local printers */
5869 if (r->in.level != 1) {
5870 return WERR_UNKNOWN_LEVEL;
5873 return WERR_INVALID_PARAM;
5876 /****************************************************************************
5878 ****************************************************************************/
5880 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5881 struct spoolss_JobInfo1 *r,
5882 const print_queue_struct *queue,
5883 int position, int snum,
5884 const NT_PRINTER_INFO_LEVEL *ntprinter)
5888 t = gmtime(&queue->time);
5890 r->job_id = queue->job;
5892 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5893 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5894 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5895 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5896 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5897 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5898 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5899 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5900 r->data_type = talloc_strdup(mem_ctx, "RAW");
5901 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5902 r->text_status = talloc_strdup(mem_ctx, "");
5903 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5905 r->status = nt_printj_status(queue->status);
5906 r->priority = queue->priority;
5907 r->position = position;
5908 r->total_pages = queue->page_count;
5909 r->pages_printed = 0; /* ??? */
5911 init_systemtime(&r->submitted, t);
5916 /****************************************************************************
5918 ****************************************************************************/
5920 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5921 struct spoolss_JobInfo2 *r,
5922 const print_queue_struct *queue,
5923 int position, int snum,
5924 const NT_PRINTER_INFO_LEVEL *ntprinter,
5925 struct spoolss_DeviceMode *devmode)
5929 t = gmtime(&queue->time);
5931 r->job_id = queue->job;
5933 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5934 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5935 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5936 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5937 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5938 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5939 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5940 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5941 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
5942 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5943 r->data_type = talloc_strdup(mem_ctx, "RAW");
5944 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5945 r->print_processor = talloc_strdup(mem_ctx, "winprint");
5946 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5947 r->parameters = talloc_strdup(mem_ctx, "");
5948 W_ERROR_HAVE_NO_MEMORY(r->parameters);
5949 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
5950 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5952 r->devmode = devmode;
5954 r->text_status = talloc_strdup(mem_ctx, "");
5955 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5959 r->status = nt_printj_status(queue->status);
5960 r->priority = queue->priority;
5961 r->position = position;
5964 r->total_pages = queue->page_count;
5965 r->size = queue->size;
5966 init_systemtime(&r->submitted, t);
5968 r->pages_printed = 0; /* ??? */
5973 /****************************************************************************
5975 ****************************************************************************/
5977 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
5978 struct spoolss_JobInfo3 *r,
5979 const print_queue_struct *queue,
5980 const print_queue_struct *next_queue,
5981 int position, int snum,
5982 const NT_PRINTER_INFO_LEVEL *ntprinter)
5984 r->job_id = queue->job;
5987 r->next_job_id = next_queue->job;
5994 /****************************************************************************
5995 Enumjobs at level 1.
5996 ****************************************************************************/
5998 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
5999 const print_queue_struct *queue,
6000 uint32_t num_queues, int snum,
6001 const NT_PRINTER_INFO_LEVEL *ntprinter,
6002 union spoolss_JobInfo **info_p,
6005 union spoolss_JobInfo *info;
6007 WERROR result = WERR_OK;
6009 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6010 W_ERROR_HAVE_NO_MEMORY(info);
6012 *count = num_queues;
6014 for (i=0; i<*count; i++) {
6015 result = fill_job_info1(info,
6021 if (!W_ERROR_IS_OK(result)) {
6027 if (!W_ERROR_IS_OK(result)) {
6038 /****************************************************************************
6039 Enumjobs at level 2.
6040 ****************************************************************************/
6042 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6043 const print_queue_struct *queue,
6044 uint32_t num_queues, int snum,
6045 const NT_PRINTER_INFO_LEVEL *ntprinter,
6046 union spoolss_JobInfo **info_p,
6049 union spoolss_JobInfo *info;
6051 WERROR result = WERR_OK;
6053 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6054 W_ERROR_HAVE_NO_MEMORY(info);
6056 *count = num_queues;
6058 for (i=0; i<*count; i++) {
6060 struct spoolss_DeviceMode *devmode;
6062 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6064 result = WERR_NOMEM;
6068 result = fill_job_info2(info,
6075 if (!W_ERROR_IS_OK(result)) {
6081 if (!W_ERROR_IS_OK(result)) {
6092 /****************************************************************************
6093 Enumjobs at level 3.
6094 ****************************************************************************/
6096 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6097 const print_queue_struct *queue,
6098 uint32_t num_queues, int snum,
6099 const NT_PRINTER_INFO_LEVEL *ntprinter,
6100 union spoolss_JobInfo **info_p,
6103 union spoolss_JobInfo *info;
6105 WERROR result = WERR_OK;
6107 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6108 W_ERROR_HAVE_NO_MEMORY(info);
6110 *count = num_queues;
6112 for (i=0; i<*count; i++) {
6113 const print_queue_struct *next_queue = NULL;
6116 next_queue = &queue[i+1];
6119 result = fill_job_info3(info,
6126 if (!W_ERROR_IS_OK(result)) {
6132 if (!W_ERROR_IS_OK(result)) {
6143 /****************************************************************
6145 ****************************************************************/
6147 WERROR _spoolss_EnumJobs(pipes_struct *p,
6148 struct spoolss_EnumJobs *r)
6151 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6153 print_status_struct prt_status;
6154 print_queue_struct *queue = NULL;
6157 /* that's an [in out] buffer */
6159 if (!r->in.buffer && (r->in.offered != 0)) {
6160 return WERR_INVALID_PARAM;
6163 DEBUG(4,("_spoolss_EnumJobs\n"));
6167 *r->out.info = NULL;
6169 /* lookup the printer snum and tdb entry */
6171 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6175 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6176 if (!W_ERROR_IS_OK(result)) {
6180 count = print_queue_status(snum, &queue, &prt_status);
6181 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6182 count, prt_status.status, prt_status.message));
6186 free_a_printer(&ntprinter, 2);
6190 switch (r->in.level) {
6192 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6193 ntprinter, r->out.info, r->out.count);
6196 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6197 ntprinter, r->out.info, r->out.count);
6200 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6201 ntprinter, r->out.info, r->out.count);
6204 result = WERR_UNKNOWN_LEVEL;
6209 free_a_printer(&ntprinter, 2);
6211 if (!W_ERROR_IS_OK(result)) {
6215 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6217 *r->out.info, r->in.level,
6219 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6220 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6222 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6225 /****************************************************************
6226 _spoolss_ScheduleJob
6227 ****************************************************************/
6229 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6230 struct spoolss_ScheduleJob *r)
6235 /****************************************************************
6236 ****************************************************************/
6238 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6239 const char *printer_name,
6241 struct spoolss_SetJobInfo1 *r)
6245 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6249 if (strequal(old_doc_name, r->document_name)) {
6253 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6260 /****************************************************************
6262 ****************************************************************/
6264 WERROR _spoolss_SetJob(pipes_struct *p,
6265 struct spoolss_SetJob *r)
6268 WERROR errcode = WERR_BADFUNC;
6270 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6274 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6275 return WERR_INVALID_PRINTER_NAME;
6278 switch (r->in.command) {
6279 case SPOOLSS_JOB_CONTROL_CANCEL:
6280 case SPOOLSS_JOB_CONTROL_DELETE:
6281 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6285 case SPOOLSS_JOB_CONTROL_PAUSE:
6286 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6290 case SPOOLSS_JOB_CONTROL_RESTART:
6291 case SPOOLSS_JOB_CONTROL_RESUME:
6292 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6300 return WERR_UNKNOWN_LEVEL;
6303 if (!W_ERROR_IS_OK(errcode)) {
6307 if (r->in.ctr == NULL) {
6311 switch (r->in.ctr->level) {
6313 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6315 r->in.ctr->info.info1);
6321 return WERR_UNKNOWN_LEVEL;
6327 /****************************************************************************
6328 Enumerates all printer drivers by level and architecture.
6329 ****************************************************************************/
6331 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6332 const char *servername,
6333 const char *architecture,
6335 union spoolss_DriverInfo **info_p,
6341 fstring *list = NULL;
6342 struct spoolss_DriverInfo8 *driver;
6343 union spoolss_DriverInfo *info = NULL;
6345 WERROR result = WERR_OK;
6350 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6352 ndrivers = get_ntdrivers(&list, architecture, version);
6353 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6354 ndrivers, architecture, version));
6356 if (ndrivers == -1) {
6357 result = WERR_NOMEM;
6361 if (ndrivers != 0) {
6362 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6363 union spoolss_DriverInfo,
6366 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6367 "failed to enlarge driver info buffer!\n"));
6368 result = WERR_NOMEM;
6373 for (i=0; i<ndrivers; i++) {
6374 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6375 ZERO_STRUCT(driver);
6376 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6377 architecture, version);
6378 if (!W_ERROR_IS_OK(result)) {
6384 result = fill_printer_driver_info1(info, &info[count+i].info1,
6385 driver, servername);
6388 result = fill_printer_driver_info2(info, &info[count+i].info2,
6389 driver, servername);
6392 result = fill_printer_driver_info3(info, &info[count+i].info3,
6393 driver, servername);
6396 result = fill_printer_driver_info4(info, &info[count+i].info4,
6397 driver, servername);
6400 result = fill_printer_driver_info5(info, &info[count+i].info5,
6401 driver, servername);
6404 result = fill_printer_driver_info6(info, &info[count+i].info6,
6405 driver, servername);
6408 result = fill_printer_driver_info8(info, &info[count+i].info8,
6409 driver, servername);
6412 result = WERR_UNKNOWN_LEVEL;
6416 free_a_printer_driver(driver);
6418 if (!W_ERROR_IS_OK(result)) {
6430 if (!W_ERROR_IS_OK(result)) {
6441 /****************************************************************************
6442 Enumerates all printer drivers by level.
6443 ****************************************************************************/
6445 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6446 const char *servername,
6447 const char *architecture,
6449 union spoolss_DriverInfo **info_p,
6453 WERROR result = WERR_OK;
6455 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6457 for (a=0; archi_table[a].long_archi != NULL; a++) {
6459 union spoolss_DriverInfo *info = NULL;
6462 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6464 archi_table[a].long_archi,
6468 if (!W_ERROR_IS_OK(result)) {
6472 for (i=0; i < count; i++) {
6473 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6474 info[i], info_p, count_p);
6481 return enumprinterdrivers_level_by_architecture(mem_ctx,
6489 /****************************************************************
6490 _spoolss_EnumPrinterDrivers
6491 ****************************************************************/
6493 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6494 struct spoolss_EnumPrinterDrivers *r)
6496 const char *cservername;
6499 /* that's an [in out] buffer */
6501 if (!r->in.buffer && (r->in.offered != 0)) {
6502 return WERR_INVALID_PARAM;
6505 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6509 *r->out.info = NULL;
6511 cservername = canon_servername(r->in.server);
6513 if (!is_myname_or_ipaddr(cservername)) {
6514 return WERR_UNKNOWN_PRINTER_DRIVER;
6517 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6522 if (!W_ERROR_IS_OK(result)) {
6526 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6527 spoolss_EnumPrinterDrivers,
6528 *r->out.info, r->in.level,
6530 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6531 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6533 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6536 /****************************************************************************
6537 ****************************************************************************/
6539 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6540 struct spoolss_FormInfo1 *r,
6541 const nt_forms_struct *form)
6543 r->form_name = talloc_strdup(mem_ctx, form->name);
6544 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6546 r->flags = form->flag;
6547 r->size.width = form->width;
6548 r->size.height = form->length;
6549 r->area.left = form->left;
6550 r->area.top = form->top;
6551 r->area.right = form->right;
6552 r->area.bottom = form->bottom;
6557 /****************************************************************
6558 spoolss_enumforms_level1
6559 ****************************************************************/
6561 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
6562 const nt_forms_struct *builtin_forms,
6563 uint32_t num_builtin_forms,
6564 const nt_forms_struct *user_forms,
6565 uint32_t num_user_forms,
6566 union spoolss_FormInfo **info_p,
6569 union spoolss_FormInfo *info;
6570 WERROR result = WERR_OK;
6573 *count = num_builtin_forms + num_user_forms;
6575 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
6576 W_ERROR_HAVE_NO_MEMORY(info);
6578 /* construct the list of form structures */
6579 for (i=0; i<num_builtin_forms; i++) {
6580 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
6581 result = fill_form_info_1(info, &info[i].info1,
6583 if (!W_ERROR_IS_OK(result)) {
6588 for (i=0; i<num_user_forms; i++) {
6589 DEBUGADD(6,("Filling user form number [%d]\n",i));
6590 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
6592 if (!W_ERROR_IS_OK(result)) {
6598 if (!W_ERROR_IS_OK(result)) {
6609 /****************************************************************
6611 ****************************************************************/
6613 WERROR _spoolss_EnumForms(pipes_struct *p,
6614 struct spoolss_EnumForms *r)
6617 nt_forms_struct *user_forms = NULL;
6618 nt_forms_struct *builtin_forms = NULL;
6619 uint32_t num_user_forms;
6620 uint32_t num_builtin_forms;
6624 *r->out.info = NULL;
6626 /* that's an [in out] buffer */
6628 if (!r->in.buffer && (r->in.offered != 0) ) {
6629 return WERR_INVALID_PARAM;
6632 DEBUG(4,("_spoolss_EnumForms\n"));
6633 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6634 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6636 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
6637 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
6638 num_user_forms = get_ntforms(&user_forms);
6639 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
6641 if (num_user_forms + num_builtin_forms == 0) {
6642 SAFE_FREE(builtin_forms);
6643 SAFE_FREE(user_forms);
6644 return WERR_NO_MORE_ITEMS;
6647 switch (r->in.level) {
6649 result = spoolss_enumforms_level1(p->mem_ctx,
6658 result = WERR_UNKNOWN_LEVEL;
6662 SAFE_FREE(user_forms);
6663 SAFE_FREE(builtin_forms);
6665 if (!W_ERROR_IS_OK(result)) {
6669 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6671 *r->out.info, r->in.level,
6673 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6674 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6676 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6679 /****************************************************************
6680 ****************************************************************/
6682 static WERROR find_form_byname(const char *name,
6683 nt_forms_struct *form)
6685 nt_forms_struct *list = NULL;
6686 int num_forms = 0, i = 0;
6688 if (get_a_builtin_ntform_by_string(name, form)) {
6692 num_forms = get_ntforms(&list);
6693 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6695 if (num_forms == 0) {
6699 /* Check if the requested name is in the list of form structures */
6700 for (i = 0; i < num_forms; i++) {
6702 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6704 if (strequal(name, list[i].name)) {
6705 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6717 /****************************************************************
6719 ****************************************************************/
6721 WERROR _spoolss_GetForm(pipes_struct *p,
6722 struct spoolss_GetForm *r)
6725 nt_forms_struct form;
6727 /* that's an [in out] buffer */
6729 if (!r->in.buffer && (r->in.offered != 0)) {
6730 return WERR_INVALID_PARAM;
6733 DEBUG(4,("_spoolss_GetForm\n"));
6734 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6735 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6737 result = find_form_byname(r->in.form_name, &form);
6738 if (!W_ERROR_IS_OK(result)) {
6739 TALLOC_FREE(r->out.info);
6743 switch (r->in.level) {
6745 result = fill_form_info_1(p->mem_ctx,
6746 &r->out.info->info1,
6751 result = WERR_UNKNOWN_LEVEL;
6755 if (!W_ERROR_IS_OK(result)) {
6756 TALLOC_FREE(r->out.info);
6760 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6761 r->out.info, r->in.level);
6762 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6764 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6767 /****************************************************************************
6768 ****************************************************************************/
6770 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6771 struct spoolss_PortInfo1 *r,
6774 r->port_name = talloc_strdup(mem_ctx, name);
6775 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6780 /****************************************************************************
6781 TODO: This probably needs distinguish between TCP/IP and Local ports
6783 ****************************************************************************/
6785 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6786 struct spoolss_PortInfo2 *r,
6789 r->port_name = talloc_strdup(mem_ctx, name);
6790 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6792 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6793 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6795 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6796 W_ERROR_HAVE_NO_MEMORY(r->description);
6798 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6805 /****************************************************************************
6806 wrapper around the enumer ports command
6807 ****************************************************************************/
6809 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6811 char *cmd = lp_enumports_cmd();
6812 char **qlines = NULL;
6813 char *command = NULL;
6821 /* if no hook then just fill in the default port */
6824 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6827 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6828 TALLOC_FREE(qlines);
6835 /* we have a valid enumport command */
6837 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6842 DEBUG(10,("Running [%s]\n", command));
6843 ret = smbrun(command, &fd);
6844 DEBUG(10,("Returned [%d]\n", ret));
6845 TALLOC_FREE(command);
6850 return WERR_ACCESS_DENIED;
6854 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6855 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6865 /****************************************************************************
6867 ****************************************************************************/
6869 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6870 union spoolss_PortInfo **info_p,
6873 union spoolss_PortInfo *info = NULL;
6875 WERROR result = WERR_OK;
6876 char **qlines = NULL;
6879 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6880 if (!W_ERROR_IS_OK(result)) {
6885 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6887 DEBUG(10,("Returning WERR_NOMEM\n"));
6888 result = WERR_NOMEM;
6892 for (i=0; i<numlines; i++) {
6893 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6894 result = fill_port_1(info, &info[i].info1, qlines[i]);
6895 if (!W_ERROR_IS_OK(result)) {
6900 TALLOC_FREE(qlines);
6903 if (!W_ERROR_IS_OK(result)) {
6905 TALLOC_FREE(qlines);
6917 /****************************************************************************
6919 ****************************************************************************/
6921 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6922 union spoolss_PortInfo **info_p,
6925 union spoolss_PortInfo *info = NULL;
6927 WERROR result = WERR_OK;
6928 char **qlines = NULL;
6931 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6932 if (!W_ERROR_IS_OK(result)) {
6937 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6939 DEBUG(10,("Returning WERR_NOMEM\n"));
6940 result = WERR_NOMEM;
6944 for (i=0; i<numlines; i++) {
6945 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6946 result = fill_port_2(info, &info[i].info2, qlines[i]);
6947 if (!W_ERROR_IS_OK(result)) {
6952 TALLOC_FREE(qlines);
6955 if (!W_ERROR_IS_OK(result)) {
6957 TALLOC_FREE(qlines);
6969 /****************************************************************
6971 ****************************************************************/
6973 WERROR _spoolss_EnumPorts(pipes_struct *p,
6974 struct spoolss_EnumPorts *r)
6978 /* that's an [in out] buffer */
6980 if (!r->in.buffer && (r->in.offered != 0)) {
6981 return WERR_INVALID_PARAM;
6984 DEBUG(4,("_spoolss_EnumPorts\n"));
6988 *r->out.info = NULL;
6990 switch (r->in.level) {
6992 result = enumports_level_1(p->mem_ctx, r->out.info,
6996 result = enumports_level_2(p->mem_ctx, r->out.info,
7000 return WERR_UNKNOWN_LEVEL;
7003 if (!W_ERROR_IS_OK(result)) {
7007 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7009 *r->out.info, r->in.level,
7011 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7012 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7014 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7017 /****************************************************************************
7018 ****************************************************************************/
7020 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7022 struct spoolss_SetPrinterInfoCtr *info_ctr,
7023 struct spoolss_DeviceMode *devmode,
7024 struct security_descriptor *sec_desc,
7025 struct spoolss_UserLevelCtr *user_ctr,
7026 struct policy_handle *handle)
7028 NT_PRINTER_INFO_LEVEL *printer = NULL;
7031 WERROR err = WERR_OK;
7033 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7034 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7038 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7039 if (!convert_printer_info(info_ctr, printer)) {
7040 free_a_printer(&printer, 2);
7044 /* samba does not have a concept of local, non-shared printers yet, so
7045 * make sure we always setup sharename - gd */
7046 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7047 DEBUG(5, ("spoolss_addprinterex_level_2: "
7048 "no sharename has been set, setting printername %s as sharename\n",
7049 printer->info_2->printername));
7050 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7053 /* check to see if the printer already exists */
7055 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7056 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7057 printer->info_2->sharename));
7058 free_a_printer(&printer, 2);
7059 return WERR_PRINTER_ALREADY_EXISTS;
7062 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7063 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7064 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7065 printer->info_2->printername));
7066 free_a_printer(&printer, 2);
7067 return WERR_PRINTER_ALREADY_EXISTS;
7071 /* validate printer info struct */
7072 if (!info_ctr->info.info2->printername ||
7073 strlen(info_ctr->info.info2->printername) == 0) {
7074 free_a_printer(&printer,2);
7075 return WERR_INVALID_PRINTER_NAME;
7077 if (!info_ctr->info.info2->portname ||
7078 strlen(info_ctr->info.info2->portname) == 0) {
7079 free_a_printer(&printer,2);
7080 return WERR_UNKNOWN_PORT;
7082 if (!info_ctr->info.info2->drivername ||
7083 strlen(info_ctr->info.info2->drivername) == 0) {
7084 free_a_printer(&printer,2);
7085 return WERR_UNKNOWN_PRINTER_DRIVER;
7087 if (!info_ctr->info.info2->printprocessor ||
7088 strlen(info_ctr->info.info2->printprocessor) == 0) {
7089 free_a_printer(&printer,2);
7090 return WERR_UNKNOWN_PRINTPROCESSOR;
7093 /* FIXME!!! smbd should check to see if the driver is installed before
7094 trying to add a printer like this --jerry */
7096 if (*lp_addprinter_cmd() ) {
7097 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7099 free_a_printer(&printer,2);
7100 return WERR_ACCESS_DENIED;
7103 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7104 "smb.conf parameter \"addprinter command\" is defined. This"
7105 "parameter must exist for this call to succeed\n",
7106 printer->info_2->sharename ));
7109 /* use our primary netbios name since get_a_printer() will convert
7110 it to what the client expects on a case by case basis */
7112 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7113 printer->info_2->sharename);
7116 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7117 free_a_printer(&printer,2);
7118 return WERR_ACCESS_DENIED;
7121 /* you must be a printer admin to add a new printer */
7122 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7123 free_a_printer(&printer,2);
7124 return WERR_ACCESS_DENIED;
7128 * Do sanity check on the requested changes for Samba.
7131 if (!check_printer_ok(printer->info_2, snum)) {
7132 free_a_printer(&printer,2);
7133 return WERR_INVALID_PARAM;
7137 * When a printer is created, the drivername bound to the printer is used
7138 * to lookup previously saved driver initialization info, which is then
7139 * bound to the new printer, simulating what happens in the Windows arch.
7144 /* A valid devmode was included, convert and link it
7146 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7148 err = copy_devicemode(printer, devmode,
7149 &printer->info_2->devmode);
7150 if (!W_ERROR_IS_OK(err)) {
7155 /* write the ASCII on disk */
7156 err = mod_a_printer(printer, 2);
7157 if (!W_ERROR_IS_OK(err)) {
7158 free_a_printer(&printer,2);
7162 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7163 /* Handle open failed - remove addition. */
7164 del_a_printer(printer->info_2->sharename);
7165 free_a_printer(&printer,2);
7166 ZERO_STRUCTP(handle);
7167 return WERR_ACCESS_DENIED;
7170 update_c_setprinter(false);
7171 free_a_printer(&printer,2);
7176 /****************************************************************
7177 _spoolss_AddPrinterEx
7178 ****************************************************************/
7180 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7181 struct spoolss_AddPrinterEx *r)
7183 switch (r->in.info_ctr->level) {
7185 /* we don't handle yet */
7186 /* but I know what to do ... */
7187 return WERR_UNKNOWN_LEVEL;
7189 return spoolss_addprinterex_level_2(p, r->in.server,
7191 r->in.devmode_ctr->devmode,
7192 r->in.secdesc_ctr->sd,
7193 r->in.userlevel_ctr,
7196 return WERR_UNKNOWN_LEVEL;
7200 /****************************************************************
7202 ****************************************************************/
7204 WERROR _spoolss_AddPrinter(pipes_struct *p,
7205 struct spoolss_AddPrinter *r)
7207 struct spoolss_AddPrinterEx a;
7208 struct spoolss_UserLevelCtr userlevel_ctr;
7210 ZERO_STRUCT(userlevel_ctr);
7212 userlevel_ctr.level = 1;
7214 a.in.server = r->in.server;
7215 a.in.info_ctr = r->in.info_ctr;
7216 a.in.devmode_ctr = r->in.devmode_ctr;
7217 a.in.secdesc_ctr = r->in.secdesc_ctr;
7218 a.in.userlevel_ctr = &userlevel_ctr;
7219 a.out.handle = r->out.handle;
7221 return _spoolss_AddPrinterEx(p, &a);
7224 /****************************************************************
7225 _spoolss_AddPrinterDriverEx
7226 ****************************************************************/
7228 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7229 struct spoolss_AddPrinterDriverEx *r)
7231 WERROR err = WERR_OK;
7232 char *driver_name = NULL;
7237 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7238 fn = "_spoolss_AddPrinterDriver";
7240 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7241 fn = "_spoolss_AddPrinterDriverEx";
7244 return WERR_INVALID_PARAM;
7248 * we only support the semantics of AddPrinterDriver()
7249 * i.e. only copy files that are newer than existing ones
7252 if (r->in.flags == 0) {
7253 return WERR_INVALID_PARAM;
7256 if (r->in.flags != APD_COPY_NEW_FILES) {
7257 return WERR_ACCESS_DENIED;
7261 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7262 /* Clever hack from Martin Zielinski <mz@seh.de>
7263 * to allow downgrade from level 8 (Vista).
7265 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7266 r->in.info_ctr->level));
7267 return WERR_UNKNOWN_LEVEL;
7270 DEBUG(5,("Cleaning driver's information\n"));
7271 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7272 if (!W_ERROR_IS_OK(err))
7275 DEBUG(5,("Moving driver to final destination\n"));
7276 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7281 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7282 err = WERR_ACCESS_DENIED;
7287 * I think this is where he DrvUpgradePrinter() hook would be
7288 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7289 * server. Right now, we just need to send ourselves a message
7290 * to update each printer bound to this driver. --jerry
7293 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7294 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7302 /****************************************************************
7303 _spoolss_AddPrinterDriver
7304 ****************************************************************/
7306 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7307 struct spoolss_AddPrinterDriver *r)
7309 struct spoolss_AddPrinterDriverEx a;
7311 switch (r->in.info_ctr->level) {
7318 return WERR_UNKNOWN_LEVEL;
7321 a.in.servername = r->in.servername;
7322 a.in.info_ctr = r->in.info_ctr;
7323 a.in.flags = APD_COPY_NEW_FILES;
7325 return _spoolss_AddPrinterDriverEx(p, &a);
7328 /****************************************************************************
7329 ****************************************************************************/
7331 struct _spoolss_paths {
7337 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7339 static const struct _spoolss_paths spoolss_paths[]= {
7340 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7341 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7344 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7345 const char *servername,
7346 const char *environment,
7350 const char *pservername = NULL;
7351 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7352 const char *short_archi;
7356 /* environment may be empty */
7357 if (environment && strlen(environment)) {
7358 long_archi = environment;
7361 /* servername may be empty */
7362 if (servername && strlen(servername)) {
7363 pservername = canon_servername(servername);
7365 if (!is_myname_or_ipaddr(pservername)) {
7366 return WERR_INVALID_PARAM;
7370 if (!(short_archi = get_short_archi(long_archi))) {
7371 return WERR_INVALID_ENVIRONMENT;
7374 switch (component) {
7375 case SPOOLSS_PRTPROCS_PATH:
7376 case SPOOLSS_DRIVER_PATH:
7378 *path = talloc_asprintf(mem_ctx,
7381 spoolss_paths[component].share,
7384 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7385 SPOOLSS_DEFAULT_SERVER_PATH,
7386 spoolss_paths[component].dir,
7391 return WERR_INVALID_PARAM;
7401 /****************************************************************************
7402 ****************************************************************************/
7404 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7405 const char *servername,
7406 const char *environment,
7407 struct spoolss_DriverDirectoryInfo1 *r)
7412 werr = compose_spoolss_server_path(mem_ctx,
7415 SPOOLSS_DRIVER_PATH,
7417 if (!W_ERROR_IS_OK(werr)) {
7421 DEBUG(4,("printer driver directory: [%s]\n", path));
7423 r->directory_name = path;
7428 /****************************************************************
7429 _spoolss_GetPrinterDriverDirectory
7430 ****************************************************************/
7432 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7433 struct spoolss_GetPrinterDriverDirectory *r)
7437 /* that's an [in out] buffer */
7439 if (!r->in.buffer && (r->in.offered != 0)) {
7440 return WERR_INVALID_PARAM;
7443 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7448 /* r->in.level is ignored */
7450 werror = getprinterdriverdir_level_1(p->mem_ctx,
7453 &r->out.info->info1);
7454 if (!W_ERROR_IS_OK(werror)) {
7455 TALLOC_FREE(r->out.info);
7459 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7460 r->out.info, r->in.level);
7461 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7463 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7466 /****************************************************************
7467 _spoolss_EnumPrinterData
7468 ****************************************************************/
7470 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7471 struct spoolss_EnumPrinterData *r)
7474 struct spoolss_EnumPrinterDataEx r2;
7476 struct spoolss_PrinterEnumValues *info, *val = NULL;
7479 r2.in.handle = r->in.handle;
7480 r2.in.key_name = "PrinterDriverData";
7482 r2.out.count = &count;
7483 r2.out.info = &info;
7484 r2.out.needed = &needed;
7486 result = _spoolss_EnumPrinterDataEx(p, &r2);
7487 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7488 r2.in.offered = needed;
7489 result = _spoolss_EnumPrinterDataEx(p, &r2);
7491 if (!W_ERROR_IS_OK(result)) {
7496 * The NT machine wants to know the biggest size of value and data
7498 * cf: MSDN EnumPrinterData remark section
7501 if (!r->in.value_offered && !r->in.data_offered) {
7502 uint32_t biggest_valuesize = 0;
7503 uint32_t biggest_datasize = 0;
7506 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7508 for (i=0; i<count; i++) {
7510 name_length = strlen(info[i].value_name);
7511 if (strlen(info[i].value_name) > biggest_valuesize) {
7512 biggest_valuesize = name_length;
7515 if (info[i].data_length > biggest_datasize) {
7516 biggest_datasize = info[i].data_length;
7519 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7523 /* the value is an UNICODE string but real_value_size is the length
7524 in bytes including the trailing 0 */
7526 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7527 *r->out.data_needed = biggest_datasize;
7529 DEBUG(6,("final values: [%d], [%d]\n",
7530 *r->out.value_needed, *r->out.data_needed));
7535 if (r->in.enum_index < count) {
7536 val = &info[r->in.enum_index];
7540 /* out_value should default to "" or else NT4 has
7541 problems unmarshalling the response */
7543 if (r->in.value_offered) {
7544 *r->out.value_needed = 1;
7545 r->out.value_name = talloc_strdup(r, "");
7546 if (!r->out.value_name) {
7550 r->out.value_name = NULL;
7551 *r->out.value_needed = 0;
7554 /* the data is counted in bytes */
7556 *r->out.data_needed = r->in.data_offered;
7558 result = WERR_NO_MORE_ITEMS;
7562 * - counted in bytes in the request
7563 * - counted in UNICODE chars in the max reply
7564 * - counted in bytes in the real size
7566 * take a pause *before* coding not *during* coding
7570 if (r->in.value_offered) {
7571 r->out.value_name = talloc_strdup(r, val->value_name);
7572 if (!r->out.value_name) {
7575 *r->out.value_needed = val->value_name_len;
7577 r->out.value_name = NULL;
7578 *r->out.value_needed = 0;
7583 *r->out.type = val->type;
7585 /* data - counted in bytes */
7588 * See the section "Dynamically Typed Query Parameters"
7592 if (r->out.data && val->data && val->data->data &&
7593 val->data_length && r->in.data_offered) {
7594 memcpy(r->out.data, val->data->data,
7595 MIN(val->data_length,r->in.data_offered));
7598 *r->out.data_needed = val->data_length;
7606 /****************************************************************
7607 _spoolss_SetPrinterData
7608 ****************************************************************/
7610 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7611 struct spoolss_SetPrinterData *r)
7613 struct spoolss_SetPrinterDataEx r2;
7615 r2.in.handle = r->in.handle;
7616 r2.in.key_name = "PrinterDriverData";
7617 r2.in.value_name = r->in.value_name;
7618 r2.in.type = r->in.type;
7619 r2.in.data = r->in.data;
7620 r2.in.offered = r->in.offered;
7622 return _spoolss_SetPrinterDataEx(p, &r2);
7625 /****************************************************************
7626 _spoolss_ResetPrinter
7627 ****************************************************************/
7629 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7630 struct spoolss_ResetPrinter *r)
7632 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7635 DEBUG(5,("_spoolss_ResetPrinter\n"));
7638 * All we do is to check to see if the handle and queue is valid.
7639 * This call really doesn't mean anything to us because we only
7640 * support RAW printing. --jerry
7644 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7645 OUR_HANDLE(r->in.handle)));
7649 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7653 /* blindly return success */
7657 /****************************************************************
7658 _spoolss_DeletePrinterData
7659 ****************************************************************/
7661 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7662 struct spoolss_DeletePrinterData *r)
7664 struct spoolss_DeletePrinterDataEx r2;
7666 r2.in.handle = r->in.handle;
7667 r2.in.key_name = "PrinterDriverData";
7668 r2.in.value_name = r->in.value_name;
7670 return _spoolss_DeletePrinterDataEx(p, &r2);
7673 /****************************************************************
7675 ****************************************************************/
7677 WERROR _spoolss_AddForm(pipes_struct *p,
7678 struct spoolss_AddForm *r)
7680 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7681 nt_forms_struct tmpForm;
7683 WERROR status = WERR_OK;
7684 NT_PRINTER_INFO_LEVEL *printer = NULL;
7685 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7688 nt_forms_struct *list=NULL;
7689 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7692 DEBUG(5,("_spoolss_AddForm\n"));
7695 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7696 OUR_HANDLE(r->in.handle)));
7701 /* forms can be added on printer or on the print server handle */
7703 if ( Printer->printer_type == SPLHND_PRINTER )
7705 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7708 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7709 if (!W_ERROR_IS_OK(status))
7713 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7714 and not a printer admin, then fail */
7716 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7717 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7718 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7719 p->server_info->info3->base.domain.string,
7721 p->server_info->ptok,
7722 lp_printer_admin(snum))) {
7723 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7724 status = WERR_ACCESS_DENIED;
7728 switch (form->flags) {
7729 case SPOOLSS_FORM_USER:
7730 case SPOOLSS_FORM_BUILTIN:
7731 case SPOOLSS_FORM_PRINTER:
7734 status = WERR_INVALID_PARAM;
7738 /* can't add if builtin */
7740 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7741 status = WERR_FILE_EXISTS;
7745 count = get_ntforms(&list);
7747 for (i=0; i < count; i++) {
7748 if (strequal(form->form_name, list[i].name)) {
7749 status = WERR_FILE_EXISTS;
7754 if(!add_a_form(&list, form, &count)) {
7755 status = WERR_NOMEM;
7760 write_ntforms(&list, count);
7764 * ChangeID must always be set if this is a printer
7767 if ( Printer->printer_type == SPLHND_PRINTER )
7768 status = mod_a_printer(printer, 2);
7772 free_a_printer(&printer, 2);
7778 /****************************************************************
7780 ****************************************************************/
7782 WERROR _spoolss_DeleteForm(pipes_struct *p,
7783 struct spoolss_DeleteForm *r)
7785 const char *form_name = r->in.form_name;
7786 nt_forms_struct tmpForm;
7788 nt_forms_struct *list=NULL;
7789 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7791 WERROR status = WERR_OK;
7792 NT_PRINTER_INFO_LEVEL *printer = NULL;
7793 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7796 DEBUG(5,("_spoolss_DeleteForm\n"));
7799 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7800 OUR_HANDLE(r->in.handle)));
7804 /* forms can be deleted on printer of on the print server handle */
7806 if ( Printer->printer_type == SPLHND_PRINTER )
7808 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7811 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7812 if (!W_ERROR_IS_OK(status))
7816 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7817 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7818 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7819 p->server_info->info3->base.domain.string,
7821 p->server_info->ptok,
7822 lp_printer_admin(snum))) {
7823 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7824 return WERR_ACCESS_DENIED;
7828 /* can't delete if builtin */
7830 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7831 status = WERR_INVALID_PARAM;
7835 count = get_ntforms(&list);
7838 ret = delete_a_form(&list, form_name, &count, &status);
7845 * ChangeID must always be set if this is a printer
7848 if ( Printer->printer_type == SPLHND_PRINTER )
7849 status = mod_a_printer(printer, 2);
7853 free_a_printer(&printer, 2);
7859 /****************************************************************
7861 ****************************************************************/
7863 WERROR _spoolss_SetForm(pipes_struct *p,
7864 struct spoolss_SetForm *r)
7866 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7867 nt_forms_struct tmpForm;
7869 WERROR status = WERR_OK;
7870 NT_PRINTER_INFO_LEVEL *printer = NULL;
7871 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7874 nt_forms_struct *list=NULL;
7875 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7877 DEBUG(5,("_spoolss_SetForm\n"));
7880 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7881 OUR_HANDLE(r->in.handle)));
7885 /* forms can be modified on printer of on the print server handle */
7887 if ( Printer->printer_type == SPLHND_PRINTER )
7889 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7892 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7893 if (!W_ERROR_IS_OK(status))
7897 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7898 and not a printer admin, then fail */
7900 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7901 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7902 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7903 p->server_info->info3->base.domain.string,
7905 p->server_info->ptok,
7906 lp_printer_admin(snum))) {
7907 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7908 status = WERR_ACCESS_DENIED;
7912 /* can't set if builtin */
7913 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7914 status = WERR_INVALID_PARAM;
7918 count = get_ntforms(&list);
7919 update_a_form(&list, form, count);
7921 write_ntforms(&list, count);
7925 * ChangeID must always be set if this is a printer
7928 if ( Printer->printer_type == SPLHND_PRINTER )
7929 status = mod_a_printer(printer, 2);
7934 free_a_printer(&printer, 2);
7940 /****************************************************************************
7941 fill_print_processor1
7942 ****************************************************************************/
7944 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7945 struct spoolss_PrintProcessorInfo1 *r,
7946 const char *print_processor_name)
7948 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7949 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7954 /****************************************************************************
7955 enumprintprocessors level 1.
7956 ****************************************************************************/
7958 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7959 union spoolss_PrintProcessorInfo **info_p,
7962 union spoolss_PrintProcessorInfo *info;
7965 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7966 W_ERROR_HAVE_NO_MEMORY(info);
7970 result = fill_print_processor1(info, &info[0].info1, "winprint");
7971 if (!W_ERROR_IS_OK(result)) {
7976 if (!W_ERROR_IS_OK(result)) {
7987 /****************************************************************
7988 _spoolss_EnumPrintProcessors
7989 ****************************************************************/
7991 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7992 struct spoolss_EnumPrintProcessors *r)
7996 /* that's an [in out] buffer */
7998 if (!r->in.buffer && (r->in.offered != 0)) {
7999 return WERR_INVALID_PARAM;
8002 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8005 * Enumerate the print processors ...
8007 * Just reply with "winprint", to keep NT happy
8008 * and I can use my nice printer checker.
8013 *r->out.info = NULL;
8015 switch (r->in.level) {
8017 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8021 return WERR_UNKNOWN_LEVEL;
8024 if (!W_ERROR_IS_OK(result)) {
8028 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8029 spoolss_EnumPrintProcessors,
8030 *r->out.info, r->in.level,
8032 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8033 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8035 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8038 /****************************************************************************
8039 fill_printprocdatatype1
8040 ****************************************************************************/
8042 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8043 struct spoolss_PrintProcDataTypesInfo1 *r,
8044 const char *name_array)
8046 r->name_array = talloc_strdup(mem_ctx, name_array);
8047 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8052 /****************************************************************************
8053 enumprintprocdatatypes level 1.
8054 ****************************************************************************/
8056 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8057 union spoolss_PrintProcDataTypesInfo **info_p,
8061 union spoolss_PrintProcDataTypesInfo *info;
8063 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8064 W_ERROR_HAVE_NO_MEMORY(info);
8068 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8069 if (!W_ERROR_IS_OK(result)) {
8074 if (!W_ERROR_IS_OK(result)) {
8085 /****************************************************************
8086 _spoolss_EnumPrintProcDataTypes
8087 ****************************************************************/
8089 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8090 struct spoolss_EnumPrintProcDataTypes *r)
8094 /* that's an [in out] buffer */
8096 if (!r->in.buffer && (r->in.offered != 0)) {
8097 return WERR_INVALID_PARAM;
8100 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8104 *r->out.info = NULL;
8106 switch (r->in.level) {
8108 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8112 return WERR_UNKNOWN_LEVEL;
8115 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8116 spoolss_EnumPrintProcDataTypes,
8117 *r->out.info, r->in.level,
8119 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8120 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8122 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8125 /****************************************************************************
8127 ****************************************************************************/
8129 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8130 struct spoolss_MonitorInfo1 *r,
8131 const char *monitor_name)
8133 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8134 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8139 /****************************************************************************
8141 ****************************************************************************/
8143 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8144 struct spoolss_MonitorInfo2 *r,
8145 const char *monitor_name,
8146 const char *environment,
8147 const char *dll_name)
8149 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8150 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8151 r->environment = talloc_strdup(mem_ctx, environment);
8152 W_ERROR_HAVE_NO_MEMORY(r->environment);
8153 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8154 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8159 /****************************************************************************
8160 enumprintmonitors level 1.
8161 ****************************************************************************/
8163 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8164 union spoolss_MonitorInfo **info_p,
8167 union spoolss_MonitorInfo *info;
8168 WERROR result = WERR_OK;
8170 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8171 W_ERROR_HAVE_NO_MEMORY(info);
8175 result = fill_monitor_1(info, &info[0].info1,
8177 if (!W_ERROR_IS_OK(result)) {
8181 result = fill_monitor_1(info, &info[1].info1,
8183 if (!W_ERROR_IS_OK(result)) {
8188 if (!W_ERROR_IS_OK(result)) {
8199 /****************************************************************************
8200 enumprintmonitors level 2.
8201 ****************************************************************************/
8203 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8204 union spoolss_MonitorInfo **info_p,
8207 union spoolss_MonitorInfo *info;
8208 WERROR result = WERR_OK;
8210 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8211 W_ERROR_HAVE_NO_MEMORY(info);
8215 result = fill_monitor_2(info, &info[0].info2,
8217 "Windows NT X86", /* FIXME */
8219 if (!W_ERROR_IS_OK(result)) {
8223 result = fill_monitor_2(info, &info[1].info2,
8225 "Windows NT X86", /* FIXME */
8227 if (!W_ERROR_IS_OK(result)) {
8232 if (!W_ERROR_IS_OK(result)) {
8243 /****************************************************************
8244 _spoolss_EnumMonitors
8245 ****************************************************************/
8247 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8248 struct spoolss_EnumMonitors *r)
8252 /* that's an [in out] buffer */
8254 if (!r->in.buffer && (r->in.offered != 0)) {
8255 return WERR_INVALID_PARAM;
8258 DEBUG(5,("_spoolss_EnumMonitors\n"));
8261 * Enumerate the print monitors ...
8263 * Just reply with "Local Port", to keep NT happy
8264 * and I can use my nice printer checker.
8269 *r->out.info = NULL;
8271 switch (r->in.level) {
8273 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8277 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8281 return WERR_UNKNOWN_LEVEL;
8284 if (!W_ERROR_IS_OK(result)) {
8288 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8289 spoolss_EnumMonitors,
8290 *r->out.info, r->in.level,
8292 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8293 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8295 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8298 /****************************************************************************
8299 ****************************************************************************/
8301 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8302 const print_queue_struct *queue,
8303 int count, int snum,
8304 const NT_PRINTER_INFO_LEVEL *ntprinter,
8306 struct spoolss_JobInfo1 *r)
8311 for (i=0; i<count; i++) {
8312 if (queue[i].job == (int)jobid) {
8318 if (found == false) {
8319 /* NT treats not found as bad param... yet another bad choice */
8320 return WERR_INVALID_PARAM;
8323 return fill_job_info1(mem_ctx,
8331 /****************************************************************************
8332 ****************************************************************************/
8334 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8335 const print_queue_struct *queue,
8336 int count, int snum,
8337 const NT_PRINTER_INFO_LEVEL *ntprinter,
8339 struct spoolss_JobInfo2 *r)
8343 struct spoolss_DeviceMode *devmode;
8345 for (i=0; i<count; i++) {
8346 if (queue[i].job == (int)jobid) {
8352 if (found == false) {
8353 /* NT treats not found as bad param... yet another bad
8355 return WERR_INVALID_PARAM;
8359 * if the print job does not have a DEVMODE associated with it,
8360 * just use the one for the printer. A NULL devicemode is not
8361 * a failure condition
8364 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8366 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8367 W_ERROR_HAVE_NO_MEMORY(devmode);
8370 return fill_job_info2(mem_ctx,
8379 /****************************************************************
8381 ****************************************************************/
8383 WERROR _spoolss_GetJob(pipes_struct *p,
8384 struct spoolss_GetJob *r)
8386 WERROR result = WERR_OK;
8387 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8390 print_queue_struct *queue = NULL;
8391 print_status_struct prt_status;
8393 /* that's an [in out] buffer */
8395 if (!r->in.buffer && (r->in.offered != 0)) {
8396 return WERR_INVALID_PARAM;
8399 DEBUG(5,("_spoolss_GetJob\n"));
8403 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8407 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8408 if (!W_ERROR_IS_OK(result)) {
8412 count = print_queue_status(snum, &queue, &prt_status);
8414 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8415 count, prt_status.status, prt_status.message));
8417 switch (r->in.level) {
8419 result = getjob_level_1(p->mem_ctx,
8420 queue, count, snum, ntprinter,
8421 r->in.job_id, &r->out.info->info1);
8424 result = getjob_level_2(p->mem_ctx,
8425 queue, count, snum, ntprinter,
8426 r->in.job_id, &r->out.info->info2);
8429 result = WERR_UNKNOWN_LEVEL;
8434 free_a_printer(&ntprinter, 2);
8436 if (!W_ERROR_IS_OK(result)) {
8437 TALLOC_FREE(r->out.info);
8441 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8443 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8445 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8448 /****************************************************************
8449 _spoolss_GetPrinterDataEx
8450 ****************************************************************/
8452 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8453 struct spoolss_GetPrinterDataEx *r)
8456 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8457 struct regval_blob *val = NULL;
8458 NT_PRINTER_INFO_LEVEL *printer = NULL;
8460 WERROR result = WERR_OK;
8463 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8465 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8466 r->in.key_name, r->in.value_name));
8468 /* in case of problem, return some default values */
8471 *r->out.type = REG_NONE;
8474 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8475 OUR_HANDLE(r->in.handle)));
8476 result = WERR_BADFID;
8480 /* Is the handle to a printer or to the server? */
8482 if (Printer->printer_type == SPLHND_SERVER) {
8484 union spoolss_PrinterData data;
8486 result = getprinterdata_printer_server(p->mem_ctx,
8490 if (!W_ERROR_IS_OK(result)) {
8494 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8495 *r->out.type, &data);
8496 if (!W_ERROR_IS_OK(result)) {
8500 *r->out.needed = blob.length;
8502 if (r->in.offered >= *r->out.needed) {
8503 memcpy(r->out.data, blob.data, blob.length);
8506 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8509 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8510 result = WERR_BADFID;
8514 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8515 if (!W_ERROR_IS_OK(result)) {
8519 /* check to see if the keyname is valid */
8520 if (!strlen(r->in.key_name)) {
8521 result = WERR_INVALID_PARAM;
8525 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8527 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8528 strequal(r->in.value_name, "ChangeId")) {
8529 *r->out.type = REG_DWORD;
8531 if (r->in.offered >= *r->out.needed) {
8532 SIVAL(r->out.data, 0, printer->info_2->changeid);
8538 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
8539 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8540 "Invalid keyname [%s]\n", r->in.key_name ));
8541 result = WERR_BADFILE;
8545 val = get_printer_data(printer->info_2,
8546 r->in.key_name, r->in.value_name);
8548 result = WERR_BADFILE;
8552 *r->out.needed = regval_size(val);
8553 *r->out.type = regval_type(val);
8555 if (r->in.offered >= *r->out.needed) {
8556 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8560 free_a_printer(&printer, 2);
8563 if (!W_ERROR_IS_OK(result)) {
8567 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8568 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8570 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8573 /****************************************************************
8574 _spoolss_SetPrinterDataEx
8575 ****************************************************************/
8577 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8578 struct spoolss_SetPrinterDataEx *r)
8580 NT_PRINTER_INFO_LEVEL *printer = NULL;
8582 WERROR result = WERR_OK;
8583 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8586 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8588 /* From MSDN documentation of SetPrinterDataEx: pass request to
8589 SetPrinterData if key is "PrinterDriverData" */
8592 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8593 OUR_HANDLE(r->in.handle)));
8597 if (Printer->printer_type == SPLHND_SERVER) {
8598 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8599 "Not implemented for server handles yet\n"));
8600 return WERR_INVALID_PARAM;
8603 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8608 * Access check : NT returns "access denied" if you make a
8609 * SetPrinterData call without the necessary privildge.
8610 * we were originally returning OK if nothing changed
8611 * which made Win2k issue **a lot** of SetPrinterData
8612 * when connecting to a printer --jerry
8615 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8616 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8617 "change denied by handle access permissions\n"));
8618 return WERR_ACCESS_DENIED;
8621 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8622 if (!W_ERROR_IS_OK(result)) {
8626 /* check for OID in valuename */
8628 oid_string = strchr(r->in.value_name, ',');
8634 /* save the registry data */
8636 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
8637 r->in.type, r->in.data, r->in.offered);
8639 if (W_ERROR_IS_OK(result)) {
8640 /* save the OID if one was specified */
8642 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8643 r->in.key_name, SPOOL_OID_KEY);
8645 result = WERR_NOMEM;
8650 * I'm not checking the status here on purpose. Don't know
8651 * if this is right, but I'm returning the status from the
8652 * previous set_printer_dataex() call. I have no idea if
8653 * this is right. --jerry
8656 set_printer_dataex(printer, str, r->in.value_name,
8657 REG_SZ, (uint8_t *)oid_string,
8658 strlen(oid_string)+1);
8661 result = mod_a_printer(printer, 2);
8665 free_a_printer(&printer, 2);
8670 /****************************************************************
8671 _spoolss_DeletePrinterDataEx
8672 ****************************************************************/
8674 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8675 struct spoolss_DeletePrinterDataEx *r)
8677 NT_PRINTER_INFO_LEVEL *printer = NULL;
8679 WERROR status = WERR_OK;
8680 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8682 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8685 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8686 "Invalid handle (%s:%u:%u).\n",
8687 OUR_HANDLE(r->in.handle)));
8691 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8694 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8695 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8696 "printer properties change denied by handle\n"));
8697 return WERR_ACCESS_DENIED;
8700 if (!r->in.value_name || !r->in.key_name) {
8704 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8705 if (!W_ERROR_IS_OK(status))
8708 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
8710 if ( W_ERROR_IS_OK(status) )
8711 mod_a_printer( printer, 2 );
8713 free_a_printer(&printer, 2);
8718 /****************************************************************
8719 _spoolss_EnumPrinterKey
8720 ****************************************************************/
8722 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8723 struct spoolss_EnumPrinterKey *r)
8725 fstring *keynames = NULL;
8727 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8728 NT_PRINTER_DATA *data;
8729 NT_PRINTER_INFO_LEVEL *printer = NULL;
8731 WERROR result = WERR_BADFILE;
8733 const char **array = NULL;
8736 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8739 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8740 OUR_HANDLE(r->in.handle)));
8744 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8748 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8749 if (!W_ERROR_IS_OK(result)) {
8753 /* get the list of subkey names */
8755 data = printer->info_2->data;
8757 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
8758 if (num_keys == -1) {
8759 result = WERR_BADFILE;
8763 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 2);
8765 result = WERR_NOMEM;
8770 array[0] = talloc_strdup(array, "");
8772 result = WERR_NOMEM;
8777 for (i=0; i < num_keys; i++) {
8779 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8782 array[i] = talloc_strdup(array, keynames[i]);
8784 result = WERR_NOMEM;
8789 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8790 result = WERR_NOMEM;
8794 *r->out._ndr_size = r->in.offered / 2;
8795 *r->out.needed = blob.length;
8797 if (r->in.offered < *r->out.needed) {
8798 result = WERR_MORE_DATA;
8801 r->out.key_buffer->string_array = array;
8805 if (!W_ERROR_IS_OK(result)) {
8807 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8812 free_a_printer(&printer, 2);
8813 SAFE_FREE(keynames);
8818 /****************************************************************
8819 _spoolss_DeletePrinterKey
8820 ****************************************************************/
8822 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8823 struct spoolss_DeletePrinterKey *r)
8825 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8826 NT_PRINTER_INFO_LEVEL *printer = NULL;
8830 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8833 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8834 OUR_HANDLE(r->in.handle)));
8838 /* if keyname == NULL, return error */
8840 if ( !r->in.key_name )
8841 return WERR_INVALID_PARAM;
8843 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8846 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8847 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8848 "printer properties change denied by handle\n"));
8849 return WERR_ACCESS_DENIED;
8852 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8853 if (!W_ERROR_IS_OK(status))
8856 /* delete the key and all subneys */
8858 status = delete_all_printer_data( printer->info_2, r->in.key_name );
8860 if ( W_ERROR_IS_OK(status) )
8861 status = mod_a_printer(printer, 2);
8863 free_a_printer( &printer, 2 );
8868 /****************************************************************
8869 ****************************************************************/
8871 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
8872 struct regval_blob *v,
8873 struct spoolss_PrinterEnumValues *r)
8875 r->data = TALLOC_ZERO_P(mem_ctx, DATA_BLOB);
8876 W_ERROR_HAVE_NO_MEMORY(r->data);
8878 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
8879 W_ERROR_HAVE_NO_MEMORY(r->value_name);
8881 r->value_name_len = strlen_m_term(regval_name(v)) * 2;
8883 r->type = regval_type(v);
8884 r->data_length = regval_size(v);
8886 if (r->data_length) {
8887 *r->data = data_blob_talloc(r->data, regval_data_p(v), regval_size(v));
8893 /****************************************************************
8894 _spoolss_EnumPrinterDataEx
8895 ****************************************************************/
8897 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8898 struct spoolss_EnumPrinterDataEx *r)
8901 NT_PRINTER_INFO_LEVEL *printer = NULL;
8902 struct spoolss_PrinterEnumValues *info = NULL;
8903 NT_PRINTER_DATA *p_data;
8904 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8910 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8914 *r->out.info = NULL;
8917 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8918 OUR_HANDLE(r->in.handle)));
8923 * first check for a keyname of NULL or "". Win2k seems to send
8924 * this a lot and we should send back WERR_INVALID_PARAM
8925 * no need to spend time looking up the printer in this case.
8929 if (!strlen(r->in.key_name)) {
8930 result = WERR_INVALID_PARAM;
8934 /* get the printer off of disk */
8936 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8940 ZERO_STRUCT(printer);
8941 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8942 if (!W_ERROR_IS_OK(result)) {
8946 /* now look for a match on the key name */
8948 p_data = printer->info_2->data;
8950 key_index = lookup_printerkey(p_data, r->in.key_name);
8951 if (key_index == -1) {
8952 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
8954 result = WERR_INVALID_PARAM;
8958 /* allocate the memory for the array of pointers -- if necessary */
8960 count = regval_ctr_numvals(p_data->keys[key_index].values);
8962 result = WERR_OK; /* ??? */
8966 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
8967 struct spoolss_PrinterEnumValues,
8970 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
8971 result = WERR_NOMEM;
8976 * loop through all params and build the array to pass
8977 * back to the client
8980 for (i=0; i < count; i++) {
8982 struct regval_blob *val;
8984 /* lookup the registry value */
8986 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
8988 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
8992 result = registry_value_to_printer_enum_value(info, val, &info[i]);
8993 if (!W_ERROR_IS_OK(result)) {
8998 #if 0 /* FIXME - gd */
8999 /* housekeeping information in the reply */
9001 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9002 * the hand marshalled container size is a multiple
9003 * of 4 bytes for RPC alignment.
9007 needed += 4-(needed % 4);
9010 *r->out.count = count;
9011 *r->out.info = info;
9016 free_a_printer(&printer, 2);
9019 if (!W_ERROR_IS_OK(result)) {
9023 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9024 spoolss_EnumPrinterDataEx,
9027 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9028 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9030 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9033 /****************************************************************************
9034 ****************************************************************************/
9036 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9037 const char *servername,
9038 const char *environment,
9039 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9044 werr = compose_spoolss_server_path(mem_ctx,
9047 SPOOLSS_PRTPROCS_PATH,
9049 if (!W_ERROR_IS_OK(werr)) {
9053 DEBUG(4,("print processor directory: [%s]\n", path));
9055 r->directory_name = path;
9060 /****************************************************************
9061 _spoolss_GetPrintProcessorDirectory
9062 ****************************************************************/
9064 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9065 struct spoolss_GetPrintProcessorDirectory *r)
9069 /* that's an [in out] buffer */
9071 if (!r->in.buffer && (r->in.offered != 0)) {
9072 return WERR_INVALID_PARAM;
9075 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9080 /* r->in.level is ignored */
9082 /* We always should reply with a local print processor directory so that
9083 * users are not forced to have a [prnproc$] share on the Samba spoolss
9084 * server - Guenther */
9086 result = getprintprocessordirectory_level_1(p->mem_ctx,
9087 NULL, /* r->in.server */
9089 &r->out.info->info1);
9090 if (!W_ERROR_IS_OK(result)) {
9091 TALLOC_FREE(r->out.info);
9095 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9096 r->out.info, r->in.level);
9097 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9099 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9102 /*******************************************************************
9103 ********************************************************************/
9105 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9106 const char *dllname)
9108 enum ndr_err_code ndr_err;
9109 struct spoolss_MonitorUi ui;
9111 ui.dll_name = dllname;
9113 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9114 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9115 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9116 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9118 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9121 /*******************************************************************
9122 Streams the monitor UI DLL name in UNICODE
9123 *******************************************************************/
9125 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9126 NT_USER_TOKEN *token, DATA_BLOB *in,
9127 DATA_BLOB *out, uint32_t *needed)
9129 const char *dllname = "tcpmonui.dll";
9131 *needed = (strlen(dllname)+1) * 2;
9133 if (out->length < *needed) {
9134 return WERR_INSUFFICIENT_BUFFER;
9137 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9144 /*******************************************************************
9145 ********************************************************************/
9147 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9148 struct spoolss_PortData1 *port1,
9149 const DATA_BLOB *buf)
9151 enum ndr_err_code ndr_err;
9152 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9153 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9154 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9155 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9157 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9160 /*******************************************************************
9161 ********************************************************************/
9163 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9164 struct spoolss_PortData2 *port2,
9165 const DATA_BLOB *buf)
9167 enum ndr_err_code ndr_err;
9168 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9169 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9170 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9171 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9173 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9176 /*******************************************************************
9177 Create a new TCP/IP port
9178 *******************************************************************/
9180 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9181 NT_USER_TOKEN *token, DATA_BLOB *in,
9182 DATA_BLOB *out, uint32_t *needed)
9184 struct spoolss_PortData1 port1;
9185 struct spoolss_PortData2 port2;
9186 char *device_uri = NULL;
9189 const char *portname;
9190 const char *hostaddress;
9192 uint32_t port_number;
9195 /* peek for spoolss_PortData version */
9197 if (!in || (in->length < (128 + 4))) {
9198 return WERR_GENERAL_FAILURE;
9201 version = IVAL(in->data, 128);
9207 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9211 portname = port1.portname;
9212 hostaddress = port1.hostaddress;
9213 queue = port1.queue;
9214 protocol = port1.protocol;
9215 port_number = port1.port_number;
9221 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9225 portname = port2.portname;
9226 hostaddress = port2.hostaddress;
9227 queue = port2.queue;
9228 protocol = port2.protocol;
9229 port_number = port2.port_number;
9233 DEBUG(1,("xcvtcp_addport: "
9234 "unknown version of port_data: %d\n", version));
9235 return WERR_UNKNOWN_PORT;
9238 /* create the device URI and call the add_port_hook() */
9241 case PROTOCOL_RAWTCP_TYPE:
9242 device_uri = talloc_asprintf(mem_ctx,
9243 "socket://%s:%d/", hostaddress,
9247 case PROTOCOL_LPR_TYPE:
9248 device_uri = talloc_asprintf(mem_ctx,
9249 "lpr://%s/%s", hostaddress, queue );
9253 return WERR_UNKNOWN_PORT;
9260 return add_port_hook(mem_ctx, token, portname, device_uri);
9263 /*******************************************************************
9264 *******************************************************************/
9266 struct xcv_api_table xcvtcp_cmds[] = {
9267 { "MonitorUI", xcvtcp_monitorui },
9268 { "AddPort", xcvtcp_addport},
9272 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9273 NT_USER_TOKEN *token, const char *command,
9280 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9282 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9283 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9284 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9287 return WERR_BADFUNC;
9290 /*******************************************************************
9291 *******************************************************************/
9292 #if 0 /* don't support management using the "Local Port" monitor */
9294 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9295 NT_USER_TOKEN *token, DATA_BLOB *in,
9296 DATA_BLOB *out, uint32_t *needed)
9298 const char *dllname = "localui.dll";
9300 *needed = (strlen(dllname)+1) * 2;
9302 if (out->length < *needed) {
9303 return WERR_INSUFFICIENT_BUFFER;
9306 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9313 /*******************************************************************
9314 *******************************************************************/
9316 struct xcv_api_table xcvlocal_cmds[] = {
9317 { "MonitorUI", xcvlocal_monitorui },
9321 struct xcv_api_table xcvlocal_cmds[] = {
9328 /*******************************************************************
9329 *******************************************************************/
9331 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9332 NT_USER_TOKEN *token, const char *command,
9333 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9338 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9340 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9341 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9342 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9344 return WERR_BADFUNC;
9347 /****************************************************************
9349 ****************************************************************/
9351 WERROR _spoolss_XcvData(pipes_struct *p,
9352 struct spoolss_XcvData *r)
9354 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9355 DATA_BLOB out_data = data_blob_null;
9359 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9360 OUR_HANDLE(r->in.handle)));
9364 /* Has to be a handle to the TCP/IP port monitor */
9366 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9367 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9371 /* requires administrative access to the server */
9373 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9374 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9375 return WERR_ACCESS_DENIED;
9378 /* Allocate the outgoing buffer */
9380 if (r->in.out_data_size) {
9381 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9382 if (out_data.data == NULL) {
9387 switch ( Printer->printer_type ) {
9388 case SPLHND_PORTMON_TCP:
9389 werror = process_xcvtcp_command(p->mem_ctx,
9390 p->server_info->ptok,
9391 r->in.function_name,
9392 &r->in.in_data, &out_data,
9395 case SPLHND_PORTMON_LOCAL:
9396 werror = process_xcvlocal_command(p->mem_ctx,
9397 p->server_info->ptok,
9398 r->in.function_name,
9399 &r->in.in_data, &out_data,
9403 werror = WERR_INVALID_PRINT_MONITOR;
9406 if (!W_ERROR_IS_OK(werror)) {
9410 *r->out.status_code = 0;
9412 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9413 memcpy(r->out.out_data, out_data.data,
9414 MIN(r->in.out_data_size, out_data.length));
9420 /****************************************************************
9421 _spoolss_AddPrintProcessor
9422 ****************************************************************/
9424 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9425 struct spoolss_AddPrintProcessor *r)
9427 /* for now, just indicate success and ignore the add. We'll
9428 automatically set the winprint processor for printer
9429 entries later. Used to debug the LexMark Optra S 1855 PCL
9435 /****************************************************************
9437 ****************************************************************/
9439 WERROR _spoolss_AddPort(pipes_struct *p,
9440 struct spoolss_AddPort *r)
9442 /* do what w2k3 does */
9444 return WERR_NOT_SUPPORTED;
9447 /****************************************************************
9448 _spoolss_GetPrinterDriver
9449 ****************************************************************/
9451 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9452 struct spoolss_GetPrinterDriver *r)
9454 p->rng_fault_state = true;
9455 return WERR_NOT_SUPPORTED;
9458 /****************************************************************
9459 _spoolss_ReadPrinter
9460 ****************************************************************/
9462 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9463 struct spoolss_ReadPrinter *r)
9465 p->rng_fault_state = true;
9466 return WERR_NOT_SUPPORTED;
9469 /****************************************************************
9470 _spoolss_WaitForPrinterChange
9471 ****************************************************************/
9473 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9474 struct spoolss_WaitForPrinterChange *r)
9476 p->rng_fault_state = true;
9477 return WERR_NOT_SUPPORTED;
9480 /****************************************************************
9481 _spoolss_ConfigurePort
9482 ****************************************************************/
9484 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9485 struct spoolss_ConfigurePort *r)
9487 p->rng_fault_state = true;
9488 return WERR_NOT_SUPPORTED;
9491 /****************************************************************
9493 ****************************************************************/
9495 WERROR _spoolss_DeletePort(pipes_struct *p,
9496 struct spoolss_DeletePort *r)
9498 p->rng_fault_state = true;
9499 return WERR_NOT_SUPPORTED;
9502 /****************************************************************
9503 _spoolss_CreatePrinterIC
9504 ****************************************************************/
9506 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9507 struct spoolss_CreatePrinterIC *r)
9509 p->rng_fault_state = true;
9510 return WERR_NOT_SUPPORTED;
9513 /****************************************************************
9514 _spoolss_PlayGDIScriptOnPrinterIC
9515 ****************************************************************/
9517 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9518 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9520 p->rng_fault_state = true;
9521 return WERR_NOT_SUPPORTED;
9524 /****************************************************************
9525 _spoolss_DeletePrinterIC
9526 ****************************************************************/
9528 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9529 struct spoolss_DeletePrinterIC *r)
9531 p->rng_fault_state = true;
9532 return WERR_NOT_SUPPORTED;
9535 /****************************************************************
9536 _spoolss_AddPrinterConnection
9537 ****************************************************************/
9539 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9540 struct spoolss_AddPrinterConnection *r)
9542 p->rng_fault_state = true;
9543 return WERR_NOT_SUPPORTED;
9546 /****************************************************************
9547 _spoolss_DeletePrinterConnection
9548 ****************************************************************/
9550 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9551 struct spoolss_DeletePrinterConnection *r)
9553 p->rng_fault_state = true;
9554 return WERR_NOT_SUPPORTED;
9557 /****************************************************************
9558 _spoolss_PrinterMessageBox
9559 ****************************************************************/
9561 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9562 struct spoolss_PrinterMessageBox *r)
9564 p->rng_fault_state = true;
9565 return WERR_NOT_SUPPORTED;
9568 /****************************************************************
9570 ****************************************************************/
9572 WERROR _spoolss_AddMonitor(pipes_struct *p,
9573 struct spoolss_AddMonitor *r)
9575 p->rng_fault_state = true;
9576 return WERR_NOT_SUPPORTED;
9579 /****************************************************************
9580 _spoolss_DeleteMonitor
9581 ****************************************************************/
9583 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9584 struct spoolss_DeleteMonitor *r)
9586 p->rng_fault_state = true;
9587 return WERR_NOT_SUPPORTED;
9590 /****************************************************************
9591 _spoolss_DeletePrintProcessor
9592 ****************************************************************/
9594 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9595 struct spoolss_DeletePrintProcessor *r)
9597 p->rng_fault_state = true;
9598 return WERR_NOT_SUPPORTED;
9601 /****************************************************************
9602 _spoolss_AddPrintProvidor
9603 ****************************************************************/
9605 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9606 struct spoolss_AddPrintProvidor *r)
9608 p->rng_fault_state = true;
9609 return WERR_NOT_SUPPORTED;
9612 /****************************************************************
9613 _spoolss_DeletePrintProvidor
9614 ****************************************************************/
9616 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9617 struct spoolss_DeletePrintProvidor *r)
9619 p->rng_fault_state = true;
9620 return WERR_NOT_SUPPORTED;
9623 /****************************************************************
9624 _spoolss_FindFirstPrinterChangeNotification
9625 ****************************************************************/
9627 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9628 struct spoolss_FindFirstPrinterChangeNotification *r)
9630 p->rng_fault_state = true;
9631 return WERR_NOT_SUPPORTED;
9634 /****************************************************************
9635 _spoolss_FindNextPrinterChangeNotification
9636 ****************************************************************/
9638 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9639 struct spoolss_FindNextPrinterChangeNotification *r)
9641 p->rng_fault_state = true;
9642 return WERR_NOT_SUPPORTED;
9645 /****************************************************************
9646 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9647 ****************************************************************/
9649 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9650 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9652 p->rng_fault_state = true;
9653 return WERR_NOT_SUPPORTED;
9656 /****************************************************************
9657 _spoolss_ReplyOpenPrinter
9658 ****************************************************************/
9660 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9661 struct spoolss_ReplyOpenPrinter *r)
9663 p->rng_fault_state = true;
9664 return WERR_NOT_SUPPORTED;
9667 /****************************************************************
9668 _spoolss_RouterReplyPrinter
9669 ****************************************************************/
9671 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9672 struct spoolss_RouterReplyPrinter *r)
9674 p->rng_fault_state = true;
9675 return WERR_NOT_SUPPORTED;
9678 /****************************************************************
9679 _spoolss_ReplyClosePrinter
9680 ****************************************************************/
9682 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9683 struct spoolss_ReplyClosePrinter *r)
9685 p->rng_fault_state = true;
9686 return WERR_NOT_SUPPORTED;
9689 /****************************************************************
9691 ****************************************************************/
9693 WERROR _spoolss_AddPortEx(pipes_struct *p,
9694 struct spoolss_AddPortEx *r)
9696 p->rng_fault_state = true;
9697 return WERR_NOT_SUPPORTED;
9700 /****************************************************************
9701 _spoolss_RouterFindFirstPrinterChangeNotification
9702 ****************************************************************/
9704 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9705 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9707 p->rng_fault_state = true;
9708 return WERR_NOT_SUPPORTED;
9711 /****************************************************************
9712 _spoolss_SpoolerInit
9713 ****************************************************************/
9715 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9716 struct spoolss_SpoolerInit *r)
9718 p->rng_fault_state = true;
9719 return WERR_NOT_SUPPORTED;
9722 /****************************************************************
9723 _spoolss_ResetPrinterEx
9724 ****************************************************************/
9726 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9727 struct spoolss_ResetPrinterEx *r)
9729 p->rng_fault_state = true;
9730 return WERR_NOT_SUPPORTED;
9733 /****************************************************************
9734 _spoolss_RouterReplyPrinterEx
9735 ****************************************************************/
9737 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9738 struct spoolss_RouterReplyPrinterEx *r)
9740 p->rng_fault_state = true;
9741 return WERR_NOT_SUPPORTED;
9744 /****************************************************************
9746 ****************************************************************/
9748 WERROR _spoolss_44(pipes_struct *p,
9749 struct spoolss_44 *r)
9751 p->rng_fault_state = true;
9752 return WERR_NOT_SUPPORTED;
9755 /****************************************************************
9757 ****************************************************************/
9759 WERROR _spoolss_47(pipes_struct *p,
9760 struct spoolss_47 *r)
9762 p->rng_fault_state = true;
9763 return WERR_NOT_SUPPORTED;
9766 /****************************************************************
9768 ****************************************************************/
9770 WERROR _spoolss_4a(pipes_struct *p,
9771 struct spoolss_4a *r)
9773 p->rng_fault_state = true;
9774 return WERR_NOT_SUPPORTED;
9777 /****************************************************************
9779 ****************************************************************/
9781 WERROR _spoolss_4b(pipes_struct *p,
9782 struct spoolss_4b *r)
9784 p->rng_fault_state = true;
9785 return WERR_NOT_SUPPORTED;
9788 /****************************************************************
9790 ****************************************************************/
9792 WERROR _spoolss_4c(pipes_struct *p,
9793 struct spoolss_4c *r)
9795 p->rng_fault_state = true;
9796 return WERR_NOT_SUPPORTED;
9799 /****************************************************************
9801 ****************************************************************/
9803 WERROR _spoolss_53(pipes_struct *p,
9804 struct spoolss_53 *r)
9806 p->rng_fault_state = true;
9807 return WERR_NOT_SUPPORTED;
9810 /****************************************************************
9812 ****************************************************************/
9814 WERROR _spoolss_55(pipes_struct *p,
9815 struct spoolss_55 *r)
9817 p->rng_fault_state = true;
9818 return WERR_NOT_SUPPORTED;
9821 /****************************************************************
9823 ****************************************************************/
9825 WERROR _spoolss_56(pipes_struct *p,
9826 struct spoolss_56 *r)
9828 p->rng_fault_state = true;
9829 return WERR_NOT_SUPPORTED;
9832 /****************************************************************
9834 ****************************************************************/
9836 WERROR _spoolss_57(pipes_struct *p,
9837 struct spoolss_57 *r)
9839 p->rng_fault_state = true;
9840 return WERR_NOT_SUPPORTED;
9843 /****************************************************************
9845 ****************************************************************/
9847 WERROR _spoolss_5a(pipes_struct *p,
9848 struct spoolss_5a *r)
9850 p->rng_fault_state = true;
9851 return WERR_NOT_SUPPORTED;
9854 /****************************************************************
9856 ****************************************************************/
9858 WERROR _spoolss_5b(pipes_struct *p,
9859 struct spoolss_5b *r)
9861 p->rng_fault_state = true;
9862 return WERR_NOT_SUPPORTED;
9865 /****************************************************************
9867 ****************************************************************/
9869 WERROR _spoolss_5c(pipes_struct *p,
9870 struct spoolss_5c *r)
9872 p->rng_fault_state = true;
9873 return WERR_NOT_SUPPORTED;
9876 /****************************************************************
9878 ****************************************************************/
9880 WERROR _spoolss_5d(pipes_struct *p,
9881 struct spoolss_5d *r)
9883 p->rng_fault_state = true;
9884 return WERR_NOT_SUPPORTED;
9887 /****************************************************************
9889 ****************************************************************/
9891 WERROR _spoolss_5e(pipes_struct *p,
9892 struct spoolss_5e *r)
9894 p->rng_fault_state = true;
9895 return WERR_NOT_SUPPORTED;
9898 /****************************************************************
9900 ****************************************************************/
9902 WERROR _spoolss_5f(pipes_struct *p,
9903 struct spoolss_5f *r)
9905 p->rng_fault_state = true;
9906 return WERR_NOT_SUPPORTED;
9909 /****************************************************************
9911 ****************************************************************/
9913 WERROR _spoolss_60(pipes_struct *p,
9914 struct spoolss_60 *r)
9916 p->rng_fault_state = true;
9917 return WERR_NOT_SUPPORTED;
9920 /****************************************************************
9922 ****************************************************************/
9924 WERROR _spoolss_61(pipes_struct *p,
9925 struct spoolss_61 *r)
9927 p->rng_fault_state = true;
9928 return WERR_NOT_SUPPORTED;
9931 /****************************************************************
9933 ****************************************************************/
9935 WERROR _spoolss_62(pipes_struct *p,
9936 struct spoolss_62 *r)
9938 p->rng_fault_state = true;
9939 return WERR_NOT_SUPPORTED;
9942 /****************************************************************
9944 ****************************************************************/
9946 WERROR _spoolss_63(pipes_struct *p,
9947 struct spoolss_63 *r)
9949 p->rng_fault_state = true;
9950 return WERR_NOT_SUPPORTED;
9953 /****************************************************************
9955 ****************************************************************/
9957 WERROR _spoolss_64(pipes_struct *p,
9958 struct spoolss_64 *r)
9960 p->rng_fault_state = true;
9961 return WERR_NOT_SUPPORTED;
9964 /****************************************************************
9966 ****************************************************************/
9968 WERROR _spoolss_65(pipes_struct *p,
9969 struct spoolss_65 *r)
9971 p->rng_fault_state = true;
9972 return WERR_NOT_SUPPORTED;
9975 /****************************************************************
9976 _spoolss_GetCorePrinterDrivers
9977 ****************************************************************/
9979 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9980 struct spoolss_GetCorePrinterDrivers *r)
9982 p->rng_fault_state = true;
9983 return WERR_NOT_SUPPORTED;
9986 /****************************************************************
9988 ****************************************************************/
9990 WERROR _spoolss_67(pipes_struct *p,
9991 struct spoolss_67 *r)
9993 p->rng_fault_state = true;
9994 return WERR_NOT_SUPPORTED;
9997 /****************************************************************
9998 _spoolss_GetPrinterDriverPackagePath
9999 ****************************************************************/
10001 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
10002 struct spoolss_GetPrinterDriverPackagePath *r)
10004 p->rng_fault_state = true;
10005 return WERR_NOT_SUPPORTED;
10008 /****************************************************************
10010 ****************************************************************/
10012 WERROR _spoolss_69(pipes_struct *p,
10013 struct spoolss_69 *r)
10015 p->rng_fault_state = true;
10016 return WERR_NOT_SUPPORTED;
10019 /****************************************************************
10021 ****************************************************************/
10023 WERROR _spoolss_6a(pipes_struct *p,
10024 struct spoolss_6a *r)
10026 p->rng_fault_state = true;
10027 return WERR_NOT_SUPPORTED;
10030 /****************************************************************
10032 ****************************************************************/
10034 WERROR _spoolss_6b(pipes_struct *p,
10035 struct spoolss_6b *r)
10037 p->rng_fault_state = true;
10038 return WERR_NOT_SUPPORTED;
10041 /****************************************************************
10043 ****************************************************************/
10045 WERROR _spoolss_6c(pipes_struct *p,
10046 struct spoolss_6c *r)
10048 p->rng_fault_state = true;
10049 return WERR_NOT_SUPPORTED;
10052 /****************************************************************
10054 ****************************************************************/
10056 WERROR _spoolss_6d(pipes_struct *p,
10057 struct spoolss_6d *r)
10059 p->rng_fault_state = true;
10060 return WERR_NOT_SUPPORTED;