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.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
31 #include "srv_spoolss_util.h"
32 #include "../librpc/gen_ndr/srv_spoolss.h"
33 #include "../librpc/gen_ndr/cli_spoolss.h"
34 #include "rpc_client/init_spoolss.h"
35 #include "librpc/gen_ndr/messaging.h"
37 #include "registry/reg_objects.h"
39 /* macros stolen from s4 spoolss server */
40 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
41 ((info)?ndr_size_##fn(info, level, 0):0)
43 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
44 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
46 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
47 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
49 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
52 extern userdom_struct current_user_info;
55 #define DBGC_CLASS DBGC_RPC_SRV
57 #ifndef MAX_OPEN_PRINTER_EXS
58 #define MAX_OPEN_PRINTER_EXS 50
61 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
63 static Printer_entry *printers_list;
65 typedef struct _counter_printer_0 {
66 struct _counter_printer_0 *next;
67 struct _counter_printer_0 *prev;
73 static counter_printer_0 *counter_list;
75 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
76 static uint32_t smb_connections = 0;
79 /* in printing/nt_printing.c */
81 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
83 /* API table for Xcv Monitor functions */
85 struct xcv_api_table {
87 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
90 /********************************************************************
91 * Canonicalize servername.
92 ********************************************************************/
94 static const char *canon_servername(const char *servername)
96 const char *pservername = servername;
97 while (*pservername == '\\') {
103 /* translate between internal status numbers and NT status numbers */
104 static int nt_printj_status(int v)
110 return JOB_STATUS_PAUSED;
112 return JOB_STATUS_SPOOLING;
114 return JOB_STATUS_PRINTING;
116 return JOB_STATUS_ERROR;
118 return JOB_STATUS_DELETING;
120 return JOB_STATUS_OFFLINE;
122 return JOB_STATUS_PAPEROUT;
124 return JOB_STATUS_PRINTED;
126 return JOB_STATUS_DELETED;
128 return JOB_STATUS_BLOCKED_DEVQ;
129 case LPQ_USER_INTERVENTION:
130 return JOB_STATUS_USER_INTERVENTION;
135 static int nt_printq_status(int v)
139 return PRINTER_STATUS_PAUSED;
148 /***************************************************************************
149 Disconnect from the client
150 ****************************************************************************/
152 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
158 * Tell the specific printing tdb we no longer want messages for this printer
159 * by deregistering our PID.
162 if (!print_notify_deregister_pid(snum))
163 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
165 /* weird if the test succeds !!! */
166 if (smb_connections==0) {
167 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
171 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
174 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
175 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
176 win_errstr(result)));
178 /* if it's the last connection, deconnect the IPC$ share */
179 if (smb_connections==1) {
181 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
182 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
184 messaging_deregister(smbd_messaging_context(),
185 MSG_PRINTER_NOTIFY2, NULL);
187 /* Tell the connections db we're no longer interested in
188 * printer notify messages. */
190 serverid_register_msg_flags(
191 messaging_server_id(smbd_messaging_context()),
192 false, FLAG_MSG_PRINT_NOTIFY);
198 /****************************************************************************
199 Functions to free a printer entry datastruct.
200 ****************************************************************************/
202 static int printer_entry_destructor(Printer_entry *Printer)
204 if (Printer->notify.client_connected == true) {
207 if ( Printer->printer_type == SPLHND_SERVER) {
209 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
210 } else if (Printer->printer_type == SPLHND_PRINTER) {
211 snum = print_queue_snum(Printer->sharename);
213 srv_spoolss_replycloseprinter(snum,
214 &Printer->notify.client_hnd);
218 Printer->notify.flags=0;
219 Printer->notify.options=0;
220 Printer->notify.localmachine[0]='\0';
221 Printer->notify.printerlocal=0;
222 TALLOC_FREE(Printer->notify.option);
223 Printer->notify.client_connected = false;
225 TALLOC_FREE(Printer->devmode);
226 free_a_printer( &Printer->printer_info, 2 );
228 /* Remove from the internal list. */
229 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 find printer index by handle
235 ****************************************************************************/
237 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
238 struct policy_handle *hnd)
240 Printer_entry *find_printer = NULL;
242 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
243 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
250 /****************************************************************************
251 Close printer index by handle.
252 ****************************************************************************/
254 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
256 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
259 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
264 close_policy_hnd(p, hnd);
269 /****************************************************************************
270 Delete a printer given a handle.
271 ****************************************************************************/
273 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
275 char *cmd = lp_deleteprinter_cmd();
276 char *command = NULL;
278 SE_PRIV se_printop = SE_PRINT_OPERATOR;
279 bool is_print_op = false;
281 /* can't fail if we don't try */
286 command = talloc_asprintf(ctx,
293 is_print_op = user_has_privileges( token, &se_printop );
295 DEBUG(10,("Running [%s]\n", command));
297 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
302 if ( (ret = smbrun(command, NULL)) == 0 ) {
303 /* Tell everyone we updated smb.conf. */
304 message_send_all(smbd_messaging_context(),
305 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
311 /********** END SePrintOperatorPrivlege BLOCK **********/
313 DEBUGADD(10,("returned [%d]\n", ret));
315 TALLOC_FREE(command);
318 return WERR_BADFID; /* What to return here? */
320 /* go ahead and re-read the services immediately */
322 reload_services(false);
325 if ( lp_servicenumber( sharename ) > 0 )
326 return WERR_ACCESS_DENIED;
331 /****************************************************************************
332 Delete a printer given a handle.
333 ****************************************************************************/
335 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
337 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
340 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
346 * It turns out that Windows allows delete printer on a handle
347 * opened by an admin user, then used on a pipe handle created
348 * by an anonymous user..... but they're working on security.... riiight !
352 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
353 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
354 return WERR_ACCESS_DENIED;
357 /* this does not need a become root since the access check has been
358 done on the handle already */
360 if (del_a_printer( Printer->sharename ) != 0) {
361 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
365 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
366 Printer->sharename );
369 /****************************************************************************
370 Return the snum of a printer corresponding to an handle.
371 ****************************************************************************/
373 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
374 int *number, struct share_params **params)
376 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
379 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
384 switch (Printer->printer_type) {
386 DEBUG(4,("short name:%s\n", Printer->sharename));
387 *number = print_queue_snum(Printer->sharename);
388 return (*number != -1);
396 /****************************************************************************
397 Set printer handle type.
398 Check if it's \\server or \\server\printer
399 ****************************************************************************/
401 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
403 DEBUG(3,("Setting printer type=%s\n", handlename));
405 if ( strlen(handlename) < 3 ) {
406 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
410 /* it's a print server */
411 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
412 DEBUGADD(4,("Printer is a print server\n"));
413 Printer->printer_type = SPLHND_SERVER;
415 /* it's a printer (set_printer_hnd_name() will handle port monitors */
417 DEBUGADD(4,("Printer is a printer\n"));
418 Printer->printer_type = SPLHND_PRINTER;
424 /****************************************************************************
425 Set printer handle name.. Accept names like \\server, \\server\printer,
426 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
427 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
428 XcvDataPort() interface.
429 ****************************************************************************/
431 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
434 int n_services=lp_numservices();
435 char *aprinter, *printername;
436 const char *servername;
439 NT_PRINTER_INFO_LEVEL *printer = NULL;
442 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
443 (unsigned long)strlen(handlename)));
445 aprinter = CONST_DISCARD(char *, handlename);
446 if ( *handlename == '\\' ) {
447 servername = canon_servername(handlename);
448 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
453 servername = global_myname();
456 /* save the servername to fill in replies on this handle */
458 if ( !is_myname_or_ipaddr( servername ) )
461 fstrcpy( Printer->servername, servername );
463 if ( Printer->printer_type == SPLHND_SERVER )
466 if ( Printer->printer_type != SPLHND_PRINTER )
469 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
471 /* check for the Port Monitor Interface */
473 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
474 Printer->printer_type = SPLHND_PORTMON_TCP;
475 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
478 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
479 Printer->printer_type = SPLHND_PORTMON_LOCAL;
480 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
484 /* Search all sharenames first as this is easier than pulling
485 the printer_info_2 off of disk. Don't use find_service() since
486 that calls out to map_username() */
488 /* do another loop to look for printernames */
490 for (snum=0; !found && snum<n_services; snum++) {
492 /* no point going on if this is not a printer */
494 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
497 fstrcpy(sname, lp_servicename(snum));
498 if ( strequal( aprinter, sname ) ) {
503 /* no point looking up the printer object if
504 we aren't allowing printername != sharename */
506 if ( lp_force_printername(snum) )
509 fstrcpy(sname, lp_servicename(snum));
513 /* This call doesn't fill in the location or comment from
514 * a CUPS server for efficiency with large numbers of printers.
518 result = get_a_printer_search( NULL, &printer, 2, sname );
519 if ( !W_ERROR_IS_OK(result) ) {
520 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
521 sname, win_errstr(result)));
525 /* printername is always returned as \\server\printername */
526 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
527 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
528 printer->info_2->printername));
529 free_a_printer( &printer, 2);
535 if ( strequal(printername, aprinter) ) {
536 free_a_printer( &printer, 2);
541 DEBUGADD(10, ("printername: %s\n", printername));
543 free_a_printer( &printer, 2);
546 free_a_printer( &printer, 2);
549 DEBUGADD(4,("Printer not found\n"));
553 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
555 fstrcpy(Printer->sharename, sname);
560 /****************************************************************************
561 Find first available printer slot. creates a printer handle for you.
562 ****************************************************************************/
564 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
565 const char *name, uint32_t access_granted)
567 Printer_entry *new_printer;
569 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
571 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
572 if (new_printer == NULL) {
575 talloc_set_destructor(new_printer, printer_entry_destructor);
577 if (!create_policy_hnd(p, hnd, new_printer)) {
578 TALLOC_FREE(new_printer);
582 /* Add to the internal list. */
583 DLIST_ADD(printers_list, new_printer);
585 new_printer->notify.option=NULL;
587 if (!set_printer_hnd_printertype(new_printer, name)) {
588 close_printer_handle(p, hnd);
592 if (!set_printer_hnd_name(new_printer, name)) {
593 close_printer_handle(p, hnd);
597 new_printer->access_granted = access_granted;
599 DEBUG(5, ("%d printer handles active\n",
600 (int)num_pipe_handles(p)));
605 /***************************************************************************
606 check to see if the client motify handle is monitoring the notification
607 given by (notify_type, notify_field).
608 **************************************************************************/
610 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
611 uint16_t notify_field)
616 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
617 uint16_t notify_field)
619 struct spoolss_NotifyOption *option = p->notify.option;
623 * Flags should always be zero when the change notify
624 * is registered by the client's spooler. A user Win32 app
625 * might use the flags though instead of the NOTIFY_OPTION_INFO
634 return is_monitoring_event_flags(
635 p->notify.flags, notify_type, notify_field);
637 for (i = 0; i < option->count; i++) {
639 /* Check match for notify_type */
641 if (option->types[i].type != notify_type)
644 /* Check match for field */
646 for (j = 0; j < option->types[i].count; j++) {
647 if (option->types[i].fields[j].field == notify_field) {
653 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
654 p->servername, p->sharename, notify_type, notify_field));
659 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
660 _data->data.integer[0] = _integer; \
661 _data->data.integer[1] = 0;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
665 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
666 if (!_data->data.string.string) {\
667 _data->data.string.size = 0; \
669 _data->data.string.size = strlen_m_term(_p) * 2;
671 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
672 _data->data.devmode.devmode = _devmode;
674 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
675 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
676 if (!_data->data.sd.sd) { \
677 _data->data.sd.sd_size = 0; \
679 _data->data.sd.sd_size = _size;
681 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
686 struct spoolss_Time st;
690 if (!init_systemtime(&st, t)) {
694 p = talloc_array(mem_ctx, char, len);
700 * Systemtime must be linearized as a set of UINT16's.
701 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
704 SSVAL(p, 0, st.year);
705 SSVAL(p, 2, st.month);
706 SSVAL(p, 4, st.day_of_week);
708 SSVAL(p, 8, st.hour);
709 SSVAL(p, 10, st.minute);
710 SSVAL(p, 12, st.second);
711 SSVAL(p, 14, st.millisecond);
717 /* Convert a notification message to a struct spoolss_Notify */
719 static void notify_one_value(struct spoolss_notify_msg *msg,
720 struct spoolss_Notify *data,
723 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
726 static void notify_string(struct spoolss_notify_msg *msg,
727 struct spoolss_Notify *data,
730 /* The length of the message includes the trailing \0 */
732 data->data.string.size = msg->len * 2;
733 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
734 if (!data->data.string.string) {
735 data->data.string.size = 0;
740 static void notify_system_time(struct spoolss_notify_msg *msg,
741 struct spoolss_Notify *data,
744 data->data.string.string = NULL;
745 data->data.string.size = 0;
747 if (msg->len != sizeof(time_t)) {
748 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
753 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
754 &data->data.string.string,
755 &data->data.string.size);
758 struct notify2_message_table {
760 void (*fn)(struct spoolss_notify_msg *msg,
761 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
764 static struct notify2_message_table printer_notify_table[] = {
765 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
766 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
767 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
768 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
769 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
770 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
771 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
772 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
773 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
774 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
775 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
776 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
777 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
778 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
779 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
780 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
781 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
782 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
783 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
786 static struct notify2_message_table job_notify_table[] = {
787 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
788 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
789 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
790 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
791 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
792 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
793 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
794 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
795 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
796 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
797 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
798 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
799 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
800 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
801 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
802 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
803 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
804 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
805 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
806 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
807 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
808 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
809 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
810 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
814 /***********************************************************************
815 Allocate talloc context for container object
816 **********************************************************************/
818 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
823 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
828 /***********************************************************************
829 release all allocated memory and zero out structure
830 **********************************************************************/
832 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
838 talloc_destroy(ctr->ctx);
845 /***********************************************************************
846 **********************************************************************/
848 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
856 /***********************************************************************
857 **********************************************************************/
859 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
861 if ( !ctr || !ctr->msg_groups )
864 if ( idx >= ctr->num_groups )
867 return &ctr->msg_groups[idx];
871 /***********************************************************************
872 How many groups of change messages do we have ?
873 **********************************************************************/
875 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
880 return ctr->num_groups;
883 /***********************************************************************
884 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
885 **********************************************************************/
887 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
889 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
890 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
891 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
897 /* loop over all groups looking for a matching printer name */
899 for ( i=0; i<ctr->num_groups; i++ ) {
900 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
904 /* add a new group? */
906 if ( i == ctr->num_groups ) {
909 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
913 ctr->msg_groups = groups;
915 /* clear the new entry and set the printer name */
917 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
918 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
921 /* add the change messages; 'i' is the correct index now regardless */
923 msg_grp = &ctr->msg_groups[i];
927 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
928 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
931 msg_grp->msgs = msg_list;
933 new_slot = msg_grp->num_msgs-1;
934 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
936 /* need to allocate own copy of data */
939 msg_grp->msgs[new_slot].notify.data = (char *)
940 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
942 return ctr->num_groups;
945 void construct_info_data(struct spoolss_Notify *info_data,
946 enum spoolss_NotifyType type,
950 /***********************************************************************
951 Send a change notication message on all handles which have a call
953 **********************************************************************/
955 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
958 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
959 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
960 SPOOLSS_NOTIFY_MSG *messages;
961 int sending_msg_count;
964 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
968 messages = msg_group->msgs;
971 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
975 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
977 /* loop over all printers */
979 for (p = printers_list; p; p = p->next) {
980 struct spoolss_Notify *notifies;
985 /* Is there notification on this handle? */
987 if ( !p->notify.client_connected )
990 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
992 /* For this printer? Print servers always receive
995 if ( ( p->printer_type == SPLHND_PRINTER ) &&
996 ( !strequal(msg_group->printername, p->sharename) ) )
999 DEBUG(10,("Our printer\n"));
1001 /* allocate the max entries possible */
1003 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1039 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1056 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 if ( sending_msg_count ) {
1080 union spoolss_ReplyPrinterInfo info;
1081 struct spoolss_NotifyInfo info0;
1082 uint32_t reply_result;
1084 info0.version = 0x2;
1085 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1086 info0.count = count;
1087 info0.notifies = notifies;
1089 info.info0 = &info0;
1091 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1092 &p->notify.client_hnd,
1093 p->notify.change, /* color */
1096 0, /* reply_type, must be 0 */
1099 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1100 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1101 notify_cli_pipe->srv_name_slash,
1104 switch (reply_result) {
1107 case PRINTER_NOTIFY_INFO_DISCARDED:
1108 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1109 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1118 DEBUG(8,("send_notify2_changes: Exit...\n"));
1122 /***********************************************************************
1123 **********************************************************************/
1125 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1128 uint32_t tv_sec, tv_usec;
1131 /* Unpack message */
1133 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1136 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1138 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1141 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1142 &msg->notify.value[0], &msg->notify.value[1]);
1144 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1145 &msg->len, &msg->notify.data);
1147 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1148 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1150 tv->tv_sec = tv_sec;
1151 tv->tv_usec = tv_usec;
1154 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1155 msg->notify.value[1]));
1157 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1162 /********************************************************************
1163 Receive a notify2 message list
1164 ********************************************************************/
1166 static void receive_notify2_message_list(struct messaging_context *msg,
1169 struct server_id server_id,
1172 size_t msg_count, i;
1173 char *buf = (char *)data->data;
1176 SPOOLSS_NOTIFY_MSG notify;
1177 SPOOLSS_NOTIFY_MSG_CTR messages;
1180 if (data->length < 4) {
1181 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1185 msg_count = IVAL(buf, 0);
1188 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1190 if (msg_count == 0) {
1191 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1195 /* initialize the container */
1197 ZERO_STRUCT( messages );
1198 notify_msg_ctr_init( &messages );
1201 * build message groups for each printer identified
1202 * in a change_notify msg. Remember that a PCN message
1203 * includes the handle returned for the srv_spoolss_replyopenprinter()
1204 * call. Therefore messages are grouped according to printer handle.
1207 for ( i=0; i<msg_count; i++ ) {
1208 struct timeval msg_tv;
1210 if (msg_ptr + 4 - buf > data->length) {
1211 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1215 msg_len = IVAL(msg_ptr,0);
1218 if (msg_ptr + msg_len - buf > data->length) {
1219 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1223 /* unpack messages */
1225 ZERO_STRUCT( notify );
1226 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1229 /* add to correct list in container */
1231 notify_msg_ctr_addmsg( &messages, ¬ify );
1233 /* free memory that might have been allocated by notify2_unpack_msg() */
1235 if ( notify.len != 0 )
1236 SAFE_FREE( notify.notify.data );
1239 /* process each group of messages */
1241 num_groups = notify_msg_ctr_numgroups( &messages );
1242 for ( i=0; i<num_groups; i++ )
1243 send_notify2_changes( &messages, i );
1248 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1249 (uint32_t)msg_count ));
1251 notify_msg_ctr_destroy( &messages );
1256 /********************************************************************
1257 Send a message to ourself about new driver being installed
1258 so we can upgrade the information for each printer bound to this
1260 ********************************************************************/
1262 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1264 int len = strlen(drivername);
1269 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1272 messaging_send_buf(smbd_messaging_context(),
1273 messaging_server_id(smbd_messaging_context()),
1274 MSG_PRINTER_DRVUPGRADE,
1275 (uint8_t *)drivername, len+1);
1280 /**********************************************************************
1281 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1282 over all printers, upgrading ones as necessary
1283 **********************************************************************/
1285 void do_drv_upgrade_printer(struct messaging_context *msg,
1288 struct server_id server_id,
1293 int n_services = lp_numservices();
1296 len = MIN(data->length,sizeof(drivername)-1);
1297 strncpy(drivername, (const char *)data->data, len);
1299 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1301 /* Iterate the printer list */
1303 for (snum=0; snum<n_services; snum++)
1305 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1308 NT_PRINTER_INFO_LEVEL *printer = NULL;
1310 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1311 if (!W_ERROR_IS_OK(result))
1314 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1316 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1318 /* all we care about currently is the change_id */
1320 result = mod_a_printer(printer, 2);
1321 if (!W_ERROR_IS_OK(result)) {
1322 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1323 win_errstr(result)));
1327 free_a_printer(&printer, 2);
1334 /********************************************************************
1335 Update the cache for all printq's with a registered client
1337 ********************************************************************/
1339 void update_monitored_printq_cache( void )
1341 Printer_entry *printer = printers_list;
1344 /* loop through all printers and update the cache where
1345 client_connected == true */
1348 if ( (printer->printer_type == SPLHND_PRINTER)
1349 && printer->notify.client_connected )
1351 snum = print_queue_snum(printer->sharename);
1352 print_queue_status( snum, NULL, NULL );
1355 printer = printer->next;
1361 /****************************************************************
1362 _spoolss_OpenPrinter
1363 ****************************************************************/
1365 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1366 struct spoolss_OpenPrinter *r)
1368 struct spoolss_OpenPrinterEx e;
1371 ZERO_STRUCT(e.in.userlevel);
1373 e.in.printername = r->in.printername;
1374 e.in.datatype = r->in.datatype;
1375 e.in.devmode_ctr = r->in.devmode_ctr;
1376 e.in.access_mask = r->in.access_mask;
1379 e.out.handle = r->out.handle;
1381 werr = _spoolss_OpenPrinterEx(p, &e);
1383 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1384 /* OpenPrinterEx returns this for a bad
1385 * printer name. We must return WERR_INVALID_PRINTER_NAME
1388 werr = WERR_INVALID_PRINTER_NAME;
1394 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1395 struct spoolss_DeviceMode *orig,
1396 struct spoolss_DeviceMode **dest)
1398 struct spoolss_DeviceMode *dm;
1400 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1405 /* copy all values, then duplicate strings and structs */
1408 dm->devicename = talloc_strdup(dm, orig->devicename);
1409 if (!dm->devicename) {
1412 dm->formname = talloc_strdup(dm, orig->formname);
1413 if (!dm->formname) {
1416 if (orig->driverextra_data.data) {
1417 dm->driverextra_data.data =
1418 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1419 orig->driverextra_data.length);
1420 if (!dm->driverextra_data.data) {
1429 /****************************************************************
1430 _spoolss_OpenPrinterEx
1431 ****************************************************************/
1433 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1434 struct spoolss_OpenPrinterEx *r)
1437 Printer_entry *Printer=NULL;
1439 if (!r->in.printername) {
1440 return WERR_INVALID_PARAM;
1443 /* some sanity check because you can open a printer or a print server */
1444 /* aka: \\server\printer or \\server */
1446 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1448 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1449 ZERO_STRUCTP(r->out.handle);
1450 return WERR_INVALID_PARAM;
1453 Printer = find_printer_index_by_hnd(p, r->out.handle);
1455 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1456 "handle we created for printer %s\n", r->in.printername));
1457 close_printer_handle(p, r->out.handle);
1458 ZERO_STRUCTP(r->out.handle);
1459 return WERR_INVALID_PARAM;
1463 * First case: the user is opening the print server:
1465 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1466 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1468 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1469 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1470 * or if the user is listed in the smb.conf printer admin parameter.
1472 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1473 * client view printer folder, but does not show the MSAPW.
1475 * Note: this test needs code to check access rights here too. Jeremy
1476 * could you look at this?
1478 * Second case: the user is opening a printer:
1479 * NT doesn't let us connect to a printer if the connecting user
1480 * doesn't have print permission.
1482 * Third case: user is opening a Port Monitor
1483 * access checks same as opening a handle to the print server.
1486 switch (Printer->printer_type )
1489 case SPLHND_PORTMON_TCP:
1490 case SPLHND_PORTMON_LOCAL:
1491 /* Printserver handles use global struct... */
1495 /* Map standard access rights to object specific access rights */
1497 se_map_standard(&r->in.access_mask,
1498 &printserver_std_mapping);
1500 /* Deny any object specific bits that don't apply to print
1501 servers (i.e printer and job specific bits) */
1503 r->in.access_mask &= SEC_MASK_SPECIFIC;
1505 if (r->in.access_mask &
1506 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1507 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1508 close_printer_handle(p, r->out.handle);
1509 ZERO_STRUCTP(r->out.handle);
1510 return WERR_ACCESS_DENIED;
1513 /* Allow admin access */
1515 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1517 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1519 if (!lp_ms_add_printer_wizard()) {
1520 close_printer_handle(p, r->out.handle);
1521 ZERO_STRUCTP(r->out.handle);
1522 return WERR_ACCESS_DENIED;
1525 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1526 and not a printer admin, then fail */
1528 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1529 !user_has_privileges(p->server_info->ptok,
1531 !token_contains_name_in_list(
1532 uidtoname(p->server_info->utok.uid),
1533 p->server_info->info3->base.domain.string,
1535 p->server_info->ptok,
1536 lp_printer_admin(snum))) {
1537 close_printer_handle(p, r->out.handle);
1538 ZERO_STRUCTP(r->out.handle);
1539 return WERR_ACCESS_DENIED;
1542 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1546 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1549 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1550 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1552 /* We fall through to return WERR_OK */
1555 case SPLHND_PRINTER:
1556 /* NT doesn't let us connect to a printer if the connecting user
1557 doesn't have print permission. */
1559 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1560 close_printer_handle(p, r->out.handle);
1561 ZERO_STRUCTP(r->out.handle);
1565 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1566 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1569 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1571 /* map an empty access mask to the minimum access mask */
1572 if (r->in.access_mask == 0x0)
1573 r->in.access_mask = PRINTER_ACCESS_USE;
1576 * If we are not serving the printer driver for this printer,
1577 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1578 * will keep NT clients happy --jerry
1581 if (lp_use_client_driver(snum)
1582 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1584 r->in.access_mask = PRINTER_ACCESS_USE;
1587 /* check smb.conf parameters and the the sec_desc */
1589 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1590 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1591 ZERO_STRUCTP(r->out.handle);
1592 return WERR_ACCESS_DENIED;
1595 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1596 p->server_info->ptok, snum) ||
1597 !print_access_check(p->server_info, snum,
1598 r->in.access_mask)) {
1599 DEBUG(3, ("access DENIED for printer open\n"));
1600 close_printer_handle(p, r->out.handle);
1601 ZERO_STRUCTP(r->out.handle);
1602 return WERR_ACCESS_DENIED;
1605 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1606 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1607 close_printer_handle(p, r->out.handle);
1608 ZERO_STRUCTP(r->out.handle);
1609 return WERR_ACCESS_DENIED;
1612 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1613 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1615 r->in.access_mask = PRINTER_ACCESS_USE;
1617 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1618 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1623 /* sanity check to prevent programmer error */
1624 ZERO_STRUCTP(r->out.handle);
1628 Printer->access_granted = r->in.access_mask;
1631 * If the client sent a devmode in the OpenPrinter() call, then
1632 * save it here in case we get a job submission on this handle
1635 if ((Printer->printer_type != SPLHND_SERVER) &&
1636 r->in.devmode_ctr.devmode) {
1637 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1641 #if 0 /* JERRY -- I'm doubtful this is really effective */
1642 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1643 optimization in Windows 2000 clients --jerry */
1645 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1646 && (RA_WIN2K == get_remote_arch()) )
1648 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1649 sys_usleep( 500000 );
1656 /****************************************************************************
1657 ****************************************************************************/
1659 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1660 NT_PRINTER_INFO_LEVEL_2 *d)
1662 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1668 d->attributes = r->attributes;
1669 d->priority = r->priority;
1670 d->default_priority = r->defaultpriority;
1671 d->starttime = r->starttime;
1672 d->untiltime = r->untiltime;
1673 d->status = r->status;
1674 d->cjobs = r->cjobs;
1676 fstrcpy(d->servername, r->servername);
1677 fstrcpy(d->printername, r->printername);
1678 fstrcpy(d->sharename, r->sharename);
1679 fstrcpy(d->portname, r->portname);
1680 fstrcpy(d->drivername, r->drivername);
1681 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1682 fstrcpy(d->location, r->location);
1683 fstrcpy(d->sepfile, r->sepfile);
1684 fstrcpy(d->printprocessor, r->printprocessor);
1685 fstrcpy(d->datatype, r->datatype);
1686 fstrcpy(d->parameters, r->parameters);
1691 /****************************************************************************
1692 ****************************************************************************/
1694 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1695 NT_PRINTER_INFO_LEVEL *printer)
1699 switch (info_ctr->level) {
1701 /* allocate memory if needed. Messy because
1702 convert_printer_info is used to update an existing
1703 printer or build a new one */
1705 if (!printer->info_2) {
1706 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1707 if (!printer->info_2) {
1708 DEBUG(0,("convert_printer_info: "
1709 "talloc() failed!\n"));
1714 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1716 printer->info_2->setuptime = time(NULL);
1723 /****************************************************************
1724 _spoolss_ClosePrinter
1725 ****************************************************************/
1727 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1728 struct spoolss_ClosePrinter *r)
1730 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1732 if (Printer && Printer->document_started) {
1733 struct spoolss_EndDocPrinter e;
1735 e.in.handle = r->in.handle;
1737 _spoolss_EndDocPrinter(p, &e);
1740 if (!close_printer_handle(p, r->in.handle))
1743 /* clear the returned printer handle. Observed behavior
1744 from Win2k server. Don't think this really matters.
1745 Previous code just copied the value of the closed
1748 ZERO_STRUCTP(r->out.handle);
1753 /****************************************************************
1754 _spoolss_DeletePrinter
1755 ****************************************************************/
1757 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1758 struct spoolss_DeletePrinter *r)
1760 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1763 if (Printer && Printer->document_started) {
1764 struct spoolss_EndDocPrinter e;
1766 e.in.handle = r->in.handle;
1768 _spoolss_EndDocPrinter(p, &e);
1771 result = delete_printer_handle(p, r->in.handle);
1773 update_c_setprinter(false);
1778 /*******************************************************************
1779 * static function to lookup the version id corresponding to an
1780 * long architecture string
1781 ******************************************************************/
1783 static const struct print_architecture_table_node archi_table[]= {
1785 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1786 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1787 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1788 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1789 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1790 {"Windows IA64", SPL_ARCH_IA64, 3 },
1791 {"Windows x64", SPL_ARCH_X64, 3 },
1795 static int get_version_id(const char *arch)
1799 for (i=0; archi_table[i].long_archi != NULL; i++)
1801 if (strcmp(arch, archi_table[i].long_archi) == 0)
1802 return (archi_table[i].version);
1808 /****************************************************************
1809 _spoolss_DeletePrinterDriver
1810 ****************************************************************/
1812 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1813 struct spoolss_DeletePrinterDriver *r)
1816 struct spoolss_DriverInfo8 *info = NULL;
1817 struct spoolss_DriverInfo8 *info_win2k = NULL;
1820 WERROR status_win2k = WERR_ACCESS_DENIED;
1821 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1823 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824 and not a printer admin, then fail */
1826 if ( (p->server_info->utok.uid != sec_initial_uid())
1827 && !user_has_privileges(p->server_info->ptok, &se_printop )
1828 && !token_contains_name_in_list(
1829 uidtoname(p->server_info->utok.uid),
1830 p->server_info->info3->base.domain.string,
1832 p->server_info->ptok,
1833 lp_printer_admin(-1)) )
1835 return WERR_ACCESS_DENIED;
1838 /* check that we have a valid driver name first */
1840 if ((version = get_version_id(r->in.architecture)) == -1)
1841 return WERR_INVALID_ENVIRONMENT;
1843 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1847 /* try for Win2k driver if "Windows NT x86" */
1849 if ( version == 2 ) {
1851 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1856 status = WERR_UNKNOWN_PRINTER_DRIVER;
1860 /* otherwise it was a failure */
1862 status = WERR_UNKNOWN_PRINTER_DRIVER;
1868 if (printer_driver_in_use(info)) {
1869 status = WERR_PRINTER_DRIVER_IN_USE;
1875 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1878 r->in.architecture, 3)))
1880 /* if we get to here, we now have 2 driver info structures to remove */
1881 /* remove the Win2k driver first*/
1883 status_win2k = delete_printer_driver(
1884 p, info_win2k, 3, false);
1885 free_a_printer_driver(info_win2k);
1887 /* this should not have failed---if it did, report to client */
1888 if ( !W_ERROR_IS_OK(status_win2k) )
1890 status = status_win2k;
1896 status = delete_printer_driver(p, info, version, false);
1898 /* if at least one of the deletes succeeded return OK */
1900 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
1904 free_a_printer_driver(info);
1909 /****************************************************************
1910 _spoolss_DeletePrinterDriverEx
1911 ****************************************************************/
1913 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
1914 struct spoolss_DeletePrinterDriverEx *r)
1916 struct spoolss_DriverInfo8 *info = NULL;
1917 struct spoolss_DriverInfo8 *info_win2k = NULL;
1921 WERROR status_win2k = WERR_ACCESS_DENIED;
1922 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1924 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1925 and not a printer admin, then fail */
1927 if ( (p->server_info->utok.uid != sec_initial_uid())
1928 && !user_has_privileges(p->server_info->ptok, &se_printop )
1929 && !token_contains_name_in_list(
1930 uidtoname(p->server_info->utok.uid),
1931 p->server_info->info3->base.domain.string,
1933 p->server_info->ptok, lp_printer_admin(-1)) )
1935 return WERR_ACCESS_DENIED;
1938 /* check that we have a valid driver name first */
1939 if ((version = get_version_id(r->in.architecture)) == -1) {
1940 /* this is what NT returns */
1941 return WERR_INVALID_ENVIRONMENT;
1944 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
1945 version = r->in.version;
1947 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1948 r->in.architecture, version);
1950 if ( !W_ERROR_IS_OK(status) )
1953 * if the client asked for a specific version,
1954 * or this is something other than Windows NT x86,
1958 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
1961 /* try for Win2k driver if "Windows NT x86" */
1964 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1967 status = WERR_UNKNOWN_PRINTER_DRIVER;
1972 if (printer_driver_in_use(info)) {
1973 status = WERR_PRINTER_DRIVER_IN_USE;
1978 * we have a couple of cases to consider.
1979 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1980 * then the delete should fail if **any** files overlap with
1982 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1983 * non-overlapping files
1984 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1985 * is set, the do not delete any files
1986 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1989 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
1991 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1993 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
1994 /* no idea of the correct error here */
1995 status = WERR_ACCESS_DENIED;
2000 /* also check for W32X86/3 if necessary; maybe we already have? */
2002 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2003 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2005 r->in.architecture, 3)))
2008 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2009 /* no idea of the correct error here */
2010 free_a_printer_driver(info_win2k);
2011 status = WERR_ACCESS_DENIED;
2015 /* if we get to here, we now have 2 driver info structures to remove */
2016 /* remove the Win2k driver first*/
2018 status_win2k = delete_printer_driver(
2019 p, info_win2k, 3, delete_files);
2020 free_a_printer_driver(info_win2k);
2022 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k) )
2029 status = delete_printer_driver(p, info, version, delete_files);
2031 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2034 free_a_printer_driver(info);
2040 /****************************************************************************
2041 Internal routine for storing printerdata
2042 ***************************************************************************/
2044 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2045 const char *key, const char *value,
2046 uint32_t type, uint8_t *data, int real_len)
2048 /* the registry objects enforce uniqueness based on value name */
2050 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2053 /********************************************************************
2054 GetPrinterData on a printer server Handle.
2055 ********************************************************************/
2057 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2059 enum winreg_Type *type,
2060 union spoolss_PrinterData *data)
2062 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2064 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2070 if (!StrCaseCmp(value, "BeepEnabled")) {
2076 if (!StrCaseCmp(value, "EventLog")) {
2078 /* formally was 0x1b */
2083 if (!StrCaseCmp(value, "NetPopup")) {
2089 if (!StrCaseCmp(value, "MajorVersion")) {
2092 /* Windows NT 4.0 seems to not allow uploading of drivers
2093 to a server that reports 0x3 as the MajorVersion.
2094 need to investigate more how Win2k gets around this .
2097 if (RA_WINNT == get_remote_arch()) {
2106 if (!StrCaseCmp(value, "MinorVersion")) {
2113 * uint32_t size = 0x114
2114 * uint32_t major = 5
2115 * uint32_t minor = [0|1]
2116 * uint32_t build = [2195|2600]
2117 * extra unicode string = e.g. "Service Pack 3"
2119 if (!StrCaseCmp(value, "OSVersion")) {
2121 enum ndr_err_code ndr_err;
2122 struct spoolss_OSVersion os;
2124 os.major = 5; /* Windows 2000 == 5.0 */
2126 os.build = 2195; /* build */
2127 os.extra_string = ""; /* leave extra string empty */
2129 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2130 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2131 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2132 return WERR_GENERAL_FAILURE;
2136 data->binary = blob;
2142 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2145 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2146 W_ERROR_HAVE_NO_MEMORY(data->string);
2151 if (!StrCaseCmp(value, "Architecture")) {
2153 data->string = talloc_strdup(mem_ctx,
2154 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2155 W_ERROR_HAVE_NO_MEMORY(data->string);
2160 if (!StrCaseCmp(value, "DsPresent")) {
2163 /* only show the publish check box if we are a
2164 member of a AD domain */
2166 if (lp_security() == SEC_ADS) {
2174 if (!StrCaseCmp(value, "DNSMachineName")) {
2175 const char *hostname = get_mydnsfullname();
2178 return WERR_BADFILE;
2182 data->string = talloc_strdup(mem_ctx, hostname);
2183 W_ERROR_HAVE_NO_MEMORY(data->string);
2190 return WERR_INVALID_PARAM;
2193 /****************************************************************
2194 _spoolss_GetPrinterData
2195 ****************************************************************/
2197 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2198 struct spoolss_GetPrinterData *r)
2200 struct spoolss_GetPrinterDataEx r2;
2202 r2.in.handle = r->in.handle;
2203 r2.in.key_name = "PrinterDriverData";
2204 r2.in.value_name = r->in.value_name;
2205 r2.in.offered = r->in.offered;
2206 r2.out.type = r->out.type;
2207 r2.out.data = r->out.data;
2208 r2.out.needed = r->out.needed;
2210 return _spoolss_GetPrinterDataEx(p, &r2);
2213 /*********************************************************
2214 Connect to the client machine.
2215 **********************************************************/
2217 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2218 struct sockaddr_storage *client_ss, const char *remote_machine)
2221 struct cli_state *the_cli;
2222 struct sockaddr_storage rm_addr;
2223 char addr[INET6_ADDRSTRLEN];
2225 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2226 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2228 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2229 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2232 print_sockaddr(addr, sizeof(addr), &rm_addr);
2234 rm_addr = *client_ss;
2235 print_sockaddr(addr, sizeof(addr), &rm_addr);
2236 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2240 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2241 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2246 /* setup the connection */
2247 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2248 &rm_addr, 0, "IPC$", "IPC",
2252 0, lp_client_signing(), NULL );
2254 if ( !NT_STATUS_IS_OK( ret ) ) {
2255 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2260 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2261 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2262 cli_shutdown(the_cli);
2267 * Ok - we have an anonymous connection to the IPC$ share.
2268 * Now start the NT Domain stuff :-).
2271 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2272 if (!NT_STATUS_IS_OK(ret)) {
2273 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2274 remote_machine, nt_errstr(ret)));
2275 cli_shutdown(the_cli);
2282 /***************************************************************************
2283 Connect to the client.
2284 ****************************************************************************/
2286 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2287 uint32_t localprinter, uint32_t type,
2288 struct policy_handle *handle,
2289 struct sockaddr_storage *client_ss)
2295 * If it's the first connection, contact the client
2296 * and connect to the IPC$ share anonymously
2298 if (smb_connections==0) {
2299 fstring unix_printer;
2301 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2303 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2306 messaging_register(smbd_messaging_context(), NULL,
2307 MSG_PRINTER_NOTIFY2,
2308 receive_notify2_message_list);
2309 /* Tell the connections db we're now interested in printer
2310 * notify messages. */
2311 serverid_register_msg_flags(
2312 messaging_server_id(smbd_messaging_context()),
2313 true, FLAG_MSG_PRINT_NOTIFY);
2317 * Tell the specific printing tdb we want messages for this printer
2318 * by registering our PID.
2321 if (!print_notify_register_pid(snum))
2322 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2326 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2334 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2335 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2336 win_errstr(result)));
2338 return (W_ERROR_IS_OK(result));
2341 /****************************************************************
2342 ****************************************************************/
2344 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2345 const struct spoolss_NotifyOption *r)
2347 struct spoolss_NotifyOption *option;
2354 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2361 if (!option->count) {
2365 option->types = talloc_zero_array(option,
2366 struct spoolss_NotifyOptionType, option->count);
2367 if (!option->types) {
2368 talloc_free(option);
2372 for (i=0; i < option->count; i++) {
2373 option->types[i] = r->types[i];
2375 if (option->types[i].count) {
2376 option->types[i].fields = talloc_zero_array(option,
2377 union spoolss_Field, option->types[i].count);
2378 if (!option->types[i].fields) {
2379 talloc_free(option);
2382 for (k=0; k<option->types[i].count; k++) {
2383 option->types[i].fields[k] =
2384 r->types[i].fields[k];
2392 /****************************************************************
2393 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2395 * before replying OK: status=0 a rpc call is made to the workstation
2396 * asking ReplyOpenPrinter
2398 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2399 * called from api_spoolss_rffpcnex
2400 ****************************************************************/
2402 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2403 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2406 struct spoolss_NotifyOption *option = r->in.notify_options;
2407 struct sockaddr_storage client_ss;
2409 /* store the notify value in the printer struct */
2411 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2414 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2415 "Invalid handle (%s:%u:%u).\n",
2416 OUR_HANDLE(r->in.handle)));
2420 Printer->notify.flags = r->in.flags;
2421 Printer->notify.options = r->in.options;
2422 Printer->notify.printerlocal = r->in.printer_local;
2424 TALLOC_FREE(Printer->notify.option);
2425 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2427 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2429 /* Connect to the client machine and send a ReplyOpenPrinter */
2431 if ( Printer->printer_type == SPLHND_SERVER)
2433 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2434 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2437 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2438 "client_address is %s\n", p->client_address));
2440 if (!interpret_string_addr(&client_ss, p->client_address,
2442 return WERR_SERVER_UNAVAILABLE;
2445 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2446 Printer->notify.printerlocal, 1,
2447 &Printer->notify.client_hnd, &client_ss))
2448 return WERR_SERVER_UNAVAILABLE;
2450 Printer->notify.client_connected = true;
2455 /*******************************************************************
2456 * fill a notify_info_data with the servername
2457 ********************************************************************/
2459 static void spoolss_notify_server_name(int snum,
2460 struct spoolss_Notify *data,
2461 print_queue_struct *queue,
2462 NT_PRINTER_INFO_LEVEL *printer,
2463 TALLOC_CTX *mem_ctx)
2465 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2468 /*******************************************************************
2469 * fill a notify_info_data with the printername (not including the servername).
2470 ********************************************************************/
2472 static void spoolss_notify_printer_name(int snum,
2473 struct spoolss_Notify *data,
2474 print_queue_struct *queue,
2475 NT_PRINTER_INFO_LEVEL *printer,
2476 TALLOC_CTX *mem_ctx)
2478 /* the notify name should not contain the \\server\ part */
2479 char *p = strrchr(printer->info_2->printername, '\\');
2482 p = printer->info_2->printername;
2487 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2490 /*******************************************************************
2491 * fill a notify_info_data with the servicename
2492 ********************************************************************/
2494 static void spoolss_notify_share_name(int snum,
2495 struct spoolss_Notify *data,
2496 print_queue_struct *queue,
2497 NT_PRINTER_INFO_LEVEL *printer,
2498 TALLOC_CTX *mem_ctx)
2500 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2503 /*******************************************************************
2504 * fill a notify_info_data with the port name
2505 ********************************************************************/
2507 static void spoolss_notify_port_name(int snum,
2508 struct spoolss_Notify *data,
2509 print_queue_struct *queue,
2510 NT_PRINTER_INFO_LEVEL *printer,
2511 TALLOC_CTX *mem_ctx)
2513 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2516 /*******************************************************************
2517 * fill a notify_info_data with the printername
2518 * but it doesn't exist, have to see what to do
2519 ********************************************************************/
2521 static void spoolss_notify_driver_name(int snum,
2522 struct spoolss_Notify *data,
2523 print_queue_struct *queue,
2524 NT_PRINTER_INFO_LEVEL *printer,
2525 TALLOC_CTX *mem_ctx)
2527 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2530 /*******************************************************************
2531 * fill a notify_info_data with the comment
2532 ********************************************************************/
2534 static void spoolss_notify_comment(int snum,
2535 struct spoolss_Notify *data,
2536 print_queue_struct *queue,
2537 NT_PRINTER_INFO_LEVEL *printer,
2538 TALLOC_CTX *mem_ctx)
2542 if (*printer->info_2->comment == '\0') {
2543 p = lp_comment(snum);
2545 p = printer->info_2->comment;
2548 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2551 /*******************************************************************
2552 * fill a notify_info_data with the comment
2553 * location = "Room 1, floor 2, building 3"
2554 ********************************************************************/
2556 static void spoolss_notify_location(int snum,
2557 struct spoolss_Notify *data,
2558 print_queue_struct *queue,
2559 NT_PRINTER_INFO_LEVEL *printer,
2560 TALLOC_CTX *mem_ctx)
2562 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2565 /*******************************************************************
2566 * fill a notify_info_data with the device mode
2567 * jfm:xxxx don't to it for know but that's a real problem !!!
2568 ********************************************************************/
2570 static void spoolss_notify_devmode(int snum,
2571 struct spoolss_Notify *data,
2572 print_queue_struct *queue,
2573 NT_PRINTER_INFO_LEVEL *printer,
2574 TALLOC_CTX *mem_ctx)
2576 /* for a dummy implementation we have to zero the fields */
2577 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2580 /*******************************************************************
2581 * fill a notify_info_data with the separator file name
2582 ********************************************************************/
2584 static void spoolss_notify_sepfile(int snum,
2585 struct spoolss_Notify *data,
2586 print_queue_struct *queue,
2587 NT_PRINTER_INFO_LEVEL *printer,
2588 TALLOC_CTX *mem_ctx)
2590 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2593 /*******************************************************************
2594 * fill a notify_info_data with the print processor
2595 * jfm:xxxx return always winprint to indicate we don't do anything to it
2596 ********************************************************************/
2598 static void spoolss_notify_print_processor(int snum,
2599 struct spoolss_Notify *data,
2600 print_queue_struct *queue,
2601 NT_PRINTER_INFO_LEVEL *printer,
2602 TALLOC_CTX *mem_ctx)
2604 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2607 /*******************************************************************
2608 * fill a notify_info_data with the print processor options
2609 * jfm:xxxx send an empty string
2610 ********************************************************************/
2612 static void spoolss_notify_parameters(int snum,
2613 struct spoolss_Notify *data,
2614 print_queue_struct *queue,
2615 NT_PRINTER_INFO_LEVEL *printer,
2616 TALLOC_CTX *mem_ctx)
2618 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2621 /*******************************************************************
2622 * fill a notify_info_data with the data type
2623 * jfm:xxxx always send RAW as data type
2624 ********************************************************************/
2626 static void spoolss_notify_datatype(int snum,
2627 struct spoolss_Notify *data,
2628 print_queue_struct *queue,
2629 NT_PRINTER_INFO_LEVEL *printer,
2630 TALLOC_CTX *mem_ctx)
2632 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2635 /*******************************************************************
2636 * fill a notify_info_data with the security descriptor
2637 * jfm:xxxx send an null pointer to say no security desc
2638 * have to implement security before !
2639 ********************************************************************/
2641 static void spoolss_notify_security_desc(int snum,
2642 struct spoolss_Notify *data,
2643 print_queue_struct *queue,
2644 NT_PRINTER_INFO_LEVEL *printer,
2645 TALLOC_CTX *mem_ctx)
2647 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2648 printer->info_2->secdesc_buf->sd_size,
2649 printer->info_2->secdesc_buf->sd);
2652 /*******************************************************************
2653 * fill a notify_info_data with the attributes
2654 * jfm:xxxx a samba printer is always shared
2655 ********************************************************************/
2657 static void spoolss_notify_attributes(int snum,
2658 struct spoolss_Notify *data,
2659 print_queue_struct *queue,
2660 NT_PRINTER_INFO_LEVEL *printer,
2661 TALLOC_CTX *mem_ctx)
2663 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2666 /*******************************************************************
2667 * fill a notify_info_data with the priority
2668 ********************************************************************/
2670 static void spoolss_notify_priority(int snum,
2671 struct spoolss_Notify *data,
2672 print_queue_struct *queue,
2673 NT_PRINTER_INFO_LEVEL *printer,
2674 TALLOC_CTX *mem_ctx)
2676 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2679 /*******************************************************************
2680 * fill a notify_info_data with the default priority
2681 ********************************************************************/
2683 static void spoolss_notify_default_priority(int snum,
2684 struct spoolss_Notify *data,
2685 print_queue_struct *queue,
2686 NT_PRINTER_INFO_LEVEL *printer,
2687 TALLOC_CTX *mem_ctx)
2689 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2692 /*******************************************************************
2693 * fill a notify_info_data with the start time
2694 ********************************************************************/
2696 static void spoolss_notify_start_time(int snum,
2697 struct spoolss_Notify *data,
2698 print_queue_struct *queue,
2699 NT_PRINTER_INFO_LEVEL *printer,
2700 TALLOC_CTX *mem_ctx)
2702 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2705 /*******************************************************************
2706 * fill a notify_info_data with the until time
2707 ********************************************************************/
2709 static void spoolss_notify_until_time(int snum,
2710 struct spoolss_Notify *data,
2711 print_queue_struct *queue,
2712 NT_PRINTER_INFO_LEVEL *printer,
2713 TALLOC_CTX *mem_ctx)
2715 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2718 /*******************************************************************
2719 * fill a notify_info_data with the status
2720 ********************************************************************/
2722 static void spoolss_notify_status(int snum,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 NT_PRINTER_INFO_LEVEL *printer,
2726 TALLOC_CTX *mem_ctx)
2728 print_status_struct status;
2730 print_queue_length(snum, &status);
2731 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2734 /*******************************************************************
2735 * fill a notify_info_data with the number of jobs queued
2736 ********************************************************************/
2738 static void spoolss_notify_cjobs(int snum,
2739 struct spoolss_Notify *data,
2740 print_queue_struct *queue,
2741 NT_PRINTER_INFO_LEVEL *printer,
2742 TALLOC_CTX *mem_ctx)
2744 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2747 /*******************************************************************
2748 * fill a notify_info_data with the average ppm
2749 ********************************************************************/
2751 static void spoolss_notify_average_ppm(int snum,
2752 struct spoolss_Notify *data,
2753 print_queue_struct *queue,
2754 NT_PRINTER_INFO_LEVEL *printer,
2755 TALLOC_CTX *mem_ctx)
2757 /* always respond 8 pages per minutes */
2758 /* a little hard ! */
2759 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2762 /*******************************************************************
2763 * fill a notify_info_data with username
2764 ********************************************************************/
2766 static void spoolss_notify_username(int snum,
2767 struct spoolss_Notify *data,
2768 print_queue_struct *queue,
2769 NT_PRINTER_INFO_LEVEL *printer,
2770 TALLOC_CTX *mem_ctx)
2772 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2775 /*******************************************************************
2776 * fill a notify_info_data with job status
2777 ********************************************************************/
2779 static void spoolss_notify_job_status(int snum,
2780 struct spoolss_Notify *data,
2781 print_queue_struct *queue,
2782 NT_PRINTER_INFO_LEVEL *printer,
2783 TALLOC_CTX *mem_ctx)
2785 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2788 /*******************************************************************
2789 * fill a notify_info_data with job name
2790 ********************************************************************/
2792 static void spoolss_notify_job_name(int snum,
2793 struct spoolss_Notify *data,
2794 print_queue_struct *queue,
2795 NT_PRINTER_INFO_LEVEL *printer,
2796 TALLOC_CTX *mem_ctx)
2798 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2801 /*******************************************************************
2802 * fill a notify_info_data with job status
2803 ********************************************************************/
2805 static void spoolss_notify_job_status_string(int snum,
2806 struct spoolss_Notify *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2812 * Now we're returning job status codes we just return a "" here. JRA.
2817 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2820 switch (queue->status) {
2825 p = ""; /* NT provides the paused string */
2834 #endif /* NO LONGER NEEDED. */
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2839 /*******************************************************************
2840 * fill a notify_info_data with job time
2841 ********************************************************************/
2843 static void spoolss_notify_job_time(int snum,
2844 struct spoolss_Notify *data,
2845 print_queue_struct *queue,
2846 NT_PRINTER_INFO_LEVEL *printer,
2847 TALLOC_CTX *mem_ctx)
2849 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2852 /*******************************************************************
2853 * fill a notify_info_data with job size
2854 ********************************************************************/
2856 static void spoolss_notify_job_size(int snum,
2857 struct spoolss_Notify *data,
2858 print_queue_struct *queue,
2859 NT_PRINTER_INFO_LEVEL *printer,
2860 TALLOC_CTX *mem_ctx)
2862 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2865 /*******************************************************************
2866 * fill a notify_info_data with page info
2867 ********************************************************************/
2868 static void spoolss_notify_total_pages(int snum,
2869 struct spoolss_Notify *data,
2870 print_queue_struct *queue,
2871 NT_PRINTER_INFO_LEVEL *printer,
2872 TALLOC_CTX *mem_ctx)
2874 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2877 /*******************************************************************
2878 * fill a notify_info_data with pages printed info.
2879 ********************************************************************/
2880 static void spoolss_notify_pages_printed(int snum,
2881 struct spoolss_Notify *data,
2882 print_queue_struct *queue,
2883 NT_PRINTER_INFO_LEVEL *printer,
2884 TALLOC_CTX *mem_ctx)
2886 /* Add code when back-end tracks this */
2887 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2890 /*******************************************************************
2891 Fill a notify_info_data with job position.
2892 ********************************************************************/
2894 static void spoolss_notify_job_position(int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 NT_PRINTER_INFO_LEVEL *printer,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
2903 /*******************************************************************
2904 Fill a notify_info_data with submitted time.
2905 ********************************************************************/
2907 static void spoolss_notify_submitted_time(int snum,
2908 struct spoolss_Notify *data,
2909 print_queue_struct *queue,
2910 NT_PRINTER_INFO_LEVEL *printer,
2911 TALLOC_CTX *mem_ctx)
2913 data->data.string.string = NULL;
2914 data->data.string.size = 0;
2916 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
2917 &data->data.string.string,
2918 &data->data.string.size);
2922 struct s_notify_info_data_table
2924 enum spoolss_NotifyType type;
2927 enum spoolss_NotifyTable variable_type;
2928 void (*fn) (int snum, struct spoolss_Notify *data,
2929 print_queue_struct *queue,
2930 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
2933 /* A table describing the various print notification constants and
2934 whether the notification data is a pointer to a variable sized
2935 buffer, a one value uint32_t or a two value uint32_t. */
2937 static const struct s_notify_info_data_table notify_info_data_table[] =
2939 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2940 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2941 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
2942 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2943 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2944 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
2945 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
2946 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2947 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
2948 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2949 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2950 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2951 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
2952 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
2953 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2954 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
2955 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2956 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2957 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
2958 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
2959 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
2960 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
2961 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
2962 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2963 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
2964 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
2965 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
2966 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
2967 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
2968 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2969 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
2970 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
2971 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
2972 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
2973 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
2974 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
2975 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
2976 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
2977 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
2978 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
2979 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
2980 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
2981 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
2982 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
2983 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
2984 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
2985 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
2986 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
2987 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
2990 /*******************************************************************
2991 Return the variable_type of info_data structure.
2992 ********************************************************************/
2994 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
2999 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3000 if ( (notify_info_data_table[i].type == type) &&
3001 (notify_info_data_table[i].field == field) ) {
3002 return notify_info_data_table[i].variable_type;
3006 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3011 /****************************************************************************
3012 ****************************************************************************/
3014 static bool search_notify(enum spoolss_NotifyType type,
3020 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3021 if (notify_info_data_table[i].type == type &&
3022 notify_info_data_table[i].field == field &&
3023 notify_info_data_table[i].fn != NULL) {
3032 /****************************************************************************
3033 ****************************************************************************/
3035 void construct_info_data(struct spoolss_Notify *info_data,
3036 enum spoolss_NotifyType type,
3040 info_data->type = type;
3041 info_data->field.field = field;
3042 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3043 info_data->job_id = id;
3046 /*******************************************************************
3048 * fill a notify_info struct with info asked
3050 ********************************************************************/
3052 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3053 struct spoolss_NotifyInfo *info,
3055 const struct spoolss_NotifyOptionType *option_type,
3057 TALLOC_CTX *mem_ctx)
3060 enum spoolss_NotifyType type;
3063 struct spoolss_Notify *current_data;
3064 NT_PRINTER_INFO_LEVEL *printer = NULL;
3065 print_queue_struct *queue=NULL;
3067 type = option_type->type;
3069 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3070 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3071 option_type->count, lp_servicename(snum)));
3073 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3076 for(field_num=0; field_num < option_type->count; field_num++) {
3077 field = option_type->fields[field_num].field;
3079 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3081 if (!search_notify(type, field, &j) )
3084 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3085 struct spoolss_Notify,
3087 if (info->notifies == NULL) {
3088 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3089 free_a_printer(&printer, 2);
3093 current_data = &info->notifies[info->count];
3095 construct_info_data(current_data, type, field, id);
3097 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3098 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3100 notify_info_data_table[j].fn(snum, current_data, queue,
3106 free_a_printer(&printer, 2);
3110 /*******************************************************************
3112 * fill a notify_info struct with info asked
3114 ********************************************************************/
3116 static bool construct_notify_jobs_info(print_queue_struct *queue,
3117 struct spoolss_NotifyInfo *info,
3118 NT_PRINTER_INFO_LEVEL *printer,
3120 const struct spoolss_NotifyOptionType *option_type,
3122 TALLOC_CTX *mem_ctx)
3125 enum spoolss_NotifyType type;
3127 struct spoolss_Notify *current_data;
3129 DEBUG(4,("construct_notify_jobs_info\n"));
3131 type = option_type->type;
3133 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3134 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3135 option_type->count));
3137 for(field_num=0; field_num<option_type->count; field_num++) {
3138 field = option_type->fields[field_num].field;
3140 if (!search_notify(type, field, &j) )
3143 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3144 struct spoolss_Notify,
3146 if (info->notifies == NULL) {
3147 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3151 current_data=&(info->notifies[info->count]);
3153 construct_info_data(current_data, type, field, id);
3154 notify_info_data_table[j].fn(snum, current_data, queue,
3163 * JFM: The enumeration is not that simple, it's even non obvious.
3165 * let's take an example: I want to monitor the PRINTER SERVER for
3166 * the printer's name and the number of jobs currently queued.
3167 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3168 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3170 * I have 3 printers on the back of my server.
3172 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3175 * 1 printer 1 name 1
3176 * 2 printer 1 cjob 1
3177 * 3 printer 2 name 2
3178 * 4 printer 2 cjob 2
3179 * 5 printer 3 name 3
3180 * 6 printer 3 name 3
3182 * that's the print server case, the printer case is even worse.
3185 /*******************************************************************
3187 * enumerate all printers on the printserver
3188 * fill a notify_info struct with info asked
3190 ********************************************************************/
3192 static WERROR printserver_notify_info(pipes_struct *p,
3193 struct policy_handle *hnd,
3194 struct spoolss_NotifyInfo *info,
3195 TALLOC_CTX *mem_ctx)
3198 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3199 int n_services=lp_numservices();
3201 struct spoolss_NotifyOption *option;
3202 struct spoolss_NotifyOptionType option_type;
3204 DEBUG(4,("printserver_notify_info\n"));
3209 option = Printer->notify.option;
3212 info->notifies = NULL;
3215 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3216 sending a ffpcn() request first */
3221 for (i=0; i<option->count; i++) {
3222 option_type = option->types[i];
3224 if (option_type.type != PRINTER_NOTIFY_TYPE)
3227 for (snum=0; snum<n_services; snum++)
3229 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3230 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3236 * Debugging information, don't delete.
3239 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3240 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3241 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3243 for (i=0; i<info->count; i++) {
3244 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3245 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3246 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3253 /*******************************************************************
3255 * fill a notify_info struct with info asked
3257 ********************************************************************/
3259 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3260 struct spoolss_NotifyInfo *info,
3261 TALLOC_CTX *mem_ctx)
3264 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3267 struct spoolss_NotifyOption *option;
3268 struct spoolss_NotifyOptionType option_type;
3270 print_queue_struct *queue=NULL;
3271 print_status_struct status;
3273 DEBUG(4,("printer_notify_info\n"));
3278 option = Printer->notify.option;
3282 info->notifies = NULL;
3285 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3286 sending a ffpcn() request first */
3291 get_printer_snum(p, hnd, &snum, NULL);
3293 for (i=0; i<option->count; i++) {
3294 option_type = option->types[i];
3296 switch (option_type.type) {
3297 case PRINTER_NOTIFY_TYPE:
3298 if(construct_notify_printer_info(Printer, info, snum,
3304 case JOB_NOTIFY_TYPE: {
3305 NT_PRINTER_INFO_LEVEL *printer = NULL;
3307 count = print_queue_status(snum, &queue, &status);
3309 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3312 for (j=0; j<count; j++) {
3313 construct_notify_jobs_info(&queue[j], info,
3320 free_a_printer(&printer, 2);
3330 * Debugging information, don't delete.
3333 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3334 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3335 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3337 for (i=0; i<info->count; i++) {
3338 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3339 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3340 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3346 /****************************************************************
3347 _spoolss_RouterRefreshPrinterChangeNotify
3348 ****************************************************************/
3350 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3351 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3353 struct spoolss_NotifyInfo *info;
3355 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3356 WERROR result = WERR_BADFID;
3358 /* we always have a spoolss_NotifyInfo struct */
3359 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3361 result = WERR_NOMEM;
3365 *r->out.info = info;
3368 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3369 "Invalid handle (%s:%u:%u).\n",
3370 OUR_HANDLE(r->in.handle)));
3374 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3377 * We are now using the change value, and
3378 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3379 * I don't have a global notification system, I'm sending back all the
3380 * informations even when _NOTHING_ has changed.
3383 /* We need to keep track of the change value to send back in
3384 RRPCN replies otherwise our updates are ignored. */
3386 Printer->notify.fnpcn = true;
3388 if (Printer->notify.client_connected) {
3389 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3390 "Saving change value in request [%x]\n",
3392 Printer->notify.change = r->in.change_low;
3395 /* just ignore the spoolss_NotifyOption */
3397 switch (Printer->printer_type) {
3399 result = printserver_notify_info(p, r->in.handle,
3403 case SPLHND_PRINTER:
3404 result = printer_notify_info(p, r->in.handle,
3409 Printer->notify.fnpcn = false;
3415 /********************************************************************
3416 * construct_printer_info_0
3417 * fill a printer_info_0 struct
3418 ********************************************************************/
3420 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3421 const NT_PRINTER_INFO_LEVEL *ntprinter,
3422 struct spoolss_PrinterInfo0 *r,
3426 counter_printer_0 *session_counter;
3428 print_status_struct status;
3430 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3431 W_ERROR_HAVE_NO_MEMORY(r->printername);
3433 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3434 W_ERROR_HAVE_NO_MEMORY(r->servername);
3436 count = print_queue_length(snum, &status);
3438 /* check if we already have a counter for this printer */
3439 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3440 if (session_counter->snum == snum)
3444 /* it's the first time, add it to the list */
3445 if (session_counter == NULL) {
3446 session_counter = SMB_MALLOC_P(counter_printer_0);
3447 W_ERROR_HAVE_NO_MEMORY(session_counter);
3448 ZERO_STRUCTP(session_counter);
3449 session_counter->snum = snum;
3450 session_counter->counter = 0;
3451 DLIST_ADD(counter_list, session_counter);
3455 session_counter->counter++;
3461 setuptime = (time_t)ntprinter->info_2->setuptime;
3463 init_systemtime(&r->time, gmtime(&setuptime));
3466 * the global_counter should be stored in a TDB as it's common to all the clients
3467 * and should be zeroed on samba startup
3469 r->global_counter = session_counter->counter;
3471 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3472 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3473 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3474 r->free_build = SPOOLSS_RELEASE_BUILD;
3476 r->max_spooling = 0;
3477 r->session_counter = session_counter->counter;
3478 r->num_error_out_of_paper = 0x0;
3479 r->num_error_not_ready = 0x0; /* number of print failure */
3481 r->number_of_processors = 0x1;
3482 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3483 r->high_part_total_bytes = 0x0;
3484 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3485 r->last_error = WERR_OK;
3486 r->status = nt_printq_status(status.status);
3487 r->enumerate_network_printers = 0x0;
3488 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3489 r->processor_architecture = 0x0;
3490 r->processor_level = 0x6; /* 6 ???*/
3499 /****************************************************************************
3500 Create a spoolss_DeviceMode struct. Returns talloced memory.
3501 ****************************************************************************/
3503 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3504 const char *servicename)
3506 NT_PRINTER_INFO_LEVEL *printer = NULL;
3507 struct spoolss_DeviceMode *devmode = NULL;
3509 DEBUG(7,("construct_dev_mode\n"));
3511 DEBUGADD(8,("getting printer characteristics\n"));
3513 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3516 if (!printer->info_2->devmode) {
3517 DEBUG(5, ("BONG! There was no device mode!\n"));
3521 devmode = talloc_steal(mem_ctx, printer->info_2->devmode);
3524 free_a_printer(&printer,2);
3529 /********************************************************************
3530 * construct_printer_info1
3531 * fill a spoolss_PrinterInfo1 struct
3532 ********************************************************************/
3534 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3535 const NT_PRINTER_INFO_LEVEL *ntprinter,
3537 struct spoolss_PrinterInfo1 *r,
3542 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3543 ntprinter->info_2->printername,
3544 ntprinter->info_2->drivername,
3545 ntprinter->info_2->location);
3546 W_ERROR_HAVE_NO_MEMORY(r->description);
3548 if (*ntprinter->info_2->comment == '\0') {
3549 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3551 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
3553 W_ERROR_HAVE_NO_MEMORY(r->comment);
3555 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3556 W_ERROR_HAVE_NO_MEMORY(r->name);
3561 /********************************************************************
3562 * construct_printer_info2
3563 * fill a spoolss_PrinterInfo2 struct
3564 ********************************************************************/
3566 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3567 const NT_PRINTER_INFO_LEVEL *ntprinter,
3568 struct spoolss_PrinterInfo2 *r,
3573 print_status_struct status;
3575 count = print_queue_length(snum, &status);
3577 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3578 W_ERROR_HAVE_NO_MEMORY(r->servername);
3579 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3580 W_ERROR_HAVE_NO_MEMORY(r->printername);
3581 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3582 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3583 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3584 W_ERROR_HAVE_NO_MEMORY(r->portname);
3585 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
3586 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3588 if (*ntprinter->info_2->comment == '\0') {
3589 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3591 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
3593 W_ERROR_HAVE_NO_MEMORY(r->comment);
3595 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
3596 W_ERROR_HAVE_NO_MEMORY(r->location);
3597 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
3598 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3599 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
3600 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3601 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
3602 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3603 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
3604 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3606 r->attributes = ntprinter->info_2->attributes;
3608 r->priority = ntprinter->info_2->priority;
3609 r->defaultpriority = ntprinter->info_2->default_priority;
3610 r->starttime = ntprinter->info_2->starttime;
3611 r->untiltime = ntprinter->info_2->untiltime;
3612 r->status = nt_printq_status(status.status);
3614 r->averageppm = ntprinter->info_2->averageppm;
3616 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3618 DEBUG(8,("Returning NULL Devicemode!\n"));
3623 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3624 /* don't use talloc_steal() here unless you do a deep steal of all
3625 the SEC_DESC members */
3627 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
3633 /********************************************************************
3634 * construct_printer_info3
3635 * fill a spoolss_PrinterInfo3 struct
3636 ********************************************************************/
3638 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3639 const NT_PRINTER_INFO_LEVEL *ntprinter,
3640 struct spoolss_PrinterInfo3 *r,
3643 /* These are the components of the SD we are returning. */
3645 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3646 /* don't use talloc_steal() here unless you do a deep steal of all
3647 the SEC_DESC members */
3649 r->secdesc = dup_sec_desc(mem_ctx,
3650 ntprinter->info_2->secdesc_buf->sd);
3651 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3657 /********************************************************************
3658 * construct_printer_info4
3659 * fill a spoolss_PrinterInfo4 struct
3660 ********************************************************************/
3662 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3663 const NT_PRINTER_INFO_LEVEL *ntprinter,
3664 struct spoolss_PrinterInfo4 *r,
3667 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3668 W_ERROR_HAVE_NO_MEMORY(r->printername);
3669 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3670 W_ERROR_HAVE_NO_MEMORY(r->servername);
3672 r->attributes = ntprinter->info_2->attributes;
3677 /********************************************************************
3678 * construct_printer_info5
3679 * fill a spoolss_PrinterInfo5 struct
3680 ********************************************************************/
3682 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3683 const NT_PRINTER_INFO_LEVEL *ntprinter,
3684 struct spoolss_PrinterInfo5 *r,
3687 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3688 W_ERROR_HAVE_NO_MEMORY(r->printername);
3689 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
3690 W_ERROR_HAVE_NO_MEMORY(r->portname);
3692 r->attributes = ntprinter->info_2->attributes;
3694 /* these two are not used by NT+ according to MSDN */
3696 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3697 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3702 /********************************************************************
3703 * construct_printer_info_6
3704 * fill a spoolss_PrinterInfo6 struct
3705 ********************************************************************/
3707 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3708 const NT_PRINTER_INFO_LEVEL *ntprinter,
3709 struct spoolss_PrinterInfo6 *r,
3713 print_status_struct status;
3715 count = print_queue_length(snum, &status);
3717 r->status = nt_printq_status(status.status);
3722 /********************************************************************
3723 * construct_printer_info7
3724 * fill a spoolss_PrinterInfo7 struct
3725 ********************************************************************/
3727 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3728 Printer_entry *print_hnd,
3729 struct spoolss_PrinterInfo7 *r,
3734 if (is_printer_published(print_hnd, snum, &guid)) {
3735 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3736 r->action = DSPRINT_PUBLISH;
3738 r->guid = talloc_strdup(mem_ctx, "");
3739 r->action = DSPRINT_UNPUBLISH;
3741 W_ERROR_HAVE_NO_MEMORY(r->guid);
3746 /********************************************************************
3747 * construct_printer_info8
3748 * fill a spoolss_PrinterInfo8 struct
3749 ********************************************************************/
3751 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3752 const NT_PRINTER_INFO_LEVEL *ntprinter,
3753 struct spoolss_DeviceModeInfo *r,
3756 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
3758 DEBUG(8,("Returning NULL Devicemode!\n"));
3765 /********************************************************************
3766 ********************************************************************/
3768 static bool snum_is_shared_printer(int snum)
3770 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3773 /********************************************************************
3774 Spoolss_enumprinters.
3775 ********************************************************************/
3777 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3780 union spoolss_PrinterInfo **info_p,
3784 int n_services = lp_numservices();
3785 union spoolss_PrinterInfo *info = NULL;
3787 WERROR result = WERR_OK;
3792 for (snum = 0; snum < n_services; snum++) {
3794 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3796 if (!snum_is_shared_printer(snum)) {
3800 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3801 lp_servicename(snum), snum));
3803 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3804 union spoolss_PrinterInfo,
3807 result = WERR_NOMEM;
3811 result = get_a_printer(NULL, &ntprinter, 2,
3812 lp_const_servicename(snum));
3813 if (!W_ERROR_IS_OK(result)) {
3819 result = construct_printer_info0(info, ntprinter,
3820 &info[count].info0, snum);
3823 result = construct_printer_info1(info, ntprinter, flags,
3824 &info[count].info1, snum);
3827 result = construct_printer_info2(info, ntprinter,
3828 &info[count].info2, snum);
3831 result = construct_printer_info4(info, ntprinter,
3832 &info[count].info4, snum);
3835 result = construct_printer_info5(info, ntprinter,
3836 &info[count].info5, snum);
3840 result = WERR_UNKNOWN_LEVEL;
3841 free_a_printer(&ntprinter, 2);
3845 free_a_printer(&ntprinter, 2);
3846 if (!W_ERROR_IS_OK(result)) {
3857 if (!W_ERROR_IS_OK(result)) {
3867 /********************************************************************
3868 * handle enumeration of printers at level 0
3869 ********************************************************************/
3871 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
3873 const char *servername,
3874 union spoolss_PrinterInfo **info,
3877 DEBUG(4,("enum_all_printers_info_0\n"));
3879 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
3883 /********************************************************************
3884 ********************************************************************/
3886 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
3888 union spoolss_PrinterInfo **info,
3891 DEBUG(4,("enum_all_printers_info_1\n"));
3893 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
3896 /********************************************************************
3897 enum_all_printers_info_1_local.
3898 *********************************************************************/
3900 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
3901 union spoolss_PrinterInfo **info,
3904 DEBUG(4,("enum_all_printers_info_1_local\n"));
3906 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3909 /********************************************************************
3910 enum_all_printers_info_1_name.
3911 *********************************************************************/
3913 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
3915 union spoolss_PrinterInfo **info,
3918 const char *s = name;
3920 DEBUG(4,("enum_all_printers_info_1_name\n"));
3922 if ((name[0] == '\\') && (name[1] == '\\')) {
3926 if (!is_myname_or_ipaddr(s)) {
3927 return WERR_INVALID_NAME;
3930 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
3933 /********************************************************************
3934 enum_all_printers_info_1_network.
3935 *********************************************************************/
3937 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
3939 union spoolss_PrinterInfo **info,
3942 const char *s = name;
3944 DEBUG(4,("enum_all_printers_info_1_network\n"));
3946 /* If we respond to a enum_printers level 1 on our name with flags
3947 set to PRINTER_ENUM_REMOTE with a list of printers then these
3948 printers incorrectly appear in the APW browse list.
3949 Specifically the printers for the server appear at the workgroup
3950 level where all the other servers in the domain are
3951 listed. Windows responds to this call with a
3952 WERR_CAN_NOT_COMPLETE so we should do the same. */
3954 if (name[0] == '\\' && name[1] == '\\') {
3958 if (is_myname_or_ipaddr(s)) {
3959 return WERR_CAN_NOT_COMPLETE;
3962 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
3965 /********************************************************************
3966 * api_spoolss_enumprinters
3968 * called from api_spoolss_enumprinters (see this to understand)
3969 ********************************************************************/
3971 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
3972 union spoolss_PrinterInfo **info,
3975 DEBUG(4,("enum_all_printers_info_2\n"));
3977 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
3980 /********************************************************************
3981 * handle enumeration of printers at level 1
3982 ********************************************************************/
3984 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
3987 union spoolss_PrinterInfo **info,
3990 /* Not all the flags are equals */
3992 if (flags & PRINTER_ENUM_LOCAL) {
3993 return enum_all_printers_info_1_local(mem_ctx, info, count);
3996 if (flags & PRINTER_ENUM_NAME) {
3997 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4000 if (flags & PRINTER_ENUM_NETWORK) {
4001 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4004 return WERR_OK; /* NT4sp5 does that */
4007 /********************************************************************
4008 * handle enumeration of printers at level 2
4009 ********************************************************************/
4011 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4013 const char *servername,
4014 union spoolss_PrinterInfo **info,
4017 if (flags & PRINTER_ENUM_LOCAL) {
4018 return enum_all_printers_info_2(mem_ctx, info, count);
4021 if (flags & PRINTER_ENUM_NAME) {
4022 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4023 return WERR_INVALID_NAME;
4026 return enum_all_printers_info_2(mem_ctx, info, count);
4029 if (flags & PRINTER_ENUM_REMOTE) {
4030 return WERR_UNKNOWN_LEVEL;
4036 /********************************************************************
4037 * handle enumeration of printers at level 4
4038 ********************************************************************/
4040 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4042 const char *servername,
4043 union spoolss_PrinterInfo **info,
4046 DEBUG(4,("enum_all_printers_info_4\n"));
4048 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4052 /********************************************************************
4053 * handle enumeration of printers at level 5
4054 ********************************************************************/
4056 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4058 const char *servername,
4059 union spoolss_PrinterInfo **info,
4062 DEBUG(4,("enum_all_printers_info_5\n"));
4064 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4067 /****************************************************************
4068 _spoolss_EnumPrinters
4069 ****************************************************************/
4071 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4072 struct spoolss_EnumPrinters *r)
4074 const char *name = NULL;
4077 /* that's an [in out] buffer */
4079 if (!r->in.buffer && (r->in.offered != 0)) {
4080 return WERR_INVALID_PARAM;
4083 DEBUG(4,("_spoolss_EnumPrinters\n"));
4087 *r->out.info = NULL;
4091 * flags==PRINTER_ENUM_NAME
4092 * if name=="" then enumerates all printers
4093 * if name!="" then enumerate the printer
4094 * flags==PRINTER_ENUM_REMOTE
4095 * name is NULL, enumerate printers
4096 * Level 2: name!="" enumerates printers, name can't be NULL
4097 * Level 3: doesn't exist
4098 * Level 4: does a local registry lookup
4099 * Level 5: same as Level 2
4103 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4104 W_ERROR_HAVE_NO_MEMORY(name);
4107 switch (r->in.level) {
4109 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4110 r->out.info, r->out.count);
4113 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4114 r->out.info, r->out.count);
4117 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4118 r->out.info, r->out.count);
4121 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4122 r->out.info, r->out.count);
4125 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4126 r->out.info, r->out.count);
4129 return WERR_UNKNOWN_LEVEL;
4132 if (!W_ERROR_IS_OK(result)) {
4136 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4137 spoolss_EnumPrinters,
4138 *r->out.info, r->in.level,
4140 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4141 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4143 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4146 /****************************************************************
4148 ****************************************************************/
4150 WERROR _spoolss_GetPrinter(pipes_struct *p,
4151 struct spoolss_GetPrinter *r)
4153 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4154 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4155 WERROR result = WERR_OK;
4159 /* that's an [in out] buffer */
4161 if (!r->in.buffer && (r->in.offered != 0)) {
4162 return WERR_INVALID_PARAM;
4167 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4171 result = get_a_printer(Printer, &ntprinter, 2,
4172 lp_const_servicename(snum));
4173 if (!W_ERROR_IS_OK(result)) {
4177 switch (r->in.level) {
4179 result = construct_printer_info0(p->mem_ctx, ntprinter,
4180 &r->out.info->info0, snum);
4183 result = construct_printer_info1(p->mem_ctx, ntprinter,
4185 &r->out.info->info1, snum);
4188 result = construct_printer_info2(p->mem_ctx, ntprinter,
4189 &r->out.info->info2, snum);
4192 result = construct_printer_info3(p->mem_ctx, ntprinter,
4193 &r->out.info->info3, snum);
4196 result = construct_printer_info4(p->mem_ctx, ntprinter,
4197 &r->out.info->info4, snum);
4200 result = construct_printer_info5(p->mem_ctx, ntprinter,
4201 &r->out.info->info5, snum);
4204 result = construct_printer_info6(p->mem_ctx, ntprinter,
4205 &r->out.info->info6, snum);
4208 result = construct_printer_info7(p->mem_ctx, Printer,
4209 &r->out.info->info7, snum);
4212 result = construct_printer_info8(p->mem_ctx, ntprinter,
4213 &r->out.info->info8, snum);
4216 result = WERR_UNKNOWN_LEVEL;
4220 free_a_printer(&ntprinter, 2);
4222 if (!W_ERROR_IS_OK(result)) {
4223 TALLOC_FREE(r->out.info);
4227 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4228 r->out.info, r->in.level);
4229 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4231 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4234 /********************************************************************
4235 ********************************************************************/
4237 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4238 const char **string_array,
4239 const char *cservername)
4241 int i, num_strings = 0;
4242 const char **array = NULL;
4244 if (!string_array) {
4248 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4250 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4251 cservername, string_array[i]);
4258 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4265 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4266 &array, &num_strings);
4272 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4274 if (in && strlen(in)) { \
4275 out = talloc_strdup(mem_ctx, in); \
4276 W_ERROR_HAVE_NO_MEMORY(out); \
4282 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4284 if (in && strlen(in)) { \
4285 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4287 out = talloc_strdup(mem_ctx, ""); \
4289 W_ERROR_HAVE_NO_MEMORY(out); \
4292 /********************************************************************
4293 * fill a spoolss_DriverInfo1 struct
4294 ********************************************************************/
4296 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4297 struct spoolss_DriverInfo1 *r,
4298 const struct spoolss_DriverInfo8 *driver,
4299 const char *servername)
4301 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4302 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4307 /********************************************************************
4308 * fill a spoolss_DriverInfo2 struct
4309 ********************************************************************/
4311 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4312 struct spoolss_DriverInfo2 *r,
4313 const struct spoolss_DriverInfo8 *driver,
4314 const char *servername)
4317 const char *cservername = canon_servername(servername);
4319 r->version = driver->version;
4321 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4322 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4323 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4324 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4326 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4327 driver->driver_path,
4330 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4334 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4335 driver->config_file,
4341 /********************************************************************
4342 * fill a spoolss_DriverInfo3 struct
4343 ********************************************************************/
4345 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4346 struct spoolss_DriverInfo3 *r,
4347 const struct spoolss_DriverInfo8 *driver,
4348 const char *servername)
4350 const char *cservername = canon_servername(servername);
4352 r->version = driver->version;
4354 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4355 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4356 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4357 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4359 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4360 driver->driver_path,
4363 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4367 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4368 driver->config_file,
4371 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4375 FILL_DRIVER_STRING(mem_ctx,
4376 driver->monitor_name,
4379 FILL_DRIVER_STRING(mem_ctx,
4380 driver->default_datatype,
4381 r->default_datatype);
4383 r->dependent_files = string_array_from_driver_info(mem_ctx,
4384 driver->dependent_files,
4389 /********************************************************************
4390 * fill a spoolss_DriverInfo4 struct
4391 ********************************************************************/
4393 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4394 struct spoolss_DriverInfo4 *r,
4395 const struct spoolss_DriverInfo8 *driver,
4396 const char *servername)
4398 const char *cservername = canon_servername(servername);
4400 r->version = driver->version;
4402 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4403 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4404 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4405 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4407 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4408 driver->driver_path,
4411 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4415 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4416 driver->config_file,
4419 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4423 r->dependent_files = string_array_from_driver_info(mem_ctx,
4424 driver->dependent_files,
4427 FILL_DRIVER_STRING(mem_ctx,
4428 driver->monitor_name,
4431 FILL_DRIVER_STRING(mem_ctx,
4432 driver->default_datatype,
4433 r->default_datatype);
4435 r->previous_names = string_array_from_driver_info(mem_ctx,
4436 driver->previous_names,
4442 /********************************************************************
4443 * fill a spoolss_DriverInfo5 struct
4444 ********************************************************************/
4446 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4447 struct spoolss_DriverInfo5 *r,
4448 const struct spoolss_DriverInfo8 *driver,
4449 const char *servername)
4451 const char *cservername = canon_servername(servername);
4453 r->version = driver->version;
4455 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4456 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4457 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4458 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4460 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4461 driver->driver_path,
4464 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4468 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4469 driver->config_file,
4472 r->driver_attributes = 0;
4473 r->config_version = 0;
4474 r->driver_version = 0;
4478 /********************************************************************
4479 * fill a spoolss_DriverInfo6 struct
4480 ********************************************************************/
4482 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4483 struct spoolss_DriverInfo6 *r,
4484 const struct spoolss_DriverInfo8 *driver,
4485 const char *servername)
4487 const char *cservername = canon_servername(servername);
4489 r->version = driver->version;
4491 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4492 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4493 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4494 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4496 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4497 driver->driver_path,
4500 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4504 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4505 driver->config_file,
4508 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4512 FILL_DRIVER_STRING(mem_ctx,
4513 driver->monitor_name,
4516 FILL_DRIVER_STRING(mem_ctx,
4517 driver->default_datatype,
4518 r->default_datatype);
4520 r->dependent_files = string_array_from_driver_info(mem_ctx,
4521 driver->dependent_files,
4523 r->previous_names = string_array_from_driver_info(mem_ctx,
4524 driver->previous_names,
4527 r->driver_date = driver->driver_date;
4528 r->driver_version = driver->driver_version;
4530 FILL_DRIVER_STRING(mem_ctx,
4531 driver->manufacturer_name,
4532 r->manufacturer_name);
4533 FILL_DRIVER_STRING(mem_ctx,
4534 driver->manufacturer_url,
4535 r->manufacturer_url);
4536 FILL_DRIVER_STRING(mem_ctx,
4537 driver->hardware_id,
4539 FILL_DRIVER_STRING(mem_ctx,
4546 /********************************************************************
4547 * fill a spoolss_DriverInfo8 struct
4548 ********************************************************************/
4550 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4551 struct spoolss_DriverInfo8 *r,
4552 const struct spoolss_DriverInfo8 *driver,
4553 const char *servername)
4555 const char *cservername = canon_servername(servername);
4557 r->version = driver->version;
4559 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4560 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4561 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4562 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4564 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4565 driver->driver_path,
4568 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4572 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573 driver->config_file,
4576 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4580 FILL_DRIVER_STRING(mem_ctx,
4581 driver->monitor_name,
4584 FILL_DRIVER_STRING(mem_ctx,
4585 driver->default_datatype,
4586 r->default_datatype);
4588 r->dependent_files = string_array_from_driver_info(mem_ctx,
4589 driver->dependent_files,
4591 r->previous_names = string_array_from_driver_info(mem_ctx,
4592 driver->previous_names,
4595 r->driver_date = driver->driver_date;
4596 r->driver_version = driver->driver_version;
4598 FILL_DRIVER_STRING(mem_ctx,
4599 driver->manufacturer_name,
4600 r->manufacturer_name);
4601 FILL_DRIVER_STRING(mem_ctx,
4602 driver->manufacturer_url,
4603 r->manufacturer_url);
4604 FILL_DRIVER_STRING(mem_ctx,
4605 driver->hardware_id,
4607 FILL_DRIVER_STRING(mem_ctx,
4611 FILL_DRIVER_STRING(mem_ctx,
4612 driver->print_processor,
4613 r->print_processor);
4614 FILL_DRIVER_STRING(mem_ctx,
4615 driver->vendor_setup,
4618 r->color_profiles = string_array_from_driver_info(mem_ctx,
4619 driver->color_profiles,
4622 FILL_DRIVER_STRING(mem_ctx,
4626 r->printer_driver_attributes = driver->printer_driver_attributes;
4628 r->core_driver_dependencies = string_array_from_driver_info(mem_ctx,
4629 driver->core_driver_dependencies,
4632 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4633 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4638 #if 0 /* disabled until marshalling issues are resolved - gd */
4639 /********************************************************************
4640 ********************************************************************/
4642 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4643 struct spoolss_DriverFileInfo *r,
4644 const char *cservername,
4645 const char *file_name,
4646 enum spoolss_DriverFileType file_type,
4647 uint32_t file_version)
4649 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4650 cservername, file_name);
4651 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4652 r->file_type = file_type;
4653 r->file_version = file_version;
4658 /********************************************************************
4659 ********************************************************************/
4661 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4662 const struct spoolss_DriverInfo8 *driver,
4663 const char *cservername,
4664 struct spoolss_DriverFileInfo **info_p,
4667 struct spoolss_DriverFileInfo *info = NULL;
4675 if (strlen(driver->driver_path)) {
4676 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4677 struct spoolss_DriverFileInfo,
4679 W_ERROR_HAVE_NO_MEMORY(info);
4680 result = fill_spoolss_DriverFileInfo(info,
4683 driver->driver_path,
4684 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4686 W_ERROR_NOT_OK_RETURN(result);
4690 if (strlen(driver->config_file)) {
4691 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4692 struct spoolss_DriverFileInfo,
4694 W_ERROR_HAVE_NO_MEMORY(info);
4695 result = fill_spoolss_DriverFileInfo(info,
4698 driver->config_file,
4699 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4701 W_ERROR_NOT_OK_RETURN(result);
4705 if (strlen(driver->data_file)) {
4706 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4707 struct spoolss_DriverFileInfo,
4709 W_ERROR_HAVE_NO_MEMORY(info);
4710 result = fill_spoolss_DriverFileInfo(info,
4714 SPOOLSS_DRIVER_FILE_TYPE_DATA,
4716 W_ERROR_NOT_OK_RETURN(result);
4720 if (strlen(driver->help_file)) {
4721 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4722 struct spoolss_DriverFileInfo,
4724 W_ERROR_HAVE_NO_MEMORY(info);
4725 result = fill_spoolss_DriverFileInfo(info,
4729 SPOOLSS_DRIVER_FILE_TYPE_HELP,
4731 W_ERROR_NOT_OK_RETURN(result);
4735 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
4736 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4737 struct spoolss_DriverFileInfo,
4739 W_ERROR_HAVE_NO_MEMORY(info);
4740 result = fill_spoolss_DriverFileInfo(info,
4743 driver->dependent_files[i],
4744 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
4746 W_ERROR_NOT_OK_RETURN(result);
4756 /********************************************************************
4757 * fill a spoolss_DriverInfo101 struct
4758 ********************************************************************/
4760 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
4761 struct spoolss_DriverInfo101 *r,
4762 const struct spoolss_DriverInfo8 *driver,
4763 const char *servername)
4765 const char *cservername = canon_servername(servername);
4768 r->version = driver->version;
4770 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4771 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4772 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4773 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4775 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
4779 if (!W_ERROR_IS_OK(result)) {
4783 FILL_DRIVER_STRING(mem_ctx,
4784 driver->monitor_name,
4787 FILL_DRIVER_STRING(mem_ctx,
4788 driver->default_datatype,
4789 r->default_datatype);
4791 r->previous_names = string_array_from_driver_info(mem_ctx,
4792 driver->previous_names,
4794 r->driver_date = driver->driver_date;
4795 r->driver_version = driver->driver_version;
4797 FILL_DRIVER_STRING(mem_ctx,
4798 driver->manufacturer_name,
4799 r->manufacturer_name);
4800 FILL_DRIVER_STRING(mem_ctx,
4801 driver->manufacturer_url,
4802 r->manufacturer_url);
4803 FILL_DRIVER_STRING(mem_ctx,
4804 driver->hardware_id,
4806 FILL_DRIVER_STRING(mem_ctx,
4813 /********************************************************************
4814 ********************************************************************/
4816 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
4818 union spoolss_DriverInfo *r,
4820 const char *servername,
4821 const char *architecture,
4824 NT_PRINTER_INFO_LEVEL *printer = NULL;
4825 struct spoolss_DriverInfo8 *driver;
4828 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
4830 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4831 win_errstr(result)));
4833 if (!W_ERROR_IS_OK(result)) {
4834 return WERR_INVALID_PRINTER_NAME;
4837 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4838 architecture, version);
4840 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4841 win_errstr(result)));
4843 if (!W_ERROR_IS_OK(result)) {
4845 * Is this a W2k client ?
4849 free_a_printer(&printer, 2);
4850 return WERR_UNKNOWN_PRINTER_DRIVER;
4853 /* Yes - try again with a WinNT driver. */
4855 result = get_a_printer_driver(mem_ctx, &driver, printer->info_2->drivername,
4856 architecture, version);
4857 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4858 win_errstr(result)));
4859 if (!W_ERROR_IS_OK(result)) {
4860 free_a_printer(&printer, 2);
4861 return WERR_UNKNOWN_PRINTER_DRIVER;
4867 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
4870 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
4873 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
4876 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
4879 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
4882 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
4885 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
4887 #if 0 /* disabled until marshalling issues are resolved - gd */
4889 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
4893 result = WERR_UNKNOWN_LEVEL;
4897 free_a_printer(&printer, 2);
4898 free_a_printer_driver(driver);
4903 /****************************************************************
4904 _spoolss_GetPrinterDriver2
4905 ****************************************************************/
4907 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
4908 struct spoolss_GetPrinterDriver2 *r)
4910 Printer_entry *printer;
4913 const char *servername;
4916 /* that's an [in out] buffer */
4918 if (!r->in.buffer && (r->in.offered != 0)) {
4919 return WERR_INVALID_PARAM;
4922 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
4924 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
4925 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
4926 return WERR_INVALID_PRINTER_NAME;
4930 *r->out.server_major_version = 0;
4931 *r->out.server_minor_version = 0;
4933 servername = get_server_name(printer);
4935 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4939 result = construct_printer_driver_info_level(p->mem_ctx, r->in.level,
4943 r->in.client_major_version);
4944 if (!W_ERROR_IS_OK(result)) {
4945 TALLOC_FREE(r->out.info);
4949 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
4950 r->out.info, r->in.level);
4951 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4953 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4957 /****************************************************************
4958 _spoolss_StartPagePrinter
4959 ****************************************************************/
4961 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
4962 struct spoolss_StartPagePrinter *r)
4964 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4967 DEBUG(3,("_spoolss_StartPagePrinter: "
4968 "Error in startpageprinter printer handle\n"));
4972 Printer->page_started = true;
4976 /****************************************************************
4977 _spoolss_EndPagePrinter
4978 ****************************************************************/
4980 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
4981 struct spoolss_EndPagePrinter *r)
4985 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4988 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
4989 OUR_HANDLE(r->in.handle)));
4993 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
4996 Printer->page_started = false;
4997 print_job_endpage(snum, Printer->jobid);
5002 /****************************************************************
5003 _spoolss_StartDocPrinter
5004 ****************************************************************/
5006 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5007 struct spoolss_StartDocPrinter *r)
5009 struct spoolss_DocumentInfo1 *info_1;
5011 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5014 DEBUG(2,("_spoolss_StartDocPrinter: "
5015 "Invalid handle (%s:%u:%u)\n",
5016 OUR_HANDLE(r->in.handle)));
5020 if (r->in.level != 1) {
5021 return WERR_UNKNOWN_LEVEL;
5024 info_1 = r->in.info.info1;
5027 * a nice thing with NT is it doesn't listen to what you tell it.
5028 * when asked to send _only_ RAW datas, it tries to send datas
5031 * So I add checks like in NT Server ...
5034 if (info_1->datatype) {
5035 if (strcmp(info_1->datatype, "RAW") != 0) {
5037 return WERR_INVALID_DATATYPE;
5041 /* get the share number of the printer */
5042 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5046 Printer->jobid = print_job_start(p->server_info, snum,
5047 info_1->document_name,
5050 /* An error occured in print_job_start() so return an appropriate
5053 if (Printer->jobid == -1) {
5054 return map_werror_from_unix(errno);
5057 Printer->document_started = true;
5058 *r->out.job_id = Printer->jobid;
5063 /****************************************************************
5064 _spoolss_EndDocPrinter
5065 ****************************************************************/
5067 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5068 struct spoolss_EndDocPrinter *r)
5070 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5074 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5075 OUR_HANDLE(r->in.handle)));
5079 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5083 Printer->document_started = false;
5084 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5085 /* error codes unhandled so far ... */
5090 /****************************************************************
5091 _spoolss_WritePrinter
5092 ****************************************************************/
5094 WERROR _spoolss_WritePrinter(pipes_struct *p,
5095 struct spoolss_WritePrinter *r)
5097 ssize_t buffer_written;
5099 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5102 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5103 OUR_HANDLE(r->in.handle)));
5104 *r->out.num_written = r->in._data_size;
5108 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5111 buffer_written = print_job_write(snum, Printer->jobid,
5112 (const char *)r->in.data.data,
5114 (size_t)r->in._data_size);
5115 if (buffer_written == (ssize_t)-1) {
5116 *r->out.num_written = 0;
5117 if (errno == ENOSPC)
5118 return WERR_NO_SPOOL_SPACE;
5120 return WERR_ACCESS_DENIED;
5123 *r->out.num_written = r->in._data_size;
5128 /********************************************************************
5129 * api_spoolss_getprinter
5130 * called from the spoolss dispatcher
5132 ********************************************************************/
5134 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5138 WERROR errcode = WERR_BADFUNC;
5139 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5142 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5143 OUR_HANDLE(handle)));
5147 if (!get_printer_snum(p, handle, &snum, NULL))
5151 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5152 errcode = print_queue_pause(p->server_info, snum);
5154 case SPOOLSS_PRINTER_CONTROL_RESUME:
5155 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5156 errcode = print_queue_resume(p->server_info, snum);
5158 case SPOOLSS_PRINTER_CONTROL_PURGE:
5159 errcode = print_queue_purge(p->server_info, snum);
5162 return WERR_UNKNOWN_LEVEL;
5169 /****************************************************************
5170 _spoolss_AbortPrinter
5171 * From MSDN: "Deletes printer's spool file if printer is configured
5173 ****************************************************************/
5175 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5176 struct spoolss_AbortPrinter *r)
5178 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5180 WERROR errcode = WERR_OK;
5183 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5184 OUR_HANDLE(r->in.handle)));
5188 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5191 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5196 /********************************************************************
5197 * called by spoolss_api_setprinter
5198 * when updating a printer description
5199 ********************************************************************/
5201 static WERROR update_printer_sec(struct policy_handle *handle,
5202 pipes_struct *p, struct sec_desc_buf *secdesc_ctr)
5204 struct sec_desc_buf *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5208 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5210 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5211 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5212 OUR_HANDLE(handle)));
5214 result = WERR_BADFID;
5219 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5220 result = WERR_INVALID_PARAM;
5224 /* Check the user has permissions to change the security
5225 descriptor. By experimentation with two NT machines, the user
5226 requires Full Access to the printer to change security
5229 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5230 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5231 result = WERR_ACCESS_DENIED;
5235 /* NT seems to like setting the security descriptor even though
5236 nothing may have actually changed. */
5238 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5239 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5240 result = WERR_BADFID;
5244 if (DEBUGLEVEL >= 10) {
5245 struct security_acl *the_acl;
5248 the_acl = old_secdesc_ctr->sd->dacl;
5249 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5250 lp_printername(snum), the_acl->num_aces));
5252 for (i = 0; i < the_acl->num_aces; i++) {
5253 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5254 &the_acl->aces[i].trustee),
5255 the_acl->aces[i].access_mask));
5258 the_acl = secdesc_ctr->sd->dacl;
5261 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5262 lp_printername(snum), the_acl->num_aces));
5264 for (i = 0; i < the_acl->num_aces; i++) {
5265 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5266 &the_acl->aces[i].trustee),
5267 the_acl->aces[i].access_mask));
5270 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5274 new_secdesc_ctr = sec_desc_merge_buf(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5275 if (!new_secdesc_ctr) {
5276 result = WERR_NOMEM;
5280 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5285 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5292 /********************************************************************
5293 Canonicalize printer info from a client
5295 ATTN: It does not matter what we set the servername to hear
5296 since we do the necessary work in get_a_printer() to set it to
5297 the correct value based on what the client sent in the
5298 _spoolss_open_printer_ex().
5299 ********************************************************************/
5301 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5303 fstring printername;
5306 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5307 "portname=%s drivername=%s comment=%s location=%s\n",
5308 info->servername, info->printername, info->sharename,
5309 info->portname, info->drivername, info->comment, info->location));
5311 /* we force some elements to "correct" values */
5312 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5313 fstrcpy(info->sharename, lp_servicename(snum));
5315 /* check to see if we allow printername != sharename */
5317 if ( lp_force_printername(snum) ) {
5318 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5319 global_myname(), info->sharename );
5322 /* make sure printername is in \\server\printername format */
5324 fstrcpy( printername, info->printername );
5326 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5327 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5331 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5332 global_myname(), p );
5335 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5336 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5343 /****************************************************************************
5344 ****************************************************************************/
5346 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5348 char *cmd = lp_addport_cmd();
5349 char *command = NULL;
5351 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5352 bool is_print_op = false;
5355 return WERR_ACCESS_DENIED;
5358 command = talloc_asprintf(ctx,
5359 "%s \"%s\" \"%s\"", cmd, portname, uri );
5365 is_print_op = user_has_privileges( token, &se_printop );
5367 DEBUG(10,("Running [%s]\n", command));
5369 /********* BEGIN SePrintOperatorPrivilege **********/
5374 ret = smbrun(command, NULL);
5379 /********* END SePrintOperatorPrivilege **********/
5381 DEBUGADD(10,("returned [%d]\n", ret));
5383 TALLOC_FREE(command);
5386 return WERR_ACCESS_DENIED;
5392 /****************************************************************************
5393 ****************************************************************************/
5395 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5397 char *cmd = lp_addprinter_cmd();
5399 char *command = NULL;
5403 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5404 bool is_print_op = false;
5405 char *remote_machine = talloc_strdup(ctx, "%m");
5407 if (!remote_machine) {
5410 remote_machine = talloc_sub_basic(ctx,
5411 current_user_info.smb_name,
5412 current_user_info.domain,
5414 if (!remote_machine) {
5418 command = talloc_asprintf(ctx,
5419 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5420 cmd, printer->info_2->printername, printer->info_2->sharename,
5421 printer->info_2->portname, printer->info_2->drivername,
5422 printer->info_2->location, printer->info_2->comment, remote_machine);
5428 is_print_op = user_has_privileges( token, &se_printop );
5430 DEBUG(10,("Running [%s]\n", command));
5432 /********* BEGIN SePrintOperatorPrivilege **********/
5437 if ( (ret = smbrun(command, &fd)) == 0 ) {
5438 /* Tell everyone we updated smb.conf. */
5439 message_send_all(smbd_messaging_context(),
5440 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5446 /********* END SePrintOperatorPrivilege **********/
5448 DEBUGADD(10,("returned [%d]\n", ret));
5450 TALLOC_FREE(command);
5451 TALLOC_FREE(remote_machine);
5459 /* reload our services immediately */
5461 reload_services(false);
5465 /* Get lines and convert them back to dos-codepage */
5466 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5467 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5470 /* Set the portname to what the script says the portname should be. */
5471 /* but don't require anything to be return from the script exit a good error code */
5474 /* Set the portname to what the script says the portname should be. */
5475 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
5476 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5479 TALLOC_FREE(qlines);
5484 /********************************************************************
5485 * Called by spoolss_api_setprinter
5486 * when updating a printer description.
5487 ********************************************************************/
5489 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
5490 struct spoolss_SetPrinterInfoCtr *info_ctr,
5491 struct spoolss_DeviceMode *devmode)
5494 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
5495 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5500 DEBUG(8,("update_printer\n"));
5505 result = WERR_BADFID;
5509 if (!get_printer_snum(p, handle, &snum, NULL)) {
5510 result = WERR_BADFID;
5514 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
5515 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
5516 result = WERR_BADFID;
5520 DEBUGADD(8,("Converting info_2 struct\n"));
5523 * convert_printer_info converts the incoming
5524 * info from the client and overwrites the info
5525 * just read from the tdb in the pointer 'printer'.
5528 if (!convert_printer_info(info_ctr, printer)) {
5529 result = WERR_NOMEM;
5534 /* we have a valid devmode
5535 convert it and link it*/
5537 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5538 result = copy_devicemode(printer->info_2, devmode,
5539 &printer->info_2->devmode);
5540 if (!W_ERROR_IS_OK(result)) {
5545 /* Do sanity check on the requested changes for Samba */
5547 if (!check_printer_ok(printer->info_2, snum)) {
5548 result = WERR_INVALID_PARAM;
5552 /* FIXME!!! If the driver has changed we really should verify that
5553 it is installed before doing much else --jerry */
5555 /* Check calling user has permission to update printer description */
5557 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5558 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5559 result = WERR_ACCESS_DENIED;
5563 /* Call addprinter hook */
5564 /* Check changes to see if this is really needed */
5566 if ( *lp_addprinter_cmd()
5567 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
5568 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
5569 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
5570 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
5572 /* add_printer_hook() will call reload_services() */
5574 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
5576 result = WERR_ACCESS_DENIED;
5582 * When a *new* driver is bound to a printer, the drivername is used to
5583 * lookup previously saved driver initialization info, which is then
5584 * bound to the printer, simulating what happens in the Windows arch.
5586 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
5588 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5589 printer->info_2->drivername));
5591 notify_printer_driver(snum, printer->info_2->drivername);
5595 * flag which changes actually occured. This is a small subset of
5596 * all the possible changes. We also have to update things in the
5600 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
5601 push_reg_sz(talloc_tos(), &buffer, printer->info_2->comment);
5602 winreg_set_printer_dataex(p->mem_ctx,
5604 printer->info_2->sharename,
5605 SPOOL_DSSPOOLER_KEY,
5611 notify_printer_comment(snum, printer->info_2->comment);
5614 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
5615 push_reg_sz(talloc_tos(), &buffer, printer->info_2->sharename);
5616 winreg_set_printer_dataex(p->mem_ctx,
5618 printer->info_2->sharename,
5619 SPOOL_DSSPOOLER_KEY,
5625 notify_printer_sharename(snum, printer->info_2->sharename);
5628 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
5631 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
5634 pname = printer->info_2->printername;
5637 push_reg_sz(talloc_tos(), &buffer, pname);
5638 winreg_set_printer_dataex(p->mem_ctx,
5640 printer->info_2->sharename,
5641 SPOOL_DSSPOOLER_KEY,
5647 notify_printer_printername( snum, pname );
5650 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
5651 push_reg_sz(talloc_tos(), &buffer, printer->info_2->portname);
5652 winreg_set_printer_dataex(p->mem_ctx,
5654 printer->info_2->sharename,
5655 SPOOL_DSSPOOLER_KEY,
5661 notify_printer_port(snum, printer->info_2->portname);
5664 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
5665 push_reg_sz(talloc_tos(), &buffer, printer->info_2->location);
5666 winreg_set_printer_dataex(p->mem_ctx,
5668 printer->info_2->sharename,
5669 SPOOL_DSSPOOLER_KEY,
5675 notify_printer_location(snum, printer->info_2->location);
5678 /* here we need to update some more DsSpooler keys */
5679 /* uNCName, serverName, shortServerName */
5681 push_reg_sz(talloc_tos(), &buffer, global_myname());
5682 winreg_set_printer_dataex(p->mem_ctx,
5684 printer->info_2->sharename,
5685 SPOOL_DSSPOOLER_KEY,
5690 winreg_set_printer_dataex(p->mem_ctx,
5692 printer->info_2->sharename,
5693 SPOOL_DSSPOOLER_KEY,
5699 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
5700 global_myname(), printer->info_2->sharename );
5701 push_reg_sz(talloc_tos(), &buffer, asc_buffer);
5702 winreg_set_printer_dataex(p->mem_ctx,
5704 printer->info_2->sharename,
5705 SPOOL_DSSPOOLER_KEY,
5711 /* Update printer info */
5712 result = mod_a_printer(printer, 2);
5715 free_a_printer(&printer, 2);
5716 free_a_printer(&old_printer, 2);
5722 /****************************************************************************
5723 ****************************************************************************/
5724 static WERROR publish_or_unpublish_printer(pipes_struct *p,
5725 struct policy_handle *handle,
5726 struct spoolss_SetPrinterInfo7 *info7)
5730 Printer_entry *Printer;
5732 if ( lp_security() != SEC_ADS ) {
5733 return WERR_UNKNOWN_LEVEL;
5736 Printer = find_printer_index_by_hnd(p, handle);
5738 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
5743 if (!get_printer_snum(p, handle, &snum, NULL))
5746 nt_printer_publish(Printer, snum, info7->action);
5750 return WERR_UNKNOWN_LEVEL;
5754 /********************************************************************
5755 ********************************************************************/
5757 static WERROR update_printer_devmode(pipes_struct *p, struct policy_handle *handle,
5758 struct spoolss_DeviceMode *devmode)
5761 NT_PRINTER_INFO_LEVEL *printer = NULL;
5762 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5765 DEBUG(8,("update_printer_devmode\n"));
5770 result = WERR_BADFID;
5774 if (!get_printer_snum(p, handle, &snum, NULL)) {
5775 result = WERR_BADFID;
5779 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum)))) {
5780 result = WERR_BADFID;
5785 /* we have a valid devmode, copy it */
5787 DEBUGADD(8, ("update_printer: Copying the devicemode struct\n"));
5788 result = copy_devicemode(printer->info_2, devmode,
5789 &printer->info_2->devmode);
5790 if (!W_ERROR_IS_OK(result)) {
5795 /* Check calling user has permission to update printer description */
5797 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
5798 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5799 result = WERR_ACCESS_DENIED;
5804 /* Update printer info */
5805 result = mod_a_printer(printer, 2);
5808 free_a_printer(&printer, 2);
5814 /****************************************************************
5816 ****************************************************************/
5818 WERROR _spoolss_SetPrinter(pipes_struct *p,
5819 struct spoolss_SetPrinter *r)
5823 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5826 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5827 OUR_HANDLE(r->in.handle)));
5831 /* check the level */
5832 switch (r->in.info_ctr->level) {
5834 return control_printer(r->in.handle, r->in.command, p);
5836 result = update_printer(p, r->in.handle,
5838 r->in.devmode_ctr->devmode);
5839 if (!W_ERROR_IS_OK(result))
5841 if (r->in.secdesc_ctr->sd)
5842 result = update_printer_sec(r->in.handle, p,
5846 return update_printer_sec(r->in.handle, p,
5849 return publish_or_unpublish_printer(p, r->in.handle,
5850 r->in.info_ctr->info.info7);
5852 return update_printer_devmode(p, r->in.handle,
5853 r->in.devmode_ctr->devmode);
5855 return WERR_UNKNOWN_LEVEL;
5859 /****************************************************************
5860 _spoolss_FindClosePrinterNotify
5861 ****************************************************************/
5863 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
5864 struct spoolss_FindClosePrinterNotify *r)
5866 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5869 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5870 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
5874 if (Printer->notify.client_connected == true) {
5877 if ( Printer->printer_type == SPLHND_SERVER)
5879 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
5880 !get_printer_snum(p, r->in.handle, &snum, NULL) )
5883 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
5886 Printer->notify.flags=0;
5887 Printer->notify.options=0;
5888 Printer->notify.localmachine[0]='\0';
5889 Printer->notify.printerlocal=0;
5890 TALLOC_FREE(Printer->notify.option);
5891 Printer->notify.client_connected = false;
5896 /****************************************************************
5898 ****************************************************************/
5900 WERROR _spoolss_AddJob(pipes_struct *p,
5901 struct spoolss_AddJob *r)
5903 if (!r->in.buffer && (r->in.offered != 0)) {
5904 return WERR_INVALID_PARAM;
5907 /* this is what a NT server returns for AddJob. AddJob must fail on
5908 * non-local printers */
5910 if (r->in.level != 1) {
5911 return WERR_UNKNOWN_LEVEL;
5914 return WERR_INVALID_PARAM;
5917 /****************************************************************************
5919 ****************************************************************************/
5921 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
5922 struct spoolss_JobInfo1 *r,
5923 const print_queue_struct *queue,
5924 int position, int snum,
5925 const NT_PRINTER_INFO_LEVEL *ntprinter)
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->data_type = talloc_strdup(mem_ctx, "RAW");
5942 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5943 r->text_status = talloc_strdup(mem_ctx, "");
5944 W_ERROR_HAVE_NO_MEMORY(r->text_status);
5946 r->status = nt_printj_status(queue->status);
5947 r->priority = queue->priority;
5948 r->position = position;
5949 r->total_pages = queue->page_count;
5950 r->pages_printed = 0; /* ??? */
5952 init_systemtime(&r->submitted, t);
5957 /****************************************************************************
5959 ****************************************************************************/
5961 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
5962 struct spoolss_JobInfo2 *r,
5963 const print_queue_struct *queue,
5964 int position, int snum,
5965 const NT_PRINTER_INFO_LEVEL *ntprinter,
5966 struct spoolss_DeviceMode *devmode)
5970 t = gmtime(&queue->time);
5972 r->job_id = queue->job;
5974 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
5975 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
5976 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
5977 W_ERROR_HAVE_NO_MEMORY(r->server_name);
5978 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
5979 W_ERROR_HAVE_NO_MEMORY(r->user_name);
5980 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
5981 W_ERROR_HAVE_NO_MEMORY(r->document_name);
5982 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
5983 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
5984 r->data_type = talloc_strdup(mem_ctx, "RAW");
5985 W_ERROR_HAVE_NO_MEMORY(r->data_type);
5986 r->print_processor = talloc_strdup(mem_ctx, "winprint");
5987 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
5988 r->parameters = talloc_strdup(mem_ctx, "");
5989 W_ERROR_HAVE_NO_MEMORY(r->parameters);
5990 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
5991 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5993 r->devmode = devmode;
5995 r->text_status = talloc_strdup(mem_ctx, "");
5996 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6000 r->status = nt_printj_status(queue->status);
6001 r->priority = queue->priority;
6002 r->position = position;
6005 r->total_pages = queue->page_count;
6006 r->size = queue->size;
6007 init_systemtime(&r->submitted, t);
6009 r->pages_printed = 0; /* ??? */
6014 /****************************************************************************
6016 ****************************************************************************/
6018 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6019 struct spoolss_JobInfo3 *r,
6020 const print_queue_struct *queue,
6021 const print_queue_struct *next_queue,
6022 int position, int snum,
6023 const NT_PRINTER_INFO_LEVEL *ntprinter)
6025 r->job_id = queue->job;
6028 r->next_job_id = next_queue->job;
6035 /****************************************************************************
6036 Enumjobs at level 1.
6037 ****************************************************************************/
6039 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6040 const print_queue_struct *queue,
6041 uint32_t num_queues, int snum,
6042 const NT_PRINTER_INFO_LEVEL *ntprinter,
6043 union spoolss_JobInfo **info_p,
6046 union spoolss_JobInfo *info;
6048 WERROR result = WERR_OK;
6050 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6051 W_ERROR_HAVE_NO_MEMORY(info);
6053 *count = num_queues;
6055 for (i=0; i<*count; i++) {
6056 result = fill_job_info1(info,
6062 if (!W_ERROR_IS_OK(result)) {
6068 if (!W_ERROR_IS_OK(result)) {
6079 /****************************************************************************
6080 Enumjobs at level 2.
6081 ****************************************************************************/
6083 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6084 const print_queue_struct *queue,
6085 uint32_t num_queues, int snum,
6086 const NT_PRINTER_INFO_LEVEL *ntprinter,
6087 union spoolss_JobInfo **info_p,
6090 union spoolss_JobInfo *info;
6092 WERROR result = WERR_OK;
6094 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6095 W_ERROR_HAVE_NO_MEMORY(info);
6097 *count = num_queues;
6099 for (i=0; i<*count; i++) {
6101 struct spoolss_DeviceMode *devmode;
6103 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6105 result = WERR_NOMEM;
6109 result = fill_job_info2(info,
6116 if (!W_ERROR_IS_OK(result)) {
6122 if (!W_ERROR_IS_OK(result)) {
6133 /****************************************************************************
6134 Enumjobs at level 3.
6135 ****************************************************************************/
6137 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6138 const print_queue_struct *queue,
6139 uint32_t num_queues, int snum,
6140 const NT_PRINTER_INFO_LEVEL *ntprinter,
6141 union spoolss_JobInfo **info_p,
6144 union spoolss_JobInfo *info;
6146 WERROR result = WERR_OK;
6148 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6149 W_ERROR_HAVE_NO_MEMORY(info);
6151 *count = num_queues;
6153 for (i=0; i<*count; i++) {
6154 const print_queue_struct *next_queue = NULL;
6157 next_queue = &queue[i+1];
6160 result = fill_job_info3(info,
6167 if (!W_ERROR_IS_OK(result)) {
6173 if (!W_ERROR_IS_OK(result)) {
6184 /****************************************************************
6186 ****************************************************************/
6188 WERROR _spoolss_EnumJobs(pipes_struct *p,
6189 struct spoolss_EnumJobs *r)
6192 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6194 print_status_struct prt_status;
6195 print_queue_struct *queue = NULL;
6198 /* that's an [in out] buffer */
6200 if (!r->in.buffer && (r->in.offered != 0)) {
6201 return WERR_INVALID_PARAM;
6204 DEBUG(4,("_spoolss_EnumJobs\n"));
6208 *r->out.info = NULL;
6210 /* lookup the printer snum and tdb entry */
6212 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6216 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6217 if (!W_ERROR_IS_OK(result)) {
6221 count = print_queue_status(snum, &queue, &prt_status);
6222 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6223 count, prt_status.status, prt_status.message));
6227 free_a_printer(&ntprinter, 2);
6231 switch (r->in.level) {
6233 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6234 ntprinter, r->out.info, r->out.count);
6237 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6238 ntprinter, r->out.info, r->out.count);
6241 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6242 ntprinter, r->out.info, r->out.count);
6245 result = WERR_UNKNOWN_LEVEL;
6250 free_a_printer(&ntprinter, 2);
6252 if (!W_ERROR_IS_OK(result)) {
6256 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6258 *r->out.info, r->in.level,
6260 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6261 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6263 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6266 /****************************************************************
6267 _spoolss_ScheduleJob
6268 ****************************************************************/
6270 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6271 struct spoolss_ScheduleJob *r)
6276 /****************************************************************
6277 ****************************************************************/
6279 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6280 const char *printer_name,
6282 struct spoolss_SetJobInfo1 *r)
6286 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6290 if (strequal(old_doc_name, r->document_name)) {
6294 if (!print_job_set_name(printer_name, job_id, r->document_name)) {
6301 /****************************************************************
6303 ****************************************************************/
6305 WERROR _spoolss_SetJob(pipes_struct *p,
6306 struct spoolss_SetJob *r)
6309 WERROR errcode = WERR_BADFUNC;
6311 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6315 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6316 return WERR_INVALID_PRINTER_NAME;
6319 switch (r->in.command) {
6320 case SPOOLSS_JOB_CONTROL_CANCEL:
6321 case SPOOLSS_JOB_CONTROL_DELETE:
6322 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6326 case SPOOLSS_JOB_CONTROL_PAUSE:
6327 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6331 case SPOOLSS_JOB_CONTROL_RESTART:
6332 case SPOOLSS_JOB_CONTROL_RESUME:
6333 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6341 return WERR_UNKNOWN_LEVEL;
6344 if (!W_ERROR_IS_OK(errcode)) {
6348 if (r->in.ctr == NULL) {
6352 switch (r->in.ctr->level) {
6354 errcode = spoolss_setjob_1(p->mem_ctx, lp_const_servicename(snum),
6356 r->in.ctr->info.info1);
6362 return WERR_UNKNOWN_LEVEL;
6368 /****************************************************************************
6369 Enumerates all printer drivers by level and architecture.
6370 ****************************************************************************/
6372 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6373 const char *servername,
6374 const char *architecture,
6376 union spoolss_DriverInfo **info_p,
6382 fstring *list = NULL;
6383 struct spoolss_DriverInfo8 *driver;
6384 union spoolss_DriverInfo *info = NULL;
6386 WERROR result = WERR_OK;
6391 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6393 ndrivers = get_ntdrivers(&list, architecture, version);
6394 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6395 ndrivers, architecture, version));
6397 if (ndrivers == -1) {
6398 result = WERR_NOMEM;
6402 if (ndrivers != 0) {
6403 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6404 union spoolss_DriverInfo,
6407 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6408 "failed to enlarge driver info buffer!\n"));
6409 result = WERR_NOMEM;
6414 for (i=0; i<ndrivers; i++) {
6415 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6416 ZERO_STRUCT(driver);
6417 result = get_a_printer_driver(mem_ctx, &driver, list[i],
6418 architecture, version);
6419 if (!W_ERROR_IS_OK(result)) {
6425 result = fill_printer_driver_info1(info, &info[count+i].info1,
6426 driver, servername);
6429 result = fill_printer_driver_info2(info, &info[count+i].info2,
6430 driver, servername);
6433 result = fill_printer_driver_info3(info, &info[count+i].info3,
6434 driver, servername);
6437 result = fill_printer_driver_info4(info, &info[count+i].info4,
6438 driver, servername);
6441 result = fill_printer_driver_info5(info, &info[count+i].info5,
6442 driver, servername);
6445 result = fill_printer_driver_info6(info, &info[count+i].info6,
6446 driver, servername);
6449 result = fill_printer_driver_info8(info, &info[count+i].info8,
6450 driver, servername);
6453 result = WERR_UNKNOWN_LEVEL;
6457 free_a_printer_driver(driver);
6459 if (!W_ERROR_IS_OK(result)) {
6471 if (!W_ERROR_IS_OK(result)) {
6482 /****************************************************************************
6483 Enumerates all printer drivers by level.
6484 ****************************************************************************/
6486 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6487 const char *servername,
6488 const char *architecture,
6490 union spoolss_DriverInfo **info_p,
6494 WERROR result = WERR_OK;
6496 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6498 for (a=0; archi_table[a].long_archi != NULL; a++) {
6500 union spoolss_DriverInfo *info = NULL;
6503 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6505 archi_table[a].long_archi,
6509 if (!W_ERROR_IS_OK(result)) {
6513 for (i=0; i < count; i++) {
6514 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6515 info[i], info_p, count_p);
6522 return enumprinterdrivers_level_by_architecture(mem_ctx,
6530 /****************************************************************
6531 _spoolss_EnumPrinterDrivers
6532 ****************************************************************/
6534 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6535 struct spoolss_EnumPrinterDrivers *r)
6537 const char *cservername;
6540 /* that's an [in out] buffer */
6542 if (!r->in.buffer && (r->in.offered != 0)) {
6543 return WERR_INVALID_PARAM;
6546 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6550 *r->out.info = NULL;
6552 cservername = canon_servername(r->in.server);
6554 if (!is_myname_or_ipaddr(cservername)) {
6555 return WERR_UNKNOWN_PRINTER_DRIVER;
6558 result = enumprinterdrivers_level(p->mem_ctx, cservername,
6563 if (!W_ERROR_IS_OK(result)) {
6567 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6568 spoolss_EnumPrinterDrivers,
6569 *r->out.info, r->in.level,
6571 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6572 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6574 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6577 /****************************************************************************
6578 ****************************************************************************/
6580 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
6581 struct spoolss_FormInfo1 *r,
6582 const nt_forms_struct *form)
6584 r->form_name = talloc_strdup(mem_ctx, form->name);
6585 W_ERROR_HAVE_NO_MEMORY(r->form_name);
6587 r->flags = form->flag;
6588 r->size.width = form->width;
6589 r->size.height = form->length;
6590 r->area.left = form->left;
6591 r->area.top = form->top;
6592 r->area.right = form->right;
6593 r->area.bottom = form->bottom;
6598 /****************************************************************
6600 ****************************************************************/
6602 WERROR _spoolss_EnumForms(pipes_struct *p,
6603 struct spoolss_EnumForms *r)
6609 *r->out.info = NULL;
6611 /* that's an [in out] buffer */
6613 if (!r->in.buffer && (r->in.offered != 0) ) {
6614 return WERR_INVALID_PARAM;
6617 DEBUG(4,("_spoolss_EnumForms\n"));
6618 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6619 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6621 switch (r->in.level) {
6623 result = winreg_printer_enumforms1(p->mem_ctx,
6629 result = WERR_UNKNOWN_LEVEL;
6633 if (!W_ERROR_IS_OK(result)) {
6637 if (*r->out.count == 0) {
6638 return WERR_NO_MORE_ITEMS;
6641 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6643 *r->out.info, r->in.level,
6645 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6646 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6648 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6651 /****************************************************************
6652 ****************************************************************/
6654 static WERROR find_form_byname(const char *name,
6655 nt_forms_struct *form)
6657 nt_forms_struct *list = NULL;
6658 int num_forms = 0, i = 0;
6660 if (get_a_builtin_ntform_by_string(name, form)) {
6664 num_forms = get_ntforms(&list);
6665 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
6667 if (num_forms == 0) {
6671 /* Check if the requested name is in the list of form structures */
6672 for (i = 0; i < num_forms; i++) {
6674 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
6676 if (strequal(name, list[i].name)) {
6677 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
6689 /****************************************************************
6691 ****************************************************************/
6693 WERROR _spoolss_GetForm(pipes_struct *p,
6694 struct spoolss_GetForm *r)
6697 nt_forms_struct form;
6699 /* that's an [in out] buffer */
6701 if (!r->in.buffer && (r->in.offered != 0)) {
6702 return WERR_INVALID_PARAM;
6705 DEBUG(4,("_spoolss_GetForm\n"));
6706 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
6707 DEBUGADD(5,("Info level [%d]\n", r->in.level));
6709 result = find_form_byname(r->in.form_name, &form);
6710 if (!W_ERROR_IS_OK(result)) {
6711 TALLOC_FREE(r->out.info);
6715 switch (r->in.level) {
6717 result = fill_form_info_1(p->mem_ctx,
6718 &r->out.info->info1,
6723 result = WERR_UNKNOWN_LEVEL;
6727 if (!W_ERROR_IS_OK(result)) {
6728 TALLOC_FREE(r->out.info);
6732 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
6733 r->out.info, r->in.level);
6734 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
6736 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6739 /****************************************************************************
6740 ****************************************************************************/
6742 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
6743 struct spoolss_PortInfo1 *r,
6746 r->port_name = talloc_strdup(mem_ctx, name);
6747 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6752 /****************************************************************************
6753 TODO: This probably needs distinguish between TCP/IP and Local ports
6755 ****************************************************************************/
6757 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
6758 struct spoolss_PortInfo2 *r,
6761 r->port_name = talloc_strdup(mem_ctx, name);
6762 W_ERROR_HAVE_NO_MEMORY(r->port_name);
6764 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
6765 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
6767 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
6768 W_ERROR_HAVE_NO_MEMORY(r->description);
6770 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
6777 /****************************************************************************
6778 wrapper around the enumer ports command
6779 ****************************************************************************/
6781 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
6783 char *cmd = lp_enumports_cmd();
6784 char **qlines = NULL;
6785 char *command = NULL;
6793 /* if no hook then just fill in the default port */
6796 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
6799 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
6800 TALLOC_FREE(qlines);
6807 /* we have a valid enumport command */
6809 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
6814 DEBUG(10,("Running [%s]\n", command));
6815 ret = smbrun(command, &fd);
6816 DEBUG(10,("Returned [%d]\n", ret));
6817 TALLOC_FREE(command);
6822 return WERR_ACCESS_DENIED;
6826 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6827 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6837 /****************************************************************************
6839 ****************************************************************************/
6841 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
6842 union spoolss_PortInfo **info_p,
6845 union spoolss_PortInfo *info = NULL;
6847 WERROR result = WERR_OK;
6848 char **qlines = NULL;
6851 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6852 if (!W_ERROR_IS_OK(result)) {
6857 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6859 DEBUG(10,("Returning WERR_NOMEM\n"));
6860 result = WERR_NOMEM;
6864 for (i=0; i<numlines; i++) {
6865 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6866 result = fill_port_1(info, &info[i].info1, qlines[i]);
6867 if (!W_ERROR_IS_OK(result)) {
6872 TALLOC_FREE(qlines);
6875 if (!W_ERROR_IS_OK(result)) {
6877 TALLOC_FREE(qlines);
6889 /****************************************************************************
6891 ****************************************************************************/
6893 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
6894 union spoolss_PortInfo **info_p,
6897 union spoolss_PortInfo *info = NULL;
6899 WERROR result = WERR_OK;
6900 char **qlines = NULL;
6903 result = enumports_hook(talloc_tos(), &numlines, &qlines );
6904 if (!W_ERROR_IS_OK(result)) {
6909 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
6911 DEBUG(10,("Returning WERR_NOMEM\n"));
6912 result = WERR_NOMEM;
6916 for (i=0; i<numlines; i++) {
6917 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
6918 result = fill_port_2(info, &info[i].info2, qlines[i]);
6919 if (!W_ERROR_IS_OK(result)) {
6924 TALLOC_FREE(qlines);
6927 if (!W_ERROR_IS_OK(result)) {
6929 TALLOC_FREE(qlines);
6941 /****************************************************************
6943 ****************************************************************/
6945 WERROR _spoolss_EnumPorts(pipes_struct *p,
6946 struct spoolss_EnumPorts *r)
6950 /* that's an [in out] buffer */
6952 if (!r->in.buffer && (r->in.offered != 0)) {
6953 return WERR_INVALID_PARAM;
6956 DEBUG(4,("_spoolss_EnumPorts\n"));
6960 *r->out.info = NULL;
6962 switch (r->in.level) {
6964 result = enumports_level_1(p->mem_ctx, r->out.info,
6968 result = enumports_level_2(p->mem_ctx, r->out.info,
6972 return WERR_UNKNOWN_LEVEL;
6975 if (!W_ERROR_IS_OK(result)) {
6979 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6981 *r->out.info, r->in.level,
6983 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6984 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6986 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6989 /****************************************************************************
6990 ****************************************************************************/
6992 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
6994 struct spoolss_SetPrinterInfoCtr *info_ctr,
6995 struct spoolss_DeviceMode *devmode,
6996 struct security_descriptor *sec_desc,
6997 struct spoolss_UserLevelCtr *user_ctr,
6998 struct policy_handle *handle)
7000 NT_PRINTER_INFO_LEVEL *printer = NULL;
7003 WERROR err = WERR_OK;
7005 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7006 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7010 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7011 if (!convert_printer_info(info_ctr, printer)) {
7012 free_a_printer(&printer, 2);
7016 /* samba does not have a concept of local, non-shared printers yet, so
7017 * make sure we always setup sharename - gd */
7018 if ((printer->info_2->sharename[0] == '\0') && (printer->info_2->printername != '\0')) {
7019 DEBUG(5, ("spoolss_addprinterex_level_2: "
7020 "no sharename has been set, setting printername %s as sharename\n",
7021 printer->info_2->printername));
7022 fstrcpy(printer->info_2->sharename, printer->info_2->printername);
7025 /* check to see if the printer already exists */
7027 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7028 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7029 printer->info_2->sharename));
7030 free_a_printer(&printer, 2);
7031 return WERR_PRINTER_ALREADY_EXISTS;
7034 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7035 if ((snum = print_queue_snum(printer->info_2->printername)) != -1) {
7036 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7037 printer->info_2->printername));
7038 free_a_printer(&printer, 2);
7039 return WERR_PRINTER_ALREADY_EXISTS;
7043 /* validate printer info struct */
7044 if (!info_ctr->info.info2->printername ||
7045 strlen(info_ctr->info.info2->printername) == 0) {
7046 free_a_printer(&printer,2);
7047 return WERR_INVALID_PRINTER_NAME;
7049 if (!info_ctr->info.info2->portname ||
7050 strlen(info_ctr->info.info2->portname) == 0) {
7051 free_a_printer(&printer,2);
7052 return WERR_UNKNOWN_PORT;
7054 if (!info_ctr->info.info2->drivername ||
7055 strlen(info_ctr->info.info2->drivername) == 0) {
7056 free_a_printer(&printer,2);
7057 return WERR_UNKNOWN_PRINTER_DRIVER;
7059 if (!info_ctr->info.info2->printprocessor ||
7060 strlen(info_ctr->info.info2->printprocessor) == 0) {
7061 free_a_printer(&printer,2);
7062 return WERR_UNKNOWN_PRINTPROCESSOR;
7065 /* FIXME!!! smbd should check to see if the driver is installed before
7066 trying to add a printer like this --jerry */
7068 if (*lp_addprinter_cmd() ) {
7069 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7071 free_a_printer(&printer,2);
7072 return WERR_ACCESS_DENIED;
7075 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7076 "smb.conf parameter \"addprinter command\" is defined. This"
7077 "parameter must exist for this call to succeed\n",
7078 printer->info_2->sharename ));
7081 /* use our primary netbios name since get_a_printer() will convert
7082 it to what the client expects on a case by case basis */
7084 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7085 printer->info_2->sharename);
7088 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7089 free_a_printer(&printer,2);
7090 return WERR_ACCESS_DENIED;
7093 /* you must be a printer admin to add a new printer */
7094 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7095 free_a_printer(&printer,2);
7096 return WERR_ACCESS_DENIED;
7100 * Do sanity check on the requested changes for Samba.
7103 if (!check_printer_ok(printer->info_2, snum)) {
7104 free_a_printer(&printer,2);
7105 return WERR_INVALID_PARAM;
7109 * When a printer is created, the drivername bound to the printer is used
7110 * to lookup previously saved driver initialization info, which is then
7111 * bound to the new printer, simulating what happens in the Windows arch.
7116 /* A valid devmode was included, convert and link it
7118 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7120 err = copy_devicemode(printer, devmode,
7121 &printer->info_2->devmode);
7122 if (!W_ERROR_IS_OK(err)) {
7127 /* write the ASCII on disk */
7128 err = mod_a_printer(printer, 2);
7129 if (!W_ERROR_IS_OK(err)) {
7130 free_a_printer(&printer,2);
7134 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7135 /* Handle open failed - remove addition. */
7136 del_a_printer(printer->info_2->sharename);
7137 free_a_printer(&printer,2);
7138 ZERO_STRUCTP(handle);
7139 return WERR_ACCESS_DENIED;
7142 update_c_setprinter(false);
7143 free_a_printer(&printer,2);
7148 /****************************************************************
7149 _spoolss_AddPrinterEx
7150 ****************************************************************/
7152 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7153 struct spoolss_AddPrinterEx *r)
7155 switch (r->in.info_ctr->level) {
7157 /* we don't handle yet */
7158 /* but I know what to do ... */
7159 return WERR_UNKNOWN_LEVEL;
7161 return spoolss_addprinterex_level_2(p, r->in.server,
7163 r->in.devmode_ctr->devmode,
7164 r->in.secdesc_ctr->sd,
7165 r->in.userlevel_ctr,
7168 return WERR_UNKNOWN_LEVEL;
7172 /****************************************************************
7174 ****************************************************************/
7176 WERROR _spoolss_AddPrinter(pipes_struct *p,
7177 struct spoolss_AddPrinter *r)
7179 struct spoolss_AddPrinterEx a;
7180 struct spoolss_UserLevelCtr userlevel_ctr;
7182 ZERO_STRUCT(userlevel_ctr);
7184 userlevel_ctr.level = 1;
7186 a.in.server = r->in.server;
7187 a.in.info_ctr = r->in.info_ctr;
7188 a.in.devmode_ctr = r->in.devmode_ctr;
7189 a.in.secdesc_ctr = r->in.secdesc_ctr;
7190 a.in.userlevel_ctr = &userlevel_ctr;
7191 a.out.handle = r->out.handle;
7193 return _spoolss_AddPrinterEx(p, &a);
7196 /****************************************************************
7197 _spoolss_AddPrinterDriverEx
7198 ****************************************************************/
7200 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7201 struct spoolss_AddPrinterDriverEx *r)
7203 WERROR err = WERR_OK;
7204 char *driver_name = NULL;
7209 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7210 fn = "_spoolss_AddPrinterDriver";
7212 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7213 fn = "_spoolss_AddPrinterDriverEx";
7216 return WERR_INVALID_PARAM;
7220 * we only support the semantics of AddPrinterDriver()
7221 * i.e. only copy files that are newer than existing ones
7224 if (r->in.flags == 0) {
7225 return WERR_INVALID_PARAM;
7228 if (r->in.flags != APD_COPY_NEW_FILES) {
7229 return WERR_ACCESS_DENIED;
7233 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7234 /* Clever hack from Martin Zielinski <mz@seh.de>
7235 * to allow downgrade from level 8 (Vista).
7237 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7238 r->in.info_ctr->level));
7239 return WERR_UNKNOWN_LEVEL;
7242 DEBUG(5,("Cleaning driver's information\n"));
7243 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7244 if (!W_ERROR_IS_OK(err))
7247 DEBUG(5,("Moving driver to final destination\n"));
7248 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7253 if (add_a_printer_driver(p->mem_ctx, r->in.info_ctr, &driver_name, &version)!=0) {
7254 err = WERR_ACCESS_DENIED;
7259 * I think this is where he DrvUpgradePrinter() hook would be
7260 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7261 * server. Right now, we just need to send ourselves a message
7262 * to update each printer bound to this driver. --jerry
7265 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7266 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7274 /****************************************************************
7275 _spoolss_AddPrinterDriver
7276 ****************************************************************/
7278 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7279 struct spoolss_AddPrinterDriver *r)
7281 struct spoolss_AddPrinterDriverEx a;
7283 switch (r->in.info_ctr->level) {
7290 return WERR_UNKNOWN_LEVEL;
7293 a.in.servername = r->in.servername;
7294 a.in.info_ctr = r->in.info_ctr;
7295 a.in.flags = APD_COPY_NEW_FILES;
7297 return _spoolss_AddPrinterDriverEx(p, &a);
7300 /****************************************************************************
7301 ****************************************************************************/
7303 struct _spoolss_paths {
7309 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7311 static const struct _spoolss_paths spoolss_paths[]= {
7312 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7313 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7316 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7317 const char *servername,
7318 const char *environment,
7322 const char *pservername = NULL;
7323 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7324 const char *short_archi;
7328 /* environment may be empty */
7329 if (environment && strlen(environment)) {
7330 long_archi = environment;
7333 /* servername may be empty */
7334 if (servername && strlen(servername)) {
7335 pservername = canon_servername(servername);
7337 if (!is_myname_or_ipaddr(pservername)) {
7338 return WERR_INVALID_PARAM;
7342 if (!(short_archi = get_short_archi(long_archi))) {
7343 return WERR_INVALID_ENVIRONMENT;
7346 switch (component) {
7347 case SPOOLSS_PRTPROCS_PATH:
7348 case SPOOLSS_DRIVER_PATH:
7350 *path = talloc_asprintf(mem_ctx,
7353 spoolss_paths[component].share,
7356 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7357 SPOOLSS_DEFAULT_SERVER_PATH,
7358 spoolss_paths[component].dir,
7363 return WERR_INVALID_PARAM;
7373 /****************************************************************************
7374 ****************************************************************************/
7376 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7377 const char *servername,
7378 const char *environment,
7379 struct spoolss_DriverDirectoryInfo1 *r)
7384 werr = compose_spoolss_server_path(mem_ctx,
7387 SPOOLSS_DRIVER_PATH,
7389 if (!W_ERROR_IS_OK(werr)) {
7393 DEBUG(4,("printer driver directory: [%s]\n", path));
7395 r->directory_name = path;
7400 /****************************************************************
7401 _spoolss_GetPrinterDriverDirectory
7402 ****************************************************************/
7404 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7405 struct spoolss_GetPrinterDriverDirectory *r)
7409 /* that's an [in out] buffer */
7411 if (!r->in.buffer && (r->in.offered != 0)) {
7412 return WERR_INVALID_PARAM;
7415 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7420 /* r->in.level is ignored */
7422 werror = getprinterdriverdir_level_1(p->mem_ctx,
7425 &r->out.info->info1);
7426 if (!W_ERROR_IS_OK(werror)) {
7427 TALLOC_FREE(r->out.info);
7431 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7432 r->out.info, r->in.level);
7433 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7435 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7438 /****************************************************************
7439 _spoolss_EnumPrinterData
7440 ****************************************************************/
7442 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
7443 struct spoolss_EnumPrinterData *r)
7446 struct spoolss_EnumPrinterDataEx r2;
7448 struct spoolss_PrinterEnumValues *info, *val = NULL;
7451 r2.in.handle = r->in.handle;
7452 r2.in.key_name = "PrinterDriverData";
7454 r2.out.count = &count;
7455 r2.out.info = &info;
7456 r2.out.needed = &needed;
7458 result = _spoolss_EnumPrinterDataEx(p, &r2);
7459 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7460 r2.in.offered = needed;
7461 result = _spoolss_EnumPrinterDataEx(p, &r2);
7463 if (!W_ERROR_IS_OK(result)) {
7468 * The NT machine wants to know the biggest size of value and data
7470 * cf: MSDN EnumPrinterData remark section
7473 if (!r->in.value_offered && !r->in.data_offered) {
7474 uint32_t biggest_valuesize = 0;
7475 uint32_t biggest_datasize = 0;
7478 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7480 for (i=0; i<count; i++) {
7482 name_length = strlen(info[i].value_name);
7483 if (strlen(info[i].value_name) > biggest_valuesize) {
7484 biggest_valuesize = name_length;
7487 if (info[i].data_length > biggest_datasize) {
7488 biggest_datasize = info[i].data_length;
7491 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7495 /* the value is an UNICODE string but real_value_size is the length
7496 in bytes including the trailing 0 */
7498 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7499 *r->out.data_needed = biggest_datasize;
7501 DEBUG(6,("final values: [%d], [%d]\n",
7502 *r->out.value_needed, *r->out.data_needed));
7507 if (r->in.enum_index < count) {
7508 val = &info[r->in.enum_index];
7512 /* out_value should default to "" or else NT4 has
7513 problems unmarshalling the response */
7515 if (r->in.value_offered) {
7516 *r->out.value_needed = 1;
7517 r->out.value_name = talloc_strdup(r, "");
7518 if (!r->out.value_name) {
7522 r->out.value_name = NULL;
7523 *r->out.value_needed = 0;
7526 /* the data is counted in bytes */
7528 *r->out.data_needed = r->in.data_offered;
7530 result = WERR_NO_MORE_ITEMS;
7534 * - counted in bytes in the request
7535 * - counted in UNICODE chars in the max reply
7536 * - counted in bytes in the real size
7538 * take a pause *before* coding not *during* coding
7542 if (r->in.value_offered) {
7543 r->out.value_name = talloc_strdup(r, val->value_name);
7544 if (!r->out.value_name) {
7547 *r->out.value_needed = val->value_name_len;
7549 r->out.value_name = NULL;
7550 *r->out.value_needed = 0;
7555 *r->out.type = val->type;
7557 /* data - counted in bytes */
7560 * See the section "Dynamically Typed Query Parameters"
7564 if (r->out.data && val->data && val->data->data &&
7565 val->data_length && r->in.data_offered) {
7566 memcpy(r->out.data, val->data->data,
7567 MIN(val->data_length,r->in.data_offered));
7570 *r->out.data_needed = val->data_length;
7578 /****************************************************************
7579 _spoolss_SetPrinterData
7580 ****************************************************************/
7582 WERROR _spoolss_SetPrinterData(pipes_struct *p,
7583 struct spoolss_SetPrinterData *r)
7585 struct spoolss_SetPrinterDataEx r2;
7587 r2.in.handle = r->in.handle;
7588 r2.in.key_name = "PrinterDriverData";
7589 r2.in.value_name = r->in.value_name;
7590 r2.in.type = r->in.type;
7591 r2.in.data = r->in.data;
7592 r2.in.offered = r->in.offered;
7594 return _spoolss_SetPrinterDataEx(p, &r2);
7597 /****************************************************************
7598 _spoolss_ResetPrinter
7599 ****************************************************************/
7601 WERROR _spoolss_ResetPrinter(pipes_struct *p,
7602 struct spoolss_ResetPrinter *r)
7604 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7607 DEBUG(5,("_spoolss_ResetPrinter\n"));
7610 * All we do is to check to see if the handle and queue is valid.
7611 * This call really doesn't mean anything to us because we only
7612 * support RAW printing. --jerry
7616 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7617 OUR_HANDLE(r->in.handle)));
7621 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7625 /* blindly return success */
7629 /****************************************************************
7630 _spoolss_DeletePrinterData
7631 ****************************************************************/
7633 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
7634 struct spoolss_DeletePrinterData *r)
7636 struct spoolss_DeletePrinterDataEx r2;
7638 r2.in.handle = r->in.handle;
7639 r2.in.key_name = "PrinterDriverData";
7640 r2.in.value_name = r->in.value_name;
7642 return _spoolss_DeletePrinterDataEx(p, &r2);
7645 /****************************************************************
7647 ****************************************************************/
7649 WERROR _spoolss_AddForm(pipes_struct *p,
7650 struct spoolss_AddForm *r)
7652 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7653 nt_forms_struct tmpForm;
7655 WERROR status = WERR_OK;
7656 NT_PRINTER_INFO_LEVEL *printer = NULL;
7657 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7660 nt_forms_struct *list=NULL;
7661 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7664 DEBUG(5,("_spoolss_AddForm\n"));
7667 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7668 OUR_HANDLE(r->in.handle)));
7673 /* forms can be added on printer or on the print server handle */
7675 if ( Printer->printer_type == SPLHND_PRINTER )
7677 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7680 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7681 if (!W_ERROR_IS_OK(status))
7685 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7686 and not a printer admin, then fail */
7688 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7689 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7690 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7691 p->server_info->info3->base.domain.string,
7693 p->server_info->ptok,
7694 lp_printer_admin(snum))) {
7695 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7696 status = WERR_ACCESS_DENIED;
7700 switch (form->flags) {
7701 case SPOOLSS_FORM_USER:
7702 case SPOOLSS_FORM_BUILTIN:
7703 case SPOOLSS_FORM_PRINTER:
7706 status = WERR_INVALID_PARAM;
7710 /* can't add if builtin */
7712 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7713 status = WERR_FILE_EXISTS;
7717 count = get_ntforms(&list);
7719 for (i=0; i < count; i++) {
7720 if (strequal(form->form_name, list[i].name)) {
7721 status = WERR_FILE_EXISTS;
7726 if(!add_a_form(&list, form, &count)) {
7727 status = WERR_NOMEM;
7732 write_ntforms(&list, count);
7736 * ChangeID must always be set if this is a printer
7739 if ( Printer->printer_type == SPLHND_PRINTER )
7740 status = mod_a_printer(printer, 2);
7744 free_a_printer(&printer, 2);
7750 /****************************************************************
7752 ****************************************************************/
7754 WERROR _spoolss_DeleteForm(pipes_struct *p,
7755 struct spoolss_DeleteForm *r)
7757 const char *form_name = r->in.form_name;
7758 nt_forms_struct tmpForm;
7760 nt_forms_struct *list=NULL;
7761 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7763 WERROR status = WERR_OK;
7764 NT_PRINTER_INFO_LEVEL *printer = NULL;
7765 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7768 DEBUG(5,("_spoolss_DeleteForm\n"));
7771 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7772 OUR_HANDLE(r->in.handle)));
7776 /* forms can be deleted on printer of on the print server handle */
7778 if ( Printer->printer_type == SPLHND_PRINTER )
7780 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7783 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7784 if (!W_ERROR_IS_OK(status))
7788 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7789 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7790 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7791 p->server_info->info3->base.domain.string,
7793 p->server_info->ptok,
7794 lp_printer_admin(snum))) {
7795 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7796 return WERR_ACCESS_DENIED;
7800 /* can't delete if builtin */
7802 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
7803 status = WERR_INVALID_PARAM;
7807 count = get_ntforms(&list);
7810 ret = delete_a_form(&list, form_name, &count, &status);
7817 * ChangeID must always be set if this is a printer
7820 if ( Printer->printer_type == SPLHND_PRINTER )
7821 status = mod_a_printer(printer, 2);
7825 free_a_printer(&printer, 2);
7831 /****************************************************************
7833 ****************************************************************/
7835 WERROR _spoolss_SetForm(pipes_struct *p,
7836 struct spoolss_SetForm *r)
7838 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7839 nt_forms_struct tmpForm;
7841 WERROR status = WERR_OK;
7842 NT_PRINTER_INFO_LEVEL *printer = NULL;
7843 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7846 nt_forms_struct *list=NULL;
7847 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7849 DEBUG(5,("_spoolss_SetForm\n"));
7852 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7853 OUR_HANDLE(r->in.handle)));
7857 /* forms can be modified on printer of on the print server handle */
7859 if ( Printer->printer_type == SPLHND_PRINTER )
7861 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7864 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7865 if (!W_ERROR_IS_OK(status))
7869 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7870 and not a printer admin, then fail */
7872 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7873 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7874 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7875 p->server_info->info3->base.domain.string,
7877 p->server_info->ptok,
7878 lp_printer_admin(snum))) {
7879 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7880 status = WERR_ACCESS_DENIED;
7884 /* can't set if builtin */
7885 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
7886 status = WERR_INVALID_PARAM;
7890 count = get_ntforms(&list);
7891 update_a_form(&list, form, count);
7893 write_ntforms(&list, count);
7897 * ChangeID must always be set if this is a printer
7900 if ( Printer->printer_type == SPLHND_PRINTER )
7901 status = mod_a_printer(printer, 2);
7906 free_a_printer(&printer, 2);
7912 /****************************************************************************
7913 fill_print_processor1
7914 ****************************************************************************/
7916 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7917 struct spoolss_PrintProcessorInfo1 *r,
7918 const char *print_processor_name)
7920 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7921 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7926 /****************************************************************************
7927 enumprintprocessors level 1.
7928 ****************************************************************************/
7930 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7931 union spoolss_PrintProcessorInfo **info_p,
7934 union spoolss_PrintProcessorInfo *info;
7937 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7938 W_ERROR_HAVE_NO_MEMORY(info);
7942 result = fill_print_processor1(info, &info[0].info1, "winprint");
7943 if (!W_ERROR_IS_OK(result)) {
7948 if (!W_ERROR_IS_OK(result)) {
7959 /****************************************************************
7960 _spoolss_EnumPrintProcessors
7961 ****************************************************************/
7963 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7964 struct spoolss_EnumPrintProcessors *r)
7968 /* that's an [in out] buffer */
7970 if (!r->in.buffer && (r->in.offered != 0)) {
7971 return WERR_INVALID_PARAM;
7974 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7977 * Enumerate the print processors ...
7979 * Just reply with "winprint", to keep NT happy
7980 * and I can use my nice printer checker.
7985 *r->out.info = NULL;
7987 switch (r->in.level) {
7989 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7993 return WERR_UNKNOWN_LEVEL;
7996 if (!W_ERROR_IS_OK(result)) {
8000 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8001 spoolss_EnumPrintProcessors,
8002 *r->out.info, r->in.level,
8004 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8005 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8007 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8010 /****************************************************************************
8011 fill_printprocdatatype1
8012 ****************************************************************************/
8014 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8015 struct spoolss_PrintProcDataTypesInfo1 *r,
8016 const char *name_array)
8018 r->name_array = talloc_strdup(mem_ctx, name_array);
8019 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8024 /****************************************************************************
8025 enumprintprocdatatypes level 1.
8026 ****************************************************************************/
8028 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8029 union spoolss_PrintProcDataTypesInfo **info_p,
8033 union spoolss_PrintProcDataTypesInfo *info;
8035 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8036 W_ERROR_HAVE_NO_MEMORY(info);
8040 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8041 if (!W_ERROR_IS_OK(result)) {
8046 if (!W_ERROR_IS_OK(result)) {
8057 /****************************************************************
8058 _spoolss_EnumPrintProcDataTypes
8059 ****************************************************************/
8061 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8062 struct spoolss_EnumPrintProcDataTypes *r)
8066 /* that's an [in out] buffer */
8068 if (!r->in.buffer && (r->in.offered != 0)) {
8069 return WERR_INVALID_PARAM;
8072 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8076 *r->out.info = NULL;
8078 switch (r->in.level) {
8080 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8084 return WERR_UNKNOWN_LEVEL;
8087 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8088 spoolss_EnumPrintProcDataTypes,
8089 *r->out.info, r->in.level,
8091 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8092 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8094 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8097 /****************************************************************************
8099 ****************************************************************************/
8101 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8102 struct spoolss_MonitorInfo1 *r,
8103 const char *monitor_name)
8105 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8106 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8111 /****************************************************************************
8113 ****************************************************************************/
8115 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8116 struct spoolss_MonitorInfo2 *r,
8117 const char *monitor_name,
8118 const char *environment,
8119 const char *dll_name)
8121 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8122 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8123 r->environment = talloc_strdup(mem_ctx, environment);
8124 W_ERROR_HAVE_NO_MEMORY(r->environment);
8125 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8126 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8131 /****************************************************************************
8132 enumprintmonitors level 1.
8133 ****************************************************************************/
8135 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8136 union spoolss_MonitorInfo **info_p,
8139 union spoolss_MonitorInfo *info;
8140 WERROR result = WERR_OK;
8142 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8143 W_ERROR_HAVE_NO_MEMORY(info);
8147 result = fill_monitor_1(info, &info[0].info1,
8149 if (!W_ERROR_IS_OK(result)) {
8153 result = fill_monitor_1(info, &info[1].info1,
8155 if (!W_ERROR_IS_OK(result)) {
8160 if (!W_ERROR_IS_OK(result)) {
8171 /****************************************************************************
8172 enumprintmonitors level 2.
8173 ****************************************************************************/
8175 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8176 union spoolss_MonitorInfo **info_p,
8179 union spoolss_MonitorInfo *info;
8180 WERROR result = WERR_OK;
8182 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8183 W_ERROR_HAVE_NO_MEMORY(info);
8187 result = fill_monitor_2(info, &info[0].info2,
8189 "Windows NT X86", /* FIXME */
8191 if (!W_ERROR_IS_OK(result)) {
8195 result = fill_monitor_2(info, &info[1].info2,
8197 "Windows NT X86", /* FIXME */
8199 if (!W_ERROR_IS_OK(result)) {
8204 if (!W_ERROR_IS_OK(result)) {
8215 /****************************************************************
8216 _spoolss_EnumMonitors
8217 ****************************************************************/
8219 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8220 struct spoolss_EnumMonitors *r)
8224 /* that's an [in out] buffer */
8226 if (!r->in.buffer && (r->in.offered != 0)) {
8227 return WERR_INVALID_PARAM;
8230 DEBUG(5,("_spoolss_EnumMonitors\n"));
8233 * Enumerate the print monitors ...
8235 * Just reply with "Local Port", to keep NT happy
8236 * and I can use my nice printer checker.
8241 *r->out.info = NULL;
8243 switch (r->in.level) {
8245 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8249 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8253 return WERR_UNKNOWN_LEVEL;
8256 if (!W_ERROR_IS_OK(result)) {
8260 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8261 spoolss_EnumMonitors,
8262 *r->out.info, r->in.level,
8264 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8265 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8267 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8270 /****************************************************************************
8271 ****************************************************************************/
8273 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8274 const print_queue_struct *queue,
8275 int count, int snum,
8276 const NT_PRINTER_INFO_LEVEL *ntprinter,
8278 struct spoolss_JobInfo1 *r)
8283 for (i=0; i<count; i++) {
8284 if (queue[i].job == (int)jobid) {
8290 if (found == false) {
8291 /* NT treats not found as bad param... yet another bad choice */
8292 return WERR_INVALID_PARAM;
8295 return fill_job_info1(mem_ctx,
8303 /****************************************************************************
8304 ****************************************************************************/
8306 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8307 const print_queue_struct *queue,
8308 int count, int snum,
8309 const NT_PRINTER_INFO_LEVEL *ntprinter,
8311 struct spoolss_JobInfo2 *r)
8315 struct spoolss_DeviceMode *devmode;
8317 for (i=0; i<count; i++) {
8318 if (queue[i].job == (int)jobid) {
8324 if (found == false) {
8325 /* NT treats not found as bad param... yet another bad
8327 return WERR_INVALID_PARAM;
8331 * if the print job does not have a DEVMODE associated with it,
8332 * just use the one for the printer. A NULL devicemode is not
8333 * a failure condition
8336 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8338 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8339 W_ERROR_HAVE_NO_MEMORY(devmode);
8342 return fill_job_info2(mem_ctx,
8351 /****************************************************************
8353 ****************************************************************/
8355 WERROR _spoolss_GetJob(pipes_struct *p,
8356 struct spoolss_GetJob *r)
8358 WERROR result = WERR_OK;
8359 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8362 print_queue_struct *queue = NULL;
8363 print_status_struct prt_status;
8365 /* that's an [in out] buffer */
8367 if (!r->in.buffer && (r->in.offered != 0)) {
8368 return WERR_INVALID_PARAM;
8371 DEBUG(5,("_spoolss_GetJob\n"));
8375 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8379 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8380 if (!W_ERROR_IS_OK(result)) {
8384 count = print_queue_status(snum, &queue, &prt_status);
8386 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8387 count, prt_status.status, prt_status.message));
8389 switch (r->in.level) {
8391 result = getjob_level_1(p->mem_ctx,
8392 queue, count, snum, ntprinter,
8393 r->in.job_id, &r->out.info->info1);
8396 result = getjob_level_2(p->mem_ctx,
8397 queue, count, snum, ntprinter,
8398 r->in.job_id, &r->out.info->info2);
8401 result = WERR_UNKNOWN_LEVEL;
8406 free_a_printer(&ntprinter, 2);
8408 if (!W_ERROR_IS_OK(result)) {
8409 TALLOC_FREE(r->out.info);
8413 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8415 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8417 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8420 /****************************************************************
8421 _spoolss_GetPrinterDataEx
8422 ****************************************************************/
8424 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8425 struct spoolss_GetPrinterDataEx *r)
8428 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8429 const char *printer;
8431 WERROR result = WERR_OK;
8433 enum winreg_Type val_type;
8438 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8440 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8441 r->in.key_name, r->in.value_name));
8443 /* in case of problem, return some default values */
8446 *r->out.type = REG_NONE;
8449 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8450 OUR_HANDLE(r->in.handle)));
8451 result = WERR_BADFID;
8455 /* Is the handle to a printer or to the server? */
8457 if (Printer->printer_type == SPLHND_SERVER) {
8459 union spoolss_PrinterData data;
8461 result = getprinterdata_printer_server(p->mem_ctx,
8465 if (!W_ERROR_IS_OK(result)) {
8469 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8470 *r->out.type, &data);
8471 if (!W_ERROR_IS_OK(result)) {
8475 *r->out.needed = blob.length;
8477 if (r->in.offered >= *r->out.needed) {
8478 memcpy(r->out.data, blob.data, blob.length);
8481 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8484 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8487 printer = lp_const_servicename(snum);
8489 /* check to see if the keyname is valid */
8490 if (!strlen(r->in.key_name)) {
8491 return WERR_INVALID_PARAM;
8494 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8495 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8496 strequal(r->in.value_name, "ChangeId")) {
8497 *r->out.type = REG_DWORD;
8499 if (r->in.offered >= *r->out.needed) {
8500 uint32_t changeid = 0;
8502 result = winreg_printer_get_changeid(p->mem_ctx,
8506 if (!W_ERROR_IS_OK(result)) {
8510 SIVAL(r->out.data, 0, changeid);
8516 result = winreg_get_printer_dataex(p->mem_ctx,
8524 if (!W_ERROR_IS_OK(result)) {
8528 *r->out.needed = val_size;
8529 *r->out.type = val_type;
8531 if (r->in.offered >= *r->out.needed) {
8532 memcpy(r->out.data, val_data, val_size);
8536 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8537 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8539 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8542 /****************************************************************
8543 _spoolss_SetPrinterDataEx
8544 ****************************************************************/
8546 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8547 struct spoolss_SetPrinterDataEx *r)
8549 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8551 WERROR result = WERR_OK;
8552 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8555 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8557 /* From MSDN documentation of SetPrinterDataEx: pass request to
8558 SetPrinterData if key is "PrinterDriverData" */
8561 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8562 OUR_HANDLE(r->in.handle)));
8566 if (Printer->printer_type == SPLHND_SERVER) {
8567 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8568 "Not implemented for server handles yet\n"));
8569 return WERR_INVALID_PARAM;
8572 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8577 * Access check : NT returns "access denied" if you make a
8578 * SetPrinterData call without the necessary privildge.
8579 * we were originally returning OK if nothing changed
8580 * which made Win2k issue **a lot** of SetPrinterData
8581 * when connecting to a printer --jerry
8584 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8585 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8586 "change denied by handle access permissions\n"));
8587 return WERR_ACCESS_DENIED;
8590 result = winreg_get_printer(Printer, p->server_info,
8591 Printer->servername,
8592 lp_servicename(snum),
8594 if (!W_ERROR_IS_OK(result)) {
8598 /* check for OID in valuename */
8600 oid_string = strchr(r->in.value_name, ',');
8606 /* save the registry data */
8608 result = winreg_set_printer_dataex(p->mem_ctx,
8617 if (W_ERROR_IS_OK(result)) {
8618 /* save the OID if one was specified */
8620 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8621 r->in.key_name, SPOOL_OID_KEY);
8623 result = WERR_NOMEM;
8628 * I'm not checking the status here on purpose. Don't know
8629 * if this is right, but I'm returning the status from the
8630 * previous set_printer_dataex() call. I have no idea if
8631 * this is right. --jerry
8633 winreg_set_printer_dataex(p->mem_ctx,
8639 (uint8_t *) oid_string,
8640 strlen(oid_string) + 1);
8643 result = winreg_printer_update_changeid(p->mem_ctx,
8645 lp_const_servicename(snum));
8650 talloc_free(pinfo2);
8654 /****************************************************************
8655 _spoolss_DeletePrinterDataEx
8656 ****************************************************************/
8658 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8659 struct spoolss_DeletePrinterDataEx *r)
8661 const char *printer;
8663 WERROR status = WERR_OK;
8664 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8666 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8669 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8670 "Invalid handle (%s:%u:%u).\n",
8671 OUR_HANDLE(r->in.handle)));
8675 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8676 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8677 "printer properties change denied by handle\n"));
8678 return WERR_ACCESS_DENIED;
8681 if (!r->in.value_name || !r->in.key_name) {
8685 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8688 printer = lp_const_servicename(snum);
8690 status = winreg_delete_printer_dataex(p->mem_ctx,
8695 if (W_ERROR_IS_OK(status)) {
8696 status = winreg_printer_update_changeid(p->mem_ctx,
8704 /****************************************************************
8705 _spoolss_EnumPrinterKey
8706 ****************************************************************/
8708 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8709 struct spoolss_EnumPrinterKey *r)
8712 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8714 WERROR result = WERR_BADFILE;
8715 const char **array = NULL;
8718 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8721 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8722 OUR_HANDLE(r->in.handle)));
8726 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8730 result = winreg_enum_printer_key(p->mem_ctx,
8732 lp_const_servicename(snum),
8736 if (!W_ERROR_IS_OK(result)) {
8740 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8741 result = WERR_NOMEM;
8745 *r->out._ndr_size = r->in.offered / 2;
8746 *r->out.needed = blob.length;
8748 if (r->in.offered < *r->out.needed) {
8749 result = WERR_MORE_DATA;
8752 r->out.key_buffer->string_array = array;
8756 if (!W_ERROR_IS_OK(result)) {
8758 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8766 /****************************************************************
8767 _spoolss_DeletePrinterKey
8768 ****************************************************************/
8770 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8771 struct spoolss_DeletePrinterKey *r)
8773 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8776 const char *printer;
8778 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8781 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8782 OUR_HANDLE(r->in.handle)));
8786 /* if keyname == NULL, return error */
8787 if ( !r->in.key_name )
8788 return WERR_INVALID_PARAM;
8790 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8794 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8795 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8796 "printer properties change denied by handle\n"));
8797 return WERR_ACCESS_DENIED;
8800 printer = lp_const_servicename(snum);
8802 /* delete the key and all subkeys */
8803 status = winreg_delete_printer_key(p->mem_ctx,
8807 if (W_ERROR_IS_OK(status)) {
8808 status = winreg_printer_update_changeid(p->mem_ctx,
8816 /****************************************************************
8817 _spoolss_EnumPrinterDataEx
8818 ****************************************************************/
8820 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8821 struct spoolss_EnumPrinterDataEx *r)
8824 struct spoolss_PrinterEnumValues *info = NULL;
8825 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8829 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8833 *r->out.info = NULL;
8836 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8837 OUR_HANDLE(r->in.handle)));
8842 * first check for a keyname of NULL or "". Win2k seems to send
8843 * this a lot and we should send back WERR_INVALID_PARAM
8844 * no need to spend time looking up the printer in this case.
8848 if (!strlen(r->in.key_name)) {
8849 result = WERR_INVALID_PARAM;
8853 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8857 /* now look for a match on the key name */
8858 result = winreg_enum_printer_dataex(p->mem_ctx,
8860 lp_const_servicename(snum),
8864 if (!W_ERROR_IS_OK(result)) {
8868 #if 0 /* FIXME - gd */
8869 /* housekeeping information in the reply */
8871 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8872 * the hand marshalled container size is a multiple
8873 * of 4 bytes for RPC alignment.
8877 needed += 4-(needed % 4);
8880 *r->out.count = count;
8881 *r->out.info = info;
8884 if (!W_ERROR_IS_OK(result)) {
8888 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8889 spoolss_EnumPrinterDataEx,
8892 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8893 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8895 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8898 /****************************************************************************
8899 ****************************************************************************/
8901 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8902 const char *servername,
8903 const char *environment,
8904 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8909 werr = compose_spoolss_server_path(mem_ctx,
8912 SPOOLSS_PRTPROCS_PATH,
8914 if (!W_ERROR_IS_OK(werr)) {
8918 DEBUG(4,("print processor directory: [%s]\n", path));
8920 r->directory_name = path;
8925 /****************************************************************
8926 _spoolss_GetPrintProcessorDirectory
8927 ****************************************************************/
8929 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8930 struct spoolss_GetPrintProcessorDirectory *r)
8934 /* that's an [in out] buffer */
8936 if (!r->in.buffer && (r->in.offered != 0)) {
8937 return WERR_INVALID_PARAM;
8940 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8945 /* r->in.level is ignored */
8947 /* We always should reply with a local print processor directory so that
8948 * users are not forced to have a [prnproc$] share on the Samba spoolss
8949 * server - Guenther */
8951 result = getprintprocessordirectory_level_1(p->mem_ctx,
8952 NULL, /* r->in.server */
8954 &r->out.info->info1);
8955 if (!W_ERROR_IS_OK(result)) {
8956 TALLOC_FREE(r->out.info);
8960 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8961 r->out.info, r->in.level);
8962 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8964 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8967 /*******************************************************************
8968 ********************************************************************/
8970 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8971 const char *dllname)
8973 enum ndr_err_code ndr_err;
8974 struct spoolss_MonitorUi ui;
8976 ui.dll_name = dllname;
8978 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8979 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8980 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8981 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8983 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8986 /*******************************************************************
8987 Streams the monitor UI DLL name in UNICODE
8988 *******************************************************************/
8990 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8991 NT_USER_TOKEN *token, DATA_BLOB *in,
8992 DATA_BLOB *out, uint32_t *needed)
8994 const char *dllname = "tcpmonui.dll";
8996 *needed = (strlen(dllname)+1) * 2;
8998 if (out->length < *needed) {
8999 return WERR_INSUFFICIENT_BUFFER;
9002 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9009 /*******************************************************************
9010 ********************************************************************/
9012 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9013 struct spoolss_PortData1 *port1,
9014 const DATA_BLOB *buf)
9016 enum ndr_err_code ndr_err;
9017 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9018 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9019 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9020 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9022 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9025 /*******************************************************************
9026 ********************************************************************/
9028 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9029 struct spoolss_PortData2 *port2,
9030 const DATA_BLOB *buf)
9032 enum ndr_err_code ndr_err;
9033 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9034 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9035 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9036 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9038 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9041 /*******************************************************************
9042 Create a new TCP/IP port
9043 *******************************************************************/
9045 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9046 NT_USER_TOKEN *token, DATA_BLOB *in,
9047 DATA_BLOB *out, uint32_t *needed)
9049 struct spoolss_PortData1 port1;
9050 struct spoolss_PortData2 port2;
9051 char *device_uri = NULL;
9054 const char *portname;
9055 const char *hostaddress;
9057 uint32_t port_number;
9060 /* peek for spoolss_PortData version */
9062 if (!in || (in->length < (128 + 4))) {
9063 return WERR_GENERAL_FAILURE;
9066 version = IVAL(in->data, 128);
9072 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9076 portname = port1.portname;
9077 hostaddress = port1.hostaddress;
9078 queue = port1.queue;
9079 protocol = port1.protocol;
9080 port_number = port1.port_number;
9086 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9090 portname = port2.portname;
9091 hostaddress = port2.hostaddress;
9092 queue = port2.queue;
9093 protocol = port2.protocol;
9094 port_number = port2.port_number;
9098 DEBUG(1,("xcvtcp_addport: "
9099 "unknown version of port_data: %d\n", version));
9100 return WERR_UNKNOWN_PORT;
9103 /* create the device URI and call the add_port_hook() */
9106 case PROTOCOL_RAWTCP_TYPE:
9107 device_uri = talloc_asprintf(mem_ctx,
9108 "socket://%s:%d/", hostaddress,
9112 case PROTOCOL_LPR_TYPE:
9113 device_uri = talloc_asprintf(mem_ctx,
9114 "lpr://%s/%s", hostaddress, queue );
9118 return WERR_UNKNOWN_PORT;
9125 return add_port_hook(mem_ctx, token, portname, device_uri);
9128 /*******************************************************************
9129 *******************************************************************/
9131 struct xcv_api_table xcvtcp_cmds[] = {
9132 { "MonitorUI", xcvtcp_monitorui },
9133 { "AddPort", xcvtcp_addport},
9137 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9138 NT_USER_TOKEN *token, const char *command,
9145 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9147 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9148 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9149 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9152 return WERR_BADFUNC;
9155 /*******************************************************************
9156 *******************************************************************/
9157 #if 0 /* don't support management using the "Local Port" monitor */
9159 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9160 NT_USER_TOKEN *token, DATA_BLOB *in,
9161 DATA_BLOB *out, uint32_t *needed)
9163 const char *dllname = "localui.dll";
9165 *needed = (strlen(dllname)+1) * 2;
9167 if (out->length < *needed) {
9168 return WERR_INSUFFICIENT_BUFFER;
9171 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9178 /*******************************************************************
9179 *******************************************************************/
9181 struct xcv_api_table xcvlocal_cmds[] = {
9182 { "MonitorUI", xcvlocal_monitorui },
9186 struct xcv_api_table xcvlocal_cmds[] = {
9193 /*******************************************************************
9194 *******************************************************************/
9196 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9197 NT_USER_TOKEN *token, const char *command,
9198 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9203 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9205 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9206 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9207 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9209 return WERR_BADFUNC;
9212 /****************************************************************
9214 ****************************************************************/
9216 WERROR _spoolss_XcvData(pipes_struct *p,
9217 struct spoolss_XcvData *r)
9219 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9220 DATA_BLOB out_data = data_blob_null;
9224 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9225 OUR_HANDLE(r->in.handle)));
9229 /* Has to be a handle to the TCP/IP port monitor */
9231 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9232 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9236 /* requires administrative access to the server */
9238 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9239 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9240 return WERR_ACCESS_DENIED;
9243 /* Allocate the outgoing buffer */
9245 if (r->in.out_data_size) {
9246 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9247 if (out_data.data == NULL) {
9252 switch ( Printer->printer_type ) {
9253 case SPLHND_PORTMON_TCP:
9254 werror = process_xcvtcp_command(p->mem_ctx,
9255 p->server_info->ptok,
9256 r->in.function_name,
9257 &r->in.in_data, &out_data,
9260 case SPLHND_PORTMON_LOCAL:
9261 werror = process_xcvlocal_command(p->mem_ctx,
9262 p->server_info->ptok,
9263 r->in.function_name,
9264 &r->in.in_data, &out_data,
9268 werror = WERR_INVALID_PRINT_MONITOR;
9271 if (!W_ERROR_IS_OK(werror)) {
9275 *r->out.status_code = 0;
9277 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9278 memcpy(r->out.out_data, out_data.data,
9279 MIN(r->in.out_data_size, out_data.length));
9285 /****************************************************************
9286 _spoolss_AddPrintProcessor
9287 ****************************************************************/
9289 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9290 struct spoolss_AddPrintProcessor *r)
9292 /* for now, just indicate success and ignore the add. We'll
9293 automatically set the winprint processor for printer
9294 entries later. Used to debug the LexMark Optra S 1855 PCL
9300 /****************************************************************
9302 ****************************************************************/
9304 WERROR _spoolss_AddPort(pipes_struct *p,
9305 struct spoolss_AddPort *r)
9307 /* do what w2k3 does */
9309 return WERR_NOT_SUPPORTED;
9312 /****************************************************************
9313 _spoolss_GetPrinterDriver
9314 ****************************************************************/
9316 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9317 struct spoolss_GetPrinterDriver *r)
9319 p->rng_fault_state = true;
9320 return WERR_NOT_SUPPORTED;
9323 /****************************************************************
9324 _spoolss_ReadPrinter
9325 ****************************************************************/
9327 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9328 struct spoolss_ReadPrinter *r)
9330 p->rng_fault_state = true;
9331 return WERR_NOT_SUPPORTED;
9334 /****************************************************************
9335 _spoolss_WaitForPrinterChange
9336 ****************************************************************/
9338 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9339 struct spoolss_WaitForPrinterChange *r)
9341 p->rng_fault_state = true;
9342 return WERR_NOT_SUPPORTED;
9345 /****************************************************************
9346 _spoolss_ConfigurePort
9347 ****************************************************************/
9349 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9350 struct spoolss_ConfigurePort *r)
9352 p->rng_fault_state = true;
9353 return WERR_NOT_SUPPORTED;
9356 /****************************************************************
9358 ****************************************************************/
9360 WERROR _spoolss_DeletePort(pipes_struct *p,
9361 struct spoolss_DeletePort *r)
9363 p->rng_fault_state = true;
9364 return WERR_NOT_SUPPORTED;
9367 /****************************************************************
9368 _spoolss_CreatePrinterIC
9369 ****************************************************************/
9371 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9372 struct spoolss_CreatePrinterIC *r)
9374 p->rng_fault_state = true;
9375 return WERR_NOT_SUPPORTED;
9378 /****************************************************************
9379 _spoolss_PlayGDIScriptOnPrinterIC
9380 ****************************************************************/
9382 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9383 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9385 p->rng_fault_state = true;
9386 return WERR_NOT_SUPPORTED;
9389 /****************************************************************
9390 _spoolss_DeletePrinterIC
9391 ****************************************************************/
9393 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9394 struct spoolss_DeletePrinterIC *r)
9396 p->rng_fault_state = true;
9397 return WERR_NOT_SUPPORTED;
9400 /****************************************************************
9401 _spoolss_AddPrinterConnection
9402 ****************************************************************/
9404 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9405 struct spoolss_AddPrinterConnection *r)
9407 p->rng_fault_state = true;
9408 return WERR_NOT_SUPPORTED;
9411 /****************************************************************
9412 _spoolss_DeletePrinterConnection
9413 ****************************************************************/
9415 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9416 struct spoolss_DeletePrinterConnection *r)
9418 p->rng_fault_state = true;
9419 return WERR_NOT_SUPPORTED;
9422 /****************************************************************
9423 _spoolss_PrinterMessageBox
9424 ****************************************************************/
9426 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9427 struct spoolss_PrinterMessageBox *r)
9429 p->rng_fault_state = true;
9430 return WERR_NOT_SUPPORTED;
9433 /****************************************************************
9435 ****************************************************************/
9437 WERROR _spoolss_AddMonitor(pipes_struct *p,
9438 struct spoolss_AddMonitor *r)
9440 p->rng_fault_state = true;
9441 return WERR_NOT_SUPPORTED;
9444 /****************************************************************
9445 _spoolss_DeleteMonitor
9446 ****************************************************************/
9448 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9449 struct spoolss_DeleteMonitor *r)
9451 p->rng_fault_state = true;
9452 return WERR_NOT_SUPPORTED;
9455 /****************************************************************
9456 _spoolss_DeletePrintProcessor
9457 ****************************************************************/
9459 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9460 struct spoolss_DeletePrintProcessor *r)
9462 p->rng_fault_state = true;
9463 return WERR_NOT_SUPPORTED;
9466 /****************************************************************
9467 _spoolss_AddPrintProvidor
9468 ****************************************************************/
9470 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9471 struct spoolss_AddPrintProvidor *r)
9473 p->rng_fault_state = true;
9474 return WERR_NOT_SUPPORTED;
9477 /****************************************************************
9478 _spoolss_DeletePrintProvidor
9479 ****************************************************************/
9481 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9482 struct spoolss_DeletePrintProvidor *r)
9484 p->rng_fault_state = true;
9485 return WERR_NOT_SUPPORTED;
9488 /****************************************************************
9489 _spoolss_FindFirstPrinterChangeNotification
9490 ****************************************************************/
9492 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9493 struct spoolss_FindFirstPrinterChangeNotification *r)
9495 p->rng_fault_state = true;
9496 return WERR_NOT_SUPPORTED;
9499 /****************************************************************
9500 _spoolss_FindNextPrinterChangeNotification
9501 ****************************************************************/
9503 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9504 struct spoolss_FindNextPrinterChangeNotification *r)
9506 p->rng_fault_state = true;
9507 return WERR_NOT_SUPPORTED;
9510 /****************************************************************
9511 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9512 ****************************************************************/
9514 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9515 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9517 p->rng_fault_state = true;
9518 return WERR_NOT_SUPPORTED;
9521 /****************************************************************
9522 _spoolss_ReplyOpenPrinter
9523 ****************************************************************/
9525 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9526 struct spoolss_ReplyOpenPrinter *r)
9528 p->rng_fault_state = true;
9529 return WERR_NOT_SUPPORTED;
9532 /****************************************************************
9533 _spoolss_RouterReplyPrinter
9534 ****************************************************************/
9536 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9537 struct spoolss_RouterReplyPrinter *r)
9539 p->rng_fault_state = true;
9540 return WERR_NOT_SUPPORTED;
9543 /****************************************************************
9544 _spoolss_ReplyClosePrinter
9545 ****************************************************************/
9547 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9548 struct spoolss_ReplyClosePrinter *r)
9550 p->rng_fault_state = true;
9551 return WERR_NOT_SUPPORTED;
9554 /****************************************************************
9556 ****************************************************************/
9558 WERROR _spoolss_AddPortEx(pipes_struct *p,
9559 struct spoolss_AddPortEx *r)
9561 p->rng_fault_state = true;
9562 return WERR_NOT_SUPPORTED;
9565 /****************************************************************
9566 _spoolss_RouterFindFirstPrinterChangeNotification
9567 ****************************************************************/
9569 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9570 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9572 p->rng_fault_state = true;
9573 return WERR_NOT_SUPPORTED;
9576 /****************************************************************
9577 _spoolss_SpoolerInit
9578 ****************************************************************/
9580 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9581 struct spoolss_SpoolerInit *r)
9583 p->rng_fault_state = true;
9584 return WERR_NOT_SUPPORTED;
9587 /****************************************************************
9588 _spoolss_ResetPrinterEx
9589 ****************************************************************/
9591 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9592 struct spoolss_ResetPrinterEx *r)
9594 p->rng_fault_state = true;
9595 return WERR_NOT_SUPPORTED;
9598 /****************************************************************
9599 _spoolss_RouterReplyPrinterEx
9600 ****************************************************************/
9602 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9603 struct spoolss_RouterReplyPrinterEx *r)
9605 p->rng_fault_state = true;
9606 return WERR_NOT_SUPPORTED;
9609 /****************************************************************
9611 ****************************************************************/
9613 WERROR _spoolss_44(pipes_struct *p,
9614 struct spoolss_44 *r)
9616 p->rng_fault_state = true;
9617 return WERR_NOT_SUPPORTED;
9620 /****************************************************************
9622 ****************************************************************/
9624 WERROR _spoolss_47(pipes_struct *p,
9625 struct spoolss_47 *r)
9627 p->rng_fault_state = true;
9628 return WERR_NOT_SUPPORTED;
9631 /****************************************************************
9633 ****************************************************************/
9635 WERROR _spoolss_4a(pipes_struct *p,
9636 struct spoolss_4a *r)
9638 p->rng_fault_state = true;
9639 return WERR_NOT_SUPPORTED;
9642 /****************************************************************
9644 ****************************************************************/
9646 WERROR _spoolss_4b(pipes_struct *p,
9647 struct spoolss_4b *r)
9649 p->rng_fault_state = true;
9650 return WERR_NOT_SUPPORTED;
9653 /****************************************************************
9655 ****************************************************************/
9657 WERROR _spoolss_4c(pipes_struct *p,
9658 struct spoolss_4c *r)
9660 p->rng_fault_state = true;
9661 return WERR_NOT_SUPPORTED;
9664 /****************************************************************
9666 ****************************************************************/
9668 WERROR _spoolss_53(pipes_struct *p,
9669 struct spoolss_53 *r)
9671 p->rng_fault_state = true;
9672 return WERR_NOT_SUPPORTED;
9675 /****************************************************************
9677 ****************************************************************/
9679 WERROR _spoolss_55(pipes_struct *p,
9680 struct spoolss_55 *r)
9682 p->rng_fault_state = true;
9683 return WERR_NOT_SUPPORTED;
9686 /****************************************************************
9688 ****************************************************************/
9690 WERROR _spoolss_56(pipes_struct *p,
9691 struct spoolss_56 *r)
9693 p->rng_fault_state = true;
9694 return WERR_NOT_SUPPORTED;
9697 /****************************************************************
9699 ****************************************************************/
9701 WERROR _spoolss_57(pipes_struct *p,
9702 struct spoolss_57 *r)
9704 p->rng_fault_state = true;
9705 return WERR_NOT_SUPPORTED;
9708 /****************************************************************
9710 ****************************************************************/
9712 WERROR _spoolss_5a(pipes_struct *p,
9713 struct spoolss_5a *r)
9715 p->rng_fault_state = true;
9716 return WERR_NOT_SUPPORTED;
9719 /****************************************************************
9721 ****************************************************************/
9723 WERROR _spoolss_5b(pipes_struct *p,
9724 struct spoolss_5b *r)
9726 p->rng_fault_state = true;
9727 return WERR_NOT_SUPPORTED;
9730 /****************************************************************
9732 ****************************************************************/
9734 WERROR _spoolss_5c(pipes_struct *p,
9735 struct spoolss_5c *r)
9737 p->rng_fault_state = true;
9738 return WERR_NOT_SUPPORTED;
9741 /****************************************************************
9743 ****************************************************************/
9745 WERROR _spoolss_5d(pipes_struct *p,
9746 struct spoolss_5d *r)
9748 p->rng_fault_state = true;
9749 return WERR_NOT_SUPPORTED;
9752 /****************************************************************
9754 ****************************************************************/
9756 WERROR _spoolss_5e(pipes_struct *p,
9757 struct spoolss_5e *r)
9759 p->rng_fault_state = true;
9760 return WERR_NOT_SUPPORTED;
9763 /****************************************************************
9765 ****************************************************************/
9767 WERROR _spoolss_5f(pipes_struct *p,
9768 struct spoolss_5f *r)
9770 p->rng_fault_state = true;
9771 return WERR_NOT_SUPPORTED;
9774 /****************************************************************
9776 ****************************************************************/
9778 WERROR _spoolss_60(pipes_struct *p,
9779 struct spoolss_60 *r)
9781 p->rng_fault_state = true;
9782 return WERR_NOT_SUPPORTED;
9785 /****************************************************************
9787 ****************************************************************/
9789 WERROR _spoolss_61(pipes_struct *p,
9790 struct spoolss_61 *r)
9792 p->rng_fault_state = true;
9793 return WERR_NOT_SUPPORTED;
9796 /****************************************************************
9798 ****************************************************************/
9800 WERROR _spoolss_62(pipes_struct *p,
9801 struct spoolss_62 *r)
9803 p->rng_fault_state = true;
9804 return WERR_NOT_SUPPORTED;
9807 /****************************************************************
9809 ****************************************************************/
9811 WERROR _spoolss_63(pipes_struct *p,
9812 struct spoolss_63 *r)
9814 p->rng_fault_state = true;
9815 return WERR_NOT_SUPPORTED;
9818 /****************************************************************
9820 ****************************************************************/
9822 WERROR _spoolss_64(pipes_struct *p,
9823 struct spoolss_64 *r)
9825 p->rng_fault_state = true;
9826 return WERR_NOT_SUPPORTED;
9829 /****************************************************************
9831 ****************************************************************/
9833 WERROR _spoolss_65(pipes_struct *p,
9834 struct spoolss_65 *r)
9836 p->rng_fault_state = true;
9837 return WERR_NOT_SUPPORTED;
9840 /****************************************************************
9841 _spoolss_GetCorePrinterDrivers
9842 ****************************************************************/
9844 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9845 struct spoolss_GetCorePrinterDrivers *r)
9847 p->rng_fault_state = true;
9848 return WERR_NOT_SUPPORTED;
9851 /****************************************************************
9853 ****************************************************************/
9855 WERROR _spoolss_67(pipes_struct *p,
9856 struct spoolss_67 *r)
9858 p->rng_fault_state = true;
9859 return WERR_NOT_SUPPORTED;
9862 /****************************************************************
9863 _spoolss_GetPrinterDriverPackagePath
9864 ****************************************************************/
9866 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9867 struct spoolss_GetPrinterDriverPackagePath *r)
9869 p->rng_fault_state = true;
9870 return WERR_NOT_SUPPORTED;
9873 /****************************************************************
9875 ****************************************************************/
9877 WERROR _spoolss_69(pipes_struct *p,
9878 struct spoolss_69 *r)
9880 p->rng_fault_state = true;
9881 return WERR_NOT_SUPPORTED;
9884 /****************************************************************
9886 ****************************************************************/
9888 WERROR _spoolss_6a(pipes_struct *p,
9889 struct spoolss_6a *r)
9891 p->rng_fault_state = true;
9892 return WERR_NOT_SUPPORTED;
9895 /****************************************************************
9897 ****************************************************************/
9899 WERROR _spoolss_6b(pipes_struct *p,
9900 struct spoolss_6b *r)
9902 p->rng_fault_state = true;
9903 return WERR_NOT_SUPPORTED;
9906 /****************************************************************
9908 ****************************************************************/
9910 WERROR _spoolss_6c(pipes_struct *p,
9911 struct spoolss_6c *r)
9913 p->rng_fault_state = true;
9914 return WERR_NOT_SUPPORTED;
9917 /****************************************************************
9919 ****************************************************************/
9921 WERROR _spoolss_6d(pipes_struct *p,
9922 struct spoolss_6d *r)
9924 p->rng_fault_state = true;
9925 return WERR_NOT_SUPPORTED;