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;
7654 WERROR status = WERR_OK;
7655 NT_PRINTER_INFO_LEVEL *printer = NULL;
7656 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7658 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7660 DEBUG(5,("_spoolss_AddForm\n"));
7663 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7664 OUR_HANDLE(r->in.handle)));
7669 /* forms can be added on printer or on the print server handle */
7671 if ( Printer->printer_type == SPLHND_PRINTER )
7673 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7676 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7677 if (!W_ERROR_IS_OK(status))
7681 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7682 and not a printer admin, then fail */
7684 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7685 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7686 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7687 p->server_info->info3->base.domain.string,
7689 p->server_info->ptok,
7690 lp_printer_admin(snum))) {
7691 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7692 status = WERR_ACCESS_DENIED;
7696 switch (form->flags) {
7697 case SPOOLSS_FORM_USER:
7698 case SPOOLSS_FORM_BUILTIN:
7699 case SPOOLSS_FORM_PRINTER:
7702 status = WERR_INVALID_PARAM;
7706 status = winreg_printer_addform1(p->mem_ctx, p->server_info, form);
7707 if (!W_ERROR_IS_OK(status)) {
7712 * ChangeID must always be set if this is a printer
7715 if ( Printer->printer_type == SPLHND_PRINTER )
7716 status = mod_a_printer(printer, 2);
7720 free_a_printer(&printer, 2);
7725 /****************************************************************
7727 ****************************************************************/
7729 WERROR _spoolss_DeleteForm(pipes_struct *p,
7730 struct spoolss_DeleteForm *r)
7732 const char *form_name = r->in.form_name;
7733 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7735 WERROR status = WERR_OK;
7736 NT_PRINTER_INFO_LEVEL *printer = NULL;
7737 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7739 DEBUG(5,("_spoolss_DeleteForm\n"));
7742 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7743 OUR_HANDLE(r->in.handle)));
7747 /* forms can be deleted on printer of on the print server handle */
7749 if ( Printer->printer_type == SPLHND_PRINTER )
7751 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7754 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7755 if (!W_ERROR_IS_OK(status))
7759 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7760 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7761 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7762 p->server_info->info3->base.domain.string,
7764 p->server_info->ptok,
7765 lp_printer_admin(snum))) {
7766 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7767 return WERR_ACCESS_DENIED;
7770 status = winreg_printer_deleteform1(p->mem_ctx,
7773 if (!W_ERROR_IS_OK(status)) {
7778 * ChangeID must always be set if this is a printer
7781 if ( Printer->printer_type == SPLHND_PRINTER )
7782 status = mod_a_printer(printer, 2);
7786 free_a_printer(&printer, 2);
7791 /****************************************************************
7793 ****************************************************************/
7795 WERROR _spoolss_SetForm(pipes_struct *p,
7796 struct spoolss_SetForm *r)
7798 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
7799 const char *form_name = r->in.form_name;
7801 WERROR status = WERR_OK;
7802 NT_PRINTER_INFO_LEVEL *printer = NULL;
7803 SE_PRIV se_printop = SE_PRINT_OPERATOR;
7805 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
7807 DEBUG(5,("_spoolss_SetForm\n"));
7810 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7811 OUR_HANDLE(r->in.handle)));
7815 /* forms can be modified on printer of on the print server handle */
7817 if ( Printer->printer_type == SPLHND_PRINTER )
7819 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
7822 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7823 if (!W_ERROR_IS_OK(status))
7827 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7828 and not a printer admin, then fail */
7830 if ((p->server_info->utok.uid != sec_initial_uid()) &&
7831 !user_has_privileges(p->server_info->ptok, &se_printop) &&
7832 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
7833 p->server_info->info3->base.domain.string,
7835 p->server_info->ptok,
7836 lp_printer_admin(snum))) {
7837 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
7838 status = WERR_ACCESS_DENIED;
7842 status = winreg_printer_setform1(p->mem_ctx,
7846 if (!W_ERROR_IS_OK(status)) {
7851 * ChangeID must always be set if this is a printer
7854 if ( Printer->printer_type == SPLHND_PRINTER )
7855 status = mod_a_printer(printer, 2);
7860 free_a_printer(&printer, 2);
7865 /****************************************************************************
7866 fill_print_processor1
7867 ****************************************************************************/
7869 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
7870 struct spoolss_PrintProcessorInfo1 *r,
7871 const char *print_processor_name)
7873 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
7874 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
7879 /****************************************************************************
7880 enumprintprocessors level 1.
7881 ****************************************************************************/
7883 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
7884 union spoolss_PrintProcessorInfo **info_p,
7887 union spoolss_PrintProcessorInfo *info;
7890 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
7891 W_ERROR_HAVE_NO_MEMORY(info);
7895 result = fill_print_processor1(info, &info[0].info1, "winprint");
7896 if (!W_ERROR_IS_OK(result)) {
7901 if (!W_ERROR_IS_OK(result)) {
7912 /****************************************************************
7913 _spoolss_EnumPrintProcessors
7914 ****************************************************************/
7916 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
7917 struct spoolss_EnumPrintProcessors *r)
7921 /* that's an [in out] buffer */
7923 if (!r->in.buffer && (r->in.offered != 0)) {
7924 return WERR_INVALID_PARAM;
7927 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
7930 * Enumerate the print processors ...
7932 * Just reply with "winprint", to keep NT happy
7933 * and I can use my nice printer checker.
7938 *r->out.info = NULL;
7940 switch (r->in.level) {
7942 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
7946 return WERR_UNKNOWN_LEVEL;
7949 if (!W_ERROR_IS_OK(result)) {
7953 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7954 spoolss_EnumPrintProcessors,
7955 *r->out.info, r->in.level,
7957 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7958 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7960 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7963 /****************************************************************************
7964 fill_printprocdatatype1
7965 ****************************************************************************/
7967 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
7968 struct spoolss_PrintProcDataTypesInfo1 *r,
7969 const char *name_array)
7971 r->name_array = talloc_strdup(mem_ctx, name_array);
7972 W_ERROR_HAVE_NO_MEMORY(r->name_array);
7977 /****************************************************************************
7978 enumprintprocdatatypes level 1.
7979 ****************************************************************************/
7981 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
7982 union spoolss_PrintProcDataTypesInfo **info_p,
7986 union spoolss_PrintProcDataTypesInfo *info;
7988 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
7989 W_ERROR_HAVE_NO_MEMORY(info);
7993 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
7994 if (!W_ERROR_IS_OK(result)) {
7999 if (!W_ERROR_IS_OK(result)) {
8010 /****************************************************************
8011 _spoolss_EnumPrintProcDataTypes
8012 ****************************************************************/
8014 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8015 struct spoolss_EnumPrintProcDataTypes *r)
8019 /* that's an [in out] buffer */
8021 if (!r->in.buffer && (r->in.offered != 0)) {
8022 return WERR_INVALID_PARAM;
8025 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8029 *r->out.info = NULL;
8031 switch (r->in.level) {
8033 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8037 return WERR_UNKNOWN_LEVEL;
8040 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8041 spoolss_EnumPrintProcDataTypes,
8042 *r->out.info, r->in.level,
8044 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8045 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8047 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8050 /****************************************************************************
8052 ****************************************************************************/
8054 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8055 struct spoolss_MonitorInfo1 *r,
8056 const char *monitor_name)
8058 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8059 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8064 /****************************************************************************
8066 ****************************************************************************/
8068 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8069 struct spoolss_MonitorInfo2 *r,
8070 const char *monitor_name,
8071 const char *environment,
8072 const char *dll_name)
8074 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8075 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8076 r->environment = talloc_strdup(mem_ctx, environment);
8077 W_ERROR_HAVE_NO_MEMORY(r->environment);
8078 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8079 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8084 /****************************************************************************
8085 enumprintmonitors level 1.
8086 ****************************************************************************/
8088 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8089 union spoolss_MonitorInfo **info_p,
8092 union spoolss_MonitorInfo *info;
8093 WERROR result = WERR_OK;
8095 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8096 W_ERROR_HAVE_NO_MEMORY(info);
8100 result = fill_monitor_1(info, &info[0].info1,
8102 if (!W_ERROR_IS_OK(result)) {
8106 result = fill_monitor_1(info, &info[1].info1,
8108 if (!W_ERROR_IS_OK(result)) {
8113 if (!W_ERROR_IS_OK(result)) {
8124 /****************************************************************************
8125 enumprintmonitors level 2.
8126 ****************************************************************************/
8128 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8129 union spoolss_MonitorInfo **info_p,
8132 union spoolss_MonitorInfo *info;
8133 WERROR result = WERR_OK;
8135 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8136 W_ERROR_HAVE_NO_MEMORY(info);
8140 result = fill_monitor_2(info, &info[0].info2,
8142 "Windows NT X86", /* FIXME */
8144 if (!W_ERROR_IS_OK(result)) {
8148 result = fill_monitor_2(info, &info[1].info2,
8150 "Windows NT X86", /* FIXME */
8152 if (!W_ERROR_IS_OK(result)) {
8157 if (!W_ERROR_IS_OK(result)) {
8168 /****************************************************************
8169 _spoolss_EnumMonitors
8170 ****************************************************************/
8172 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8173 struct spoolss_EnumMonitors *r)
8177 /* that's an [in out] buffer */
8179 if (!r->in.buffer && (r->in.offered != 0)) {
8180 return WERR_INVALID_PARAM;
8183 DEBUG(5,("_spoolss_EnumMonitors\n"));
8186 * Enumerate the print monitors ...
8188 * Just reply with "Local Port", to keep NT happy
8189 * and I can use my nice printer checker.
8194 *r->out.info = NULL;
8196 switch (r->in.level) {
8198 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8202 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8206 return WERR_UNKNOWN_LEVEL;
8209 if (!W_ERROR_IS_OK(result)) {
8213 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8214 spoolss_EnumMonitors,
8215 *r->out.info, r->in.level,
8217 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8218 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8220 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8223 /****************************************************************************
8224 ****************************************************************************/
8226 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8227 const print_queue_struct *queue,
8228 int count, int snum,
8229 const NT_PRINTER_INFO_LEVEL *ntprinter,
8231 struct spoolss_JobInfo1 *r)
8236 for (i=0; i<count; i++) {
8237 if (queue[i].job == (int)jobid) {
8243 if (found == false) {
8244 /* NT treats not found as bad param... yet another bad choice */
8245 return WERR_INVALID_PARAM;
8248 return fill_job_info1(mem_ctx,
8256 /****************************************************************************
8257 ****************************************************************************/
8259 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8260 const print_queue_struct *queue,
8261 int count, int snum,
8262 const NT_PRINTER_INFO_LEVEL *ntprinter,
8264 struct spoolss_JobInfo2 *r)
8268 struct spoolss_DeviceMode *devmode;
8270 for (i=0; i<count; i++) {
8271 if (queue[i].job == (int)jobid) {
8277 if (found == false) {
8278 /* NT treats not found as bad param... yet another bad
8280 return WERR_INVALID_PARAM;
8284 * if the print job does not have a DEVMODE associated with it,
8285 * just use the one for the printer. A NULL devicemode is not
8286 * a failure condition
8289 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8291 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
8292 W_ERROR_HAVE_NO_MEMORY(devmode);
8295 return fill_job_info2(mem_ctx,
8304 /****************************************************************
8306 ****************************************************************/
8308 WERROR _spoolss_GetJob(pipes_struct *p,
8309 struct spoolss_GetJob *r)
8311 WERROR result = WERR_OK;
8312 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8315 print_queue_struct *queue = NULL;
8316 print_status_struct prt_status;
8318 /* that's an [in out] buffer */
8320 if (!r->in.buffer && (r->in.offered != 0)) {
8321 return WERR_INVALID_PARAM;
8324 DEBUG(5,("_spoolss_GetJob\n"));
8328 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8332 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8333 if (!W_ERROR_IS_OK(result)) {
8337 count = print_queue_status(snum, &queue, &prt_status);
8339 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8340 count, prt_status.status, prt_status.message));
8342 switch (r->in.level) {
8344 result = getjob_level_1(p->mem_ctx,
8345 queue, count, snum, ntprinter,
8346 r->in.job_id, &r->out.info->info1);
8349 result = getjob_level_2(p->mem_ctx,
8350 queue, count, snum, ntprinter,
8351 r->in.job_id, &r->out.info->info2);
8354 result = WERR_UNKNOWN_LEVEL;
8359 free_a_printer(&ntprinter, 2);
8361 if (!W_ERROR_IS_OK(result)) {
8362 TALLOC_FREE(r->out.info);
8366 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8368 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8370 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8373 /****************************************************************
8374 _spoolss_GetPrinterDataEx
8375 ****************************************************************/
8377 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
8378 struct spoolss_GetPrinterDataEx *r)
8381 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8382 const char *printer;
8384 WERROR result = WERR_OK;
8386 enum winreg_Type val_type;
8391 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8393 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8394 r->in.key_name, r->in.value_name));
8396 /* in case of problem, return some default values */
8399 *r->out.type = REG_NONE;
8402 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8403 OUR_HANDLE(r->in.handle)));
8404 result = WERR_BADFID;
8408 /* Is the handle to a printer or to the server? */
8410 if (Printer->printer_type == SPLHND_SERVER) {
8412 union spoolss_PrinterData data;
8414 result = getprinterdata_printer_server(p->mem_ctx,
8418 if (!W_ERROR_IS_OK(result)) {
8422 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8423 *r->out.type, &data);
8424 if (!W_ERROR_IS_OK(result)) {
8428 *r->out.needed = blob.length;
8430 if (r->in.offered >= *r->out.needed) {
8431 memcpy(r->out.data, blob.data, blob.length);
8434 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8437 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8440 printer = lp_const_servicename(snum);
8442 /* check to see if the keyname is valid */
8443 if (!strlen(r->in.key_name)) {
8444 return WERR_INVALID_PARAM;
8447 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8448 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8449 strequal(r->in.value_name, "ChangeId")) {
8450 *r->out.type = REG_DWORD;
8452 if (r->in.offered >= *r->out.needed) {
8453 uint32_t changeid = 0;
8455 result = winreg_printer_get_changeid(p->mem_ctx,
8459 if (!W_ERROR_IS_OK(result)) {
8463 SIVAL(r->out.data, 0, changeid);
8469 result = winreg_get_printer_dataex(p->mem_ctx,
8477 if (!W_ERROR_IS_OK(result)) {
8481 *r->out.needed = val_size;
8482 *r->out.type = val_type;
8484 if (r->in.offered >= *r->out.needed) {
8485 memcpy(r->out.data, val_data, val_size);
8489 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8490 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8492 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8495 /****************************************************************
8496 _spoolss_SetPrinterDataEx
8497 ****************************************************************/
8499 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
8500 struct spoolss_SetPrinterDataEx *r)
8502 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8504 WERROR result = WERR_OK;
8505 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8508 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8510 /* From MSDN documentation of SetPrinterDataEx: pass request to
8511 SetPrinterData if key is "PrinterDriverData" */
8514 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8515 OUR_HANDLE(r->in.handle)));
8519 if (Printer->printer_type == SPLHND_SERVER) {
8520 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8521 "Not implemented for server handles yet\n"));
8522 return WERR_INVALID_PARAM;
8525 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8530 * Access check : NT returns "access denied" if you make a
8531 * SetPrinterData call without the necessary privildge.
8532 * we were originally returning OK if nothing changed
8533 * which made Win2k issue **a lot** of SetPrinterData
8534 * when connecting to a printer --jerry
8537 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8538 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8539 "change denied by handle access permissions\n"));
8540 return WERR_ACCESS_DENIED;
8543 result = winreg_get_printer(Printer, p->server_info,
8544 Printer->servername,
8545 lp_servicename(snum),
8547 if (!W_ERROR_IS_OK(result)) {
8551 /* check for OID in valuename */
8553 oid_string = strchr(r->in.value_name, ',');
8559 /* save the registry data */
8561 result = winreg_set_printer_dataex(p->mem_ctx,
8570 if (W_ERROR_IS_OK(result)) {
8571 /* save the OID if one was specified */
8573 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8574 r->in.key_name, SPOOL_OID_KEY);
8576 result = WERR_NOMEM;
8581 * I'm not checking the status here on purpose. Don't know
8582 * if this is right, but I'm returning the status from the
8583 * previous set_printer_dataex() call. I have no idea if
8584 * this is right. --jerry
8586 winreg_set_printer_dataex(p->mem_ctx,
8592 (uint8_t *) oid_string,
8593 strlen(oid_string) + 1);
8596 result = winreg_printer_update_changeid(p->mem_ctx,
8598 lp_const_servicename(snum));
8603 talloc_free(pinfo2);
8607 /****************************************************************
8608 _spoolss_DeletePrinterDataEx
8609 ****************************************************************/
8611 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
8612 struct spoolss_DeletePrinterDataEx *r)
8614 const char *printer;
8616 WERROR status = WERR_OK;
8617 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8619 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8622 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8623 "Invalid handle (%s:%u:%u).\n",
8624 OUR_HANDLE(r->in.handle)));
8628 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8629 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8630 "printer properties change denied by handle\n"));
8631 return WERR_ACCESS_DENIED;
8634 if (!r->in.value_name || !r->in.key_name) {
8638 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8641 printer = lp_const_servicename(snum);
8643 status = winreg_delete_printer_dataex(p->mem_ctx,
8648 if (W_ERROR_IS_OK(status)) {
8649 status = winreg_printer_update_changeid(p->mem_ctx,
8657 /****************************************************************
8658 _spoolss_EnumPrinterKey
8659 ****************************************************************/
8661 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
8662 struct spoolss_EnumPrinterKey *r)
8665 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8667 WERROR result = WERR_BADFILE;
8668 const char **array = NULL;
8671 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8674 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8675 OUR_HANDLE(r->in.handle)));
8679 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8683 result = winreg_enum_printer_key(p->mem_ctx,
8685 lp_const_servicename(snum),
8689 if (!W_ERROR_IS_OK(result)) {
8693 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
8694 result = WERR_NOMEM;
8698 *r->out._ndr_size = r->in.offered / 2;
8699 *r->out.needed = blob.length;
8701 if (r->in.offered < *r->out.needed) {
8702 result = WERR_MORE_DATA;
8705 r->out.key_buffer->string_array = array;
8709 if (!W_ERROR_IS_OK(result)) {
8711 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8719 /****************************************************************
8720 _spoolss_DeletePrinterKey
8721 ****************************************************************/
8723 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
8724 struct spoolss_DeletePrinterKey *r)
8726 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8729 const char *printer;
8731 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8734 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8735 OUR_HANDLE(r->in.handle)));
8739 /* if keyname == NULL, return error */
8740 if ( !r->in.key_name )
8741 return WERR_INVALID_PARAM;
8743 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8747 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8748 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8749 "printer properties change denied by handle\n"));
8750 return WERR_ACCESS_DENIED;
8753 printer = lp_const_servicename(snum);
8755 /* delete the key and all subkeys */
8756 status = winreg_delete_printer_key(p->mem_ctx,
8760 if (W_ERROR_IS_OK(status)) {
8761 status = winreg_printer_update_changeid(p->mem_ctx,
8769 /****************************************************************
8770 _spoolss_EnumPrinterDataEx
8771 ****************************************************************/
8773 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
8774 struct spoolss_EnumPrinterDataEx *r)
8777 struct spoolss_PrinterEnumValues *info = NULL;
8778 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8782 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
8786 *r->out.info = NULL;
8789 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
8790 OUR_HANDLE(r->in.handle)));
8795 * first check for a keyname of NULL or "". Win2k seems to send
8796 * this a lot and we should send back WERR_INVALID_PARAM
8797 * no need to spend time looking up the printer in this case.
8801 if (!strlen(r->in.key_name)) {
8802 result = WERR_INVALID_PARAM;
8806 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8810 /* now look for a match on the key name */
8811 result = winreg_enum_printer_dataex(p->mem_ctx,
8813 lp_const_servicename(snum),
8817 if (!W_ERROR_IS_OK(result)) {
8821 #if 0 /* FIXME - gd */
8822 /* housekeeping information in the reply */
8824 /* Fix from Martin Zielinski <mz@seh.de> - ensure
8825 * the hand marshalled container size is a multiple
8826 * of 4 bytes for RPC alignment.
8830 needed += 4-(needed % 4);
8833 *r->out.count = count;
8834 *r->out.info = info;
8837 if (!W_ERROR_IS_OK(result)) {
8841 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
8842 spoolss_EnumPrinterDataEx,
8845 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8846 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
8848 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8851 /****************************************************************************
8852 ****************************************************************************/
8854 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
8855 const char *servername,
8856 const char *environment,
8857 struct spoolss_PrintProcessorDirectoryInfo1 *r)
8862 werr = compose_spoolss_server_path(mem_ctx,
8865 SPOOLSS_PRTPROCS_PATH,
8867 if (!W_ERROR_IS_OK(werr)) {
8871 DEBUG(4,("print processor directory: [%s]\n", path));
8873 r->directory_name = path;
8878 /****************************************************************
8879 _spoolss_GetPrintProcessorDirectory
8880 ****************************************************************/
8882 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
8883 struct spoolss_GetPrintProcessorDirectory *r)
8887 /* that's an [in out] buffer */
8889 if (!r->in.buffer && (r->in.offered != 0)) {
8890 return WERR_INVALID_PARAM;
8893 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
8898 /* r->in.level is ignored */
8900 /* We always should reply with a local print processor directory so that
8901 * users are not forced to have a [prnproc$] share on the Samba spoolss
8902 * server - Guenther */
8904 result = getprintprocessordirectory_level_1(p->mem_ctx,
8905 NULL, /* r->in.server */
8907 &r->out.info->info1);
8908 if (!W_ERROR_IS_OK(result)) {
8909 TALLOC_FREE(r->out.info);
8913 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
8914 r->out.info, r->in.level);
8915 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8917 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8920 /*******************************************************************
8921 ********************************************************************/
8923 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
8924 const char *dllname)
8926 enum ndr_err_code ndr_err;
8927 struct spoolss_MonitorUi ui;
8929 ui.dll_name = dllname;
8931 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
8932 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
8933 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8934 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
8936 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8939 /*******************************************************************
8940 Streams the monitor UI DLL name in UNICODE
8941 *******************************************************************/
8943 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
8944 NT_USER_TOKEN *token, DATA_BLOB *in,
8945 DATA_BLOB *out, uint32_t *needed)
8947 const char *dllname = "tcpmonui.dll";
8949 *needed = (strlen(dllname)+1) * 2;
8951 if (out->length < *needed) {
8952 return WERR_INSUFFICIENT_BUFFER;
8955 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
8962 /*******************************************************************
8963 ********************************************************************/
8965 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
8966 struct spoolss_PortData1 *port1,
8967 const DATA_BLOB *buf)
8969 enum ndr_err_code ndr_err;
8970 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
8971 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
8972 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8973 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
8975 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8978 /*******************************************************************
8979 ********************************************************************/
8981 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
8982 struct spoolss_PortData2 *port2,
8983 const DATA_BLOB *buf)
8985 enum ndr_err_code ndr_err;
8986 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
8987 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
8988 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
8989 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
8991 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
8994 /*******************************************************************
8995 Create a new TCP/IP port
8996 *******************************************************************/
8998 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
8999 NT_USER_TOKEN *token, DATA_BLOB *in,
9000 DATA_BLOB *out, uint32_t *needed)
9002 struct spoolss_PortData1 port1;
9003 struct spoolss_PortData2 port2;
9004 char *device_uri = NULL;
9007 const char *portname;
9008 const char *hostaddress;
9010 uint32_t port_number;
9013 /* peek for spoolss_PortData version */
9015 if (!in || (in->length < (128 + 4))) {
9016 return WERR_GENERAL_FAILURE;
9019 version = IVAL(in->data, 128);
9025 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9029 portname = port1.portname;
9030 hostaddress = port1.hostaddress;
9031 queue = port1.queue;
9032 protocol = port1.protocol;
9033 port_number = port1.port_number;
9039 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9043 portname = port2.portname;
9044 hostaddress = port2.hostaddress;
9045 queue = port2.queue;
9046 protocol = port2.protocol;
9047 port_number = port2.port_number;
9051 DEBUG(1,("xcvtcp_addport: "
9052 "unknown version of port_data: %d\n", version));
9053 return WERR_UNKNOWN_PORT;
9056 /* create the device URI and call the add_port_hook() */
9059 case PROTOCOL_RAWTCP_TYPE:
9060 device_uri = talloc_asprintf(mem_ctx,
9061 "socket://%s:%d/", hostaddress,
9065 case PROTOCOL_LPR_TYPE:
9066 device_uri = talloc_asprintf(mem_ctx,
9067 "lpr://%s/%s", hostaddress, queue );
9071 return WERR_UNKNOWN_PORT;
9078 return add_port_hook(mem_ctx, token, portname, device_uri);
9081 /*******************************************************************
9082 *******************************************************************/
9084 struct xcv_api_table xcvtcp_cmds[] = {
9085 { "MonitorUI", xcvtcp_monitorui },
9086 { "AddPort", xcvtcp_addport},
9090 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9091 NT_USER_TOKEN *token, const char *command,
9098 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9100 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9101 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9102 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9105 return WERR_BADFUNC;
9108 /*******************************************************************
9109 *******************************************************************/
9110 #if 0 /* don't support management using the "Local Port" monitor */
9112 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9113 NT_USER_TOKEN *token, DATA_BLOB *in,
9114 DATA_BLOB *out, uint32_t *needed)
9116 const char *dllname = "localui.dll";
9118 *needed = (strlen(dllname)+1) * 2;
9120 if (out->length < *needed) {
9121 return WERR_INSUFFICIENT_BUFFER;
9124 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9131 /*******************************************************************
9132 *******************************************************************/
9134 struct xcv_api_table xcvlocal_cmds[] = {
9135 { "MonitorUI", xcvlocal_monitorui },
9139 struct xcv_api_table xcvlocal_cmds[] = {
9146 /*******************************************************************
9147 *******************************************************************/
9149 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9150 NT_USER_TOKEN *token, const char *command,
9151 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9156 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9158 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9159 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9160 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9162 return WERR_BADFUNC;
9165 /****************************************************************
9167 ****************************************************************/
9169 WERROR _spoolss_XcvData(pipes_struct *p,
9170 struct spoolss_XcvData *r)
9172 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9173 DATA_BLOB out_data = data_blob_null;
9177 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9178 OUR_HANDLE(r->in.handle)));
9182 /* Has to be a handle to the TCP/IP port monitor */
9184 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9185 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9189 /* requires administrative access to the server */
9191 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9192 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9193 return WERR_ACCESS_DENIED;
9196 /* Allocate the outgoing buffer */
9198 if (r->in.out_data_size) {
9199 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9200 if (out_data.data == NULL) {
9205 switch ( Printer->printer_type ) {
9206 case SPLHND_PORTMON_TCP:
9207 werror = process_xcvtcp_command(p->mem_ctx,
9208 p->server_info->ptok,
9209 r->in.function_name,
9210 &r->in.in_data, &out_data,
9213 case SPLHND_PORTMON_LOCAL:
9214 werror = process_xcvlocal_command(p->mem_ctx,
9215 p->server_info->ptok,
9216 r->in.function_name,
9217 &r->in.in_data, &out_data,
9221 werror = WERR_INVALID_PRINT_MONITOR;
9224 if (!W_ERROR_IS_OK(werror)) {
9228 *r->out.status_code = 0;
9230 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9231 memcpy(r->out.out_data, out_data.data,
9232 MIN(r->in.out_data_size, out_data.length));
9238 /****************************************************************
9239 _spoolss_AddPrintProcessor
9240 ****************************************************************/
9242 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
9243 struct spoolss_AddPrintProcessor *r)
9245 /* for now, just indicate success and ignore the add. We'll
9246 automatically set the winprint processor for printer
9247 entries later. Used to debug the LexMark Optra S 1855 PCL
9253 /****************************************************************
9255 ****************************************************************/
9257 WERROR _spoolss_AddPort(pipes_struct *p,
9258 struct spoolss_AddPort *r)
9260 /* do what w2k3 does */
9262 return WERR_NOT_SUPPORTED;
9265 /****************************************************************
9266 _spoolss_GetPrinterDriver
9267 ****************************************************************/
9269 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
9270 struct spoolss_GetPrinterDriver *r)
9272 p->rng_fault_state = true;
9273 return WERR_NOT_SUPPORTED;
9276 /****************************************************************
9277 _spoolss_ReadPrinter
9278 ****************************************************************/
9280 WERROR _spoolss_ReadPrinter(pipes_struct *p,
9281 struct spoolss_ReadPrinter *r)
9283 p->rng_fault_state = true;
9284 return WERR_NOT_SUPPORTED;
9287 /****************************************************************
9288 _spoolss_WaitForPrinterChange
9289 ****************************************************************/
9291 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
9292 struct spoolss_WaitForPrinterChange *r)
9294 p->rng_fault_state = true;
9295 return WERR_NOT_SUPPORTED;
9298 /****************************************************************
9299 _spoolss_ConfigurePort
9300 ****************************************************************/
9302 WERROR _spoolss_ConfigurePort(pipes_struct *p,
9303 struct spoolss_ConfigurePort *r)
9305 p->rng_fault_state = true;
9306 return WERR_NOT_SUPPORTED;
9309 /****************************************************************
9311 ****************************************************************/
9313 WERROR _spoolss_DeletePort(pipes_struct *p,
9314 struct spoolss_DeletePort *r)
9316 p->rng_fault_state = true;
9317 return WERR_NOT_SUPPORTED;
9320 /****************************************************************
9321 _spoolss_CreatePrinterIC
9322 ****************************************************************/
9324 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
9325 struct spoolss_CreatePrinterIC *r)
9327 p->rng_fault_state = true;
9328 return WERR_NOT_SUPPORTED;
9331 /****************************************************************
9332 _spoolss_PlayGDIScriptOnPrinterIC
9333 ****************************************************************/
9335 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
9336 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9338 p->rng_fault_state = true;
9339 return WERR_NOT_SUPPORTED;
9342 /****************************************************************
9343 _spoolss_DeletePrinterIC
9344 ****************************************************************/
9346 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
9347 struct spoolss_DeletePrinterIC *r)
9349 p->rng_fault_state = true;
9350 return WERR_NOT_SUPPORTED;
9353 /****************************************************************
9354 _spoolss_AddPrinterConnection
9355 ****************************************************************/
9357 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
9358 struct spoolss_AddPrinterConnection *r)
9360 p->rng_fault_state = true;
9361 return WERR_NOT_SUPPORTED;
9364 /****************************************************************
9365 _spoolss_DeletePrinterConnection
9366 ****************************************************************/
9368 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
9369 struct spoolss_DeletePrinterConnection *r)
9371 p->rng_fault_state = true;
9372 return WERR_NOT_SUPPORTED;
9375 /****************************************************************
9376 _spoolss_PrinterMessageBox
9377 ****************************************************************/
9379 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
9380 struct spoolss_PrinterMessageBox *r)
9382 p->rng_fault_state = true;
9383 return WERR_NOT_SUPPORTED;
9386 /****************************************************************
9388 ****************************************************************/
9390 WERROR _spoolss_AddMonitor(pipes_struct *p,
9391 struct spoolss_AddMonitor *r)
9393 p->rng_fault_state = true;
9394 return WERR_NOT_SUPPORTED;
9397 /****************************************************************
9398 _spoolss_DeleteMonitor
9399 ****************************************************************/
9401 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
9402 struct spoolss_DeleteMonitor *r)
9404 p->rng_fault_state = true;
9405 return WERR_NOT_SUPPORTED;
9408 /****************************************************************
9409 _spoolss_DeletePrintProcessor
9410 ****************************************************************/
9412 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
9413 struct spoolss_DeletePrintProcessor *r)
9415 p->rng_fault_state = true;
9416 return WERR_NOT_SUPPORTED;
9419 /****************************************************************
9420 _spoolss_AddPrintProvidor
9421 ****************************************************************/
9423 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
9424 struct spoolss_AddPrintProvidor *r)
9426 p->rng_fault_state = true;
9427 return WERR_NOT_SUPPORTED;
9430 /****************************************************************
9431 _spoolss_DeletePrintProvidor
9432 ****************************************************************/
9434 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
9435 struct spoolss_DeletePrintProvidor *r)
9437 p->rng_fault_state = true;
9438 return WERR_NOT_SUPPORTED;
9441 /****************************************************************
9442 _spoolss_FindFirstPrinterChangeNotification
9443 ****************************************************************/
9445 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
9446 struct spoolss_FindFirstPrinterChangeNotification *r)
9448 p->rng_fault_state = true;
9449 return WERR_NOT_SUPPORTED;
9452 /****************************************************************
9453 _spoolss_FindNextPrinterChangeNotification
9454 ****************************************************************/
9456 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
9457 struct spoolss_FindNextPrinterChangeNotification *r)
9459 p->rng_fault_state = true;
9460 return WERR_NOT_SUPPORTED;
9463 /****************************************************************
9464 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9465 ****************************************************************/
9467 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
9468 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9470 p->rng_fault_state = true;
9471 return WERR_NOT_SUPPORTED;
9474 /****************************************************************
9475 _spoolss_ReplyOpenPrinter
9476 ****************************************************************/
9478 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
9479 struct spoolss_ReplyOpenPrinter *r)
9481 p->rng_fault_state = true;
9482 return WERR_NOT_SUPPORTED;
9485 /****************************************************************
9486 _spoolss_RouterReplyPrinter
9487 ****************************************************************/
9489 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
9490 struct spoolss_RouterReplyPrinter *r)
9492 p->rng_fault_state = true;
9493 return WERR_NOT_SUPPORTED;
9496 /****************************************************************
9497 _spoolss_ReplyClosePrinter
9498 ****************************************************************/
9500 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
9501 struct spoolss_ReplyClosePrinter *r)
9503 p->rng_fault_state = true;
9504 return WERR_NOT_SUPPORTED;
9507 /****************************************************************
9509 ****************************************************************/
9511 WERROR _spoolss_AddPortEx(pipes_struct *p,
9512 struct spoolss_AddPortEx *r)
9514 p->rng_fault_state = true;
9515 return WERR_NOT_SUPPORTED;
9518 /****************************************************************
9519 _spoolss_RouterFindFirstPrinterChangeNotification
9520 ****************************************************************/
9522 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
9523 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9525 p->rng_fault_state = true;
9526 return WERR_NOT_SUPPORTED;
9529 /****************************************************************
9530 _spoolss_SpoolerInit
9531 ****************************************************************/
9533 WERROR _spoolss_SpoolerInit(pipes_struct *p,
9534 struct spoolss_SpoolerInit *r)
9536 p->rng_fault_state = true;
9537 return WERR_NOT_SUPPORTED;
9540 /****************************************************************
9541 _spoolss_ResetPrinterEx
9542 ****************************************************************/
9544 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
9545 struct spoolss_ResetPrinterEx *r)
9547 p->rng_fault_state = true;
9548 return WERR_NOT_SUPPORTED;
9551 /****************************************************************
9552 _spoolss_RouterReplyPrinterEx
9553 ****************************************************************/
9555 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
9556 struct spoolss_RouterReplyPrinterEx *r)
9558 p->rng_fault_state = true;
9559 return WERR_NOT_SUPPORTED;
9562 /****************************************************************
9564 ****************************************************************/
9566 WERROR _spoolss_44(pipes_struct *p,
9567 struct spoolss_44 *r)
9569 p->rng_fault_state = true;
9570 return WERR_NOT_SUPPORTED;
9573 /****************************************************************
9575 ****************************************************************/
9577 WERROR _spoolss_47(pipes_struct *p,
9578 struct spoolss_47 *r)
9580 p->rng_fault_state = true;
9581 return WERR_NOT_SUPPORTED;
9584 /****************************************************************
9586 ****************************************************************/
9588 WERROR _spoolss_4a(pipes_struct *p,
9589 struct spoolss_4a *r)
9591 p->rng_fault_state = true;
9592 return WERR_NOT_SUPPORTED;
9595 /****************************************************************
9597 ****************************************************************/
9599 WERROR _spoolss_4b(pipes_struct *p,
9600 struct spoolss_4b *r)
9602 p->rng_fault_state = true;
9603 return WERR_NOT_SUPPORTED;
9606 /****************************************************************
9608 ****************************************************************/
9610 WERROR _spoolss_4c(pipes_struct *p,
9611 struct spoolss_4c *r)
9613 p->rng_fault_state = true;
9614 return WERR_NOT_SUPPORTED;
9617 /****************************************************************
9619 ****************************************************************/
9621 WERROR _spoolss_53(pipes_struct *p,
9622 struct spoolss_53 *r)
9624 p->rng_fault_state = true;
9625 return WERR_NOT_SUPPORTED;
9628 /****************************************************************
9630 ****************************************************************/
9632 WERROR _spoolss_55(pipes_struct *p,
9633 struct spoolss_55 *r)
9635 p->rng_fault_state = true;
9636 return WERR_NOT_SUPPORTED;
9639 /****************************************************************
9641 ****************************************************************/
9643 WERROR _spoolss_56(pipes_struct *p,
9644 struct spoolss_56 *r)
9646 p->rng_fault_state = true;
9647 return WERR_NOT_SUPPORTED;
9650 /****************************************************************
9652 ****************************************************************/
9654 WERROR _spoolss_57(pipes_struct *p,
9655 struct spoolss_57 *r)
9657 p->rng_fault_state = true;
9658 return WERR_NOT_SUPPORTED;
9661 /****************************************************************
9663 ****************************************************************/
9665 WERROR _spoolss_5a(pipes_struct *p,
9666 struct spoolss_5a *r)
9668 p->rng_fault_state = true;
9669 return WERR_NOT_SUPPORTED;
9672 /****************************************************************
9674 ****************************************************************/
9676 WERROR _spoolss_5b(pipes_struct *p,
9677 struct spoolss_5b *r)
9679 p->rng_fault_state = true;
9680 return WERR_NOT_SUPPORTED;
9683 /****************************************************************
9685 ****************************************************************/
9687 WERROR _spoolss_5c(pipes_struct *p,
9688 struct spoolss_5c *r)
9690 p->rng_fault_state = true;
9691 return WERR_NOT_SUPPORTED;
9694 /****************************************************************
9696 ****************************************************************/
9698 WERROR _spoolss_5d(pipes_struct *p,
9699 struct spoolss_5d *r)
9701 p->rng_fault_state = true;
9702 return WERR_NOT_SUPPORTED;
9705 /****************************************************************
9707 ****************************************************************/
9709 WERROR _spoolss_5e(pipes_struct *p,
9710 struct spoolss_5e *r)
9712 p->rng_fault_state = true;
9713 return WERR_NOT_SUPPORTED;
9716 /****************************************************************
9718 ****************************************************************/
9720 WERROR _spoolss_5f(pipes_struct *p,
9721 struct spoolss_5f *r)
9723 p->rng_fault_state = true;
9724 return WERR_NOT_SUPPORTED;
9727 /****************************************************************
9729 ****************************************************************/
9731 WERROR _spoolss_60(pipes_struct *p,
9732 struct spoolss_60 *r)
9734 p->rng_fault_state = true;
9735 return WERR_NOT_SUPPORTED;
9738 /****************************************************************
9740 ****************************************************************/
9742 WERROR _spoolss_61(pipes_struct *p,
9743 struct spoolss_61 *r)
9745 p->rng_fault_state = true;
9746 return WERR_NOT_SUPPORTED;
9749 /****************************************************************
9751 ****************************************************************/
9753 WERROR _spoolss_62(pipes_struct *p,
9754 struct spoolss_62 *r)
9756 p->rng_fault_state = true;
9757 return WERR_NOT_SUPPORTED;
9760 /****************************************************************
9762 ****************************************************************/
9764 WERROR _spoolss_63(pipes_struct *p,
9765 struct spoolss_63 *r)
9767 p->rng_fault_state = true;
9768 return WERR_NOT_SUPPORTED;
9771 /****************************************************************
9773 ****************************************************************/
9775 WERROR _spoolss_64(pipes_struct *p,
9776 struct spoolss_64 *r)
9778 p->rng_fault_state = true;
9779 return WERR_NOT_SUPPORTED;
9782 /****************************************************************
9784 ****************************************************************/
9786 WERROR _spoolss_65(pipes_struct *p,
9787 struct spoolss_65 *r)
9789 p->rng_fault_state = true;
9790 return WERR_NOT_SUPPORTED;
9793 /****************************************************************
9794 _spoolss_GetCorePrinterDrivers
9795 ****************************************************************/
9797 WERROR _spoolss_GetCorePrinterDrivers(pipes_struct *p,
9798 struct spoolss_GetCorePrinterDrivers *r)
9800 p->rng_fault_state = true;
9801 return WERR_NOT_SUPPORTED;
9804 /****************************************************************
9806 ****************************************************************/
9808 WERROR _spoolss_67(pipes_struct *p,
9809 struct spoolss_67 *r)
9811 p->rng_fault_state = true;
9812 return WERR_NOT_SUPPORTED;
9815 /****************************************************************
9816 _spoolss_GetPrinterDriverPackagePath
9817 ****************************************************************/
9819 WERROR _spoolss_GetPrinterDriverPackagePath(pipes_struct *p,
9820 struct spoolss_GetPrinterDriverPackagePath *r)
9822 p->rng_fault_state = true;
9823 return WERR_NOT_SUPPORTED;
9826 /****************************************************************
9828 ****************************************************************/
9830 WERROR _spoolss_69(pipes_struct *p,
9831 struct spoolss_69 *r)
9833 p->rng_fault_state = true;
9834 return WERR_NOT_SUPPORTED;
9837 /****************************************************************
9839 ****************************************************************/
9841 WERROR _spoolss_6a(pipes_struct *p,
9842 struct spoolss_6a *r)
9844 p->rng_fault_state = true;
9845 return WERR_NOT_SUPPORTED;
9848 /****************************************************************
9850 ****************************************************************/
9852 WERROR _spoolss_6b(pipes_struct *p,
9853 struct spoolss_6b *r)
9855 p->rng_fault_state = true;
9856 return WERR_NOT_SUPPORTED;
9859 /****************************************************************
9861 ****************************************************************/
9863 WERROR _spoolss_6c(pipes_struct *p,
9864 struct spoolss_6c *r)
9866 p->rng_fault_state = true;
9867 return WERR_NOT_SUPPORTED;
9870 /****************************************************************
9872 ****************************************************************/
9874 WERROR _spoolss_6d(pipes_struct *p,
9875 struct spoolss_6d *r)
9877 p->rng_fault_state = true;
9878 return WERR_NOT_SUPPORTED;