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.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 /* macros stolen from s4 spoolss server */
32 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
33 ((info)?ndr_size_##fn(info, level, ic, 0):0)
35 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
36 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
38 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
39 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
41 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
44 extern userdom_struct current_user_info;
47 #define DBGC_CLASS DBGC_RPC_SRV
49 #ifndef MAX_OPEN_PRINTER_EXS
50 #define MAX_OPEN_PRINTER_EXS 50
53 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
54 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
56 static Printer_entry *printers_list;
58 typedef struct _counter_printer_0 {
59 struct _counter_printer_0 *next;
60 struct _counter_printer_0 *prev;
66 static counter_printer_0 *counter_list;
68 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
69 static uint32_t smb_connections = 0;
72 /* in printing/nt_printing.c */
74 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
76 /* API table for Xcv Monitor functions */
78 struct xcv_api_table {
80 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
83 /********************************************************************
84 * Canonicalize servername.
85 ********************************************************************/
87 static const char *canon_servername(const char *servername)
89 const char *pservername = servername;
90 while (*pservername == '\\') {
96 /* translate between internal status numbers and NT status numbers */
97 static int nt_printj_status(int v)
103 return JOB_STATUS_PAUSED;
105 return JOB_STATUS_SPOOLING;
107 return JOB_STATUS_PRINTING;
109 return JOB_STATUS_ERROR;
111 return JOB_STATUS_DELETING;
113 return JOB_STATUS_OFFLINE;
115 return JOB_STATUS_PAPEROUT;
117 return JOB_STATUS_PRINTED;
119 return JOB_STATUS_DELETED;
121 return JOB_STATUS_BLOCKED_DEVQ;
122 case LPQ_USER_INTERVENTION:
123 return JOB_STATUS_USER_INTERVENTION;
128 static int nt_printq_status(int v)
132 return PRINTER_STATUS_PAUSED;
141 /***************************************************************************
142 Disconnect from the client
143 ****************************************************************************/
145 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
151 * Tell the specific printing tdb we no longer want messages for this printer
152 * by deregistering our PID.
155 if (!print_notify_deregister_pid(snum))
156 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
158 /* weird if the test succeds !!! */
159 if (smb_connections==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
167 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
168 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
169 win_errstr(result)));
171 /* if it's the last connection, deconnect the IPC$ share */
172 if (smb_connections==1) {
174 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
175 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
177 messaging_deregister(smbd_messaging_context(),
178 MSG_PRINTER_NOTIFY2, NULL);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static int printer_entry_destructor(Printer_entry *Printer)
195 if (Printer->notify.client_connected == true) {
198 if ( Printer->printer_type == SPLHND_SERVER) {
200 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
201 } else if (Printer->printer_type == SPLHND_PRINTER) {
202 snum = print_queue_snum(Printer->sharename);
204 srv_spoolss_replycloseprinter(snum,
205 &Printer->notify.client_hnd);
209 Printer->notify.flags=0;
210 Printer->notify.options=0;
211 Printer->notify.localmachine[0]='\0';
212 Printer->notify.printerlocal=0;
213 TALLOC_FREE(Printer->notify.option);
214 Printer->notify.client_connected = false;
216 free_nt_devicemode( &Printer->nt_devmode );
217 free_a_printer( &Printer->printer_info, 2 );
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list, Printer);
224 /****************************************************************************
225 find printer index by handle
226 ****************************************************************************/
228 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
229 struct policy_handle *hnd)
231 Printer_entry *find_printer = NULL;
233 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
234 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
241 /****************************************************************************
242 Close printer index by handle.
243 ****************************************************************************/
245 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
247 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
250 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
255 close_policy_hnd(p, hnd);
260 /****************************************************************************
261 Delete a printer given a handle.
262 ****************************************************************************/
264 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
266 char *cmd = lp_deleteprinter_cmd();
267 char *command = NULL;
269 SE_PRIV se_printop = SE_PRINT_OPERATOR;
270 bool is_print_op = false;
272 /* can't fail if we don't try */
277 command = talloc_asprintf(ctx,
284 is_print_op = user_has_privileges( token, &se_printop );
286 DEBUG(10,("Running [%s]\n", command));
288 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
293 if ( (ret = smbrun(command, NULL)) == 0 ) {
294 /* Tell everyone we updated smb.conf. */
295 message_send_all(smbd_messaging_context(),
296 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
302 /********** END SePrintOperatorPrivlege BLOCK **********/
304 DEBUGADD(10,("returned [%d]\n", ret));
306 TALLOC_FREE(command);
309 return WERR_BADFID; /* What to return here? */
311 /* go ahead and re-read the services immediately */
313 reload_services(false);
316 if ( lp_servicenumber( sharename ) < 0 )
317 return WERR_ACCESS_DENIED;
322 /****************************************************************************
323 Delete a printer given a handle.
324 ****************************************************************************/
326 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
328 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
331 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
337 * It turns out that Windows allows delete printer on a handle
338 * opened by an admin user, then used on a pipe handle created
339 * by an anonymous user..... but they're working on security.... riiight !
343 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
344 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
345 return WERR_ACCESS_DENIED;
348 /* this does not need a become root since the access check has been
349 done on the handle already */
351 if (del_a_printer( Printer->sharename ) != 0) {
352 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
356 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
357 Printer->sharename );
360 /****************************************************************************
361 Return the snum of a printer corresponding to an handle.
362 ****************************************************************************/
364 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
365 int *number, struct share_params **params)
367 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
370 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
375 switch (Printer->printer_type) {
377 DEBUG(4,("short name:%s\n", Printer->sharename));
378 *number = print_queue_snum(Printer->sharename);
379 return (*number != -1);
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
394 DEBUG(3,("Setting printer type=%s\n", handlename));
396 if ( strlen(handlename) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
401 /* it's a print server */
402 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer->printer_type = SPLHND_SERVER;
406 /* it's a printer (set_printer_hnd_name() will handle port monitors */
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer->printer_type = SPLHND_PRINTER;
415 /****************************************************************************
416 Set printer handle name.. Accept names like \\server, \\server\printer,
417 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
418 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
419 XcvDataPort() interface.
420 ****************************************************************************/
422 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
425 int n_services=lp_numservices();
426 char *aprinter, *printername;
427 const char *servername;
430 NT_PRINTER_INFO_LEVEL *printer = NULL;
433 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
434 (unsigned long)strlen(handlename)));
436 aprinter = CONST_DISCARD(char *, handlename);
437 if ( *handlename == '\\' ) {
438 servername = canon_servername(handlename);
439 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
444 servername = global_myname();
447 /* save the servername to fill in replies on this handle */
449 if ( !is_myname_or_ipaddr( servername ) )
452 fstrcpy( Printer->servername, servername );
454 if ( Printer->printer_type == SPLHND_SERVER )
457 if ( Printer->printer_type != SPLHND_PRINTER )
460 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
462 /* check for the Port Monitor Interface */
464 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
465 Printer->printer_type = SPLHND_PORTMON_TCP;
466 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
469 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
470 Printer->printer_type = SPLHND_PORTMON_LOCAL;
471 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
475 /* Search all sharenames first as this is easier than pulling
476 the printer_info_2 off of disk. Don't use find_service() since
477 that calls out to map_username() */
479 /* do another loop to look for printernames */
481 for (snum=0; !found && snum<n_services; snum++) {
483 /* no point going on if this is not a printer */
485 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
488 fstrcpy(sname, lp_servicename(snum));
489 if ( strequal( aprinter, sname ) ) {
494 /* no point looking up the printer object if
495 we aren't allowing printername != sharename */
497 if ( lp_force_printername(snum) )
500 fstrcpy(sname, lp_servicename(snum));
504 /* This call doesn't fill in the location or comment from
505 * a CUPS server for efficiency with large numbers of printers.
509 result = get_a_printer_search( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, win_errstr(result)));
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
526 if ( strequal(printername, aprinter) ) {
527 free_a_printer( &printer, 2);
532 DEBUGADD(10, ("printername: %s\n", printername));
534 free_a_printer( &printer, 2);
537 free_a_printer( &printer, 2);
540 DEBUGADD(4,("Printer not found\n"));
544 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
546 fstrcpy(Printer->sharename, sname);
551 /****************************************************************************
552 Find first available printer slot. creates a printer handle for you.
553 ****************************************************************************/
555 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
556 const char *name, uint32_t access_granted)
558 Printer_entry *new_printer;
560 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
562 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
563 if (new_printer == NULL) {
566 talloc_set_destructor(new_printer, printer_entry_destructor);
568 if (!create_policy_hnd(p, hnd, new_printer)) {
569 TALLOC_FREE(new_printer);
573 /* Add to the internal list. */
574 DLIST_ADD(printers_list, new_printer);
576 new_printer->notify.option=NULL;
578 if (!set_printer_hnd_printertype(new_printer, name)) {
579 close_printer_handle(p, hnd);
583 if (!set_printer_hnd_name(new_printer, name)) {
584 close_printer_handle(p, hnd);
588 new_printer->access_granted = access_granted;
590 DEBUG(5, ("%d printer handles active\n",
591 (int)num_pipe_handles(p->pipe_handles)));
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
602 uint16_t notify_field)
607 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
608 uint16_t notify_field)
610 struct spoolss_NotifyOption *option = p->notify.option;
614 * Flags should always be zero when the change notify
615 * is registered by the client's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
625 return is_monitoring_event_flags(
626 p->notify.flags, notify_type, notify_field);
628 for (i = 0; i < option->count; i++) {
630 /* Check match for notify_type */
632 if (option->types[i].type != notify_type)
635 /* Check match for field */
637 for (j = 0; j < option->types[i].count; j++) {
638 if (option->types[i].fields[j].field == notify_field) {
644 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645 p->servername, p->sharename, notify_type, notify_field));
650 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
651 _data->data.integer[0] = _integer; \
652 _data->data.integer[1] = 0;
655 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
656 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
657 if (!_data->data.string.string) {\
658 _data->data.string.size = 0; \
660 _data->data.string.size = strlen_m_term(_p) * 2;
662 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
663 _data->data.devmode.devmode = _devmode;
665 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
666 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
667 if (!_data->data.sd.sd) { \
668 _data->data.sd.sd_size = 0; \
670 _data->data.sd.sd_size = _size;
672 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
677 struct spoolss_Time st;
681 if (!init_systemtime(&st, t)) {
685 p = talloc_array(mem_ctx, char, len);
691 * Systemtime must be linearized as a set of UINT16's.
692 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
695 SSVAL(p, 0, st.year);
696 SSVAL(p, 2, st.month);
697 SSVAL(p, 4, st.day_of_week);
699 SSVAL(p, 8, st.hour);
700 SSVAL(p, 10, st.minute);
701 SSVAL(p, 12, st.second);
702 SSVAL(p, 14, st.millisecond);
708 /* Convert a notification message to a struct spoolss_Notify */
710 static void notify_one_value(struct spoolss_notify_msg *msg,
711 struct spoolss_Notify *data,
714 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
717 static void notify_string(struct spoolss_notify_msg *msg,
718 struct spoolss_Notify *data,
721 /* The length of the message includes the trailing \0 */
723 data->data.string.size = msg->len * 2;
724 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
725 if (!data->data.string.string) {
726 data->data.string.size = 0;
731 static void notify_system_time(struct spoolss_notify_msg *msg,
732 struct spoolss_Notify *data,
735 data->data.string.string = NULL;
736 data->data.string.size = 0;
738 if (msg->len != sizeof(time_t)) {
739 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
744 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
745 &data->data.string.string,
746 &data->data.string.size);
749 struct notify2_message_table {
751 void (*fn)(struct spoolss_notify_msg *msg,
752 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
755 static struct notify2_message_table printer_notify_table[] = {
756 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
757 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
758 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
759 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
760 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
761 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
762 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
763 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
764 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
765 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
766 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
767 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
768 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
769 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
770 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
771 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
772 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
773 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
774 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
777 static struct notify2_message_table job_notify_table[] = {
778 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
779 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
780 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
781 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
782 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
783 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
784 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
785 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
786 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
787 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
788 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
789 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
790 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
791 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
792 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
793 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
794 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
795 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
796 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
797 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
798 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
799 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
800 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
801 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
805 /***********************************************************************
806 Allocate talloc context for container object
807 **********************************************************************/
809 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
814 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
819 /***********************************************************************
820 release all allocated memory and zero out structure
821 **********************************************************************/
823 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
829 talloc_destroy(ctr->ctx);
836 /***********************************************************************
837 **********************************************************************/
839 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
847 /***********************************************************************
848 **********************************************************************/
850 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
852 if ( !ctr || !ctr->msg_groups )
855 if ( idx >= ctr->num_groups )
858 return &ctr->msg_groups[idx];
862 /***********************************************************************
863 How many groups of change messages do we have ?
864 **********************************************************************/
866 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
871 return ctr->num_groups;
874 /***********************************************************************
875 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
876 **********************************************************************/
878 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
880 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
881 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
882 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
888 /* loop over all groups looking for a matching printer name */
890 for ( i=0; i<ctr->num_groups; i++ ) {
891 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
895 /* add a new group? */
897 if ( i == ctr->num_groups ) {
900 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
901 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904 ctr->msg_groups = groups;
906 /* clear the new entry and set the printer name */
908 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
909 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
912 /* add the change messages; 'i' is the correct index now regardless */
914 msg_grp = &ctr->msg_groups[i];
918 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
919 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
922 msg_grp->msgs = msg_list;
924 new_slot = msg_grp->num_msgs-1;
925 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
927 /* need to allocate own copy of data */
930 msg_grp->msgs[new_slot].notify.data = (char *)
931 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
933 return ctr->num_groups;
936 /***********************************************************************
937 Send a change notication message on all handles which have a call
939 **********************************************************************/
941 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
944 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
945 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
946 SPOOLSS_NOTIFY_MSG *messages;
947 int sending_msg_count;
950 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954 messages = msg_group->msgs;
957 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
963 /* loop over all printers */
965 for (p = printers_list; p; p = p->next) {
966 struct spoolss_Notify *notifies;
971 /* Is there notification on this handle? */
973 if ( !p->notify.client_connected )
976 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
978 /* For this printer? Print servers always receive
981 if ( ( p->printer_type == SPLHND_PRINTER ) &&
982 ( !strequal(msg_group->printername, p->sharename) ) )
985 DEBUG(10,("Our printer\n"));
987 /* allocate the max entries possible */
989 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
994 /* build the array of change notifications */
996 sending_msg_count = 0;
998 for ( i=0; i<msg_group->num_msgs; i++ ) {
999 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1001 /* Are we monitoring this event? */
1003 if (!is_monitoring_event(p, msg->type, msg->field))
1006 sending_msg_count++;
1009 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1010 msg->type, msg->field, p->sharename));
1013 * if the is a printer notification handle and not a job notification
1014 * type, then set the id to 0. Other wise just use what was specified
1017 * When registering change notification on a print server handle
1018 * we always need to send back the id (snum) matching the printer
1019 * for which the change took place. For change notify registered
1020 * on a printer handle, this does not matter and the id should be 0.
1025 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1031 /* Convert unix jobid to smb jobid */
1033 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1034 id = sysjob_to_jobid(msg->id);
1037 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1042 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1045 case PRINTER_NOTIFY_TYPE:
1046 if ( printer_notify_table[msg->field].fn )
1047 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1050 case JOB_NOTIFY_TYPE:
1051 if ( job_notify_table[msg->field].fn )
1052 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1056 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1063 if ( sending_msg_count ) {
1066 union spoolss_ReplyPrinterInfo info;
1067 struct spoolss_NotifyInfo info0;
1068 uint32_t reply_result;
1070 info0.version = 0x2;
1071 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1072 info0.count = count;
1073 info0.notifies = notifies;
1075 info.info0 = &info0;
1077 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1078 &p->notify.client_hnd,
1079 p->notify.change, /* color */
1082 0, /* reply_type, must be 0 */
1085 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1086 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1087 notify_cli_pipe->srv_name_slash,
1090 switch (reply_result) {
1093 case PRINTER_NOTIFY_INFO_DISCARDED:
1094 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1095 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1104 DEBUG(8,("send_notify2_changes: Exit...\n"));
1108 /***********************************************************************
1109 **********************************************************************/
1111 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1114 uint32_t tv_sec, tv_usec;
1117 /* Unpack message */
1119 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1122 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1124 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1127 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1128 &msg->notify.value[0], &msg->notify.value[1]);
1130 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1131 &msg->len, &msg->notify.data);
1133 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1134 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1136 tv->tv_sec = tv_sec;
1137 tv->tv_usec = tv_usec;
1140 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1141 msg->notify.value[1]));
1143 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1148 /********************************************************************
1149 Receive a notify2 message list
1150 ********************************************************************/
1152 static void receive_notify2_message_list(struct messaging_context *msg,
1155 struct server_id server_id,
1158 size_t msg_count, i;
1159 char *buf = (char *)data->data;
1162 SPOOLSS_NOTIFY_MSG notify;
1163 SPOOLSS_NOTIFY_MSG_CTR messages;
1166 if (data->length < 4) {
1167 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1171 msg_count = IVAL(buf, 0);
1174 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1176 if (msg_count == 0) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1181 /* initialize the container */
1183 ZERO_STRUCT( messages );
1184 notify_msg_ctr_init( &messages );
1187 * build message groups for each printer identified
1188 * in a change_notify msg. Remember that a PCN message
1189 * includes the handle returned for the srv_spoolss_replyopenprinter()
1190 * call. Therefore messages are grouped according to printer handle.
1193 for ( i=0; i<msg_count; i++ ) {
1194 struct timeval msg_tv;
1196 if (msg_ptr + 4 - buf > data->length) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1201 msg_len = IVAL(msg_ptr,0);
1204 if (msg_ptr + msg_len - buf > data->length) {
1205 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1209 /* unpack messages */
1211 ZERO_STRUCT( notify );
1212 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1215 /* add to correct list in container */
1217 notify_msg_ctr_addmsg( &messages, ¬ify );
1219 /* free memory that might have been allocated by notify2_unpack_msg() */
1221 if ( notify.len != 0 )
1222 SAFE_FREE( notify.notify.data );
1225 /* process each group of messages */
1227 num_groups = notify_msg_ctr_numgroups( &messages );
1228 for ( i=0; i<num_groups; i++ )
1229 send_notify2_changes( &messages, i );
1234 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1235 (uint32_t)msg_count ));
1237 notify_msg_ctr_destroy( &messages );
1242 /********************************************************************
1243 Send a message to ourself about new driver being installed
1244 so we can upgrade the information for each printer bound to this
1246 ********************************************************************/
1248 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1250 int len = strlen(drivername);
1255 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1258 messaging_send_buf(smbd_messaging_context(), procid_self(),
1259 MSG_PRINTER_DRVUPGRADE,
1260 (uint8_t *)drivername, len+1);
1265 /**********************************************************************
1266 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1267 over all printers, upgrading ones as necessary
1268 **********************************************************************/
1270 void do_drv_upgrade_printer(struct messaging_context *msg,
1273 struct server_id server_id,
1278 int n_services = lp_numservices();
1281 len = MIN(data->length,sizeof(drivername)-1);
1282 strncpy(drivername, (const char *)data->data, len);
1284 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1286 /* Iterate the printer list */
1288 for (snum=0; snum<n_services; snum++)
1290 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1293 NT_PRINTER_INFO_LEVEL *printer = NULL;
1295 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1296 if (!W_ERROR_IS_OK(result))
1299 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1301 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1303 /* all we care about currently is the change_id */
1305 result = mod_a_printer(printer, 2);
1306 if (!W_ERROR_IS_OK(result)) {
1307 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308 win_errstr(result)));
1312 free_a_printer(&printer, 2);
1319 /********************************************************************
1320 Update the cache for all printq's with a registered client
1322 ********************************************************************/
1324 void update_monitored_printq_cache( void )
1326 Printer_entry *printer = printers_list;
1329 /* loop through all printers and update the cache where
1330 client_connected == true */
1333 if ( (printer->printer_type == SPLHND_PRINTER)
1334 && printer->notify.client_connected )
1336 snum = print_queue_snum(printer->sharename);
1337 print_queue_status( snum, NULL, NULL );
1340 printer = printer->next;
1345 /********************************************************************
1346 Send a message to ourself about new driver being installed
1347 so we can upgrade the information for each printer bound to this
1349 ********************************************************************/
1351 static bool srv_spoolss_reset_printerdata(char* drivername)
1353 int len = strlen(drivername);
1358 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361 messaging_send_buf(smbd_messaging_context(), procid_self(),
1362 MSG_PRINTERDATA_INIT_RESET,
1363 (uint8_t *)drivername, len+1);
1368 /**********************************************************************
1369 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1370 over all printers, resetting printer data as neessary
1371 **********************************************************************/
1373 void reset_all_printerdata(struct messaging_context *msg,
1376 struct server_id server_id,
1381 int n_services = lp_numservices();
1384 len = MIN( data->length, sizeof(drivername)-1 );
1385 strncpy( drivername, (const char *)data->data, len );
1387 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1389 /* Iterate the printer list */
1391 for ( snum=0; snum<n_services; snum++ )
1393 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1396 NT_PRINTER_INFO_LEVEL *printer = NULL;
1398 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1399 if ( !W_ERROR_IS_OK(result) )
1403 * if the printer is bound to the driver,
1404 * then reset to the new driver initdata
1407 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1409 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1411 if ( !set_driver_init(printer, 2) ) {
1412 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1413 printer->info_2->printername, printer->info_2->drivername));
1416 result = mod_a_printer( printer, 2 );
1417 if ( !W_ERROR_IS_OK(result) ) {
1418 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1419 get_dos_error_msg(result)));
1423 free_a_printer( &printer, 2 );
1432 /****************************************************************
1433 _spoolss_OpenPrinter
1434 ****************************************************************/
1436 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1437 struct spoolss_OpenPrinter *r)
1439 struct spoolss_OpenPrinterEx e;
1442 ZERO_STRUCT(e.in.userlevel);
1444 e.in.printername = r->in.printername;
1445 e.in.datatype = r->in.datatype;
1446 e.in.devmode_ctr = r->in.devmode_ctr;
1447 e.in.access_mask = r->in.access_mask;
1450 e.out.handle = r->out.handle;
1452 werr = _spoolss_OpenPrinterEx(p, &e);
1454 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1455 /* OpenPrinterEx returns this for a bad
1456 * printer name. We must return WERR_INVALID_PRINTER_NAME
1459 werr = WERR_INVALID_PRINTER_NAME;
1465 /********************************************************************
1466 ********************************************************************/
1468 bool convert_devicemode(const char *printername,
1469 const struct spoolss_DeviceMode *devmode,
1470 NT_DEVICEMODE **pp_nt_devmode)
1472 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1475 * Ensure nt_devmode is a valid pointer
1476 * as we will be overwriting it.
1479 if (nt_devmode == NULL) {
1480 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1481 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1485 rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
1486 rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
1488 nt_devmode->specversion = devmode->specversion;
1489 nt_devmode->driverversion = devmode->driverversion;
1490 nt_devmode->size = devmode->size;
1491 nt_devmode->fields = devmode->fields;
1492 nt_devmode->orientation = devmode->orientation;
1493 nt_devmode->papersize = devmode->papersize;
1494 nt_devmode->paperlength = devmode->paperlength;
1495 nt_devmode->paperwidth = devmode->paperwidth;
1496 nt_devmode->scale = devmode->scale;
1497 nt_devmode->copies = devmode->copies;
1498 nt_devmode->defaultsource = devmode->defaultsource;
1499 nt_devmode->printquality = devmode->printquality;
1500 nt_devmode->color = devmode->color;
1501 nt_devmode->duplex = devmode->duplex;
1502 nt_devmode->yresolution = devmode->yresolution;
1503 nt_devmode->ttoption = devmode->ttoption;
1504 nt_devmode->collate = devmode->collate;
1506 nt_devmode->logpixels = devmode->logpixels;
1507 nt_devmode->bitsperpel = devmode->bitsperpel;
1508 nt_devmode->pelswidth = devmode->pelswidth;
1509 nt_devmode->pelsheight = devmode->pelsheight;
1510 nt_devmode->displayflags = devmode->displayflags;
1511 nt_devmode->displayfrequency = devmode->displayfrequency;
1512 nt_devmode->icmmethod = devmode->icmmethod;
1513 nt_devmode->icmintent = devmode->icmintent;
1514 nt_devmode->mediatype = devmode->mediatype;
1515 nt_devmode->dithertype = devmode->dithertype;
1516 nt_devmode->reserved1 = devmode->reserved1;
1517 nt_devmode->reserved2 = devmode->reserved2;
1518 nt_devmode->panningwidth = devmode->panningwidth;
1519 nt_devmode->panningheight = devmode->panningheight;
1522 * Only change private and driverextra if the incoming devmode
1523 * has a new one. JRA.
1526 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1527 SAFE_FREE(nt_devmode->nt_dev_private);
1528 nt_devmode->driverextra = devmode->__driverextra_length;
1529 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1531 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1534 *pp_nt_devmode = nt_devmode;
1539 /****************************************************************
1540 _spoolss_OpenPrinterEx
1541 ****************************************************************/
1543 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1544 struct spoolss_OpenPrinterEx *r)
1547 Printer_entry *Printer=NULL;
1549 if (!r->in.printername) {
1550 return WERR_INVALID_PARAM;
1553 /* some sanity check because you can open a printer or a print server */
1554 /* aka: \\server\printer or \\server */
1556 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1558 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1559 ZERO_STRUCTP(r->out.handle);
1560 return WERR_INVALID_PARAM;
1563 Printer = find_printer_index_by_hnd(p, r->out.handle);
1565 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1566 "handle we created for printer %s\n", r->in.printername));
1567 close_printer_handle(p, r->out.handle);
1568 ZERO_STRUCTP(r->out.handle);
1569 return WERR_INVALID_PARAM;
1573 * First case: the user is opening the print server:
1575 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1576 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1578 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1579 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1580 * or if the user is listed in the smb.conf printer admin parameter.
1582 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1583 * client view printer folder, but does not show the MSAPW.
1585 * Note: this test needs code to check access rights here too. Jeremy
1586 * could you look at this?
1588 * Second case: the user is opening a printer:
1589 * NT doesn't let us connect to a printer if the connecting user
1590 * doesn't have print permission.
1592 * Third case: user is opening a Port Monitor
1593 * access checks same as opening a handle to the print server.
1596 switch (Printer->printer_type )
1599 case SPLHND_PORTMON_TCP:
1600 case SPLHND_PORTMON_LOCAL:
1601 /* Printserver handles use global struct... */
1605 /* Map standard access rights to object specific access rights */
1607 se_map_standard(&r->in.access_mask,
1608 &printserver_std_mapping);
1610 /* Deny any object specific bits that don't apply to print
1611 servers (i.e printer and job specific bits) */
1613 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1615 if (r->in.access_mask &
1616 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1617 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1618 close_printer_handle(p, r->out.handle);
1619 ZERO_STRUCTP(r->out.handle);
1620 return WERR_ACCESS_DENIED;
1623 /* Allow admin access */
1625 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1627 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1629 if (!lp_ms_add_printer_wizard()) {
1630 close_printer_handle(p, r->out.handle);
1631 ZERO_STRUCTP(r->out.handle);
1632 return WERR_ACCESS_DENIED;
1635 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1636 and not a printer admin, then fail */
1638 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1639 !user_has_privileges(p->server_info->ptok,
1641 !token_contains_name_in_list(
1642 uidtoname(p->server_info->utok.uid),
1644 p->server_info->ptok,
1645 lp_printer_admin(snum))) {
1646 close_printer_handle(p, r->out.handle);
1647 ZERO_STRUCTP(r->out.handle);
1648 return WERR_ACCESS_DENIED;
1651 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1655 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1658 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1659 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1661 /* We fall through to return WERR_OK */
1664 case SPLHND_PRINTER:
1665 /* NT doesn't let us connect to a printer if the connecting user
1666 doesn't have print permission. */
1668 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1669 close_printer_handle(p, r->out.handle);
1670 ZERO_STRUCTP(r->out.handle);
1674 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1676 /* map an empty access mask to the minimum access mask */
1677 if (r->in.access_mask == 0x0)
1678 r->in.access_mask = PRINTER_ACCESS_USE;
1681 * If we are not serving the printer driver for this printer,
1682 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1683 * will keep NT clients happy --jerry
1686 if (lp_use_client_driver(snum)
1687 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1689 r->in.access_mask = PRINTER_ACCESS_USE;
1692 /* check smb.conf parameters and the the sec_desc */
1694 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1695 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1696 ZERO_STRUCTP(r->out.handle);
1697 return WERR_ACCESS_DENIED;
1700 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1701 p->server_info->ptok, snum) ||
1702 !print_access_check(p->server_info, snum,
1703 r->in.access_mask)) {
1704 DEBUG(3, ("access DENIED for printer open\n"));
1705 close_printer_handle(p, r->out.handle);
1706 ZERO_STRUCTP(r->out.handle);
1707 return WERR_ACCESS_DENIED;
1710 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1711 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1712 close_printer_handle(p, r->out.handle);
1713 ZERO_STRUCTP(r->out.handle);
1714 return WERR_ACCESS_DENIED;
1717 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1718 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1720 r->in.access_mask = PRINTER_ACCESS_USE;
1722 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1723 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1728 /* sanity check to prevent programmer error */
1729 ZERO_STRUCTP(r->out.handle);
1733 Printer->access_granted = r->in.access_mask;
1736 * If the client sent a devmode in the OpenPrinter() call, then
1737 * save it here in case we get a job submission on this handle
1740 if ((Printer->printer_type != SPLHND_SERVER) &&
1741 r->in.devmode_ctr.devmode) {
1742 convert_devicemode(Printer->sharename,
1743 r->in.devmode_ctr.devmode,
1744 &Printer->nt_devmode);
1747 #if 0 /* JERRY -- I'm doubtful this is really effective */
1748 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1749 optimization in Windows 2000 clients --jerry */
1751 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1752 && (RA_WIN2K == get_remote_arch()) )
1754 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1755 sys_usleep( 500000 );
1762 /****************************************************************************
1763 ****************************************************************************/
1765 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1766 NT_PRINTER_INFO_LEVEL_2 *d)
1768 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1774 d->attributes = r->attributes;
1775 d->priority = r->priority;
1776 d->default_priority = r->defaultpriority;
1777 d->starttime = r->starttime;
1778 d->untiltime = r->untiltime;
1779 d->status = r->status;
1780 d->cjobs = r->cjobs;
1782 fstrcpy(d->servername, r->servername);
1783 fstrcpy(d->printername, r->printername);
1784 fstrcpy(d->sharename, r->sharename);
1785 fstrcpy(d->portname, r->portname);
1786 fstrcpy(d->drivername, r->drivername);
1787 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1788 fstrcpy(d->location, r->location);
1789 fstrcpy(d->sepfile, r->sepfile);
1790 fstrcpy(d->printprocessor, r->printprocessor);
1791 fstrcpy(d->datatype, r->datatype);
1792 fstrcpy(d->parameters, r->parameters);
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1801 NT_PRINTER_INFO_LEVEL *printer)
1805 switch (info_ctr->level) {
1807 /* allocate memory if needed. Messy because
1808 convert_printer_info is used to update an existing
1809 printer or build a new one */
1811 if (!printer->info_2) {
1812 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1813 if (!printer->info_2) {
1814 DEBUG(0,("convert_printer_info: "
1815 "talloc() failed!\n"));
1820 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1822 printer->info_2->setuptime = time(NULL);
1829 /*******************************************************************
1830 ********************************************************************/
1832 static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
1841 *farray = SMB_MALLOC_ARRAY(fstring, 1);
1846 for (i=0; sarray[i] != NULL; i++) {
1847 *farray = SMB_REALLOC_ARRAY(*farray, fstring, i+2);
1851 fstrcpy((*farray)[i], sarray[i]);
1854 fstrcpy((*farray)[i], "");
1859 /*******************************************************************
1860 ********************************************************************/
1862 static bool driver_info3_to_nt_driver_info3(struct spoolss_AddDriverInfo3 *r,
1863 NT_PRINTER_DRIVER_INFO_LEVEL_3 **p)
1865 NT_PRINTER_DRIVER_INFO_LEVEL_3 *d;
1867 DEBUG(7,("driver_info3_to_nt_driver_info3: Converting from UNICODE to ASCII\n"));
1870 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
1879 d->cversion = r->version;
1881 fstrcpy(d->name, r->driver_name);
1882 fstrcpy(d->environment, r->architecture);
1883 fstrcpy(d->driverpath, r->driver_path);
1884 fstrcpy(d->datafile, r->data_file);
1885 fstrcpy(d->configfile, r->config_file);
1886 fstrcpy(d->helpfile, r->help_file);
1887 fstrcpy(d->monitorname, r->monitor_name);
1888 fstrcpy(d->defaultdatatype, r->default_datatype);
1890 DEBUGADD(8,( "version: %d\n", d->cversion));
1891 DEBUGADD(8,( "name: %s\n", d->name));
1892 DEBUGADD(8,( "environment: %s\n", d->environment));
1893 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1894 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1895 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1896 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1897 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1898 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1900 if (r->dependent_files) {
1901 if (!string_array_to_fstring_array(r->dependent_files->string,
1902 &d->dependentfiles)) {
1911 /*******************************************************************
1912 ********************************************************************/
1914 static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
1915 NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
1917 NT_PRINTER_DRIVER_INFO_LEVEL_6 *d;
1919 DEBUG(7,("driver_info6_to_nt_driver_info6: Converting from UNICODE to ASCII\n"));
1922 *p = SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
1931 d->version = r->version;
1933 fstrcpy(d->name, r->driver_name);
1934 fstrcpy(d->environment, r->architecture);
1935 fstrcpy(d->driverpath, r->driver_path);
1936 fstrcpy(d->datafile, r->data_file);
1937 fstrcpy(d->configfile, r->config_file);
1938 fstrcpy(d->helpfile, r->help_file);
1939 fstrcpy(d->monitorname, r->monitor_name);
1940 fstrcpy(d->defaultdatatype, r->default_datatype);
1942 DEBUGADD(8,( "version: %d\n", d->version));
1943 DEBUGADD(8,( "name: %s\n", d->name));
1944 DEBUGADD(8,( "environment: %s\n", d->environment));
1945 DEBUGADD(8,( "driverpath: %s\n", d->driverpath));
1946 DEBUGADD(8,( "datafile: %s\n", d->datafile));
1947 DEBUGADD(8,( "configfile: %s\n", d->configfile));
1948 DEBUGADD(8,( "helpfile: %s\n", d->helpfile));
1949 DEBUGADD(8,( "monitorname: %s\n", d->monitorname));
1950 DEBUGADD(8,( "defaultdatatype: %s\n", d->defaultdatatype));
1952 if (r->dependent_files) {
1953 if (!string_array_to_fstring_array(r->dependent_files->string,
1954 &d->dependentfiles)) {
1959 if (r->previous_names) {
1960 if (!string_array_to_fstring_array(r->previous_names->string,
1961 &d->previousnames)) {
1973 /********************************************************************
1974 ********************************************************************/
1976 static bool convert_printer_driver_info(const struct spoolss_AddDriverInfoCtr *r,
1977 NT_PRINTER_DRIVER_INFO_LEVEL *printer,
1982 printer->info_3 = NULL;
1983 if (!driver_info3_to_nt_driver_info3(r->info.info3, &printer->info_3)) {
1988 printer->info_6 = NULL;
1989 if (!driver_info6_to_nt_driver_info6(r->info.info6, &printer->info_6)) {
2000 /****************************************************************
2001 _spoolss_ClosePrinter
2002 ****************************************************************/
2004 WERROR _spoolss_ClosePrinter(pipes_struct *p,
2005 struct spoolss_ClosePrinter *r)
2007 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2009 if (Printer && Printer->document_started) {
2010 struct spoolss_EndDocPrinter e;
2012 e.in.handle = r->in.handle;
2014 _spoolss_EndDocPrinter(p, &e);
2017 if (!close_printer_handle(p, r->in.handle))
2020 /* clear the returned printer handle. Observed behavior
2021 from Win2k server. Don't think this really matters.
2022 Previous code just copied the value of the closed
2025 ZERO_STRUCTP(r->out.handle);
2030 /****************************************************************
2031 _spoolss_DeletePrinter
2032 ****************************************************************/
2034 WERROR _spoolss_DeletePrinter(pipes_struct *p,
2035 struct spoolss_DeletePrinter *r)
2037 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2040 if (Printer && Printer->document_started) {
2041 struct spoolss_EndDocPrinter e;
2043 e.in.handle = r->in.handle;
2045 _spoolss_EndDocPrinter(p, &e);
2048 result = delete_printer_handle(p, r->in.handle);
2050 update_c_setprinter(false);
2055 /*******************************************************************
2056 * static function to lookup the version id corresponding to an
2057 * long architecture string
2058 ******************************************************************/
2060 static int get_version_id(const char *arch)
2063 struct print_architecture_table_node archi_table[]= {
2065 {"Windows 4.0", "WIN40", 0 },
2066 {"Windows NT x86", "W32X86", 2 },
2067 {"Windows NT R4000", "W32MIPS", 2 },
2068 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2069 {"Windows NT PowerPC", "W32PPC", 2 },
2070 {"Windows IA64", "IA64", 3 },
2071 {"Windows x64", "x64", 3 },
2075 for (i=0; archi_table[i].long_archi != NULL; i++)
2077 if (strcmp(arch, archi_table[i].long_archi) == 0)
2078 return (archi_table[i].version);
2084 /****************************************************************
2085 _spoolss_DeletePrinterDriver
2086 ****************************************************************/
2088 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
2089 struct spoolss_DeletePrinterDriver *r)
2091 NT_PRINTER_DRIVER_INFO_LEVEL info;
2092 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2095 WERROR status_win2k = WERR_ACCESS_DENIED;
2096 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2098 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2099 and not a printer admin, then fail */
2101 if ( (p->server_info->utok.uid != sec_initial_uid())
2102 && !user_has_privileges(p->server_info->ptok, &se_printop )
2103 && !token_contains_name_in_list(
2104 uidtoname(p->server_info->utok.uid), NULL,
2105 NULL, p->server_info->ptok,
2106 lp_printer_admin(-1)) )
2108 return WERR_ACCESS_DENIED;
2111 /* check that we have a valid driver name first */
2113 if ((version = get_version_id(r->in.architecture)) == -1)
2114 return WERR_INVALID_ENVIRONMENT;
2117 ZERO_STRUCT(info_win2k);
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2123 /* try for Win2k driver if "Windows NT x86" */
2125 if ( version == 2 ) {
2127 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3,
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2135 /* otherwise it was a failure */
2137 status = WERR_UNKNOWN_PRINTER_DRIVER;
2143 if (printer_driver_in_use(info.info_3)) {
2144 status = WERR_PRINTER_DRIVER_IN_USE;
2150 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2152 r->in.architecture, 3)))
2154 /* if we get to here, we now have 2 driver info structures to remove */
2155 /* remove the Win2k driver first*/
2157 status_win2k = delete_printer_driver(
2158 p, info_win2k.info_3, 3, false);
2159 free_a_printer_driver( info_win2k, 3 );
2161 /* this should not have failed---if it did, report to client */
2162 if ( !W_ERROR_IS_OK(status_win2k) )
2164 status = status_win2k;
2170 status = delete_printer_driver(p, info.info_3, version, false);
2172 /* if at least one of the deletes succeeded return OK */
2174 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2178 free_a_printer_driver( info, 3 );
2183 /****************************************************************
2184 _spoolss_DeletePrinterDriverEx
2185 ****************************************************************/
2187 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2188 struct spoolss_DeletePrinterDriverEx *r)
2190 NT_PRINTER_DRIVER_INFO_LEVEL info;
2191 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2195 WERROR status_win2k = WERR_ACCESS_DENIED;
2196 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2198 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2199 and not a printer admin, then fail */
2201 if ( (p->server_info->utok.uid != sec_initial_uid())
2202 && !user_has_privileges(p->server_info->ptok, &se_printop )
2203 && !token_contains_name_in_list(
2204 uidtoname(p->server_info->utok.uid), NULL, NULL,
2205 p->server_info->ptok, lp_printer_admin(-1)) )
2207 return WERR_ACCESS_DENIED;
2210 /* check that we have a valid driver name first */
2211 if ((version = get_version_id(r->in.architecture)) == -1) {
2212 /* this is what NT returns */
2213 return WERR_INVALID_ENVIRONMENT;
2216 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2217 version = r->in.version;
2220 ZERO_STRUCT(info_win2k);
2222 status = get_a_printer_driver(&info, 3, r->in.driver,
2223 r->in.architecture, version);
2225 if ( !W_ERROR_IS_OK(status) )
2228 * if the client asked for a specific version,
2229 * or this is something other than Windows NT x86,
2233 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2236 /* try for Win2k driver if "Windows NT x86" */
2239 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, r->in.driver,
2242 status = WERR_UNKNOWN_PRINTER_DRIVER;
2247 if ( printer_driver_in_use(info.info_3) ) {
2248 status = WERR_PRINTER_DRIVER_IN_USE;
2253 * we have a couple of cases to consider.
2254 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2255 * then the delete should fail if **any** files overlap with
2257 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2258 * non-overlapping files
2259 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2260 * is set, the do not delete any files
2261 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2264 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2266 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2268 if ( delete_files && printer_driver_files_in_use(info.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2269 /* no idea of the correct error here */
2270 status = WERR_ACCESS_DENIED;
2275 /* also check for W32X86/3 if necessary; maybe we already have? */
2277 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2278 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3,
2280 r->in.architecture, 3)))
2283 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2284 /* no idea of the correct error here */
2285 free_a_printer_driver( info_win2k, 3 );
2286 status = WERR_ACCESS_DENIED;
2290 /* if we get to here, we now have 2 driver info structures to remove */
2291 /* remove the Win2k driver first*/
2293 status_win2k = delete_printer_driver(
2294 p, info_win2k.info_3, 3, delete_files);
2295 free_a_printer_driver( info_win2k, 3 );
2297 /* this should not have failed---if it did, report to client */
2299 if ( !W_ERROR_IS_OK(status_win2k) )
2304 status = delete_printer_driver(p, info.info_3, version, delete_files);
2306 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2309 free_a_printer_driver( info, 3 );
2315 /****************************************************************************
2316 Internal routine for removing printerdata
2317 ***************************************************************************/
2319 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2321 return delete_printer_data( printer->info_2, key, value );
2324 /****************************************************************************
2325 Internal routine for storing printerdata
2326 ***************************************************************************/
2328 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2329 const char *key, const char *value,
2330 uint32_t type, uint8_t *data, int real_len)
2332 /* the registry objects enforce uniqueness based on value name */
2334 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2337 /********************************************************************
2338 GetPrinterData on a printer server Handle.
2339 ********************************************************************/
2341 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2343 enum winreg_Type *type,
2344 union spoolss_PrinterData *data)
2346 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2348 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2354 if (!StrCaseCmp(value, "BeepEnabled")) {
2360 if (!StrCaseCmp(value, "EventLog")) {
2362 /* formally was 0x1b */
2367 if (!StrCaseCmp(value, "NetPopup")) {
2373 if (!StrCaseCmp(value, "MajorVersion")) {
2376 /* Windows NT 4.0 seems to not allow uploading of drivers
2377 to a server that reports 0x3 as the MajorVersion.
2378 need to investigate more how Win2k gets around this .
2381 if (RA_WINNT == get_remote_arch()) {
2390 if (!StrCaseCmp(value, "MinorVersion")) {
2397 * uint32_t size = 0x114
2398 * uint32_t major = 5
2399 * uint32_t minor = [0|1]
2400 * uint32_t build = [2195|2600]
2401 * extra unicode string = e.g. "Service Pack 3"
2403 if (!StrCaseCmp(value, "OSVersion")) {
2405 enum ndr_err_code ndr_err;
2406 struct spoolss_OSVersion os;
2408 os.major = 5; /* Windows 2000 == 5.0 */
2410 os.build = 2195; /* build */
2411 os.extra_string = ""; /* leave extra string empty */
2413 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2414 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2415 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2416 return WERR_GENERAL_FAILURE;
2420 data->binary = blob;
2426 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2429 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2430 W_ERROR_HAVE_NO_MEMORY(data->string);
2435 if (!StrCaseCmp(value, "Architecture")) {
2438 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2439 W_ERROR_HAVE_NO_MEMORY(data->string);
2444 if (!StrCaseCmp(value, "DsPresent")) {
2447 /* only show the publish check box if we are a
2448 member of a AD domain */
2450 if (lp_security() == SEC_ADS) {
2458 if (!StrCaseCmp(value, "DNSMachineName")) {
2459 const char *hostname = get_mydnsfullname();
2462 return WERR_BADFILE;
2466 data->string = talloc_strdup(mem_ctx, hostname);
2467 W_ERROR_HAVE_NO_MEMORY(data->string);
2472 return WERR_INVALID_PARAM;
2475 /****************************************************************
2476 _spoolss_GetPrinterData
2477 ****************************************************************/
2479 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2480 struct spoolss_GetPrinterData *r)
2483 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2484 NT_PRINTER_INFO_LEVEL *printer = NULL;
2488 * Reminder: when it's a string, the length is in BYTES
2489 * even if UNICODE is negociated.
2494 /* in case of problem, return some default values */
2499 DEBUG(4,("_spoolss_GetPrinterData\n"));
2502 DEBUG(2,("_spoolss_GetPrinterData: Invalid handle (%s:%u:%u).\n",
2503 OUR_HANDLE(r->in.handle)));
2504 result = WERR_BADFID;
2508 if (Printer->printer_type == SPLHND_SERVER) {
2509 result = getprinterdata_printer_server(p->mem_ctx,
2514 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
2515 result = WERR_BADFID;
2519 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2520 if (!W_ERROR_IS_OK(result)) {
2524 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2526 if (strequal(r->in.value_name, "ChangeId")) {
2527 *r->out.type = REG_DWORD;
2528 r->out.data->value = printer->info_2->changeid;
2531 struct regval_blob *v;
2534 v = get_printer_data(printer->info_2,
2535 SPOOL_PRINTERDATA_KEY,
2538 result = WERR_BADFILE;
2542 *r->out.type = v->type;
2544 blob = data_blob_const(v->data_p, v->size);
2546 result = pull_spoolss_PrinterData(p->mem_ctx, &blob,
2553 /* cleanup & exit */
2556 free_a_printer(&printer, 2);
2559 if (!W_ERROR_IS_OK(result)) {
2563 *r->out.needed = ndr_size_spoolss_PrinterData(r->out.data, *r->out.type, NULL, 0);
2564 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
2565 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
2567 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
2570 /*********************************************************
2571 Connect to the client machine.
2572 **********************************************************/
2574 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2575 struct sockaddr_storage *client_ss, const char *remote_machine)
2578 struct cli_state *the_cli;
2579 struct sockaddr_storage rm_addr;
2581 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2582 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2583 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2587 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2588 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2592 char addr[INET6_ADDRSTRLEN];
2593 rm_addr = *client_ss;
2594 print_sockaddr(addr, sizeof(addr), &rm_addr);
2595 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2599 /* setup the connection */
2601 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2602 &rm_addr, 0, "IPC$", "IPC",
2606 0, lp_client_signing(), NULL );
2608 if ( !NT_STATUS_IS_OK( ret ) ) {
2609 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2614 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2616 cli_shutdown(the_cli);
2621 * Ok - we have an anonymous connection to the IPC$ share.
2622 * Now start the NT Domain stuff :-).
2625 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2626 if (!NT_STATUS_IS_OK(ret)) {
2627 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2628 remote_machine, nt_errstr(ret)));
2629 cli_shutdown(the_cli);
2636 /***************************************************************************
2637 Connect to the client.
2638 ****************************************************************************/
2640 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2641 uint32_t localprinter, uint32_t type,
2642 struct policy_handle *handle,
2643 struct sockaddr_storage *client_ss)
2649 * If it's the first connection, contact the client
2650 * and connect to the IPC$ share anonymously
2652 if (smb_connections==0) {
2653 fstring unix_printer;
2655 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2657 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2660 messaging_register(smbd_messaging_context(), NULL,
2661 MSG_PRINTER_NOTIFY2,
2662 receive_notify2_message_list);
2663 /* Tell the connections db we're now interested in printer
2664 * notify messages. */
2665 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2669 * Tell the specific printing tdb we want messages for this printer
2670 * by registering our PID.
2673 if (!print_notify_register_pid(snum))
2674 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2678 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2686 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2687 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2688 win_errstr(result)));
2690 return (W_ERROR_IS_OK(result));
2693 /****************************************************************
2694 ****************************************************************/
2696 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2697 const struct spoolss_NotifyOption *r)
2699 struct spoolss_NotifyOption *option;
2706 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2713 if (!option->count) {
2717 option->types = talloc_zero_array(option,
2718 struct spoolss_NotifyOptionType, option->count);
2719 if (!option->types) {
2720 talloc_free(option);
2724 for (i=0; i < option->count; i++) {
2725 option->types[i] = r->types[i];
2727 if (option->types[i].count) {
2728 option->types[i].fields = talloc_zero_array(option,
2729 union spoolss_Field, option->types[i].count);
2730 if (!option->types[i].fields) {
2731 talloc_free(option);
2734 for (k=0; k<option->types[i].count; k++) {
2735 option->types[i].fields[k] =
2736 r->types[i].fields[k];
2744 /****************************************************************
2745 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2747 * before replying OK: status=0 a rpc call is made to the workstation
2748 * asking ReplyOpenPrinter
2750 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2751 * called from api_spoolss_rffpcnex
2752 ****************************************************************/
2754 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2755 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2758 struct spoolss_NotifyOption *option = r->in.notify_options;
2759 struct sockaddr_storage client_ss;
2761 /* store the notify value in the printer struct */
2763 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2766 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2767 "Invalid handle (%s:%u:%u).\n",
2768 OUR_HANDLE(r->in.handle)));
2772 Printer->notify.flags = r->in.flags;
2773 Printer->notify.options = r->in.options;
2774 Printer->notify.printerlocal = r->in.printer_local;
2776 TALLOC_FREE(Printer->notify.option);
2777 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2779 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2781 /* Connect to the client machine and send a ReplyOpenPrinter */
2783 if ( Printer->printer_type == SPLHND_SERVER)
2785 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2786 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2789 if (!interpret_string_addr(&client_ss, p->client_address,
2791 return WERR_SERVER_UNAVAILABLE;
2794 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2795 Printer->notify.printerlocal, 1,
2796 &Printer->notify.client_hnd, &client_ss))
2797 return WERR_SERVER_UNAVAILABLE;
2799 Printer->notify.client_connected = true;
2804 /*******************************************************************
2805 * fill a notify_info_data with the servername
2806 ********************************************************************/
2808 void spoolss_notify_server_name(int snum,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2817 /*******************************************************************
2818 * fill a notify_info_data with the printername (not including the servername).
2819 ********************************************************************/
2821 void spoolss_notify_printer_name(int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 /* the notify name should not contain the \\server\ part */
2828 char *p = strrchr(printer->info_2->printername, '\\');
2831 p = printer->info_2->printername;
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2839 /*******************************************************************
2840 * fill a notify_info_data with the servicename
2841 ********************************************************************/
2843 void spoolss_notify_share_name(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_STRING(data, lp_servicename(snum));
2852 /*******************************************************************
2853 * fill a notify_info_data with the port name
2854 ********************************************************************/
2856 void spoolss_notify_port_name(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_STRING(data, printer->info_2->portname);
2865 /*******************************************************************
2866 * fill a notify_info_data with the printername
2867 * but it doesn't exist, have to see what to do
2868 ********************************************************************/
2870 void spoolss_notify_driver_name(int snum,
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 NT_PRINTER_INFO_LEVEL *printer,
2874 TALLOC_CTX *mem_ctx)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2879 /*******************************************************************
2880 * fill a notify_info_data with the comment
2881 ********************************************************************/
2883 void spoolss_notify_comment(int snum,
2884 struct spoolss_Notify *data,
2885 print_queue_struct *queue,
2886 NT_PRINTER_INFO_LEVEL *printer,
2887 TALLOC_CTX *mem_ctx)
2891 if (*printer->info_2->comment == '\0') {
2892 p = lp_comment(snum);
2894 p = printer->info_2->comment;
2897 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2900 /*******************************************************************
2901 * fill a notify_info_data with the comment
2902 * location = "Room 1, floor 2, building 3"
2903 ********************************************************************/
2905 void spoolss_notify_location(int snum,
2906 struct spoolss_Notify *data,
2907 print_queue_struct *queue,
2908 NT_PRINTER_INFO_LEVEL *printer,
2909 TALLOC_CTX *mem_ctx)
2911 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2914 /*******************************************************************
2915 * fill a notify_info_data with the device mode
2916 * jfm:xxxx don't to it for know but that's a real problem !!!
2917 ********************************************************************/
2919 static void spoolss_notify_devmode(int snum,
2920 struct spoolss_Notify *data,
2921 print_queue_struct *queue,
2922 NT_PRINTER_INFO_LEVEL *printer,
2923 TALLOC_CTX *mem_ctx)
2925 /* for a dummy implementation we have to zero the fields */
2926 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2929 /*******************************************************************
2930 * fill a notify_info_data with the separator file name
2931 ********************************************************************/
2933 void spoolss_notify_sepfile(int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 NT_PRINTER_INFO_LEVEL *printer,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2942 /*******************************************************************
2943 * fill a notify_info_data with the print processor
2944 * jfm:xxxx return always winprint to indicate we don't do anything to it
2945 ********************************************************************/
2947 void spoolss_notify_print_processor(int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 NT_PRINTER_INFO_LEVEL *printer,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum,
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 NT_PRINTER_INFO_LEVEL *printer,
2965 TALLOC_CTX *mem_ctx)
2967 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2970 /*******************************************************************
2971 * fill a notify_info_data with the data type
2972 * jfm:xxxx always send RAW as data type
2973 ********************************************************************/
2975 void spoolss_notify_datatype(int snum,
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 NT_PRINTER_INFO_LEVEL *printer,
2979 TALLOC_CTX *mem_ctx)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2984 /*******************************************************************
2985 * fill a notify_info_data with the security descriptor
2986 * jfm:xxxx send an null pointer to say no security desc
2987 * have to implement security before !
2988 ********************************************************************/
2990 static void spoolss_notify_security_desc(int snum,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 NT_PRINTER_INFO_LEVEL *printer,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2997 printer->info_2->secdesc_buf->sd_size,
2998 printer->info_2->secdesc_buf->sd);
3001 /*******************************************************************
3002 * fill a notify_info_data with the attributes
3003 * jfm:xxxx a samba printer is always shared
3004 ********************************************************************/
3006 void spoolss_notify_attributes(int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 NT_PRINTER_INFO_LEVEL *printer,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
3015 /*******************************************************************
3016 * fill a notify_info_data with the priority
3017 ********************************************************************/
3019 static void spoolss_notify_priority(int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
3028 /*******************************************************************
3029 * fill a notify_info_data with the default priority
3030 ********************************************************************/
3032 static void spoolss_notify_default_priority(int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 NT_PRINTER_INFO_LEVEL *printer,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
3041 /*******************************************************************
3042 * fill a notify_info_data with the start time
3043 ********************************************************************/
3045 static void spoolss_notify_start_time(int snum,
3046 struct spoolss_Notify *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3051 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
3054 /*******************************************************************
3055 * fill a notify_info_data with the until time
3056 ********************************************************************/
3058 static void spoolss_notify_until_time(int snum,
3059 struct spoolss_Notify *data,
3060 print_queue_struct *queue,
3061 NT_PRINTER_INFO_LEVEL *printer,
3062 TALLOC_CTX *mem_ctx)
3064 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
3067 /*******************************************************************
3068 * fill a notify_info_data with the status
3069 ********************************************************************/
3071 static void spoolss_notify_status(int snum,
3072 struct spoolss_Notify *data,
3073 print_queue_struct *queue,
3074 NT_PRINTER_INFO_LEVEL *printer,
3075 TALLOC_CTX *mem_ctx)
3077 print_status_struct status;
3079 print_queue_length(snum, &status);
3080 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3083 /*******************************************************************
3084 * fill a notify_info_data with the number of jobs queued
3085 ********************************************************************/
3087 void spoolss_notify_cjobs(int snum,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 NT_PRINTER_INFO_LEVEL *printer,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
3096 /*******************************************************************
3097 * fill a notify_info_data with the average ppm
3098 ********************************************************************/
3100 static void spoolss_notify_average_ppm(int snum,
3101 struct spoolss_Notify *data,
3102 print_queue_struct *queue,
3103 NT_PRINTER_INFO_LEVEL *printer,
3104 TALLOC_CTX *mem_ctx)
3106 /* always respond 8 pages per minutes */
3107 /* a little hard ! */
3108 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
3111 /*******************************************************************
3112 * fill a notify_info_data with username
3113 ********************************************************************/
3115 static void spoolss_notify_username(int snum,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 NT_PRINTER_INFO_LEVEL *printer,
3119 TALLOC_CTX *mem_ctx)
3121 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3124 /*******************************************************************
3125 * fill a notify_info_data with job status
3126 ********************************************************************/
3128 static void spoolss_notify_job_status(int snum,
3129 struct spoolss_Notify *data,
3130 print_queue_struct *queue,
3131 NT_PRINTER_INFO_LEVEL *printer,
3132 TALLOC_CTX *mem_ctx)
3134 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3137 /*******************************************************************
3138 * fill a notify_info_data with job name
3139 ********************************************************************/
3141 static void spoolss_notify_job_name(int snum,
3142 struct spoolss_Notify *data,
3143 print_queue_struct *queue,
3144 NT_PRINTER_INFO_LEVEL *printer,
3145 TALLOC_CTX *mem_ctx)
3147 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3150 /*******************************************************************
3151 * fill a notify_info_data with job status
3152 ********************************************************************/
3154 static void spoolss_notify_job_status_string(int snum,
3155 struct spoolss_Notify *data,
3156 print_queue_struct *queue,
3157 NT_PRINTER_INFO_LEVEL *printer,
3158 TALLOC_CTX *mem_ctx)
3161 * Now we're returning job status codes we just return a "" here. JRA.
3166 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3169 switch (queue->status) {
3174 p = ""; /* NT provides the paused string */
3183 #endif /* NO LONGER NEEDED. */
3185 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3188 /*******************************************************************
3189 * fill a notify_info_data with job time
3190 ********************************************************************/
3192 static void spoolss_notify_job_time(int snum,
3193 struct spoolss_Notify *data,
3194 print_queue_struct *queue,
3195 NT_PRINTER_INFO_LEVEL *printer,
3196 TALLOC_CTX *mem_ctx)
3198 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 /*******************************************************************
3202 * fill a notify_info_data with job size
3203 ********************************************************************/
3205 static void spoolss_notify_job_size(int snum,
3206 struct spoolss_Notify *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3214 /*******************************************************************
3215 * fill a notify_info_data with page info
3216 ********************************************************************/
3217 static void spoolss_notify_total_pages(int snum,
3218 struct spoolss_Notify *data,
3219 print_queue_struct *queue,
3220 NT_PRINTER_INFO_LEVEL *printer,
3221 TALLOC_CTX *mem_ctx)
3223 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3226 /*******************************************************************
3227 * fill a notify_info_data with pages printed info.
3228 ********************************************************************/
3229 static void spoolss_notify_pages_printed(int snum,
3230 struct spoolss_Notify *data,
3231 print_queue_struct *queue,
3232 NT_PRINTER_INFO_LEVEL *printer,
3233 TALLOC_CTX *mem_ctx)
3235 /* Add code when back-end tracks this */
3236 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3239 /*******************************************************************
3240 Fill a notify_info_data with job position.
3241 ********************************************************************/
3243 static void spoolss_notify_job_position(int snum,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 NT_PRINTER_INFO_LEVEL *printer,
3247 TALLOC_CTX *mem_ctx)
3249 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3252 /*******************************************************************
3253 Fill a notify_info_data with submitted time.
3254 ********************************************************************/
3256 static void spoolss_notify_submitted_time(int snum,
3257 struct spoolss_Notify *data,
3258 print_queue_struct *queue,
3259 NT_PRINTER_INFO_LEVEL *printer,
3260 TALLOC_CTX *mem_ctx)
3262 data->data.string.string = NULL;
3263 data->data.string.size = 0;
3265 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3266 &data->data.string.string,
3267 &data->data.string.size);
3271 struct s_notify_info_data_table
3273 enum spoolss_NotifyType type;
3276 enum spoolss_NotifyTable variable_type;
3277 void (*fn) (int snum, struct spoolss_Notify *data,
3278 print_queue_struct *queue,
3279 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3282 /* A table describing the various print notification constants and
3283 whether the notification data is a pointer to a variable sized
3284 buffer, a one value uint32_t or a two value uint32_t. */
3286 static const struct s_notify_info_data_table notify_info_data_table[] =
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3339 /*******************************************************************
3340 Return the variable_type of info_data structure.
3341 ********************************************************************/
3343 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3348 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3349 if ( (notify_info_data_table[i].type == type) &&
3350 (notify_info_data_table[i].field == field) ) {
3351 return notify_info_data_table[i].variable_type;
3355 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3360 /****************************************************************************
3361 ****************************************************************************/
3363 static bool search_notify(enum spoolss_NotifyType type,
3369 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3370 if (notify_info_data_table[i].type == type &&
3371 notify_info_data_table[i].field == field &&
3372 notify_info_data_table[i].fn != NULL) {
3381 /****************************************************************************
3382 ****************************************************************************/
3384 void construct_info_data(struct spoolss_Notify *info_data,
3385 enum spoolss_NotifyType type,
3389 info_data->type = type;
3390 info_data->field.field = field;
3391 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3392 info_data->job_id = id;
3395 /*******************************************************************
3397 * fill a notify_info struct with info asked
3399 ********************************************************************/
3401 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3402 struct spoolss_NotifyInfo *info,
3404 const struct spoolss_NotifyOptionType *option_type,
3406 TALLOC_CTX *mem_ctx)
3409 enum spoolss_NotifyType type;
3412 struct spoolss_Notify *current_data;
3413 NT_PRINTER_INFO_LEVEL *printer = NULL;
3414 print_queue_struct *queue=NULL;
3416 type = option_type->type;
3418 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3419 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3420 option_type->count, lp_servicename(snum)));
3422 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3425 for(field_num=0; field_num < option_type->count; field_num++) {
3426 field = option_type->fields[field_num].field;
3428 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3430 if (!search_notify(type, field, &j) )
3433 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3434 struct spoolss_Notify,
3436 if (info->notifies == NULL) {
3437 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3438 free_a_printer(&printer, 2);
3442 current_data = &info->notifies[info->count];
3444 construct_info_data(current_data, type, field, id);
3446 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3447 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3449 notify_info_data_table[j].fn(snum, current_data, queue,
3455 free_a_printer(&printer, 2);
3459 /*******************************************************************
3461 * fill a notify_info struct with info asked
3463 ********************************************************************/
3465 static bool construct_notify_jobs_info(print_queue_struct *queue,
3466 struct spoolss_NotifyInfo *info,
3467 NT_PRINTER_INFO_LEVEL *printer,
3469 const struct spoolss_NotifyOptionType *option_type,
3471 TALLOC_CTX *mem_ctx)
3474 enum spoolss_NotifyType type;
3476 struct spoolss_Notify *current_data;
3478 DEBUG(4,("construct_notify_jobs_info\n"));
3480 type = option_type->type;
3482 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3483 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3484 option_type->count));
3486 for(field_num=0; field_num<option_type->count; field_num++) {
3487 field = option_type->fields[field_num].field;
3489 if (!search_notify(type, field, &j) )
3492 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3493 struct spoolss_Notify,
3495 if (info->notifies == NULL) {
3496 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3500 current_data=&(info->notifies[info->count]);
3502 construct_info_data(current_data, type, field, id);
3503 notify_info_data_table[j].fn(snum, current_data, queue,
3512 * JFM: The enumeration is not that simple, it's even non obvious.
3514 * let's take an example: I want to monitor the PRINTER SERVER for
3515 * the printer's name and the number of jobs currently queued.
3516 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3517 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3519 * I have 3 printers on the back of my server.
3521 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3524 * 1 printer 1 name 1
3525 * 2 printer 1 cjob 1
3526 * 3 printer 2 name 2
3527 * 4 printer 2 cjob 2
3528 * 5 printer 3 name 3
3529 * 6 printer 3 name 3
3531 * that's the print server case, the printer case is even worse.
3534 /*******************************************************************
3536 * enumerate all printers on the printserver
3537 * fill a notify_info struct with info asked
3539 ********************************************************************/
3541 static WERROR printserver_notify_info(pipes_struct *p,
3542 struct policy_handle *hnd,
3543 struct spoolss_NotifyInfo *info,
3544 TALLOC_CTX *mem_ctx)
3547 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3548 int n_services=lp_numservices();
3550 struct spoolss_NotifyOption *option;
3551 struct spoolss_NotifyOptionType option_type;
3553 DEBUG(4,("printserver_notify_info\n"));
3558 option = Printer->notify.option;
3561 info->notifies = NULL;
3564 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3565 sending a ffpcn() request first */
3570 for (i=0; i<option->count; i++) {
3571 option_type = option->types[i];
3573 if (option_type.type != PRINTER_NOTIFY_TYPE)
3576 for (snum=0; snum<n_services; snum++)
3578 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3579 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3585 * Debugging information, don't delete.
3588 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3589 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3590 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3592 for (i=0; i<info->count; i++) {
3593 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3594 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3595 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3602 /*******************************************************************
3604 * fill a notify_info struct with info asked
3606 ********************************************************************/
3608 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3609 struct spoolss_NotifyInfo *info,
3610 TALLOC_CTX *mem_ctx)
3613 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3616 struct spoolss_NotifyOption *option;
3617 struct spoolss_NotifyOptionType option_type;
3619 print_queue_struct *queue=NULL;
3620 print_status_struct status;
3622 DEBUG(4,("printer_notify_info\n"));
3627 option = Printer->notify.option;
3631 info->notifies = NULL;
3634 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3635 sending a ffpcn() request first */
3640 get_printer_snum(p, hnd, &snum, NULL);
3642 for (i=0; i<option->count; i++) {
3643 option_type = option->types[i];
3645 switch (option_type.type) {
3646 case PRINTER_NOTIFY_TYPE:
3647 if(construct_notify_printer_info(Printer, info, snum,
3653 case JOB_NOTIFY_TYPE: {
3654 NT_PRINTER_INFO_LEVEL *printer = NULL;
3656 count = print_queue_status(snum, &queue, &status);
3658 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3661 for (j=0; j<count; j++) {
3662 construct_notify_jobs_info(&queue[j], info,
3669 free_a_printer(&printer, 2);
3679 * Debugging information, don't delete.
3682 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3683 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3684 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3686 for (i=0; i<info->count; i++) {
3687 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3688 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3689 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3695 /****************************************************************
3696 _spoolss_RouterRefreshPrinterChangeNotify
3697 ****************************************************************/
3699 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3700 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3702 struct spoolss_NotifyInfo *info;
3704 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3705 WERROR result = WERR_BADFID;
3707 /* we always have a spoolss_NotifyInfo struct */
3708 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3710 result = WERR_NOMEM;
3714 *r->out.info = info;
3717 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3718 "Invalid handle (%s:%u:%u).\n",
3719 OUR_HANDLE(r->in.handle)));
3723 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3726 * We are now using the change value, and
3727 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3728 * I don't have a global notification system, I'm sending back all the
3729 * informations even when _NOTHING_ has changed.
3732 /* We need to keep track of the change value to send back in
3733 RRPCN replies otherwise our updates are ignored. */
3735 Printer->notify.fnpcn = true;
3737 if (Printer->notify.client_connected) {
3738 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3739 "Saving change value in request [%x]\n",
3741 Printer->notify.change = r->in.change_low;
3744 /* just ignore the spoolss_NotifyOption */
3746 switch (Printer->printer_type) {
3748 result = printserver_notify_info(p, r->in.handle,
3752 case SPLHND_PRINTER:
3753 result = printer_notify_info(p, r->in.handle,
3758 Printer->notify.fnpcn = false;
3764 /********************************************************************
3765 * construct_printer_info_0
3766 * fill a printer_info_0 struct
3767 ********************************************************************/
3769 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3770 const NT_PRINTER_INFO_LEVEL *ntprinter,
3771 struct spoolss_PrinterInfo0 *r,
3775 counter_printer_0 *session_counter;
3777 print_status_struct status;
3779 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3780 W_ERROR_HAVE_NO_MEMORY(r->printername);
3782 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3783 W_ERROR_HAVE_NO_MEMORY(r->servername);
3785 count = print_queue_length(snum, &status);
3787 /* check if we already have a counter for this printer */
3788 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3789 if (session_counter->snum == snum)
3793 /* it's the first time, add it to the list */
3794 if (session_counter == NULL) {
3795 session_counter = SMB_MALLOC_P(counter_printer_0);
3796 W_ERROR_HAVE_NO_MEMORY(session_counter);
3797 ZERO_STRUCTP(session_counter);
3798 session_counter->snum = snum;
3799 session_counter->counter = 0;
3800 DLIST_ADD(counter_list, session_counter);
3804 session_counter->counter++;
3810 setuptime = (time_t)ntprinter->info_2->setuptime;
3812 init_systemtime(&r->time, gmtime(&setuptime));
3815 * the global_counter should be stored in a TDB as it's common to all the clients
3816 * and should be zeroed on samba startup
3818 r->global_counter = session_counter->counter;
3820 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3821 r->version = 0x0005; /* NT 5 */
3822 r->free_build = 0x0893; /* build 2195 */
3824 r->max_spooling = 0;
3825 r->session_counter = session_counter->counter;
3826 r->num_error_out_of_paper = 0x0;
3827 r->num_error_not_ready = 0x0; /* number of print failure */
3829 r->number_of_processors = 0x1;
3830 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3831 r->high_part_total_bytes = 0x0;
3832 r->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3833 r->last_error = WERR_OK;
3834 r->status = nt_printq_status(status.status);
3835 r->enumerate_network_printers = 0x0;
3836 r->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3837 r->processor_architecture = 0x0;
3838 r->processor_level = 0x6; /* 6 ???*/
3846 /****************************************************************************
3847 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3848 should be valid upon entry
3849 ****************************************************************************/
3851 static WERROR convert_nt_devicemode(TALLOC_CTX *mem_ctx,
3852 struct spoolss_DeviceMode *r,
3853 const NT_DEVICEMODE *ntdevmode)
3855 if (!r || !ntdevmode) {
3856 return WERR_INVALID_PARAM;
3859 r->devicename = talloc_strdup(mem_ctx, ntdevmode->devicename);
3860 W_ERROR_HAVE_NO_MEMORY(r->devicename);
3862 r->specversion = ntdevmode->specversion;
3863 r->driverversion = ntdevmode->driverversion;
3864 r->size = ntdevmode->size;
3865 r->__driverextra_length = ntdevmode->driverextra;
3866 r->fields = ntdevmode->fields;
3868 r->orientation = ntdevmode->orientation;
3869 r->papersize = ntdevmode->papersize;
3870 r->paperlength = ntdevmode->paperlength;
3871 r->paperwidth = ntdevmode->paperwidth;
3872 r->scale = ntdevmode->scale;
3873 r->copies = ntdevmode->copies;
3874 r->defaultsource = ntdevmode->defaultsource;
3875 r->printquality = ntdevmode->printquality;
3876 r->color = ntdevmode->color;
3877 r->duplex = ntdevmode->duplex;
3878 r->yresolution = ntdevmode->yresolution;
3879 r->ttoption = ntdevmode->ttoption;
3880 r->collate = ntdevmode->collate;
3882 r->formname = talloc_strdup(mem_ctx, ntdevmode->formname);
3883 W_ERROR_HAVE_NO_MEMORY(r->formname);
3885 /* all 0 below are values that have not been set in the old parsing/copy
3886 * function, maybe they should... - gd */
3892 r->displayflags = 0;
3893 r->displayfrequency = 0;
3894 r->icmmethod = ntdevmode->icmmethod;
3895 r->icmintent = ntdevmode->icmintent;
3896 r->mediatype = ntdevmode->mediatype;
3897 r->dithertype = ntdevmode->dithertype;
3900 r->panningwidth = 0;
3901 r->panningheight = 0;
3903 if (ntdevmode->nt_dev_private != NULL) {
3904 r->driverextra_data = data_blob_talloc(mem_ctx,
3905 ntdevmode->nt_dev_private,
3906 ntdevmode->driverextra);
3907 W_ERROR_HAVE_NO_MEMORY(r->driverextra_data.data);
3914 /****************************************************************************
3915 Create a spoolss_DeviceMode struct. Returns talloced memory.
3916 ****************************************************************************/
3918 struct spoolss_DeviceMode *construct_dev_mode(TALLOC_CTX *mem_ctx,
3919 const char *servicename)
3922 NT_PRINTER_INFO_LEVEL *printer = NULL;
3923 struct spoolss_DeviceMode *devmode = NULL;
3925 DEBUG(7,("construct_dev_mode\n"));
3927 DEBUGADD(8,("getting printer characteristics\n"));
3929 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
3932 if (!printer->info_2->devmode) {
3933 DEBUG(5, ("BONG! There was no device mode!\n"));
3937 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
3939 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3943 DEBUGADD(8,("loading DEVICEMODE\n"));
3945 result = convert_nt_devicemode(mem_ctx, devmode, printer->info_2->devmode);
3946 if (!W_ERROR_IS_OK(result)) {
3947 TALLOC_FREE(devmode);
3951 free_a_printer(&printer,2);
3956 /********************************************************************
3957 * construct_printer_info3
3958 * fill a spoolss_PrinterInfo3 struct
3959 ********************************************************************/
3961 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3962 const NT_PRINTER_INFO_LEVEL *ntprinter,
3963 struct spoolss_PrinterInfo3 *r,
3966 /* These are the components of the SD we are returning. */
3968 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
3969 /* don't use talloc_steal() here unless you do a deep steal of all
3970 the SEC_DESC members */
3972 r->secdesc = dup_sec_desc(mem_ctx,
3973 ntprinter->info_2->secdesc_buf->sd);
3974 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3980 /********************************************************************
3981 * construct_printer_info4
3982 * fill a spoolss_PrinterInfo4 struct
3983 ********************************************************************/
3985 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3986 const NT_PRINTER_INFO_LEVEL *ntprinter,
3987 struct spoolss_PrinterInfo4 *r,
3990 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3991 W_ERROR_HAVE_NO_MEMORY(r->printername);
3992 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3993 W_ERROR_HAVE_NO_MEMORY(r->servername);
3995 r->attributes = ntprinter->info_2->attributes;
4000 /********************************************************************
4001 * construct_printer_info5
4002 * fill a spoolss_PrinterInfo5 struct
4003 ********************************************************************/
4005 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4006 const NT_PRINTER_INFO_LEVEL *ntprinter,
4007 struct spoolss_PrinterInfo5 *r,
4010 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4011 W_ERROR_HAVE_NO_MEMORY(r->printername);
4012 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4013 W_ERROR_HAVE_NO_MEMORY(r->portname);
4015 r->attributes = ntprinter->info_2->attributes;
4017 /* these two are not used by NT+ according to MSDN */
4019 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4020 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4025 /********************************************************************
4026 * construct_printer_info_6
4027 * fill a spoolss_PrinterInfo6 struct
4028 ********************************************************************/
4030 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4031 const NT_PRINTER_INFO_LEVEL *ntprinter,
4032 struct spoolss_PrinterInfo6 *r,
4036 print_status_struct status;
4038 count = print_queue_length(snum, &status);
4040 r->status = nt_printq_status(status.status);
4045 /********************************************************************
4046 * construct_printer_info7
4047 * fill a spoolss_PrinterInfo7 struct
4048 ********************************************************************/
4050 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4051 Printer_entry *print_hnd,
4052 struct spoolss_PrinterInfo7 *r,
4057 if (is_printer_published(print_hnd, snum, &guid)) {
4058 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4059 r->action = DSPRINT_PUBLISH;
4061 r->guid = talloc_strdup(mem_ctx, "");
4062 r->action = DSPRINT_UNPUBLISH;
4064 W_ERROR_HAVE_NO_MEMORY(r->guid);
4069 /********************************************************************
4070 * construct_printer_info8
4071 * fill a spoolss_PrinterInfo8 struct
4072 ********************************************************************/
4074 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4075 const NT_PRINTER_INFO_LEVEL *ntprinter,
4076 struct spoolss_DeviceModeInfo *r,
4079 struct spoolss_DeviceMode *devmode;
4082 if (!ntprinter->info_2->devmode) {
4087 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
4088 W_ERROR_HAVE_NO_MEMORY(devmode);
4090 result = convert_nt_devicemode(mem_ctx, devmode, ntprinter->info_2->devmode);
4091 if (!W_ERROR_IS_OK(result)) {
4092 TALLOC_FREE(devmode);
4096 r->devmode = devmode;
4102 /********************************************************************
4103 * construct_printer_info1
4104 * fill a spoolss_PrinterInfo1 struct
4105 ********************************************************************/
4107 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4108 const NT_PRINTER_INFO_LEVEL *ntprinter,
4110 struct spoolss_PrinterInfo1 *r,
4115 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4116 ntprinter->info_2->printername,
4117 ntprinter->info_2->drivername,
4118 ntprinter->info_2->location);
4119 W_ERROR_HAVE_NO_MEMORY(r->description);
4121 if (*ntprinter->info_2->comment == '\0') {
4122 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4124 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment); /* saved comment */
4126 W_ERROR_HAVE_NO_MEMORY(r->comment);
4128 r->name = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4129 W_ERROR_HAVE_NO_MEMORY(r->name);
4134 /********************************************************************
4135 * construct_printer_info2
4136 * fill a spoolss_PrinterInfo2 struct
4137 ********************************************************************/
4139 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4140 const NT_PRINTER_INFO_LEVEL *ntprinter,
4141 struct spoolss_PrinterInfo2 *r,
4146 print_status_struct status;
4148 count = print_queue_length(snum, &status);
4150 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
4151 W_ERROR_HAVE_NO_MEMORY(r->servername);
4152 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
4153 W_ERROR_HAVE_NO_MEMORY(r->printername);
4154 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4155 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4156 r->portname = talloc_strdup(mem_ctx, ntprinter->info_2->portname);
4157 W_ERROR_HAVE_NO_MEMORY(r->portname);
4158 r->drivername = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
4159 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4161 if (*ntprinter->info_2->comment == '\0') {
4162 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4164 r->comment = talloc_strdup(mem_ctx, ntprinter->info_2->comment);
4166 W_ERROR_HAVE_NO_MEMORY(r->comment);
4168 r->location = talloc_strdup(mem_ctx, ntprinter->info_2->location);
4169 W_ERROR_HAVE_NO_MEMORY(r->location);
4170 r->sepfile = talloc_strdup(mem_ctx, ntprinter->info_2->sepfile);
4171 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4172 r->printprocessor = talloc_strdup(mem_ctx, ntprinter->info_2->printprocessor);
4173 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4174 r->datatype = talloc_strdup(mem_ctx, ntprinter->info_2->datatype);
4175 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4176 r->parameters = talloc_strdup(mem_ctx, ntprinter->info_2->parameters);
4177 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4179 r->attributes = ntprinter->info_2->attributes;
4181 r->priority = ntprinter->info_2->priority;
4182 r->defaultpriority = ntprinter->info_2->default_priority;
4183 r->starttime = ntprinter->info_2->starttime;
4184 r->untiltime = ntprinter->info_2->untiltime;
4185 r->status = nt_printq_status(status.status);
4187 r->averageppm = ntprinter->info_2->averageppm;
4189 r->devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
4191 DEBUG(8,("Returning NULL Devicemode!\n"));
4196 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4197 /* don't use talloc_steal() here unless you do a deep steal of all
4198 the SEC_DESC members */
4200 r->secdesc = dup_sec_desc(mem_ctx, ntprinter->info_2->secdesc_buf->sd);
4206 /********************************************************************
4207 ********************************************************************/
4209 static bool snum_is_shared_printer(int snum)
4211 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4214 /********************************************************************
4215 Spoolss_enumprinters.
4216 ********************************************************************/
4218 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4221 union spoolss_PrinterInfo **info_p,
4225 int n_services = lp_numservices();
4226 union spoolss_PrinterInfo *info = NULL;
4228 WERROR result = WERR_OK;
4233 for (snum = 0; snum < n_services; snum++) {
4235 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237 if (!snum_is_shared_printer(snum)) {
4241 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4242 lp_servicename(snum), snum));
4244 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4245 union spoolss_PrinterInfo,
4248 result = WERR_NOMEM;
4252 result = get_a_printer(NULL, &ntprinter, 2,
4253 lp_const_servicename(snum));
4254 if (!W_ERROR_IS_OK(result)) {
4260 result = construct_printer_info0(info, ntprinter,
4261 &info[count].info0, snum);
4264 result = construct_printer_info1(info, ntprinter, flags,
4265 &info[count].info1, snum);
4268 result = construct_printer_info2(info, ntprinter,
4269 &info[count].info2, snum);
4272 result = construct_printer_info4(info, ntprinter,
4273 &info[count].info4, snum);
4276 result = construct_printer_info5(info, ntprinter,
4277 &info[count].info5, snum);
4281 result = WERR_UNKNOWN_LEVEL;
4282 free_a_printer(&ntprinter, 2);
4286 free_a_printer(&ntprinter, 2);
4287 if (!W_ERROR_IS_OK(result)) {
4298 if (!W_ERROR_IS_OK(result)) {
4308 /********************************************************************
4309 * handle enumeration of printers at level 0
4310 ********************************************************************/
4312 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4314 const char *servername,
4315 union spoolss_PrinterInfo **info,
4318 DEBUG(4,("enum_all_printers_info_0\n"));
4320 return enum_all_printers_info_level(mem_ctx, 0, flags, info, count);
4324 /********************************************************************
4325 ********************************************************************/
4327 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4329 union spoolss_PrinterInfo **info,
4332 DEBUG(4,("enum_all_printers_info_1\n"));
4334 return enum_all_printers_info_level(mem_ctx, 1, flags, info, count);
4337 /********************************************************************
4338 enum_all_printers_info_1_local.
4339 *********************************************************************/
4341 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4342 union spoolss_PrinterInfo **info,
4345 DEBUG(4,("enum_all_printers_info_1_local\n"));
4347 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4350 /********************************************************************
4351 enum_all_printers_info_1_name.
4352 *********************************************************************/
4354 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4356 union spoolss_PrinterInfo **info,
4359 const char *s = name;
4361 DEBUG(4,("enum_all_printers_info_1_name\n"));
4363 if ((name[0] == '\\') && (name[1] == '\\')) {
4367 if (!is_myname_or_ipaddr(s)) {
4368 return WERR_INVALID_NAME;
4371 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_ICON8, info, count);
4374 /********************************************************************
4375 enum_all_printers_info_1_network.
4376 *********************************************************************/
4378 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4380 union spoolss_PrinterInfo **info,
4383 const char *s = name;
4385 DEBUG(4,("enum_all_printers_info_1_network\n"));
4387 /* If we respond to a enum_printers level 1 on our name with flags
4388 set to PRINTER_ENUM_REMOTE with a list of printers then these
4389 printers incorrectly appear in the APW browse list.
4390 Specifically the printers for the server appear at the workgroup
4391 level where all the other servers in the domain are
4392 listed. Windows responds to this call with a
4393 WERR_CAN_NOT_COMPLETE so we should do the same. */
4395 if (name[0] == '\\' && name[1] == '\\') {
4399 if (is_myname_or_ipaddr(s)) {
4400 return WERR_CAN_NOT_COMPLETE;
4403 return enum_all_printers_info_1(mem_ctx, PRINTER_ENUM_NAME, info, count);
4406 /********************************************************************
4407 * api_spoolss_enumprinters
4409 * called from api_spoolss_enumprinters (see this to understand)
4410 ********************************************************************/
4412 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4413 union spoolss_PrinterInfo **info,
4416 DEBUG(4,("enum_all_printers_info_2\n"));
4418 return enum_all_printers_info_level(mem_ctx, 2, 0, info, count);
4421 /********************************************************************
4422 * handle enumeration of printers at level 1
4423 ********************************************************************/
4425 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4428 union spoolss_PrinterInfo **info,
4431 /* Not all the flags are equals */
4433 if (flags & PRINTER_ENUM_LOCAL) {
4434 return enum_all_printers_info_1_local(mem_ctx, info, count);
4437 if (flags & PRINTER_ENUM_NAME) {
4438 return enum_all_printers_info_1_name(mem_ctx, name, info, count);
4441 if (flags & PRINTER_ENUM_NETWORK) {
4442 return enum_all_printers_info_1_network(mem_ctx, name, info, count);
4445 return WERR_OK; /* NT4sp5 does that */
4448 /********************************************************************
4449 * handle enumeration of printers at level 2
4450 ********************************************************************/
4452 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4454 const char *servername,
4455 union spoolss_PrinterInfo **info,
4458 if (flags & PRINTER_ENUM_LOCAL) {
4459 return enum_all_printers_info_2(mem_ctx, info, count);
4462 if (flags & PRINTER_ENUM_NAME) {
4463 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4464 return WERR_INVALID_NAME;
4467 return enum_all_printers_info_2(mem_ctx, info, count);
4470 if (flags & PRINTER_ENUM_REMOTE) {
4471 return WERR_UNKNOWN_LEVEL;
4477 /********************************************************************
4478 * handle enumeration of printers at level 4
4479 ********************************************************************/
4481 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4483 const char *servername,
4484 union spoolss_PrinterInfo **info,
4487 DEBUG(4,("enum_all_printers_info_4\n"));
4489 return enum_all_printers_info_level(mem_ctx, 4, flags, info, count);
4493 /********************************************************************
4494 * handle enumeration of printers at level 5
4495 ********************************************************************/
4497 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4499 const char *servername,
4500 union spoolss_PrinterInfo **info,
4503 DEBUG(4,("enum_all_printers_info_5\n"));
4505 return enum_all_printers_info_level(mem_ctx, 5, flags, info, count);
4508 /****************************************************************
4509 _spoolss_EnumPrinters
4510 ****************************************************************/
4512 WERROR _spoolss_EnumPrinters(pipes_struct *p,
4513 struct spoolss_EnumPrinters *r)
4518 /* that's an [in out] buffer */
4520 if (!r->in.buffer && (r->in.offered != 0)) {
4521 return WERR_INVALID_PARAM;
4524 DEBUG(4,("_spoolss_EnumPrinters\n"));
4528 *r->out.info = NULL;
4532 * flags==PRINTER_ENUM_NAME
4533 * if name=="" then enumerates all printers
4534 * if name!="" then enumerate the printer
4535 * flags==PRINTER_ENUM_REMOTE
4536 * name is NULL, enumerate printers
4537 * Level 2: name!="" enumerates printers, name can't be NULL
4538 * Level 3: doesn't exist
4539 * Level 4: does a local registry lookup
4540 * Level 5: same as Level 2
4543 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4544 W_ERROR_HAVE_NO_MEMORY(name);
4546 switch (r->in.level) {
4548 result = enumprinters_level0(p->mem_ctx, r->in.flags, name,
4549 r->out.info, r->out.count);
4552 result = enumprinters_level1(p->mem_ctx, r->in.flags, name,
4553 r->out.info, r->out.count);
4556 result = enumprinters_level2(p->mem_ctx, r->in.flags, name,
4557 r->out.info, r->out.count);
4560 result = enumprinters_level4(p->mem_ctx, r->in.flags, name,
4561 r->out.info, r->out.count);
4564 result = enumprinters_level5(p->mem_ctx, r->in.flags, name,
4565 r->out.info, r->out.count);
4568 return WERR_UNKNOWN_LEVEL;
4571 if (!W_ERROR_IS_OK(result)) {
4575 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4576 spoolss_EnumPrinters, NULL,
4577 *r->out.info, r->in.level,
4579 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4580 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4582 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4585 /****************************************************************
4587 ****************************************************************/
4589 WERROR _spoolss_GetPrinter(pipes_struct *p,
4590 struct spoolss_GetPrinter *r)
4592 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4593 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4594 WERROR result = WERR_OK;
4598 /* that's an [in out] buffer */
4600 if (!r->in.buffer && (r->in.offered != 0)) {
4601 return WERR_INVALID_PARAM;
4606 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4610 result = get_a_printer(Printer, &ntprinter, 2,
4611 lp_const_servicename(snum));
4612 if (!W_ERROR_IS_OK(result)) {
4616 switch (r->in.level) {
4618 result = construct_printer_info0(p->mem_ctx, ntprinter,
4619 &r->out.info->info0, snum);
4622 result = construct_printer_info1(p->mem_ctx, ntprinter,
4624 &r->out.info->info1, snum);
4627 result = construct_printer_info2(p->mem_ctx, ntprinter,
4628 &r->out.info->info2, snum);
4631 result = construct_printer_info3(p->mem_ctx, ntprinter,
4632 &r->out.info->info3, snum);
4635 result = construct_printer_info4(p->mem_ctx, ntprinter,
4636 &r->out.info->info4, snum);
4639 result = construct_printer_info5(p->mem_ctx, ntprinter,
4640 &r->out.info->info5, snum);
4643 result = construct_printer_info6(p->mem_ctx, ntprinter,
4644 &r->out.info->info6, snum);
4647 result = construct_printer_info7(p->mem_ctx, Printer,
4648 &r->out.info->info7, snum);
4651 result = construct_printer_info8(p->mem_ctx, ntprinter,
4652 &r->out.info->info8, snum);
4655 result = WERR_UNKNOWN_LEVEL;
4659 free_a_printer(&ntprinter, 2);
4661 if (!W_ERROR_IS_OK(result)) {
4662 TALLOC_FREE(r->out.info);
4666 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, NULL,
4667 r->out.info, r->in.level);
4668 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4670 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4673 /********************************************************************
4674 ********************************************************************/
4676 static const char **string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4677 fstring *fstring_array,
4678 const char *cservername)
4680 int i, num_strings = 0;
4681 const char **array = NULL;
4683 for (i=0; fstring_array && fstring_array[i][0] != '\0'; i++) {
4685 const char *str = talloc_asprintf(mem_ctx, "\\\\%s%s",
4686 cservername, fstring_array[i]);
4693 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4700 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4701 &array, &num_strings);
4707 /********************************************************************
4708 * fill a spoolss_DriverInfo1 struct
4709 ********************************************************************/
4711 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4712 struct spoolss_DriverInfo1 *r,
4713 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4714 const char *servername,
4715 const char *architecture)
4717 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4718 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4723 /********************************************************************
4724 * fill a spoolss_DriverInfo2 struct
4725 ********************************************************************/
4727 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4728 struct spoolss_DriverInfo2 *r,
4729 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4730 const char *servername)
4733 const char *cservername = canon_servername(servername);
4735 r->version = driver->info_3->cversion;
4737 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4738 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4739 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4740 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4742 if (strlen(driver->info_3->driverpath)) {
4743 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4744 cservername, driver->info_3->driverpath);
4746 r->driver_path = talloc_strdup(mem_ctx, "");
4748 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4750 if (strlen(driver->info_3->datafile)) {
4751 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4752 cservername, driver->info_3->datafile);
4754 r->data_file = talloc_strdup(mem_ctx, "");
4756 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4758 if (strlen(driver->info_3->configfile)) {
4759 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4760 cservername, driver->info_3->configfile);
4762 r->config_file = talloc_strdup(mem_ctx, "");
4764 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4769 /********************************************************************
4770 * fill a spoolss_DriverInfo3 struct
4771 ********************************************************************/
4773 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4774 struct spoolss_DriverInfo3 *r,
4775 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4776 const char *servername)
4778 const char *cservername = canon_servername(servername);
4780 r->version = driver->info_3->cversion;
4782 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4783 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4784 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4785 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4787 if (strlen(driver->info_3->driverpath)) {
4788 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4789 cservername, driver->info_3->driverpath);
4791 r->driver_path = talloc_strdup(mem_ctx, "");
4793 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4795 if (strlen(driver->info_3->datafile)) {
4796 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4797 cservername, driver->info_3->datafile);
4799 r->data_file = talloc_strdup(mem_ctx, "");
4801 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4803 if (strlen(driver->info_3->configfile)) {
4804 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4805 cservername, driver->info_3->configfile);
4807 r->config_file = talloc_strdup(mem_ctx, "");
4809 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4811 if (strlen(driver->info_3->helpfile)) {
4812 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4813 cservername, driver->info_3->helpfile);
4815 r->help_file = talloc_strdup(mem_ctx, "");
4817 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4819 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4820 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4821 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4822 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4824 r->dependent_files = string_array_from_driver_info(mem_ctx,
4825 driver->info_3->dependentfiles,
4830 /********************************************************************
4831 * fill a spoolss_DriverInfo4 struct
4832 ********************************************************************/
4834 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4835 struct spoolss_DriverInfo4 *r,
4836 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4837 const char *servername)
4839 const char *cservername = canon_servername(servername);
4841 r->version = driver->info_3->cversion;
4843 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4844 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4845 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4846 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4848 if (strlen(driver->info_3->driverpath)) {
4849 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4850 cservername, driver->info_3->driverpath);
4852 r->driver_path = talloc_strdup(mem_ctx, "");
4854 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4856 if (strlen(driver->info_3->datafile)) {
4857 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4858 cservername, driver->info_3->datafile);
4860 r->data_file = talloc_strdup(mem_ctx, "");
4862 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4864 if (strlen(driver->info_3->configfile)) {
4865 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4866 cservername, driver->info_3->configfile);
4868 r->config_file = talloc_strdup(mem_ctx, "");
4870 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4872 if (strlen(driver->info_3->helpfile)) {
4873 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4874 cservername, driver->info_3->helpfile);
4876 r->help_file = talloc_strdup(mem_ctx, "");
4878 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4880 r->dependent_files = string_array_from_driver_info(mem_ctx,
4881 driver->info_3->dependentfiles,
4885 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4886 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4887 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4888 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
4890 r->previous_names = string_array_from_driver_info(mem_ctx,
4897 /********************************************************************
4898 * fill a spoolss_DriverInfo5 struct
4899 ********************************************************************/
4901 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4902 struct spoolss_DriverInfo5 *r,
4903 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4904 const char *servername)
4906 const char *cservername = canon_servername(servername);
4908 r->version = driver->info_3->cversion;
4910 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4911 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4912 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4913 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4915 if (strlen(driver->info_3->driverpath)) {
4916 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4917 cservername, driver->info_3->driverpath);
4919 r->driver_path = talloc_strdup(mem_ctx, "");
4921 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4923 if (strlen(driver->info_3->datafile)) {
4924 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4925 cservername, driver->info_3->datafile);
4927 r->data_file = talloc_strdup(mem_ctx, "");
4929 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4931 if (strlen(driver->info_3->configfile)) {
4932 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4933 cservername, driver->info_3->configfile);
4935 r->config_file = talloc_strdup(mem_ctx, "");
4937 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4939 r->driver_attributes = 0;
4940 r->config_version = 0;
4941 r->driver_version = 0;
4945 /********************************************************************
4946 * fill a spoolss_DriverInfo6 struct
4947 ********************************************************************/
4949 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4950 struct spoolss_DriverInfo6 *r,
4951 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
4952 const char *servername)
4954 const char *cservername = canon_servername(servername);
4956 r->version = driver->info_3->cversion;
4958 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
4959 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4960 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
4961 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4963 if (strlen(driver->info_3->driverpath)) {
4964 r->driver_path = talloc_asprintf(mem_ctx, "\\\\%s%s",
4965 cservername, driver->info_3->driverpath);
4967 r->driver_path = talloc_strdup(mem_ctx, "");
4969 W_ERROR_HAVE_NO_MEMORY(r->driver_path);
4971 if (strlen(driver->info_3->datafile)) {
4972 r->data_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4973 cservername, driver->info_3->datafile);
4975 r->data_file = talloc_strdup(mem_ctx, "");
4977 W_ERROR_HAVE_NO_MEMORY(r->data_file);
4979 if (strlen(driver->info_3->configfile)) {
4980 r->config_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4981 cservername, driver->info_3->configfile);
4983 r->config_file = talloc_strdup(mem_ctx, "");
4985 W_ERROR_HAVE_NO_MEMORY(r->config_file);
4987 if (strlen(driver->info_3->helpfile)) {
4988 r->help_file = talloc_asprintf(mem_ctx, "\\\\%s%s",
4989 cservername, driver->info_3->helpfile);
4991 r->help_file = talloc_strdup(mem_ctx, "");
4993 W_ERROR_HAVE_NO_MEMORY(r->help_file);
4995 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
4996 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
4997 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
4998 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5000 r->dependent_files = string_array_from_driver_info(mem_ctx,
5001 driver->info_3->dependentfiles,
5003 r->previous_names = string_array_from_driver_info(mem_ctx,
5008 r->driver_version = 0;
5010 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5011 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5012 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5013 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5014 r->hardware_id = talloc_strdup(mem_ctx, "");
5015 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5016 r->provider = talloc_strdup(mem_ctx, "");
5017 W_ERROR_HAVE_NO_MEMORY(r->provider);
5022 /********************************************************************
5023 ********************************************************************/
5025 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5026 struct spoolss_DriverFileInfo *r,
5027 const char *cservername,
5028 const char *file_name,
5029 enum spoolss_DriverFileType file_type,
5030 uint32_t file_version)
5032 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5033 cservername, file_name);
5034 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5035 r->file_type = file_type;
5036 r->file_version = file_version;
5041 /********************************************************************
5042 ********************************************************************/
5044 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5045 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5046 const char *cservername,
5047 struct spoolss_DriverFileInfo **info_p,
5050 struct spoolss_DriverFileInfo *info = NULL;
5058 if (strlen(driver->info_3->driverpath)) {
5059 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5060 struct spoolss_DriverFileInfo,
5062 W_ERROR_HAVE_NO_MEMORY(info);
5063 result = fill_spoolss_DriverFileInfo(info,
5066 driver->info_3->driverpath,
5067 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5069 W_ERROR_NOT_OK_RETURN(result);
5073 if (strlen(driver->info_3->configfile)) {
5074 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5075 struct spoolss_DriverFileInfo,
5077 W_ERROR_HAVE_NO_MEMORY(info);
5078 result = fill_spoolss_DriverFileInfo(info,
5081 driver->info_3->configfile,
5082 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5084 W_ERROR_NOT_OK_RETURN(result);
5088 if (strlen(driver->info_3->datafile)) {
5089 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5090 struct spoolss_DriverFileInfo,
5092 W_ERROR_HAVE_NO_MEMORY(info);
5093 result = fill_spoolss_DriverFileInfo(info,
5096 driver->info_3->datafile,
5097 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5099 W_ERROR_NOT_OK_RETURN(result);
5103 if (strlen(driver->info_3->helpfile)) {
5104 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5105 struct spoolss_DriverFileInfo,
5107 W_ERROR_HAVE_NO_MEMORY(info);
5108 result = fill_spoolss_DriverFileInfo(info,
5111 driver->info_3->helpfile,
5112 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5114 W_ERROR_NOT_OK_RETURN(result);
5118 for (i=0; driver->info_3->dependentfiles[i][0] != '\0'; i++) {
5119 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5120 struct spoolss_DriverFileInfo,
5122 W_ERROR_HAVE_NO_MEMORY(info);
5123 result = fill_spoolss_DriverFileInfo(info,
5126 driver->info_3->dependentfiles[i],
5127 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5129 W_ERROR_NOT_OK_RETURN(result);
5139 /********************************************************************
5140 * fill a spoolss_DriverInfo101 sttruct
5141 ********************************************************************/
5143 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5144 struct spoolss_DriverInfo101 *r,
5145 const NT_PRINTER_DRIVER_INFO_LEVEL *driver,
5146 const char *servername)
5148 const char *cservername = canon_servername(servername);
5151 r->version = driver->info_3->cversion;
5153 r->driver_name = talloc_strdup(mem_ctx, driver->info_3->name);
5154 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5155 r->architecture = talloc_strdup(mem_ctx, driver->info_3->environment);
5156 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5158 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5162 if (!W_ERROR_IS_OK(result)) {
5166 r->monitor_name = talloc_strdup(mem_ctx, driver->info_3->monitorname);
5167 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
5169 r->default_datatype = talloc_strdup(mem_ctx, driver->info_3->defaultdatatype);
5170 W_ERROR_HAVE_NO_MEMORY(r->default_datatype);
5172 r->previous_names = string_array_from_driver_info(mem_ctx,
5176 r->driver_version = 0;
5178 r->manufacturer_name = talloc_strdup(mem_ctx, "");
5179 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_name);
5180 r->manufacturer_url = talloc_strdup(mem_ctx, "");
5181 W_ERROR_HAVE_NO_MEMORY(r->manufacturer_url);
5182 r->hardware_id = talloc_strdup(mem_ctx, "");
5183 W_ERROR_HAVE_NO_MEMORY(r->hardware_id);
5184 r->provider = talloc_strdup(mem_ctx, "");
5185 W_ERROR_HAVE_NO_MEMORY(r->provider);
5190 /********************************************************************
5191 * construct_printer_driver_info_1
5192 ********************************************************************/
5194 static WERROR construct_printer_driver_info_1(TALLOC_CTX *mem_ctx,
5195 struct spoolss_DriverInfo1 *r,
5197 const char *servername,
5198 const char *architecture,
5201 NT_PRINTER_INFO_LEVEL *printer = NULL;
5202 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5205 ZERO_STRUCT(driver);
5207 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5208 return WERR_INVALID_PRINTER_NAME;
5210 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5211 free_a_printer(&printer, 2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER;
5215 result = fill_printer_driver_info1(mem_ctx, r, &driver, servername, architecture);
5217 free_a_printer(&printer,2);
5222 /********************************************************************
5223 * construct_printer_driver_info_2
5224 * fill a printer_info_2 struct
5225 ********************************************************************/
5227 static WERROR construct_printer_driver_info_2(TALLOC_CTX *mem_ctx,
5228 struct spoolss_DriverInfo2 *r,
5230 const char *servername,
5231 const char *architecture,
5234 NT_PRINTER_INFO_LEVEL *printer = NULL;
5235 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5238 ZERO_STRUCT(printer);
5239 ZERO_STRUCT(driver);
5241 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5242 return WERR_INVALID_PRINTER_NAME;
5244 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5245 free_a_printer(&printer, 2);
5246 return WERR_UNKNOWN_PRINTER_DRIVER;
5249 result = fill_printer_driver_info2(mem_ctx, r, &driver, servername);
5251 free_a_printer(&printer,2);
5256 /********************************************************************
5257 * construct_printer_info_3
5258 * fill a printer_info_3 struct
5259 ********************************************************************/
5261 static WERROR construct_printer_driver_info_3(TALLOC_CTX *mem_ctx,
5262 struct spoolss_DriverInfo3 *r,
5264 const char *servername,
5265 const char *architecture,
5268 NT_PRINTER_INFO_LEVEL *printer = NULL;
5269 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5271 ZERO_STRUCT(driver);
5273 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5274 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5275 if (!W_ERROR_IS_OK(status))
5276 return WERR_INVALID_PRINTER_NAME;
5278 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5279 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5284 * I put this code in during testing. Helpful when commenting out the
5285 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5286 * as win2k always queries the driver using an infor level of 6.
5287 * I've left it in (but ifdef'd out) because I'll probably
5288 * use it in experimentation again in the future. --jerry 22/01/2002
5291 if (!W_ERROR_IS_OK(status)) {
5293 * Is this a W2k client ?
5296 /* Yes - try again with a WinNT driver. */
5298 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5299 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", win_errstr(status)));
5303 if (!W_ERROR_IS_OK(status)) {
5304 free_a_printer(&printer,2);
5305 return WERR_UNKNOWN_PRINTER_DRIVER;
5313 status = fill_printer_driver_info3(mem_ctx, r, &driver, servername);
5315 free_a_printer(&printer,2);
5320 /********************************************************************
5321 * construct_printer_info_6
5322 * fill a printer_info_6 struct
5323 ********************************************************************/
5325 static WERROR construct_printer_driver_info_6(TALLOC_CTX *mem_ctx,
5326 struct spoolss_DriverInfo6 *r,
5328 const char *servername,
5329 const char *architecture,
5332 NT_PRINTER_INFO_LEVEL *printer = NULL;
5333 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5336 ZERO_STRUCT(driver);
5338 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5340 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5342 if (!W_ERROR_IS_OK(status))
5343 return WERR_INVALID_PRINTER_NAME;
5345 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5347 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5349 if (!W_ERROR_IS_OK(status))
5352 * Is this a W2k client ?
5356 free_a_printer(&printer,2);
5357 return WERR_UNKNOWN_PRINTER_DRIVER;
5360 /* Yes - try again with a WinNT driver. */
5362 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5363 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", win_errstr(status)));
5364 if (!W_ERROR_IS_OK(status)) {
5365 free_a_printer(&printer,2);
5366 return WERR_UNKNOWN_PRINTER_DRIVER;
5370 status = fill_printer_driver_info6(mem_ctx, r, &driver, servername);
5372 free_a_printer(&printer,2);
5373 free_a_printer_driver(driver, 3);
5378 /********************************************************************
5379 * construct_printer_info_101
5380 * fill a printer_info_101 struct
5381 ********************************************************************/
5383 static WERROR construct_printer_driver_info_101(TALLOC_CTX *mem_ctx,
5384 struct spoolss_DriverInfo101 *r,
5386 const char *servername,
5387 const char *architecture,
5390 NT_PRINTER_INFO_LEVEL *printer = NULL;
5391 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5394 ZERO_STRUCT(driver);
5396 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
5398 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5399 win_errstr(result)));
5401 if (!W_ERROR_IS_OK(result)) {
5402 return WERR_INVALID_PRINTER_NAME;
5405 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5406 architecture, version);
5408 DEBUG(8,("construct_printer_driver_info_101: status: %s\n",
5409 win_errstr(result)));
5411 if (!W_ERROR_IS_OK(result)) {
5413 * Is this a W2k client ?
5417 free_a_printer(&printer, 2);
5418 return WERR_UNKNOWN_PRINTER_DRIVER;
5421 /* Yes - try again with a WinNT driver. */
5423 result = get_a_printer_driver(&driver, 3, printer->info_2->drivername,
5424 architecture, version);
5425 DEBUG(8,("construct_printer_driver_info_6: status: %s\n",
5426 win_errstr(result)));
5427 if (!W_ERROR_IS_OK(result)) {
5428 free_a_printer(&printer, 2);
5429 return WERR_UNKNOWN_PRINTER_DRIVER;
5433 result = fill_printer_driver_info101(mem_ctx, r, &driver, servername);
5435 free_a_printer(&printer, 2);
5436 free_a_printer_driver(driver, 3);
5441 /****************************************************************
5442 _spoolss_GetPrinterDriver2
5443 ****************************************************************/
5445 WERROR _spoolss_GetPrinterDriver2(pipes_struct *p,
5446 struct spoolss_GetPrinterDriver2 *r)
5448 Printer_entry *printer;
5451 const char *servername;
5454 /* that's an [in out] buffer */
5456 if (!r->in.buffer && (r->in.offered != 0)) {
5457 return WERR_INVALID_PARAM;
5460 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5462 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5463 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5464 return WERR_INVALID_PRINTER_NAME;
5468 *r->out.server_major_version = 0;
5469 *r->out.server_minor_version = 0;
5471 servername = get_server_name(printer);
5473 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5477 switch (r->in.level) {
5479 result = construct_printer_driver_info_1(p->mem_ctx,
5480 &r->out.info->info1,
5484 r->in.client_major_version);
5487 result = construct_printer_driver_info_2(p->mem_ctx,
5488 &r->out.info->info2,
5492 r->in.client_major_version);
5495 result = construct_printer_driver_info_3(p->mem_ctx,
5496 &r->out.info->info3,
5500 r->in.client_major_version);
5503 result = construct_printer_driver_info_6(p->mem_ctx,
5504 &r->out.info->info6,
5508 r->in.client_major_version);
5511 result = construct_printer_driver_info_101(p->mem_ctx,
5512 &r->out.info->info101,
5516 r->in.client_major_version);
5519 result = WERR_UNKNOWN_LEVEL;
5523 if (!W_ERROR_IS_OK(result)) {
5524 TALLOC_FREE(r->out.info);
5528 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, NULL,
5529 r->out.info, r->in.level);
5530 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5532 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5536 /****************************************************************
5537 _spoolss_StartPagePrinter
5538 ****************************************************************/
5540 WERROR _spoolss_StartPagePrinter(pipes_struct *p,
5541 struct spoolss_StartPagePrinter *r)
5543 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5546 DEBUG(3,("_spoolss_StartPagePrinter: "
5547 "Error in startpageprinter printer handle\n"));
5551 Printer->page_started = true;
5555 /****************************************************************
5556 _spoolss_EndPagePrinter
5557 ****************************************************************/
5559 WERROR _spoolss_EndPagePrinter(pipes_struct *p,
5560 struct spoolss_EndPagePrinter *r)
5564 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5567 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5568 OUR_HANDLE(r->in.handle)));
5572 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5575 Printer->page_started = false;
5576 print_job_endpage(snum, Printer->jobid);
5581 /****************************************************************
5582 _spoolss_StartDocPrinter
5583 ****************************************************************/
5585 WERROR _spoolss_StartDocPrinter(pipes_struct *p,
5586 struct spoolss_StartDocPrinter *r)
5588 struct spoolss_DocumentInfo1 *info_1;
5590 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5593 DEBUG(2,("_spoolss_StartDocPrinter: "
5594 "Invalid handle (%s:%u:%u)\n",
5595 OUR_HANDLE(r->in.handle)));
5599 if (r->in.level != 1) {
5600 return WERR_UNKNOWN_LEVEL;
5603 info_1 = r->in.info.info1;
5606 * a nice thing with NT is it doesn't listen to what you tell it.
5607 * when asked to send _only_ RAW datas, it tries to send datas
5610 * So I add checks like in NT Server ...
5613 if (info_1->datatype) {
5614 if (strcmp(info_1->datatype, "RAW") != 0) {
5616 return WERR_INVALID_DATATYPE;
5620 /* get the share number of the printer */
5621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5625 Printer->jobid = print_job_start(p->server_info, snum,
5626 info_1->document_name,
5627 Printer->nt_devmode);
5629 /* An error occured in print_job_start() so return an appropriate
5632 if (Printer->jobid == -1) {
5633 return map_werror_from_unix(errno);
5636 Printer->document_started = true;
5637 *r->out.job_id = Printer->jobid;
5642 /****************************************************************
5643 _spoolss_EndDocPrinter
5644 ****************************************************************/
5646 WERROR _spoolss_EndDocPrinter(pipes_struct *p,
5647 struct spoolss_EndDocPrinter *r)
5649 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5653 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5654 OUR_HANDLE(r->in.handle)));
5658 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5662 Printer->document_started = false;
5663 print_job_end(snum, Printer->jobid, NORMAL_CLOSE);
5664 /* error codes unhandled so far ... */
5669 /****************************************************************
5670 _spoolss_WritePrinter
5671 ****************************************************************/
5673 WERROR _spoolss_WritePrinter(pipes_struct *p,
5674 struct spoolss_WritePrinter *r)
5676 uint32_t buffer_written;
5678 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5681 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5682 OUR_HANDLE(r->in.handle)));
5683 *r->out.num_written = r->in._data_size;
5687 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5690 buffer_written = (uint32_t)print_job_write(snum, Printer->jobid,
5691 (const char *)r->in.data.data,
5693 (size_t)r->in._data_size);
5694 if (buffer_written == (uint32_t)-1) {
5695 *r->out.num_written = 0;
5696 if (errno == ENOSPC)
5697 return WERR_NO_SPOOL_SPACE;
5699 return WERR_ACCESS_DENIED;
5702 *r->out.num_written = r->in._data_size;
5707 /********************************************************************
5708 * api_spoolss_getprinter
5709 * called from the spoolss dispatcher
5711 ********************************************************************/
5713 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5717 WERROR errcode = WERR_BADFUNC;
5718 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5721 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5722 OUR_HANDLE(handle)));
5726 if (!get_printer_snum(p, handle, &snum, NULL))
5730 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5731 errcode = print_queue_pause(p->server_info, snum);
5733 case SPOOLSS_PRINTER_CONTROL_RESUME:
5734 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5735 errcode = print_queue_resume(p->server_info, snum);
5737 case SPOOLSS_PRINTER_CONTROL_PURGE:
5738 errcode = print_queue_purge(p->server_info, snum);
5741 return WERR_UNKNOWN_LEVEL;
5748 /****************************************************************
5749 _spoolss_AbortPrinter
5750 * From MSDN: "Deletes printer's spool file if printer is configured
5752 ****************************************************************/
5754 WERROR _spoolss_AbortPrinter(pipes_struct *p,
5755 struct spoolss_AbortPrinter *r)
5757 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5759 WERROR errcode = WERR_OK;
5762 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5763 OUR_HANDLE(r->in.handle)));
5767 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5770 print_job_delete(p->server_info, snum, Printer->jobid, &errcode );
5775 /********************************************************************
5776 * called by spoolss_api_setprinter
5777 * when updating a printer description
5778 ********************************************************************/
5780 static WERROR update_printer_sec(struct policy_handle *handle,
5781 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5783 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5787 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5790 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5791 OUR_HANDLE(handle)));
5793 result = WERR_BADFID;
5798 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5799 result = WERR_INVALID_PARAM;
5803 /* Check the user has permissions to change the security
5804 descriptor. By experimentation with two NT machines, the user
5805 requires Full Access to the printer to change security
5808 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5809 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5810 result = WERR_ACCESS_DENIED;
5814 /* NT seems to like setting the security descriptor even though
5815 nothing may have actually changed. */
5817 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
5818 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5819 result = WERR_BADFID;
5823 if (DEBUGLEVEL >= 10) {
5827 the_acl = old_secdesc_ctr->sd->dacl;
5828 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5829 PRINTERNAME(snum), the_acl->num_aces));
5831 for (i = 0; i < the_acl->num_aces; i++) {
5832 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5833 &the_acl->aces[i].trustee),
5834 the_acl->aces[i].access_mask));
5837 the_acl = secdesc_ctr->sd->dacl;
5840 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5841 PRINTERNAME(snum), the_acl->num_aces));
5843 for (i = 0; i < the_acl->num_aces; i++) {
5844 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5845 &the_acl->aces[i].trustee),
5846 the_acl->aces[i].access_mask));
5849 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5853 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5854 if (!new_secdesc_ctr) {
5855 result = WERR_NOMEM;
5859 if (security_descriptor_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
5864 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5871 /********************************************************************
5872 Canonicalize printer info from a client
5874 ATTN: It does not matter what we set the servername to hear
5875 since we do the necessary work in get_a_printer() to set it to
5876 the correct value based on what the client sent in the
5877 _spoolss_open_printer_ex().
5878 ********************************************************************/
5880 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5882 fstring printername;
5885 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5886 "portname=%s drivername=%s comment=%s location=%s\n",
5887 info->servername, info->printername, info->sharename,
5888 info->portname, info->drivername, info->comment, info->location));
5890 /* we force some elements to "correct" values */
5891 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5892 fstrcpy(info->sharename, lp_servicename(snum));
5894 /* check to see if we allow printername != sharename */
5896 if ( lp_force_printername(snum) ) {
5897 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5898 global_myname(), info->sharename );
5901 /* make sure printername is in \\server\printername format */
5903 fstrcpy( printername, info->printername );
5905 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5906 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5910 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5911 global_myname(), p );
5914 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5915 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5922 /****************************************************************************
5923 ****************************************************************************/
5925 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5927 char *cmd = lp_addport_cmd();
5928 char *command = NULL;
5930 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5931 bool is_print_op = false;
5934 return WERR_ACCESS_DENIED;
5937 command = talloc_asprintf(ctx,
5938 "%s \"%s\" \"%s\"", cmd, portname, uri );
5944 is_print_op = user_has_privileges( token, &se_printop );
5946 DEBUG(10,("Running [%s]\n", command));
5948 /********* BEGIN SePrintOperatorPrivilege **********/
5953 ret = smbrun(command, NULL);
5958 /********* END SePrintOperatorPrivilege **********/
5960 DEBUGADD(10,("returned [%d]\n", ret));
5962 TALLOC_FREE(command);
5965 return WERR_ACCESS_DENIED;
5971 /****************************************************************************
5972 ****************************************************************************/
5974 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5976 char *cmd = lp_addprinter_cmd();
5978 char *command = NULL;
5982 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5983 bool is_print_op = false;
5984 char *remote_machine = talloc_strdup(ctx, "%m");
5986 if (!remote_machine) {
5989 remote_machine = talloc_sub_basic(ctx,
5990 current_user_info.smb_name,
5991 current_user_info.domain,
5993 if (!remote_machine) {
5997 command = talloc_asprintf(ctx,
5998 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5999 cmd, printer->info_2->printername, printer->info_2->sharename,
6000 printer->info_2->portname, printer->info_2->drivername,
6001 printer->info_2->location, printer->info_2->comment, remote_machine);
6007 is_print_op = user_has_privileges( token, &se_printop );
6009 DEBUG(10,("Running [%s]\n", command));
6011 /********* BEGIN SePrintOperatorPrivilege **********/
6016 if ( (ret = smbrun(command, &fd)) == 0 ) {
6017 /* Tell everyone we updated smb.conf. */
6018 message_send_all(smbd_messaging_context(),
6019 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6025 /********* END SePrintOperatorPrivilege **********/
6027 DEBUGADD(10,("returned [%d]\n", ret));
6029 TALLOC_FREE(command);
6030 TALLOC_FREE(remote_machine);
6038 /* reload our services immediately */
6040 reload_services(false);
6044 /* Get lines and convert them back to dos-codepage */
6045 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6046 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6049 /* Set the portname to what the script says the portname should be. */
6050 /* but don't require anything to be return from the script exit a good error code */
6053 /* Set the portname to what the script says the portname should be. */
6054 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6055 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6058 TALLOC_FREE(qlines);
6063 /********************************************************************
6064 * Called by spoolss_api_setprinter
6065 * when updating a printer description.
6066 ********************************************************************/
6068 static WERROR update_printer(pipes_struct *p, struct policy_handle *handle,
6069 struct spoolss_SetPrinterInfoCtr *info_ctr,
6070 struct spoolss_DeviceMode *devmode)
6073 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6074 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6079 DEBUG(8,("update_printer\n"));
6084 result = WERR_BADFID;
6088 if (!get_printer_snum(p, handle, &snum, NULL)) {
6089 result = WERR_BADFID;
6093 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6094 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6095 result = WERR_BADFID;
6099 DEBUGADD(8,("Converting info_2 struct\n"));
6102 * convert_printer_info converts the incoming
6103 * info from the client and overwrites the info
6104 * just read from the tdb in the pointer 'printer'.
6107 if (!convert_printer_info(info_ctr, printer)) {
6108 result = WERR_NOMEM;
6113 /* we have a valid devmode
6114 convert it and link it*/
6116 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6117 if (!convert_devicemode(printer->info_2->printername, devmode,
6118 &printer->info_2->devmode)) {
6119 result = WERR_NOMEM;
6124 /* Do sanity check on the requested changes for Samba */
6126 if (!check_printer_ok(printer->info_2, snum)) {
6127 result = WERR_INVALID_PARAM;
6131 /* FIXME!!! If the driver has changed we really should verify that
6132 it is installed before doing much else --jerry */
6134 /* Check calling user has permission to update printer description */
6136 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6137 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6138 result = WERR_ACCESS_DENIED;
6142 /* Call addprinter hook */
6143 /* Check changes to see if this is really needed */
6145 if ( *lp_addprinter_cmd()
6146 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6147 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6148 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6149 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6151 /* add_printer_hook() will call reload_services() */
6153 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
6155 result = WERR_ACCESS_DENIED;
6161 * When a *new* driver is bound to a printer, the drivername is used to
6162 * lookup previously saved driver initialization info, which is then
6163 * bound to the printer, simulating what happens in the Windows arch.
6165 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6167 if (!set_driver_init(printer, 2))
6169 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6170 printer->info_2->drivername));
6173 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6174 printer->info_2->drivername));
6176 notify_printer_driver(snum, printer->info_2->drivername);
6180 * flag which changes actually occured. This is a small subset of
6181 * all the possible changes. We also have to update things in the
6185 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6186 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6187 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6188 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6190 notify_printer_comment(snum, printer->info_2->comment);
6193 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6194 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6195 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6196 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6198 notify_printer_sharename(snum, printer->info_2->sharename);
6201 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6204 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6207 pname = printer->info_2->printername;
6210 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6211 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6212 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6214 notify_printer_printername( snum, pname );
6217 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6218 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6219 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6220 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6222 notify_printer_port(snum, printer->info_2->portname);
6225 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6226 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6227 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6228 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6230 notify_printer_location(snum, printer->info_2->location);
6233 /* here we need to update some more DsSpooler keys */
6234 /* uNCName, serverName, shortServerName */
6236 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6237 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6238 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6239 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6240 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6242 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6243 global_myname(), printer->info_2->sharename );
6244 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6245 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6246 REG_SZ, (uint8_t *)buffer.buffer, buffer.uni_str_len*2 );
6248 /* Update printer info */
6249 result = mod_a_printer(printer, 2);
6252 free_a_printer(&printer, 2);
6253 free_a_printer(&old_printer, 2);
6259 /****************************************************************************
6260 ****************************************************************************/
6261 static WERROR publish_or_unpublish_printer(pipes_struct *p,
6262 struct policy_handle *handle,
6263 struct spoolss_SetPrinterInfo7 *info7)
6267 Printer_entry *Printer;
6269 if ( lp_security() != SEC_ADS ) {
6270 return WERR_UNKNOWN_LEVEL;
6273 Printer = find_printer_index_by_hnd(p, handle);
6275 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6280 if (!get_printer_snum(p, handle, &snum, NULL))
6283 nt_printer_publish(Printer, snum, info7->action);
6287 return WERR_UNKNOWN_LEVEL;
6291 /****************************************************************
6293 ****************************************************************/
6295 WERROR _spoolss_SetPrinter(pipes_struct *p,
6296 struct spoolss_SetPrinter *r)
6300 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6303 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6304 OUR_HANDLE(r->in.handle)));
6308 /* check the level */
6309 switch (r->in.info_ctr->level) {
6311 return control_printer(r->in.handle, r->in.command, p);
6313 result = update_printer(p, r->in.handle,
6315 r->in.devmode_ctr->devmode);
6316 if (!W_ERROR_IS_OK(result))
6318 if (r->in.secdesc_ctr->sd)
6319 result = update_printer_sec(r->in.handle, p,
6323 return update_printer_sec(r->in.handle, p,
6326 return publish_or_unpublish_printer(p, r->in.handle,
6327 r->in.info_ctr->info.info7);
6329 return WERR_UNKNOWN_LEVEL;
6333 /****************************************************************
6334 _spoolss_FindClosePrinterNotify
6335 ****************************************************************/
6337 WERROR _spoolss_FindClosePrinterNotify(pipes_struct *p,
6338 struct spoolss_FindClosePrinterNotify *r)
6340 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6343 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6344 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6348 if (Printer->notify.client_connected == true) {
6351 if ( Printer->printer_type == SPLHND_SERVER)
6353 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6354 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6357 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6360 Printer->notify.flags=0;
6361 Printer->notify.options=0;
6362 Printer->notify.localmachine[0]='\0';
6363 Printer->notify.printerlocal=0;
6364 TALLOC_FREE(Printer->notify.option);
6365 Printer->notify.client_connected = false;
6370 /****************************************************************
6372 ****************************************************************/
6374 WERROR _spoolss_AddJob(pipes_struct *p,
6375 struct spoolss_AddJob *r)
6377 if (!r->in.buffer && (r->in.offered != 0)) {
6378 return WERR_INVALID_PARAM;
6381 /* this is what a NT server returns for AddJob. AddJob must fail on
6382 * non-local printers */
6384 if (r->in.level != 1) {
6385 return WERR_UNKNOWN_LEVEL;
6388 return WERR_INVALID_PARAM;
6391 /****************************************************************************
6393 ****************************************************************************/
6395 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6396 struct spoolss_JobInfo1 *r,
6397 const print_queue_struct *queue,
6398 int position, int snum,
6399 const NT_PRINTER_INFO_LEVEL *ntprinter)
6403 t = gmtime(&queue->time);
6405 r->job_id = queue->job;
6407 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6408 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6409 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6410 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6411 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6412 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6413 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6414 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6415 r->data_type = talloc_strdup(mem_ctx, "RAW");
6416 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6417 r->text_status = talloc_strdup(mem_ctx, "");
6418 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6420 r->status = nt_printj_status(queue->status);
6421 r->priority = queue->priority;
6422 r->position = position;
6423 r->total_pages = queue->page_count;
6424 r->pages_printed = 0; /* ??? */
6426 init_systemtime(&r->submitted, t);
6431 /****************************************************************************
6433 ****************************************************************************/
6435 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6436 struct spoolss_JobInfo2 *r,
6437 const print_queue_struct *queue,
6438 int position, int snum,
6439 const NT_PRINTER_INFO_LEVEL *ntprinter,
6440 struct spoolss_DeviceMode *devmode)
6444 t = gmtime(&queue->time);
6446 r->job_id = queue->job;
6448 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6449 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6450 r->server_name = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
6451 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6452 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6453 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6454 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6455 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6456 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6457 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6458 r->data_type = talloc_strdup(mem_ctx, "RAW");
6459 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6460 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6461 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6462 r->parameters = talloc_strdup(mem_ctx, "");
6463 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6464 r->driver_name = talloc_strdup(mem_ctx, ntprinter->info_2->drivername);
6465 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6467 r->devmode = devmode;
6469 r->text_status = talloc_strdup(mem_ctx, "");
6470 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6474 r->status = nt_printj_status(queue->status);
6475 r->priority = queue->priority;
6476 r->position = position;
6479 r->total_pages = queue->page_count;
6480 r->size = queue->size;
6481 init_systemtime(&r->submitted, t);
6483 r->pages_printed = 0; /* ??? */
6488 /****************************************************************************
6489 Enumjobs at level 1.
6490 ****************************************************************************/
6492 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6493 const print_queue_struct *queue,
6494 uint32_t num_queues, int snum,
6495 const NT_PRINTER_INFO_LEVEL *ntprinter,
6496 union spoolss_JobInfo **info_p,
6499 union spoolss_JobInfo *info;
6501 WERROR result = WERR_OK;
6503 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6504 W_ERROR_HAVE_NO_MEMORY(info);
6506 *count = num_queues;
6508 for (i=0; i<*count; i++) {
6509 result = fill_job_info1(info,
6515 if (!W_ERROR_IS_OK(result)) {
6521 if (!W_ERROR_IS_OK(result)) {
6532 /****************************************************************************
6533 Enumjobs at level 2.
6534 ****************************************************************************/
6536 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6537 const print_queue_struct *queue,
6538 uint32_t num_queues, int snum,
6539 const NT_PRINTER_INFO_LEVEL *ntprinter,
6540 union spoolss_JobInfo **info_p,
6543 union spoolss_JobInfo *info;
6545 WERROR result = WERR_OK;
6547 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6548 W_ERROR_HAVE_NO_MEMORY(info);
6550 *count = num_queues;
6552 for (i=0; i<*count; i++) {
6554 struct spoolss_DeviceMode *devmode;
6556 devmode = construct_dev_mode(info, lp_const_servicename(snum));
6558 result = WERR_NOMEM;
6562 result = fill_job_info2(info,
6569 if (!W_ERROR_IS_OK(result)) {
6575 if (!W_ERROR_IS_OK(result)) {
6586 /****************************************************************
6588 ****************************************************************/
6590 WERROR _spoolss_EnumJobs(pipes_struct *p,
6591 struct spoolss_EnumJobs *r)
6594 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6596 print_status_struct prt_status;
6597 print_queue_struct *queue = NULL;
6600 /* that's an [in out] buffer */
6602 if (!r->in.buffer && (r->in.offered != 0)) {
6603 return WERR_INVALID_PARAM;
6606 DEBUG(4,("_spoolss_EnumJobs\n"));
6610 *r->out.info = NULL;
6612 /* lookup the printer snum and tdb entry */
6614 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6618 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6619 if (!W_ERROR_IS_OK(result)) {
6623 count = print_queue_status(snum, &queue, &prt_status);
6624 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6625 count, prt_status.status, prt_status.message));
6629 free_a_printer(&ntprinter, 2);
6633 switch (r->in.level) {
6635 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6636 ntprinter, r->out.info, r->out.count);
6639 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6640 ntprinter, r->out.info, r->out.count);
6643 result = WERR_UNKNOWN_LEVEL;
6648 free_a_printer(&ntprinter, 2);
6650 if (!W_ERROR_IS_OK(result)) {
6654 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6655 spoolss_EnumJobs, NULL,
6656 *r->out.info, r->in.level,
6658 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6659 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6661 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6664 /****************************************************************
6665 _spoolss_ScheduleJob
6666 ****************************************************************/
6668 WERROR _spoolss_ScheduleJob(pipes_struct *p,
6669 struct spoolss_ScheduleJob *r)
6674 /****************************************************************
6676 ****************************************************************/
6678 WERROR _spoolss_SetJob(pipes_struct *p,
6679 struct spoolss_SetJob *r)
6682 WERROR errcode = WERR_BADFUNC;
6684 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6688 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6689 return WERR_INVALID_PRINTER_NAME;
6692 switch (r->in.command) {
6693 case SPOOLSS_JOB_CONTROL_CANCEL:
6694 case SPOOLSS_JOB_CONTROL_DELETE:
6695 if (print_job_delete(p->server_info, snum, r->in.job_id, &errcode)) {
6699 case SPOOLSS_JOB_CONTROL_PAUSE:
6700 if (print_job_pause(p->server_info, snum, r->in.job_id, &errcode)) {
6704 case SPOOLSS_JOB_CONTROL_RESTART:
6705 case SPOOLSS_JOB_CONTROL_RESUME:
6706 if (print_job_resume(p->server_info, snum, r->in.job_id, &errcode)) {
6711 return WERR_UNKNOWN_LEVEL;
6717 static const struct print_architecture_table_node archi_table[]= {
6719 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
6720 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
6721 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
6722 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
6723 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
6724 {"Windows IA64", SPL_ARCH_IA64, 3 },
6725 {"Windows x64", SPL_ARCH_X64, 3 },
6729 /****************************************************************************
6730 Enumerates all printer drivers by level and architecture.
6731 ****************************************************************************/
6733 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6734 const char *servername,
6735 const char *architecture,
6737 union spoolss_DriverInfo **info_p,
6743 fstring *list = NULL;
6744 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6745 union spoolss_DriverInfo *info = NULL;
6747 WERROR result = WERR_OK;
6752 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6754 ndrivers = get_ntdrivers(&list, architecture, version);
6755 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6756 ndrivers, architecture, version));
6758 if (ndrivers == -1) {
6759 result = WERR_NOMEM;
6763 if (ndrivers != 0) {
6764 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6765 union spoolss_DriverInfo,
6768 DEBUG(0,("enumprinterdrivers_level1: "
6769 "failed to enlarge driver info buffer!\n"));
6770 result = WERR_NOMEM;
6775 for (i=0; i<ndrivers; i++) {
6776 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6777 ZERO_STRUCT(driver);
6778 result = get_a_printer_driver(&driver, 3, list[i],
6779 architecture, version);
6780 if (!W_ERROR_IS_OK(result)) {
6786 result = fill_printer_driver_info1(info, &info[count+i].info1,
6787 &driver, servername,
6791 result = fill_printer_driver_info2(info, &info[count+i].info2,
6792 &driver, servername);
6795 result = fill_printer_driver_info3(info, &info[count+i].info3,
6796 &driver, servername);
6799 result = fill_printer_driver_info4(info, &info[count+i].info4,
6800 &driver, servername);
6803 result = fill_printer_driver_info5(info, &info[count+i].info5,
6804 &driver, servername);
6807 result = fill_printer_driver_info6(info, &info[count+i].info6,
6808 &driver, servername);
6811 result = WERR_UNKNOWN_LEVEL;
6815 if (!W_ERROR_IS_OK(result)) {
6816 free_a_printer_driver(driver, 3);
6819 free_a_printer_driver(driver, 3);
6829 if (!W_ERROR_IS_OK(result)) {
6840 /****************************************************************************
6841 Enumerates all printer drivers by level.
6842 ****************************************************************************/
6844 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6845 const char *servername,
6846 const char *architecture,
6848 union spoolss_DriverInfo **info_p,
6852 WERROR result = WERR_OK;
6854 if (strequal(architecture, "all")) {
6856 for (a=0; archi_table[a].long_archi != NULL; a++) {
6858 union spoolss_DriverInfo *info = NULL;
6861 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6863 archi_table[a].long_archi,
6867 if (!W_ERROR_IS_OK(result)) {
6871 for (i=0; i < count; i++) {
6872 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
6873 info[i], info_p, count_p);
6880 return enumprinterdrivers_level_by_architecture(mem_ctx,
6888 /****************************************************************************
6889 Enumerates all printer drivers at level 1.
6890 ****************************************************************************/
6892 static WERROR enumprinterdrivers_level1(TALLOC_CTX *mem_ctx,
6893 const char *servername,
6894 const char *architecture,
6895 union spoolss_DriverInfo **info_p,
6898 return enumprinterdrivers_level(mem_ctx, servername, architecture, 1,
6902 /****************************************************************************
6903 Enumerates all printer drivers at level 2.
6904 ****************************************************************************/
6906 static WERROR enumprinterdrivers_level2(TALLOC_CTX *mem_ctx,
6907 const char *servername,
6908 const char *architecture,
6909 union spoolss_DriverInfo **info_p,
6912 return enumprinterdrivers_level(mem_ctx, servername, architecture, 2,
6916 /****************************************************************************
6917 Enumerates all printer drivers at level 3.
6918 ****************************************************************************/
6920 static WERROR enumprinterdrivers_level3(TALLOC_CTX *mem_ctx,
6921 const char *servername,
6922 const char *architecture,
6923 union spoolss_DriverInfo **info_p,
6926 return enumprinterdrivers_level(mem_ctx, servername, architecture, 3,
6930 /****************************************************************************
6931 Enumerates all printer drivers at level 4.
6932 ****************************************************************************/
6934 static WERROR enumprinterdrivers_level4(TALLOC_CTX *mem_ctx,
6935 const char *servername,
6936 const char *architecture,
6937 union spoolss_DriverInfo **info_p,
6940 return enumprinterdrivers_level(mem_ctx, servername, architecture, 4,
6944 /****************************************************************************
6945 Enumerates all printer drivers at level 5.
6946 ****************************************************************************/
6948 static WERROR enumprinterdrivers_level5(TALLOC_CTX *mem_ctx,
6949 const char *servername,
6950 const char *architecture,
6951 union spoolss_DriverInfo **info_p,
6954 return enumprinterdrivers_level(mem_ctx, servername, architecture, 5,
6958 /****************************************************************************
6959 Enumerates all printer drivers at level 6.
6960 ****************************************************************************/
6962 static WERROR enumprinterdrivers_level6(TALLOC_CTX *mem_ctx,
6963 const char *servername,
6964 const char *architecture,
6965 union spoolss_DriverInfo **info_p,
6968 return enumprinterdrivers_level(mem_ctx, servername, architecture, 6,
6973 /****************************************************************
6974 _spoolss_EnumPrinterDrivers
6975 ****************************************************************/
6977 WERROR _spoolss_EnumPrinterDrivers(pipes_struct *p,
6978 struct spoolss_EnumPrinterDrivers *r)
6980 const char *cservername;
6983 /* that's an [in out] buffer */
6985 if (!r->in.buffer && (r->in.offered != 0)) {
6986 return WERR_INVALID_PARAM;
6989 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6993 *r->out.info = NULL;
6995 cservername = canon_servername(r->in.server);
6997 if (!is_myname_or_ipaddr(cservername)) {
6998 return WERR_UNKNOWN_PRINTER_DRIVER;
7001 switch (r->in.level) {
7003 result = enumprinterdrivers_level1(p->mem_ctx, cservername,
7005 r->out.info, r->out.count);
7008 result = enumprinterdrivers_level2(p->mem_ctx, cservername,
7010 r->out.info, r->out.count);
7013 result = enumprinterdrivers_level3(p->mem_ctx, cservername,
7015 r->out.info, r->out.count);
7018 result = enumprinterdrivers_level4(p->mem_ctx, cservername,
7020 r->out.info, r->out.count);
7023 result = enumprinterdrivers_level5(p->mem_ctx, cservername,
7025 r->out.info, r->out.count);
7028 result = enumprinterdrivers_level6(p->mem_ctx, cservername,
7030 r->out.info, r->out.count);
7033 return WERR_UNKNOWN_LEVEL;
7036 if (!W_ERROR_IS_OK(result)) {
7040 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7041 spoolss_EnumPrinterDrivers, NULL,
7042 *r->out.info, r->in.level,
7044 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7045 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7047 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7050 /****************************************************************************
7051 ****************************************************************************/
7053 static WERROR fill_form_info_1(TALLOC_CTX *mem_ctx,
7054 struct spoolss_FormInfo1 *r,
7055 const nt_forms_struct *form)
7057 r->form_name = talloc_strdup(mem_ctx, form->name);
7058 W_ERROR_HAVE_NO_MEMORY(r->form_name);
7060 r->flags = form->flag;
7061 r->size.width = form->width;
7062 r->size.height = form->length;
7063 r->area.left = form->left;
7064 r->area.top = form->top;
7065 r->area.right = form->right;
7066 r->area.bottom = form->bottom;
7071 /****************************************************************
7072 spoolss_enumforms_level1
7073 ****************************************************************/
7075 static WERROR spoolss_enumforms_level1(TALLOC_CTX *mem_ctx,
7076 const nt_forms_struct *builtin_forms,
7077 uint32_t num_builtin_forms,
7078 const nt_forms_struct *user_forms,
7079 uint32_t num_user_forms,
7080 union spoolss_FormInfo **info_p,
7083 union spoolss_FormInfo *info;
7084 WERROR result = WERR_OK;
7087 *count = num_builtin_forms + num_user_forms;
7089 info = TALLOC_ARRAY(mem_ctx, union spoolss_FormInfo, *count);
7090 W_ERROR_HAVE_NO_MEMORY(info);
7092 /* construct the list of form structures */
7093 for (i=0; i<num_builtin_forms; i++) {
7094 DEBUGADD(6,("Filling builtin form number [%d]\n",i));
7095 result = fill_form_info_1(info, &info[i].info1,
7097 if (!W_ERROR_IS_OK(result)) {
7102 for (i=0; i<num_user_forms; i++) {
7103 DEBUGADD(6,("Filling user form number [%d]\n",i));
7104 result = fill_form_info_1(info, &info[i+num_builtin_forms].info1,
7106 if (!W_ERROR_IS_OK(result)) {
7112 if (!W_ERROR_IS_OK(result)) {
7123 /****************************************************************
7125 ****************************************************************/
7127 WERROR _spoolss_EnumForms(pipes_struct *p,
7128 struct spoolss_EnumForms *r)
7131 nt_forms_struct *user_forms = NULL;
7132 nt_forms_struct *builtin_forms = NULL;
7133 uint32_t num_user_forms;
7134 uint32_t num_builtin_forms;
7138 *r->out.info = NULL;
7140 /* that's an [in out] buffer */
7142 if (!r->in.buffer && (r->in.offered != 0) ) {
7143 return WERR_INVALID_PARAM;
7146 DEBUG(4,("_spoolss_EnumForms\n"));
7147 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7148 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7150 num_builtin_forms = get_builtin_ntforms(&builtin_forms);
7151 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms));
7152 num_user_forms = get_ntforms(&user_forms);
7153 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms));
7155 if (num_user_forms + num_builtin_forms == 0) {
7156 SAFE_FREE(builtin_forms);
7157 SAFE_FREE(user_forms);
7158 return WERR_NO_MORE_ITEMS;
7161 switch (r->in.level) {
7163 result = spoolss_enumforms_level1(p->mem_ctx,
7172 result = WERR_UNKNOWN_LEVEL;
7176 SAFE_FREE(user_forms);
7177 SAFE_FREE(builtin_forms);
7179 if (!W_ERROR_IS_OK(result)) {
7183 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7184 spoolss_EnumForms, NULL,
7185 *r->out.info, r->in.level,
7187 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7188 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7190 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7193 /****************************************************************
7194 ****************************************************************/
7196 static WERROR find_form_byname(const char *name,
7197 nt_forms_struct *form)
7199 nt_forms_struct *list = NULL;
7200 int num_forms = 0, i = 0;
7202 if (get_a_builtin_ntform_by_string(name, form)) {
7206 num_forms = get_ntforms(&list);
7207 DEBUGADD(5,("Number of forms [%d]\n", num_forms));
7209 if (num_forms == 0) {
7213 /* Check if the requested name is in the list of form structures */
7214 for (i = 0; i < num_forms; i++) {
7216 DEBUG(4,("checking form %s (want %s)\n", list[i].name, name));
7218 if (strequal(name, list[i].name)) {
7219 DEBUGADD(6,("Found form %s number [%d]\n", name, i));
7231 /****************************************************************
7233 ****************************************************************/
7235 WERROR _spoolss_GetForm(pipes_struct *p,
7236 struct spoolss_GetForm *r)
7239 nt_forms_struct form;
7241 /* that's an [in out] buffer */
7243 if (!r->in.buffer && (r->in.offered != 0)) {
7244 return WERR_INVALID_PARAM;
7247 DEBUG(4,("_spoolss_GetForm\n"));
7248 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7249 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7251 result = find_form_byname(r->in.form_name, &form);
7252 if (!W_ERROR_IS_OK(result)) {
7253 TALLOC_FREE(r->out.info);
7257 switch (r->in.level) {
7259 result = fill_form_info_1(p->mem_ctx,
7260 &r->out.info->info1,
7265 result = WERR_UNKNOWN_LEVEL;
7269 if (!W_ERROR_IS_OK(result)) {
7270 TALLOC_FREE(r->out.info);
7274 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, NULL,
7275 r->out.info, r->in.level);
7276 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7278 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7281 /****************************************************************************
7282 ****************************************************************************/
7284 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7285 struct spoolss_PortInfo1 *r,
7288 r->port_name = talloc_strdup(mem_ctx, name);
7289 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7294 /****************************************************************************
7295 TODO: This probably needs distinguish between TCP/IP and Local ports
7297 ****************************************************************************/
7299 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7300 struct spoolss_PortInfo2 *r,
7303 r->port_name = talloc_strdup(mem_ctx, name);
7304 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7306 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7307 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7309 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7310 W_ERROR_HAVE_NO_MEMORY(r->description);
7312 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7319 /****************************************************************************
7320 wrapper around the enumer ports command
7321 ****************************************************************************/
7323 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7325 char *cmd = lp_enumports_cmd();
7326 char **qlines = NULL;
7327 char *command = NULL;
7335 /* if no hook then just fill in the default port */
7338 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7341 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7342 TALLOC_FREE(qlines);
7349 /* we have a valid enumport command */
7351 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7356 DEBUG(10,("Running [%s]\n", command));
7357 ret = smbrun(command, &fd);
7358 DEBUG(10,("Returned [%d]\n", ret));
7359 TALLOC_FREE(command);
7364 return WERR_ACCESS_DENIED;
7368 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7369 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7379 /****************************************************************************
7381 ****************************************************************************/
7383 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7384 union spoolss_PortInfo **info_p,
7387 union spoolss_PortInfo *info = NULL;
7389 WERROR result = WERR_OK;
7390 char **qlines = NULL;
7393 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7394 if (!W_ERROR_IS_OK(result)) {
7399 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7401 DEBUG(10,("Returning WERR_NOMEM\n"));
7402 result = WERR_NOMEM;
7406 for (i=0; i<numlines; i++) {
7407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7408 result = fill_port_1(info, &info[i].info1, qlines[i]);
7409 if (!W_ERROR_IS_OK(result)) {
7414 TALLOC_FREE(qlines);
7417 if (!W_ERROR_IS_OK(result)) {
7419 TALLOC_FREE(qlines);
7431 /****************************************************************************
7433 ****************************************************************************/
7435 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7436 union spoolss_PortInfo **info_p,
7439 union spoolss_PortInfo *info = NULL;
7441 WERROR result = WERR_OK;
7442 char **qlines = NULL;
7445 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7446 if (!W_ERROR_IS_OK(result)) {
7451 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7453 DEBUG(10,("Returning WERR_NOMEM\n"));
7454 result = WERR_NOMEM;
7458 for (i=0; i<numlines; i++) {
7459 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7460 result = fill_port_2(info, &info[i].info2, qlines[i]);
7461 if (!W_ERROR_IS_OK(result)) {
7466 TALLOC_FREE(qlines);
7469 if (!W_ERROR_IS_OK(result)) {
7471 TALLOC_FREE(qlines);
7483 /****************************************************************
7485 ****************************************************************/
7487 WERROR _spoolss_EnumPorts(pipes_struct *p,
7488 struct spoolss_EnumPorts *r)
7492 /* that's an [in out] buffer */
7494 if (!r->in.buffer && (r->in.offered != 0)) {
7495 return WERR_INVALID_PARAM;
7498 DEBUG(4,("_spoolss_EnumPorts\n"));
7502 *r->out.info = NULL;
7504 switch (r->in.level) {
7506 result = enumports_level_1(p->mem_ctx, r->out.info,
7510 result = enumports_level_2(p->mem_ctx, r->out.info,
7514 return WERR_UNKNOWN_LEVEL;
7517 if (!W_ERROR_IS_OK(result)) {
7521 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7522 spoolss_EnumPorts, NULL,
7523 *r->out.info, r->in.level,
7525 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7526 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7528 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7531 /****************************************************************************
7532 ****************************************************************************/
7534 static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
7536 struct spoolss_SetPrinterInfoCtr *info_ctr,
7537 struct spoolss_DeviceMode *devmode,
7538 struct security_descriptor *sec_desc,
7539 struct spoolss_UserLevelCtr *user_ctr,
7540 struct policy_handle *handle)
7542 NT_PRINTER_INFO_LEVEL *printer = NULL;
7545 WERROR err = WERR_OK;
7547 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7548 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7552 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7553 if (!convert_printer_info(info_ctr, printer)) {
7554 free_a_printer(&printer, 2);
7558 /* check to see if the printer already exists */
7560 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7561 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7562 printer->info_2->sharename));
7563 free_a_printer(&printer, 2);
7564 return WERR_PRINTER_ALREADY_EXISTS;
7567 /* FIXME!!! smbd should check to see if the driver is installed before
7568 trying to add a printer like this --jerry */
7570 if (*lp_addprinter_cmd() ) {
7571 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7573 free_a_printer(&printer,2);
7574 return WERR_ACCESS_DENIED;
7577 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7578 "smb.conf parameter \"addprinter command\" is defined. This"
7579 "parameter must exist for this call to succeed\n",
7580 printer->info_2->sharename ));
7583 /* use our primary netbios name since get_a_printer() will convert
7584 it to what the client expects on a case by case basis */
7586 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7587 printer->info_2->sharename);
7590 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7591 free_a_printer(&printer,2);
7592 return WERR_ACCESS_DENIED;
7595 /* you must be a printer admin to add a new printer */
7596 if (!print_access_check(p->server_info, snum, PRINTER_ACCESS_ADMINISTER)) {
7597 free_a_printer(&printer,2);
7598 return WERR_ACCESS_DENIED;
7602 * Do sanity check on the requested changes for Samba.
7605 if (!check_printer_ok(printer->info_2, snum)) {
7606 free_a_printer(&printer,2);
7607 return WERR_INVALID_PARAM;
7611 * When a printer is created, the drivername bound to the printer is used
7612 * to lookup previously saved driver initialization info, which is then
7613 * bound to the new printer, simulating what happens in the Windows arch.
7618 set_driver_init(printer, 2);
7622 /* A valid devmode was included, convert and link it
7624 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7626 if (!convert_devicemode(printer->info_2->printername, devmode,
7627 &printer->info_2->devmode)) {
7632 /* write the ASCII on disk */
7633 err = mod_a_printer(printer, 2);
7634 if (!W_ERROR_IS_OK(err)) {
7635 free_a_printer(&printer,2);
7639 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7640 /* Handle open failed - remove addition. */
7641 del_a_printer(printer->info_2->sharename);
7642 free_a_printer(&printer,2);
7643 ZERO_STRUCTP(handle);
7644 return WERR_ACCESS_DENIED;
7647 update_c_setprinter(false);
7648 free_a_printer(&printer,2);
7653 /****************************************************************
7654 _spoolss_AddPrinterEx
7655 ****************************************************************/
7657 WERROR _spoolss_AddPrinterEx(pipes_struct *p,
7658 struct spoolss_AddPrinterEx *r)
7660 switch (r->in.info_ctr->level) {
7662 /* we don't handle yet */
7663 /* but I know what to do ... */
7664 return WERR_UNKNOWN_LEVEL;
7666 return spoolss_addprinterex_level_2(p, r->in.server,
7668 r->in.devmode_ctr->devmode,
7669 r->in.secdesc_ctr->sd,
7670 r->in.userlevel_ctr,
7673 return WERR_UNKNOWN_LEVEL;
7677 /****************************************************************
7679 ****************************************************************/
7681 WERROR _spoolss_AddPrinter(pipes_struct *p,
7682 struct spoolss_AddPrinter *r)
7684 struct spoolss_AddPrinterEx a;
7685 struct spoolss_UserLevelCtr userlevel_ctr;
7687 ZERO_STRUCT(userlevel_ctr);
7689 userlevel_ctr.level = 1;
7691 a.in.server = r->in.server;
7692 a.in.info_ctr = r->in.info_ctr;
7693 a.in.devmode_ctr = r->in.devmode_ctr;
7694 a.in.secdesc_ctr = r->in.secdesc_ctr;
7695 a.in.userlevel_ctr = &userlevel_ctr;
7696 a.out.handle = r->out.handle;
7698 return _spoolss_AddPrinterEx(p, &a);
7701 /****************************************************************
7702 _spoolss_AddPrinterDriver
7703 ****************************************************************/
7705 WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
7706 struct spoolss_AddPrinterDriver *r)
7708 uint32_t level = r->in.info_ctr->level;
7709 struct spoolss_AddDriverInfoCtr *info = r->in.info_ctr;
7710 WERROR err = WERR_OK;
7711 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7712 const char *driver_name = NULL;
7716 switch (p->hdr_req.opnum) {
7717 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7718 fn = "_spoolss_AddPrinterDriver";
7720 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7721 fn = "_spoolss_AddPrinterDriverEx";
7724 return WERR_INVALID_PARAM;
7729 if (level != 3 && level != 6) {
7730 /* Clever hack from Martin Zielinski <mz@seh.de>
7731 * to allow downgrade from level 8 (Vista).
7733 DEBUG(0,("%s: level %d not yet implemented\n", fn, level));
7734 return WERR_UNKNOWN_LEVEL;
7737 ZERO_STRUCT(driver);
7739 if (!convert_printer_driver_info(info, &driver, level)) {
7744 DEBUG(5,("Cleaning driver's information\n"));
7745 err = clean_up_driver_struct(p, driver, level);
7746 if (!W_ERROR_IS_OK(err))
7749 DEBUG(5,("Moving driver to final destination\n"));
7750 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, driver, level,
7755 if (add_a_printer_driver(driver, level)!=0) {
7756 err = WERR_ACCESS_DENIED;
7762 driver_name = driver.info_3->name ? driver.info_3->name : "";
7765 driver_name = driver.info_6->name ? driver.info_6->name : "";
7770 * I think this is where he DrvUpgradePrinter() hook would be
7771 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7772 * server. Right now, we just need to send ourselves a message
7773 * to update each printer bound to this driver. --jerry
7776 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7777 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7782 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7783 * decide if the driver init data should be deleted. The rules are:
7784 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7785 * 2) delete init data only if there is no 2k/Xp driver
7786 * 3) always delete init data
7787 * The generalized rule is always use init data from the highest order driver.
7788 * It is necessary to follow the driver install by an initialization step to
7789 * finish off this process.
7792 version = driver.info_3->cversion;
7793 else if (level == 6)
7794 version = driver.info_6->version;
7799 * 9x printer driver - never delete init data
7802 DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
7807 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7808 * there is no 2k/Xp driver init data for this driver name.
7812 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7814 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7816 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7818 if (!del_driver_init(driver_name))
7819 DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
7823 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7825 free_a_printer_driver(driver1,3);
7826 DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
7833 * 2k or Xp printer driver - always delete init data
7836 if (!del_driver_init(driver_name))
7837 DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
7842 DEBUG(0,("%s: invalid level=%d\n", fn, level));
7848 free_a_printer_driver(driver, level);
7852 /****************************************************************
7853 _spoolss_AddPrinterDriverEx
7854 ****************************************************************/
7856 WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
7857 struct spoolss_AddPrinterDriverEx *r)
7859 struct spoolss_AddPrinterDriver a;
7862 * we only support the semantics of AddPrinterDriver()
7863 * i.e. only copy files that are newer than existing ones
7866 if (r->in.flags != APD_COPY_NEW_FILES) {
7867 return WERR_ACCESS_DENIED;
7870 a.in.servername = r->in.servername;
7871 a.in.info_ctr = r->in.info_ctr;
7873 return _spoolss_AddPrinterDriver(p, &a);
7876 /****************************************************************************
7877 ****************************************************************************/
7879 struct _spoolss_paths {
7885 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7887 static const struct _spoolss_paths spoolss_paths[]= {
7888 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7889 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7892 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7893 const char *servername,
7894 const char *environment,
7898 const char *pservername = NULL;
7899 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7900 const char *short_archi;
7904 /* environment may be empty */
7905 if (environment && strlen(environment)) {
7906 long_archi = environment;
7909 /* servername may be empty */
7910 if (servername && strlen(servername)) {
7911 pservername = canon_servername(servername);
7913 if (!is_myname_or_ipaddr(pservername)) {
7914 return WERR_INVALID_PARAM;
7918 if (!(short_archi = get_short_archi(long_archi))) {
7919 return WERR_INVALID_ENVIRONMENT;
7922 switch (component) {
7923 case SPOOLSS_PRTPROCS_PATH:
7924 case SPOOLSS_DRIVER_PATH:
7926 *path = talloc_asprintf(mem_ctx,
7929 spoolss_paths[component].share,
7932 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7933 SPOOLSS_DEFAULT_SERVER_PATH,
7934 spoolss_paths[component].dir,
7939 return WERR_INVALID_PARAM;
7949 /****************************************************************************
7950 ****************************************************************************/
7952 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7953 const char *servername,
7954 const char *environment,
7955 struct spoolss_DriverDirectoryInfo1 *r)
7960 werr = compose_spoolss_server_path(mem_ctx,
7963 SPOOLSS_DRIVER_PATH,
7965 if (!W_ERROR_IS_OK(werr)) {
7969 DEBUG(4,("printer driver directory: [%s]\n", path));
7971 r->directory_name = path;
7976 /****************************************************************
7977 _spoolss_GetPrinterDriverDirectory
7978 ****************************************************************/
7980 WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
7981 struct spoolss_GetPrinterDriverDirectory *r)
7985 /* that's an [in out] buffer */
7987 if (!r->in.buffer && (r->in.offered != 0)) {
7988 return WERR_INVALID_PARAM;
7991 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7996 /* r->in.level is ignored */
7998 werror = getprinterdriverdir_level_1(p->mem_ctx,
8001 &r->out.info->info1);
8002 if (!W_ERROR_IS_OK(werror)) {
8003 TALLOC_FREE(r->out.info);
8007 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, NULL,
8008 r->out.info, r->in.level);
8009 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8011 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8014 /****************************************************************
8015 _spoolss_EnumPrinterData
8016 ****************************************************************/
8018 WERROR _spoolss_EnumPrinterData(pipes_struct *p,
8019 struct spoolss_EnumPrinterData *r)
8021 NT_PRINTER_INFO_LEVEL *printer = NULL;
8022 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8025 struct regval_blob *val = NULL;
8026 NT_PRINTER_DATA *p_data;
8027 int i, key_index, num_values;
8030 *r->out.value_needed = 0;
8031 *r->out.type = REG_NONE;
8032 *r->out.data_needed = 0;
8034 DEBUG(5,("_spoolss_EnumPrinterData\n"));
8037 DEBUG(2,("_spoolss_EnumPrinterData: Invalid handle (%s:%u:%u).\n",
8038 OUR_HANDLE(r->in.handle)));
8042 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8046 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8047 if (!W_ERROR_IS_OK(result)) {
8051 p_data = printer->info_2->data;
8052 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8057 * The NT machine wants to know the biggest size of value and data
8059 * cf: MSDN EnumPrinterData remark section
8062 if (!r->in.value_offered && !r->in.data_offered && (key_index != -1)) {
8064 uint32_t biggest_valuesize = 0;
8065 uint32_t biggest_datasize = 0;
8067 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8069 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8071 for ( i=0; i<num_values; i++ )
8073 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8075 name_length = strlen(val->valuename);
8076 if ( strlen(val->valuename) > biggest_valuesize )
8077 biggest_valuesize = name_length;
8079 if ( val->size > biggest_datasize )
8080 biggest_datasize = val->size;
8082 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8086 /* the value is an UNICODE string but real_value_size is the length
8087 in bytes including the trailing 0 */
8089 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8090 *r->out.data_needed = biggest_datasize;
8092 DEBUG(6,("final values: [%d], [%d]\n",
8093 *r->out.value_needed, *r->out.data_needed));
8099 * the value len is wrong in NT sp3
8100 * that's the number of bytes not the number of unicode chars
8103 if (key_index != -1) {
8104 val = regval_ctr_specific_value(p_data->keys[key_index].values,
8110 /* out_value should default to "" or else NT4 has
8111 problems unmarshalling the response */
8113 if (r->in.value_offered) {
8114 *r->out.value_needed = 1;
8115 r->out.value_name = talloc_strdup(r, "");
8116 if (!r->out.value_name) {
8117 result = WERR_NOMEM;
8121 r->out.value_name = NULL;
8122 *r->out.value_needed = 0;
8125 /* the data is counted in bytes */
8127 *r->out.data_needed = r->in.data_offered;
8129 result = WERR_NO_MORE_ITEMS;
8133 * - counted in bytes in the request
8134 * - counted in UNICODE chars in the max reply
8135 * - counted in bytes in the real size
8137 * take a pause *before* coding not *during* coding
8141 if (r->in.value_offered) {
8142 r->out.value_name = talloc_strdup(r, regval_name(val));
8143 if (!r->out.value_name) {
8144 result = WERR_NOMEM;
8147 *r->out.value_needed = strlen_m(regval_name(val));
8149 r->out.value_name = NULL;
8150 *r->out.value_needed = 0;
8155 *r->out.type = regval_type(val);
8157 /* data - counted in bytes */
8159 if (r->out.data && regval_size(val)) {
8160 memcpy(r->out.data, regval_data_p(val), regval_size(val));
8163 *r->out.data_needed = regval_size(val);
8167 free_a_printer(&printer, 2);
8171 /****************************************************************
8172 _spoolss_SetPrinterData
8173 ****************************************************************/
8175 WERROR _spoolss_SetPrinterData(pipes_struct *p,
8176 struct spoolss_SetPrinterData *r)
8178 NT_PRINTER_INFO_LEVEL *printer = NULL;
8180 WERROR result = WERR_OK;
8181 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8184 DEBUG(5,("_spoolss_SetPrinterData\n"));
8187 DEBUG(2,("_spoolss_SetPrinterData: Invalid handle (%s:%u:%u).\n",
8188 OUR_HANDLE(r->in.handle)));
8192 if (Printer->printer_type == SPLHND_SERVER) {
8193 DEBUG(10,("_spoolss_SetPrinterData: "
8194 "Not implemented for server handles yet\n"));
8195 return WERR_INVALID_PARAM;
8198 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8203 * Access check : NT returns "access denied" if you make a
8204 * SetPrinterData call without the necessary privildge.
8205 * we were originally returning OK if nothing changed
8206 * which made Win2k issue **a lot** of SetPrinterData
8207 * when connecting to a printer --jerry
8210 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8211 DEBUG(3,("_spoolss_SetPrinterData: "
8212 "change denied by handle access permissions\n"));
8213 result = WERR_ACCESS_DENIED;
8217 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8218 if (!W_ERROR_IS_OK(result)) {
8222 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8223 r->in.type, &r->in.data);
8224 if (!W_ERROR_IS_OK(result)) {
8229 * When client side code sets a magic printer data key, detect it and save
8230 * the current printer data and the magic key's data (its the DEVMODE) for
8231 * future printer/driver initializations.
8233 if ((r->in.type == REG_BINARY) && strequal(r->in.value_name, PHANTOM_DEVMODE_KEY)) {
8234 /* Set devmode and printer initialization info */
8235 result = save_driver_init(printer, 2, blob.data, blob.length);
8237 srv_spoolss_reset_printerdata(printer->info_2->drivername);
8242 result = set_printer_dataex(printer, SPOOL_PRINTERDATA_KEY,
8243 r->in.value_name, r->in.type,
8244 blob.data, blob.length);
8245 if (W_ERROR_IS_OK(result)) {
8246 result = mod_a_printer(printer, 2);
8250 free_a_printer(&printer, 2);
8255 /****************************************************************
8256 _spoolss_ResetPrinter
8257 ****************************************************************/
8259 WERROR _spoolss_ResetPrinter(pipes_struct *p,
8260 struct spoolss_ResetPrinter *r)
8262 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8265 DEBUG(5,("_spoolss_ResetPrinter\n"));
8268 * All we do is to check to see if the handle and queue is valid.
8269 * This call really doesn't mean anything to us because we only
8270 * support RAW printing. --jerry
8274 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8275 OUR_HANDLE(r->in.handle)));
8279 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8283 /* blindly return success */
8287 /****************************************************************
8288 _spoolss_DeletePrinterData
8289 ****************************************************************/
8291 WERROR _spoolss_DeletePrinterData(pipes_struct *p,
8292 struct spoolss_DeletePrinterData *r)
8294 NT_PRINTER_INFO_LEVEL *printer = NULL;
8296 WERROR status = WERR_OK;
8297 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8299 DEBUG(5,("_spoolss_DeletePrinterData\n"));
8302 DEBUG(2,("_spoolss_DeletePrinterData: Invalid handle (%s:%u:%u).\n",
8303 OUR_HANDLE(r->in.handle)));
8307 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8311 DEBUG(3, ("_spoolss_DeletePrinterData: "
8312 "printer properties change denied by handle\n"));
8313 return WERR_ACCESS_DENIED;
8316 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8317 if (!W_ERROR_IS_OK(status))
8320 if (!r->in.value_name) {
8321 free_a_printer(&printer, 2);
8325 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY,
8328 if ( W_ERROR_IS_OK(status) )
8329 mod_a_printer( printer, 2 );
8331 free_a_printer(&printer, 2);
8336 /****************************************************************
8338 ****************************************************************/
8340 WERROR _spoolss_AddForm(pipes_struct *p,
8341 struct spoolss_AddForm *r)
8343 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8344 nt_forms_struct tmpForm;
8346 WERROR status = WERR_OK;
8347 NT_PRINTER_INFO_LEVEL *printer = NULL;
8348 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8351 nt_forms_struct *list=NULL;
8352 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8354 DEBUG(5,("_spoolss_AddForm\n"));
8357 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8358 OUR_HANDLE(r->in.handle)));
8363 /* forms can be added on printer of on the print server handle */
8365 if ( Printer->printer_type == SPLHND_PRINTER )
8367 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8370 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8371 if (!W_ERROR_IS_OK(status))
8375 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8376 and not a printer admin, then fail */
8378 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8379 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8380 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8382 p->server_info->ptok,
8383 lp_printer_admin(snum))) {
8384 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8385 return WERR_ACCESS_DENIED;
8388 /* can't add if builtin */
8390 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8391 status = WERR_FILE_EXISTS;
8395 count = get_ntforms(&list);
8397 if(!add_a_form(&list, form, &count)) {
8398 status = WERR_NOMEM;
8403 write_ntforms(&list, count);
8407 * ChangeID must always be set if this is a printer
8410 if ( Printer->printer_type == SPLHND_PRINTER )
8411 status = mod_a_printer(printer, 2);
8415 free_a_printer(&printer, 2);
8421 /****************************************************************
8423 ****************************************************************/
8425 WERROR _spoolss_DeleteForm(pipes_struct *p,
8426 struct spoolss_DeleteForm *r)
8428 const char *form_name = r->in.form_name;
8429 nt_forms_struct tmpForm;
8431 nt_forms_struct *list=NULL;
8432 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8434 WERROR status = WERR_OK;
8435 NT_PRINTER_INFO_LEVEL *printer = NULL;
8436 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8439 DEBUG(5,("_spoolss_DeleteForm\n"));
8442 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8443 OUR_HANDLE(r->in.handle)));
8447 /* forms can be deleted on printer of on the print server handle */
8449 if ( Printer->printer_type == SPLHND_PRINTER )
8451 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8454 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8455 if (!W_ERROR_IS_OK(status))
8459 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8460 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8461 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8463 p->server_info->ptok,
8464 lp_printer_admin(snum))) {
8465 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8466 return WERR_ACCESS_DENIED;
8470 /* can't delete if builtin */
8472 if (get_a_builtin_ntform_by_string(form_name,&tmpForm)) {
8473 status = WERR_INVALID_PARAM;
8477 count = get_ntforms(&list);
8480 ret = delete_a_form(&list, form_name, &count, &status);
8487 * ChangeID must always be set if this is a printer
8490 if ( Printer->printer_type == SPLHND_PRINTER )
8491 status = mod_a_printer(printer, 2);
8495 free_a_printer(&printer, 2);
8501 /****************************************************************
8503 ****************************************************************/
8505 WERROR _spoolss_SetForm(pipes_struct *p,
8506 struct spoolss_SetForm *r)
8508 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8509 nt_forms_struct tmpForm;
8511 WERROR status = WERR_OK;
8512 NT_PRINTER_INFO_LEVEL *printer = NULL;
8513 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8516 nt_forms_struct *list=NULL;
8517 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8519 DEBUG(5,("_spoolss_SetForm\n"));
8522 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8523 OUR_HANDLE(r->in.handle)));
8527 /* forms can be modified on printer of on the print server handle */
8529 if ( Printer->printer_type == SPLHND_PRINTER )
8531 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8534 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8535 if (!W_ERROR_IS_OK(status))
8539 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8540 and not a printer admin, then fail */
8542 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8543 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8544 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8546 p->server_info->ptok,
8547 lp_printer_admin(snum))) {
8548 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8549 return WERR_ACCESS_DENIED;
8552 /* can't set if builtin */
8553 if (get_a_builtin_ntform_by_string(form->form_name, &tmpForm)) {
8554 status = WERR_INVALID_PARAM;
8558 count = get_ntforms(&list);
8559 update_a_form(&list, form, count);
8561 write_ntforms(&list, count);
8565 * ChangeID must always be set if this is a printer
8568 if ( Printer->printer_type == SPLHND_PRINTER )
8569 status = mod_a_printer(printer, 2);
8574 free_a_printer(&printer, 2);
8580 /****************************************************************************
8581 fill_print_processor1
8582 ****************************************************************************/
8584 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8585 struct spoolss_PrintProcessorInfo1 *r,
8586 const char *print_processor_name)
8588 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8589 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8594 /****************************************************************************
8595 enumprintprocessors level 1.
8596 ****************************************************************************/
8598 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8599 union spoolss_PrintProcessorInfo **info_p,
8602 union spoolss_PrintProcessorInfo *info;
8605 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8606 W_ERROR_HAVE_NO_MEMORY(info);
8610 result = fill_print_processor1(info, &info[0].info1, "winprint");
8611 if (!W_ERROR_IS_OK(result)) {
8616 if (!W_ERROR_IS_OK(result)) {
8627 /****************************************************************
8628 _spoolss_EnumPrintProcessors
8629 ****************************************************************/
8631 WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
8632 struct spoolss_EnumPrintProcessors *r)
8636 /* that's an [in out] buffer */
8638 if (!r->in.buffer && (r->in.offered != 0)) {
8639 return WERR_INVALID_PARAM;
8642 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8645 * Enumerate the print processors ...
8647 * Just reply with "winprint", to keep NT happy
8648 * and I can use my nice printer checker.
8653 *r->out.info = NULL;
8655 switch (r->in.level) {
8657 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8661 return WERR_UNKNOWN_LEVEL;
8664 if (!W_ERROR_IS_OK(result)) {
8668 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8669 spoolss_EnumPrintProcessors, NULL,
8670 *r->out.info, r->in.level,
8672 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8673 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8675 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8678 /****************************************************************************
8679 fill_printprocdatatype1
8680 ****************************************************************************/
8682 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8683 struct spoolss_PrintProcDataTypesInfo1 *r,
8684 const char *name_array)
8686 r->name_array = talloc_strdup(mem_ctx, name_array);
8687 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8692 /****************************************************************************
8693 enumprintprocdatatypes level 1.
8694 ****************************************************************************/
8696 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8697 union spoolss_PrintProcDataTypesInfo **info_p,
8701 union spoolss_PrintProcDataTypesInfo *info;
8703 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8704 W_ERROR_HAVE_NO_MEMORY(info);
8708 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8709 if (!W_ERROR_IS_OK(result)) {
8714 if (!W_ERROR_IS_OK(result)) {
8725 /****************************************************************
8726 _spoolss_EnumPrintProcDataTypes
8727 ****************************************************************/
8729 WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
8730 struct spoolss_EnumPrintProcDataTypes *r)
8734 /* that's an [in out] buffer */
8736 if (!r->in.buffer && (r->in.offered != 0)) {
8737 return WERR_INVALID_PARAM;
8740 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8744 *r->out.info = NULL;
8746 switch (r->in.level) {
8748 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8752 return WERR_UNKNOWN_LEVEL;
8755 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8756 spoolss_EnumPrintProcDataTypes, NULL,
8757 *r->out.info, r->in.level,
8759 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8760 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8762 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8765 /****************************************************************************
8767 ****************************************************************************/
8769 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8770 struct spoolss_MonitorInfo1 *r,
8771 const char *monitor_name)
8773 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8774 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8779 /****************************************************************************
8781 ****************************************************************************/
8783 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8784 struct spoolss_MonitorInfo2 *r,
8785 const char *monitor_name,
8786 const char *environment,
8787 const char *dll_name)
8789 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8790 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8791 r->environment = talloc_strdup(mem_ctx, environment);
8792 W_ERROR_HAVE_NO_MEMORY(r->environment);
8793 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8794 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8799 /****************************************************************************
8800 enumprintmonitors level 1.
8801 ****************************************************************************/
8803 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8804 union spoolss_MonitorInfo **info_p,
8807 union spoolss_MonitorInfo *info;
8808 WERROR result = WERR_OK;
8810 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8811 W_ERROR_HAVE_NO_MEMORY(info);
8815 result = fill_monitor_1(info, &info[0].info1,
8817 if (!W_ERROR_IS_OK(result)) {
8821 result = fill_monitor_1(info, &info[1].info1,
8823 if (!W_ERROR_IS_OK(result)) {
8828 if (!W_ERROR_IS_OK(result)) {
8839 /****************************************************************************
8840 enumprintmonitors level 2.
8841 ****************************************************************************/
8843 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8844 union spoolss_MonitorInfo **info_p,
8847 union spoolss_MonitorInfo *info;
8848 WERROR result = WERR_OK;
8850 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8851 W_ERROR_HAVE_NO_MEMORY(info);
8855 result = fill_monitor_2(info, &info[0].info2,
8857 "Windows NT X86", /* FIXME */
8859 if (!W_ERROR_IS_OK(result)) {
8863 result = fill_monitor_2(info, &info[1].info2,
8865 "Windows NT X86", /* FIXME */
8867 if (!W_ERROR_IS_OK(result)) {
8872 if (!W_ERROR_IS_OK(result)) {
8883 /****************************************************************
8884 _spoolss_EnumMonitors
8885 ****************************************************************/
8887 WERROR _spoolss_EnumMonitors(pipes_struct *p,
8888 struct spoolss_EnumMonitors *r)
8892 /* that's an [in out] buffer */
8894 if (!r->in.buffer && (r->in.offered != 0)) {
8895 return WERR_INVALID_PARAM;
8898 DEBUG(5,("_spoolss_EnumMonitors\n"));
8901 * Enumerate the print monitors ...
8903 * Just reply with "Local Port", to keep NT happy
8904 * and I can use my nice printer checker.
8909 *r->out.info = NULL;
8911 switch (r->in.level) {
8913 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8917 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8921 return WERR_UNKNOWN_LEVEL;
8924 if (!W_ERROR_IS_OK(result)) {
8928 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8929 spoolss_EnumMonitors, NULL,
8930 *r->out.info, r->in.level,
8932 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8933 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8935 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8938 /****************************************************************************
8939 ****************************************************************************/
8941 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8942 const print_queue_struct *queue,
8943 int count, int snum,
8944 const NT_PRINTER_INFO_LEVEL *ntprinter,
8946 struct spoolss_JobInfo1 *r)
8951 for (i=0; i<count && found == false; i++) {
8952 if (queue[i].job == (int)jobid) {
8957 if (found == false) {
8958 /* NT treats not found as bad param... yet another bad choice */
8959 return WERR_INVALID_PARAM;
8962 return fill_job_info1(mem_ctx,
8970 /****************************************************************************
8971 ****************************************************************************/
8973 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8974 const print_queue_struct *queue,
8975 int count, int snum,
8976 const NT_PRINTER_INFO_LEVEL *ntprinter,
8978 struct spoolss_JobInfo2 *r)
8982 struct spoolss_DeviceMode *devmode;
8983 NT_DEVICEMODE *nt_devmode;
8986 for (i=0; i<count && found == false; i++) {
8987 if (queue[i].job == (int)jobid) {
8992 if (found == false) {
8993 /* NT treats not found as bad param... yet another bad
8995 return WERR_INVALID_PARAM;
8999 * if the print job does not have a DEVMODE associated with it,
9000 * just use the one for the printer. A NULL devicemode is not
9001 * a failure condition
9004 nt_devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9006 devmode = TALLOC_ZERO_P(mem_ctx, struct spoolss_DeviceMode);
9007 W_ERROR_HAVE_NO_MEMORY(devmode);
9008 result = convert_nt_devicemode(devmode, devmode, nt_devmode);
9009 if (!W_ERROR_IS_OK(result)) {
9013 devmode = construct_dev_mode(mem_ctx, lp_const_servicename(snum));
9014 W_ERROR_HAVE_NO_MEMORY(devmode);
9017 return fill_job_info2(mem_ctx,
9026 /****************************************************************
9028 ****************************************************************/
9030 WERROR _spoolss_GetJob(pipes_struct *p,
9031 struct spoolss_GetJob *r)
9033 WERROR result = WERR_OK;
9034 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9037 print_queue_struct *queue = NULL;
9038 print_status_struct prt_status;
9040 /* that's an [in out] buffer */
9042 if (!r->in.buffer && (r->in.offered != 0)) {
9043 return WERR_INVALID_PARAM;
9046 DEBUG(5,("_spoolss_GetJob\n"));
9050 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9054 result = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9055 if (!W_ERROR_IS_OK(result)) {
9059 count = print_queue_status(snum, &queue, &prt_status);
9061 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9062 count, prt_status.status, prt_status.message));
9064 switch (r->in.level) {
9066 result = getjob_level_1(p->mem_ctx,
9067 queue, count, snum, ntprinter,
9068 r->in.job_id, &r->out.info->info1);
9071 result = getjob_level_2(p->mem_ctx,
9072 queue, count, snum, ntprinter,
9073 r->in.job_id, &r->out.info->info2);
9076 result = WERR_UNKNOWN_LEVEL;
9081 free_a_printer(&ntprinter, 2);
9083 if (!W_ERROR_IS_OK(result)) {
9084 TALLOC_FREE(r->out.info);
9088 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, NULL,
9089 r->out.info, r->in.level);
9090 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9092 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9095 /****************************************************************
9096 _spoolss_GetPrinterDataEx
9098 From MSDN documentation of GetPrinterDataEx: pass request
9099 to GetPrinterData if key is "PrinterDriverData".
9100 ****************************************************************/
9102 WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
9103 struct spoolss_GetPrinterDataEx *r)
9106 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9107 struct regval_blob *val = NULL;
9108 NT_PRINTER_INFO_LEVEL *printer = NULL;
9110 WERROR result = WERR_OK;
9112 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9114 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9115 r->in.key_name, r->in.value_name));
9117 /* in case of problem, return some default values */
9120 *r->out.type = REG_NONE;
9123 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9124 OUR_HANDLE(r->in.handle)));
9125 result = WERR_BADFID;
9129 /* Is the handle to a printer or to the server? */
9131 if (Printer->printer_type == SPLHND_SERVER) {
9132 DEBUG(10,("_spoolss_GetPrinterDataEx: "
9133 "Not implemented for server handles yet\n"));
9134 result = WERR_INVALID_PARAM;
9138 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9142 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9143 if (!W_ERROR_IS_OK(result)) {
9147 /* check to see if the keyname is valid */
9148 if (!strlen(r->in.key_name)) {
9149 result = WERR_INVALID_PARAM;
9153 if (lookup_printerkey(printer->info_2->data, r->in.key_name) == -1) {
9154 DEBUG(4,("_spoolss_GetPrinterDataEx: "
9155 "Invalid keyname [%s]\n", r->in.key_name ));
9156 result = WERR_BADFILE;
9160 /* When given a new keyname, we should just create it */
9162 val = get_printer_data(printer->info_2,
9163 r->in.key_name, r->in.value_name);
9165 result = WERR_BADFILE;
9169 *r->out.needed = regval_size(val);
9171 if (*r->out.needed > r->in.offered) {
9172 result = WERR_MORE_DATA;
9176 *r->out.type = regval_type(val);
9178 memcpy(r->out.buffer, regval_data_p(val), regval_size(val));
9182 free_a_printer(&printer, 2);
9188 /****************************************************************
9189 _spoolss_SetPrinterDataEx
9190 ****************************************************************/
9192 WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
9193 struct spoolss_SetPrinterDataEx *r)
9195 NT_PRINTER_INFO_LEVEL *printer = NULL;
9197 WERROR result = WERR_OK;
9198 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9201 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9203 /* From MSDN documentation of SetPrinterDataEx: pass request to
9204 SetPrinterData if key is "PrinterDriverData" */
9207 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9208 OUR_HANDLE(r->in.handle)));
9212 if (Printer->printer_type == SPLHND_SERVER) {
9213 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9214 "Not implemented for server handles yet\n"));
9215 return WERR_INVALID_PARAM;
9218 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9223 * Access check : NT returns "access denied" if you make a
9224 * SetPrinterData call without the necessary privildge.
9225 * we were originally returning OK if nothing changed
9226 * which made Win2k issue **a lot** of SetPrinterData
9227 * when connecting to a printer --jerry
9230 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9231 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9232 "change denied by handle access permissions\n"));
9233 return WERR_ACCESS_DENIED;
9236 result = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9237 if (!W_ERROR_IS_OK(result)) {
9241 /* check for OID in valuename */
9243 oid_string = strchr(r->in.value_name, ',');
9249 /* save the registry data */
9251 result = set_printer_dataex(printer, r->in.key_name, r->in.value_name,
9252 r->in.type, r->in.buffer, r->in.offered);
9254 if (W_ERROR_IS_OK(result)) {
9255 /* save the OID if one was specified */
9257 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9258 r->in.key_name, SPOOL_OID_KEY);
9260 result = WERR_NOMEM;
9265 * I'm not checking the status here on purpose. Don't know
9266 * if this is right, but I'm returning the status from the
9267 * previous set_printer_dataex() call. I have no idea if
9268 * this is right. --jerry
9271 set_printer_dataex(printer, str, r->in.value_name,
9272 REG_SZ, (uint8_t *)oid_string,
9273 strlen(oid_string)+1);
9276 result = mod_a_printer(printer, 2);
9280 free_a_printer(&printer, 2);
9285 /****************************************************************
9286 _spoolss_DeletePrinterDataEx
9287 ****************************************************************/
9289 WERROR _spoolss_DeletePrinterDataEx(pipes_struct *p,
9290 struct spoolss_DeletePrinterDataEx *r)
9292 NT_PRINTER_INFO_LEVEL *printer = NULL;
9294 WERROR status = WERR_OK;
9295 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9297 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9300 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9301 "Invalid handle (%s:%u:%u).\n",
9302 OUR_HANDLE(r->in.handle)));
9306 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9309 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9310 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9311 "printer properties change denied by handle\n"));
9312 return WERR_ACCESS_DENIED;
9315 if (!r->in.value_name || !r->in.key_name) {
9319 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9320 if (!W_ERROR_IS_OK(status))
9323 status = delete_printer_dataex( printer, r->in.key_name, r->in.value_name );
9325 if ( W_ERROR_IS_OK(status) )
9326 mod_a_printer( printer, 2 );
9328 free_a_printer(&printer, 2);
9333 /****************************************************************
9334 _spoolss_EnumPrinterKey
9335 ****************************************************************/
9337 WERROR _spoolss_EnumPrinterKey(pipes_struct *p,
9338 struct spoolss_EnumPrinterKey *r)
9340 fstring *keynames = NULL;
9342 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9343 NT_PRINTER_DATA *data;
9344 NT_PRINTER_INFO_LEVEL *printer = NULL;
9346 WERROR result = WERR_BADFILE;
9348 const char **array = NULL;
9351 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9354 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9355 OUR_HANDLE(r->in.handle)));
9359 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9363 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9364 if (!W_ERROR_IS_OK(result)) {
9368 /* get the list of subkey names */
9370 data = printer->info_2->data;
9372 num_keys = get_printer_subkeys(data, r->in.key_name, &keynames);
9373 if (num_keys == -1) {
9374 result = WERR_BADFILE;
9380 array = talloc_zero_array(r->out.key_buffer, const char *, num_keys + 1);
9382 result = WERR_NOMEM;
9386 for (i=0; i < num_keys; i++) {
9387 array[i] = talloc_strdup(array, keynames[i]);
9389 result = WERR_NOMEM;
9393 *r->out.needed += strlen_m_term(keynames[i]) * 2;
9396 if (r->in.offered < *r->out.needed) {
9397 result = WERR_MORE_DATA;
9403 *r->out.key_buffer = array;
9406 if (!W_ERROR_IS_OK(result)) {
9408 ZERO_STRUCTP(r->out.key_buffer);
9411 free_a_printer(&printer, 2);
9412 SAFE_FREE(keynames);
9417 /****************************************************************
9418 _spoolss_DeletePrinterKey
9419 ****************************************************************/
9421 WERROR _spoolss_DeletePrinterKey(pipes_struct *p,
9422 struct spoolss_DeletePrinterKey *r)
9424 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9425 NT_PRINTER_INFO_LEVEL *printer = NULL;
9429 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9432 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9433 OUR_HANDLE(r->in.handle)));
9437 /* if keyname == NULL, return error */
9439 if ( !r->in.key_name )
9440 return WERR_INVALID_PARAM;
9442 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9445 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9446 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9447 "printer properties change denied by handle\n"));
9448 return WERR_ACCESS_DENIED;
9451 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9452 if (!W_ERROR_IS_OK(status))
9455 /* delete the key and all subneys */
9457 status = delete_all_printer_data( printer->info_2, r->in.key_name );
9459 if ( W_ERROR_IS_OK(status) )
9460 status = mod_a_printer(printer, 2);
9462 free_a_printer( &printer, 2 );
9467 /****************************************************************
9468 ****************************************************************/
9470 static WERROR registry_value_to_printer_enum_value(TALLOC_CTX *mem_ctx,
9471 struct regval_blob *v,
9472 struct spoolss_PrinterEnumValues *r)
9476 r->data = TALLOC_ZERO_P(mem_ctx, union spoolss_PrinterData);
9477 W_ERROR_HAVE_NO_MEMORY(r->data);
9479 r->value_name = talloc_strdup(mem_ctx, regval_name(v));
9480 W_ERROR_HAVE_NO_MEMORY(r->value_name);
9482 r->type = regval_type(v);
9483 r->data_length = regval_size(v);
9485 if (r->data_length) {
9486 DATA_BLOB blob = data_blob_const(regval_data_p(v),
9488 result = pull_spoolss_PrinterData(mem_ctx, &blob,
9491 if (!W_ERROR_IS_OK(result)) {
9499 /****************************************************************
9500 _spoolss_EnumPrinterDataEx
9501 ****************************************************************/
9503 WERROR _spoolss_EnumPrinterDataEx(pipes_struct *p,
9504 struct spoolss_EnumPrinterDataEx *r)
9507 NT_PRINTER_INFO_LEVEL *printer = NULL;
9508 struct spoolss_PrinterEnumValues *info = NULL;
9509 NT_PRINTER_DATA *p_data;
9510 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9516 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9520 *r->out.info = NULL;
9523 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9524 OUR_HANDLE(r->in.handle)));
9529 * first check for a keyname of NULL or "". Win2k seems to send
9530 * this a lot and we should send back WERR_INVALID_PARAM
9531 * no need to spend time looking up the printer in this case.
9535 if (!strlen(r->in.key_name)) {
9536 result = WERR_INVALID_PARAM;
9540 /* get the printer off of disk */
9542 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9546 ZERO_STRUCT(printer);
9547 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9548 if (!W_ERROR_IS_OK(result)) {
9552 /* now look for a match on the key name */
9554 p_data = printer->info_2->data;
9556 key_index = lookup_printerkey(p_data, r->in.key_name);
9557 if (key_index == -1) {
9558 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9560 result = WERR_INVALID_PARAM;
9564 /* allocate the memory for the array of pointers -- if necessary */
9566 count = regval_ctr_numvals(p_data->keys[key_index].values);
9568 result = WERR_OK; /* ??? */
9572 info = TALLOC_ZERO_ARRAY(p->mem_ctx,
9573 struct spoolss_PrinterEnumValues,
9576 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9577 result = WERR_NOMEM;
9582 * loop through all params and build the array to pass
9583 * back to the client
9586 for (i=0; i < count; i++) {
9588 struct regval_blob *val;
9590 /* lookup the registry value */
9592 val = regval_ctr_specific_value(p_data->keys[key_index].values, i);
9594 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val)));
9598 result = registry_value_to_printer_enum_value(info, val, &info[i]);
9599 if (!W_ERROR_IS_OK(result)) {
9604 #if 0 /* FIXME - gd */
9605 /* housekeeping information in the reply */
9607 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9608 * the hand marshalled container size is a multiple
9609 * of 4 bytes for RPC alignment.
9613 needed += 4-(needed % 4);
9616 *r->out.count = count;
9617 *r->out.info = info;
9622 free_a_printer(&printer, 2);
9625 if (!W_ERROR_IS_OK(result)) {
9629 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9630 spoolss_EnumPrinterDataEx, NULL,
9633 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9634 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9636 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9639 /****************************************************************************
9640 ****************************************************************************/
9642 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9643 const char *servername,
9644 const char *environment,
9645 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9650 werr = compose_spoolss_server_path(mem_ctx,
9653 SPOOLSS_PRTPROCS_PATH,
9655 if (!W_ERROR_IS_OK(werr)) {
9659 DEBUG(4,("print processor directory: [%s]\n", path));
9661 r->directory_name = path;
9666 /****************************************************************
9667 _spoolss_GetPrintProcessorDirectory
9668 ****************************************************************/
9670 WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
9671 struct spoolss_GetPrintProcessorDirectory *r)
9675 /* that's an [in out] buffer */
9677 if (!r->in.buffer && (r->in.offered != 0)) {
9678 return WERR_INVALID_PARAM;
9681 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9686 /* r->in.level is ignored */
9688 result = getprintprocessordirectory_level_1(p->mem_ctx,
9691 &r->out.info->info1);
9692 if (!W_ERROR_IS_OK(result)) {
9693 TALLOC_FREE(r->out.info);
9697 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo, NULL,
9698 r->out.info, r->in.level);
9699 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9701 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9704 /*******************************************************************
9705 ********************************************************************/
9707 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9708 const char *dllname)
9710 enum ndr_err_code ndr_err;
9711 struct spoolss_MonitorUi ui;
9713 ui.dll_name = dllname;
9715 ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
9716 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9717 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9718 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9720 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9723 /*******************************************************************
9724 Streams the monitor UI DLL name in UNICODE
9725 *******************************************************************/
9727 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9728 NT_USER_TOKEN *token, DATA_BLOB *in,
9729 DATA_BLOB *out, uint32_t *needed)
9731 const char *dllname = "tcpmonui.dll";
9733 *needed = (strlen(dllname)+1) * 2;
9735 if (out->length < *needed) {
9736 return WERR_INSUFFICIENT_BUFFER;
9739 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9746 /*******************************************************************
9747 ********************************************************************/
9749 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9750 struct spoolss_PortData1 *port1,
9751 const DATA_BLOB *buf)
9753 enum ndr_err_code ndr_err;
9754 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
9755 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9756 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9757 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9759 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9762 /*******************************************************************
9763 ********************************************************************/
9765 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9766 struct spoolss_PortData2 *port2,
9767 const DATA_BLOB *buf)
9769 enum ndr_err_code ndr_err;
9770 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
9771 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9772 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9773 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9775 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9778 /*******************************************************************
9779 Create a new TCP/IP port
9780 *******************************************************************/
9782 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9783 NT_USER_TOKEN *token, DATA_BLOB *in,
9784 DATA_BLOB *out, uint32_t *needed)
9786 struct spoolss_PortData1 port1;
9787 struct spoolss_PortData2 port2;
9788 char *device_uri = NULL;
9791 const char *portname;
9792 const char *hostaddress;
9794 uint32_t port_number;
9797 /* peek for spoolss_PortData version */
9799 if (!in || (in->length < (128 + 4))) {
9800 return WERR_GENERAL_FAILURE;
9803 version = IVAL(in->data, 128);
9809 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9813 portname = port1.portname;
9814 hostaddress = port1.hostaddress;
9815 queue = port1.queue;
9816 protocol = port1.protocol;
9817 port_number = port1.port_number;
9823 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9827 portname = port2.portname;
9828 hostaddress = port2.hostaddress;
9829 queue = port2.queue;
9830 protocol = port2.protocol;
9831 port_number = port2.port_number;
9835 DEBUG(1,("xcvtcp_addport: "
9836 "unknown version of port_data: %d\n", version));
9837 return WERR_UNKNOWN_PORT;
9840 /* create the device URI and call the add_port_hook() */
9843 case PROTOCOL_RAWTCP_TYPE:
9844 device_uri = talloc_asprintf(mem_ctx,
9845 "socket://%s:%d/", hostaddress,
9849 case PROTOCOL_LPR_TYPE:
9850 device_uri = talloc_asprintf(mem_ctx,
9851 "lpr://%s/%s", hostaddress, queue );
9855 return WERR_UNKNOWN_PORT;
9862 return add_port_hook(mem_ctx, token, portname, device_uri);
9865 /*******************************************************************
9866 *******************************************************************/
9868 struct xcv_api_table xcvtcp_cmds[] = {
9869 { "MonitorUI", xcvtcp_monitorui },
9870 { "AddPort", xcvtcp_addport},
9874 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9875 NT_USER_TOKEN *token, const char *command,
9882 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9884 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9885 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9886 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9889 return WERR_BADFUNC;
9892 /*******************************************************************
9893 *******************************************************************/
9894 #if 0 /* don't support management using the "Local Port" monitor */
9896 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9897 NT_USER_TOKEN *token, DATA_BLOB *in,
9898 DATA_BLOB *out, uint32_t *needed)
9900 const char *dllname = "localui.dll";
9902 *needed = (strlen(dllname)+1) * 2;
9904 if (out->length < *needed) {
9905 return WERR_INSUFFICIENT_BUFFER;
9908 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9915 /*******************************************************************
9916 *******************************************************************/
9918 struct xcv_api_table xcvlocal_cmds[] = {
9919 { "MonitorUI", xcvlocal_monitorui },
9923 struct xcv_api_table xcvlocal_cmds[] = {
9930 /*******************************************************************
9931 *******************************************************************/
9933 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9934 NT_USER_TOKEN *token, const char *command,
9935 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9940 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9942 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9943 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9944 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9946 return WERR_BADFUNC;
9949 /****************************************************************
9951 ****************************************************************/
9953 WERROR _spoolss_XcvData(pipes_struct *p,
9954 struct spoolss_XcvData *r)
9956 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9957 DATA_BLOB out_data = data_blob_null;
9961 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9962 OUR_HANDLE(r->in.handle)));
9966 /* Has to be a handle to the TCP/IP port monitor */
9968 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9969 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9973 /* requires administrative access to the server */
9975 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9976 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9977 return WERR_ACCESS_DENIED;
9980 /* Allocate the outgoing buffer */
9982 if (r->in.out_data_size) {
9983 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9984 if (out_data.data == NULL) {
9989 switch ( Printer->printer_type ) {
9990 case SPLHND_PORTMON_TCP:
9991 werror = process_xcvtcp_command(p->mem_ctx,
9992 p->server_info->ptok,
9993 r->in.function_name,
9994 &r->in.in_data, &out_data,
9997 case SPLHND_PORTMON_LOCAL:
9998 werror = process_xcvlocal_command(p->mem_ctx,
9999 p->server_info->ptok,
10000 r->in.function_name,
10001 &r->in.in_data, &out_data,
10005 werror = WERR_INVALID_PRINT_MONITOR;
10008 if (!W_ERROR_IS_OK(werror)) {
10012 *r->out.status_code = 0;
10014 memcpy(r->out.out_data, out_data.data, out_data.length);
10019 /****************************************************************
10020 _spoolss_AddPrintProcessor
10021 ****************************************************************/
10023 WERROR _spoolss_AddPrintProcessor(pipes_struct *p,
10024 struct spoolss_AddPrintProcessor *r)
10026 /* for now, just indicate success and ignore the add. We'll
10027 automatically set the winprint processor for printer
10028 entries later. Used to debug the LexMark Optra S 1855 PCL
10034 /****************************************************************
10036 ****************************************************************/
10038 WERROR _spoolss_AddPort(pipes_struct *p,
10039 struct spoolss_AddPort *r)
10041 /* do what w2k3 does */
10043 return WERR_NOT_SUPPORTED;
10046 /****************************************************************
10047 _spoolss_GetPrinterDriver
10048 ****************************************************************/
10050 WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
10051 struct spoolss_GetPrinterDriver *r)
10053 p->rng_fault_state = true;
10054 return WERR_NOT_SUPPORTED;
10057 /****************************************************************
10058 _spoolss_ReadPrinter
10059 ****************************************************************/
10061 WERROR _spoolss_ReadPrinter(pipes_struct *p,
10062 struct spoolss_ReadPrinter *r)
10064 p->rng_fault_state = true;
10065 return WERR_NOT_SUPPORTED;
10068 /****************************************************************
10069 _spoolss_WaitForPrinterChange
10070 ****************************************************************/
10072 WERROR _spoolss_WaitForPrinterChange(pipes_struct *p,
10073 struct spoolss_WaitForPrinterChange *r)
10075 p->rng_fault_state = true;
10076 return WERR_NOT_SUPPORTED;
10079 /****************************************************************
10080 _spoolss_ConfigurePort
10081 ****************************************************************/
10083 WERROR _spoolss_ConfigurePort(pipes_struct *p,
10084 struct spoolss_ConfigurePort *r)
10086 p->rng_fault_state = true;
10087 return WERR_NOT_SUPPORTED;
10090 /****************************************************************
10091 _spoolss_DeletePort
10092 ****************************************************************/
10094 WERROR _spoolss_DeletePort(pipes_struct *p,
10095 struct spoolss_DeletePort *r)
10097 p->rng_fault_state = true;
10098 return WERR_NOT_SUPPORTED;
10101 /****************************************************************
10102 _spoolss_CreatePrinterIC
10103 ****************************************************************/
10105 WERROR _spoolss_CreatePrinterIC(pipes_struct *p,
10106 struct spoolss_CreatePrinterIC *r)
10108 p->rng_fault_state = true;
10109 return WERR_NOT_SUPPORTED;
10112 /****************************************************************
10113 _spoolss_PlayGDIScriptOnPrinterIC
10114 ****************************************************************/
10116 WERROR _spoolss_PlayGDIScriptOnPrinterIC(pipes_struct *p,
10117 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10119 p->rng_fault_state = true;
10120 return WERR_NOT_SUPPORTED;
10123 /****************************************************************
10124 _spoolss_DeletePrinterIC
10125 ****************************************************************/
10127 WERROR _spoolss_DeletePrinterIC(pipes_struct *p,
10128 struct spoolss_DeletePrinterIC *r)
10130 p->rng_fault_state = true;
10131 return WERR_NOT_SUPPORTED;
10134 /****************************************************************
10135 _spoolss_AddPrinterConnection
10136 ****************************************************************/
10138 WERROR _spoolss_AddPrinterConnection(pipes_struct *p,
10139 struct spoolss_AddPrinterConnection *r)
10141 p->rng_fault_state = true;
10142 return WERR_NOT_SUPPORTED;
10145 /****************************************************************
10146 _spoolss_DeletePrinterConnection
10147 ****************************************************************/
10149 WERROR _spoolss_DeletePrinterConnection(pipes_struct *p,
10150 struct spoolss_DeletePrinterConnection *r)
10152 p->rng_fault_state = true;
10153 return WERR_NOT_SUPPORTED;
10156 /****************************************************************
10157 _spoolss_PrinterMessageBox
10158 ****************************************************************/
10160 WERROR _spoolss_PrinterMessageBox(pipes_struct *p,
10161 struct spoolss_PrinterMessageBox *r)
10163 p->rng_fault_state = true;
10164 return WERR_NOT_SUPPORTED;
10167 /****************************************************************
10168 _spoolss_AddMonitor
10169 ****************************************************************/
10171 WERROR _spoolss_AddMonitor(pipes_struct *p,
10172 struct spoolss_AddMonitor *r)
10174 p->rng_fault_state = true;
10175 return WERR_NOT_SUPPORTED;
10178 /****************************************************************
10179 _spoolss_DeleteMonitor
10180 ****************************************************************/
10182 WERROR _spoolss_DeleteMonitor(pipes_struct *p,
10183 struct spoolss_DeleteMonitor *r)
10185 p->rng_fault_state = true;
10186 return WERR_NOT_SUPPORTED;
10189 /****************************************************************
10190 _spoolss_DeletePrintProcessor
10191 ****************************************************************/
10193 WERROR _spoolss_DeletePrintProcessor(pipes_struct *p,
10194 struct spoolss_DeletePrintProcessor *r)
10196 p->rng_fault_state = true;
10197 return WERR_NOT_SUPPORTED;
10200 /****************************************************************
10201 _spoolss_AddPrintProvidor
10202 ****************************************************************/
10204 WERROR _spoolss_AddPrintProvidor(pipes_struct *p,
10205 struct spoolss_AddPrintProvidor *r)
10207 p->rng_fault_state = true;
10208 return WERR_NOT_SUPPORTED;
10211 /****************************************************************
10212 _spoolss_DeletePrintProvidor
10213 ****************************************************************/
10215 WERROR _spoolss_DeletePrintProvidor(pipes_struct *p,
10216 struct spoolss_DeletePrintProvidor *r)
10218 p->rng_fault_state = true;
10219 return WERR_NOT_SUPPORTED;
10222 /****************************************************************
10223 _spoolss_FindFirstPrinterChangeNotification
10224 ****************************************************************/
10226 WERROR _spoolss_FindFirstPrinterChangeNotification(pipes_struct *p,
10227 struct spoolss_FindFirstPrinterChangeNotification *r)
10229 p->rng_fault_state = true;
10230 return WERR_NOT_SUPPORTED;
10233 /****************************************************************
10234 _spoolss_FindNextPrinterChangeNotification
10235 ****************************************************************/
10237 WERROR _spoolss_FindNextPrinterChangeNotification(pipes_struct *p,
10238 struct spoolss_FindNextPrinterChangeNotification *r)
10240 p->rng_fault_state = true;
10241 return WERR_NOT_SUPPORTED;
10244 /****************************************************************
10245 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10246 ****************************************************************/
10248 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct *p,
10249 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10251 p->rng_fault_state = true;
10252 return WERR_NOT_SUPPORTED;
10255 /****************************************************************
10256 _spoolss_ReplyOpenPrinter
10257 ****************************************************************/
10259 WERROR _spoolss_ReplyOpenPrinter(pipes_struct *p,
10260 struct spoolss_ReplyOpenPrinter *r)
10262 p->rng_fault_state = true;
10263 return WERR_NOT_SUPPORTED;
10266 /****************************************************************
10267 _spoolss_RouterReplyPrinter
10268 ****************************************************************/
10270 WERROR _spoolss_RouterReplyPrinter(pipes_struct *p,
10271 struct spoolss_RouterReplyPrinter *r)
10273 p->rng_fault_state = true;
10274 return WERR_NOT_SUPPORTED;
10277 /****************************************************************
10278 _spoolss_ReplyClosePrinter
10279 ****************************************************************/
10281 WERROR _spoolss_ReplyClosePrinter(pipes_struct *p,
10282 struct spoolss_ReplyClosePrinter *r)
10284 p->rng_fault_state = true;
10285 return WERR_NOT_SUPPORTED;
10288 /****************************************************************
10290 ****************************************************************/
10292 WERROR _spoolss_AddPortEx(pipes_struct *p,
10293 struct spoolss_AddPortEx *r)
10295 p->rng_fault_state = true;
10296 return WERR_NOT_SUPPORTED;
10299 /****************************************************************
10300 _spoolss_RouterFindFirstPrinterChangeNotification
10301 ****************************************************************/
10303 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct *p,
10304 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10306 p->rng_fault_state = true;
10307 return WERR_NOT_SUPPORTED;
10310 /****************************************************************
10311 _spoolss_SpoolerInit
10312 ****************************************************************/
10314 WERROR _spoolss_SpoolerInit(pipes_struct *p,
10315 struct spoolss_SpoolerInit *r)
10317 p->rng_fault_state = true;
10318 return WERR_NOT_SUPPORTED;
10321 /****************************************************************
10322 _spoolss_ResetPrinterEx
10323 ****************************************************************/
10325 WERROR _spoolss_ResetPrinterEx(pipes_struct *p,
10326 struct spoolss_ResetPrinterEx *r)
10328 p->rng_fault_state = true;
10329 return WERR_NOT_SUPPORTED;
10332 /****************************************************************
10333 _spoolss_RouterReplyPrinterEx
10334 ****************************************************************/
10336 WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
10337 struct spoolss_RouterReplyPrinterEx *r)
10339 p->rng_fault_state = true;
10340 return WERR_NOT_SUPPORTED;
10343 /****************************************************************
10345 ****************************************************************/
10347 WERROR _spoolss_44(pipes_struct *p,
10348 struct spoolss_44 *r)
10350 p->rng_fault_state = true;
10351 return WERR_NOT_SUPPORTED;
10354 /****************************************************************
10356 ****************************************************************/
10358 WERROR _spoolss_47(pipes_struct *p,
10359 struct spoolss_47 *r)
10361 p->rng_fault_state = true;
10362 return WERR_NOT_SUPPORTED;
10365 /****************************************************************
10367 ****************************************************************/
10369 WERROR _spoolss_4a(pipes_struct *p,
10370 struct spoolss_4a *r)
10372 p->rng_fault_state = true;
10373 return WERR_NOT_SUPPORTED;
10376 /****************************************************************
10378 ****************************************************************/
10380 WERROR _spoolss_4b(pipes_struct *p,
10381 struct spoolss_4b *r)
10383 p->rng_fault_state = true;
10384 return WERR_NOT_SUPPORTED;
10387 /****************************************************************
10389 ****************************************************************/
10391 WERROR _spoolss_4c(pipes_struct *p,
10392 struct spoolss_4c *r)
10394 p->rng_fault_state = true;
10395 return WERR_NOT_SUPPORTED;
10398 /****************************************************************
10400 ****************************************************************/
10402 WERROR _spoolss_53(pipes_struct *p,
10403 struct spoolss_53 *r)
10405 p->rng_fault_state = true;
10406 return WERR_NOT_SUPPORTED;
10409 /****************************************************************
10411 ****************************************************************/
10413 WERROR _spoolss_55(pipes_struct *p,
10414 struct spoolss_55 *r)
10416 p->rng_fault_state = true;
10417 return WERR_NOT_SUPPORTED;
10420 /****************************************************************
10422 ****************************************************************/
10424 WERROR _spoolss_56(pipes_struct *p,
10425 struct spoolss_56 *r)
10427 p->rng_fault_state = true;
10428 return WERR_NOT_SUPPORTED;
10431 /****************************************************************
10433 ****************************************************************/
10435 WERROR _spoolss_57(pipes_struct *p,
10436 struct spoolss_57 *r)
10438 p->rng_fault_state = true;
10439 return WERR_NOT_SUPPORTED;
10442 /****************************************************************
10444 ****************************************************************/
10446 WERROR _spoolss_5a(pipes_struct *p,
10447 struct spoolss_5a *r)
10449 p->rng_fault_state = true;
10450 return WERR_NOT_SUPPORTED;
10453 /****************************************************************
10455 ****************************************************************/
10457 WERROR _spoolss_5b(pipes_struct *p,
10458 struct spoolss_5b *r)
10460 p->rng_fault_state = true;
10461 return WERR_NOT_SUPPORTED;
10464 /****************************************************************
10466 ****************************************************************/
10468 WERROR _spoolss_5c(pipes_struct *p,
10469 struct spoolss_5c *r)
10471 p->rng_fault_state = true;
10472 return WERR_NOT_SUPPORTED;
10475 /****************************************************************
10477 ****************************************************************/
10479 WERROR _spoolss_5d(pipes_struct *p,
10480 struct spoolss_5d *r)
10482 p->rng_fault_state = true;
10483 return WERR_NOT_SUPPORTED;
10486 /****************************************************************
10488 ****************************************************************/
10490 WERROR _spoolss_5e(pipes_struct *p,
10491 struct spoolss_5e *r)
10493 p->rng_fault_state = true;
10494 return WERR_NOT_SUPPORTED;
10497 /****************************************************************
10499 ****************************************************************/
10501 WERROR _spoolss_5f(pipes_struct *p,
10502 struct spoolss_5f *r)
10504 p->rng_fault_state = true;
10505 return WERR_NOT_SUPPORTED;