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.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 SAFE_FREE((*pp)->ctr.type);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
291 close_policy_hnd(p, hnd);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
397 switch (Printer->printer_type) {
398 case PRINTER_HANDLE_IS_PRINTER:
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
402 case PRINTER_HANDLE_IS_PRINTSERVER:
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
437 /****************************************************************************
438 Set printer handle name.
439 ****************************************************************************/
441 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
444 int n_services=lp_numservices();
445 char *aprinter, *printername;
446 const char *servername;
449 NT_PRINTER_INFO_LEVEL *printer;
452 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
454 aprinter = handlename;
455 if ( *handlename == '\\' ) {
456 servername = handlename + 2;
457 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
466 /* save the servername to fill in replies on this handle */
468 if ( !is_myname_or_ipaddr( servername ) )
471 fstrcpy( Printer->servername, servername );
473 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
476 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
479 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
481 /* Search all sharenames first as this is easier than pulling
482 the printer_info_2 off of disk. Don't use find_service() since
483 that calls out to map_username() */
485 /* do another loop to look for printernames */
487 for (snum=0; !found && snum<n_services; snum++) {
489 /* no point going on if this is not a printer */
491 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
494 fstrcpy(sname, lp_servicename(snum));
495 if ( strequal( aprinter, sname ) ) {
500 /* no point looking up the printer object if
501 we aren't allowing printername != sharename */
503 if ( lp_force_printername(snum) )
506 fstrcpy(sname, lp_servicename(snum));
509 result = get_a_printer( 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, dos_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) ) {
531 DEBUGADD(10, ("printername: %s\n", printername));
533 free_a_printer( &printer, 2);
537 DEBUGADD(4,("Printer not found\n"));
541 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
543 fstrcpy(Printer->sharename, sname);
548 /****************************************************************************
549 Find first available printer slot. creates a printer handle for you.
550 ****************************************************************************/
552 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
554 Printer_entry *new_printer;
556 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
558 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
561 ZERO_STRUCTP(new_printer);
563 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
564 SAFE_FREE(new_printer);
568 /* Add to the internal list. */
569 DLIST_ADD(printers_list, new_printer);
571 new_printer->notify.option=NULL;
573 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
574 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
575 close_printer_handle(p, hnd);
579 if (!set_printer_hnd_printertype(new_printer, name)) {
580 close_printer_handle(p, hnd);
584 if (!set_printer_hnd_name(new_printer, name)) {
585 close_printer_handle(p, hnd);
589 new_printer->access_granted = access_granted;
591 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
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 flags, uint16 notify_type,
607 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
610 SPOOL_NOTIFY_OPTION *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->ctr.type[i].type != notify_type)
635 /* Check match for field */
637 for (j = 0; j < option->ctr.type[i].count; j++) {
638 if (option->ctr.type[i].fields[j] == 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 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
652 static void notify_one_value(struct spoolss_notify_msg *msg,
653 SPOOL_NOTIFY_INFO_DATA *data,
656 data->notify_data.value[0] = msg->notify.value[0];
657 data->notify_data.value[1] = 0;
660 static void notify_string(struct spoolss_notify_msg *msg,
661 SPOOL_NOTIFY_INFO_DATA *data,
666 /* The length of the message includes the trailing \0 */
668 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
670 data->notify_data.data.length = msg->len * 2;
671 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
673 if (!data->notify_data.data.string) {
674 data->notify_data.data.length = 0;
678 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
681 static void notify_system_time(struct spoolss_notify_msg *msg,
682 SPOOL_NOTIFY_INFO_DATA *data,
688 if (msg->len != sizeof(time_t)) {
689 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
694 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
695 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
699 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
700 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
704 if (!spoolss_io_system_time("", &ps, 0, &systime))
707 data->notify_data.data.length = prs_offset(&ps);
708 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
710 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
715 struct notify2_message_table {
717 void (*fn)(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
721 static struct notify2_message_table printer_notify_table[] = {
722 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
723 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
724 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
725 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
726 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
727 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
728 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
729 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
730 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
731 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
732 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
733 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
734 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
735 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
736 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
737 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
738 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
739 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
740 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
743 static struct notify2_message_table job_notify_table[] = {
744 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
745 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
746 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
747 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
748 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
749 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
750 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
751 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
752 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
753 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
754 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
755 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
756 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
757 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
758 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
759 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
760 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
761 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
762 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
764 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
765 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
766 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
767 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
771 /***********************************************************************
772 Allocate talloc context for container object
773 **********************************************************************/
775 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
780 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
785 /***********************************************************************
786 release all allocated memory and zero out structure
787 **********************************************************************/
789 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
795 talloc_destroy(ctr->ctx);
802 /***********************************************************************
803 **********************************************************************/
805 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 /***********************************************************************
814 **********************************************************************/
816 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
818 if ( !ctr || !ctr->msg_groups )
821 if ( idx >= ctr->num_groups )
824 return &ctr->msg_groups[idx];
828 /***********************************************************************
829 How many groups of change messages do we have ?
830 **********************************************************************/
832 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 return ctr->num_groups;
840 /***********************************************************************
841 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
842 **********************************************************************/
844 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
846 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
847 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
848 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
854 /* loop over all groups looking for a matching printer name */
856 for ( i=0; i<ctr->num_groups; i++ ) {
857 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
861 /* add a new group? */
863 if ( i == ctr->num_groups ) {
866 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 ctr->msg_groups = groups;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
875 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp = &ctr->msg_groups[i];
884 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
888 msg_grp->msgs = msg_list;
890 new_slot = msg_grp->num_msgs-1;
891 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
893 /* need to allocate own copy of data */
896 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
898 return ctr->num_groups;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
909 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
910 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
911 SPOOLSS_NOTIFY_MSG *messages;
912 int sending_msg_count;
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 messages = msg_group->msgs;
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
928 /* loop over all printers */
930 for (p = printers_list; p; p = p->next) {
931 SPOOL_NOTIFY_INFO_DATA *data;
936 /* Is there notification on this handle? */
938 if ( !p->notify.client_connected )
941 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
943 /* For this printer? Print servers always receive
946 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
947 ( !strequal(msg_group->printername, p->sharename) ) )
950 DEBUG(10,("Our printer\n"));
952 /* allocate the max entries possible */
954 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
957 /* build the array of change notifications */
959 sending_msg_count = 0;
961 for ( i=0; i<msg_group->num_msgs; i++ ) {
962 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p, msg->type, msg->field))
972 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
973 msg->type, msg->field, p->sharename));
976 * if the is a printer notification handle and not a job notification
977 * type, then set the id to 0. Other wise just use what was specified
980 * When registering change notification on a print server handle
981 * we always need to send back the id (snum) matching the printer
982 * for which the change took place. For change notify registered
983 * on a printer handle, this does not matter and the id should be 0.
988 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
994 /* Convert unix jobid to smb jobid */
996 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
997 id = sysjob_to_jobid(msg->id);
1000 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1005 construct_info_data( &data[data_len], msg->type, msg->field, id );
1008 case PRINTER_NOTIFY_TYPE:
1009 if ( printer_notify_table[msg->field].fn )
1010 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1013 case JOB_NOTIFY_TYPE:
1014 if ( job_notify_table[msg->field].fn )
1015 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1019 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1026 if ( sending_msg_count ) {
1027 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1028 data_len, data, p->notify.change, 0 );
1033 DEBUG(8,("send_notify2_changes: Exit...\n"));
1037 /***********************************************************************
1038 **********************************************************************/
1040 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1043 uint32 tv_sec, tv_usec;
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1053 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1056 tdb_unpack((char *)buf + offset, len - offset, "dd",
1057 &msg->notify.value[0], &msg->notify.value[1]);
1059 tdb_unpack((char *)buf + offset, len - offset, "B",
1060 &msg->len, &msg->notify.data);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1063 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1065 tv->tv_sec = tv_sec;
1066 tv->tv_usec = tv_usec;
1069 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1070 msg->notify.value[1]));
1072 dump_data(3, msg->notify.data, msg->len);
1077 /********************************************************************
1078 Receive a notify2 message list
1079 ********************************************************************/
1081 static void receive_notify2_message_list(int msg_type, struct process_id src,
1082 void *msg, size_t len)
1084 size_t msg_count, i;
1085 char *buf = (char *)msg;
1088 SPOOLSS_NOTIFY_MSG notify;
1089 SPOOLSS_NOTIFY_MSG_CTR messages;
1093 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1097 msg_count = IVAL(buf, 0);
1100 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1102 if (msg_count == 0) {
1103 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1107 /* initialize the container */
1109 ZERO_STRUCT( messages );
1110 notify_msg_ctr_init( &messages );
1113 * build message groups for each printer identified
1114 * in a change_notify msg. Remember that a PCN message
1115 * includes the handle returned for the srv_spoolss_replyopenprinter()
1116 * call. Therefore messages are grouped according to printer handle.
1119 for ( i=0; i<msg_count; i++ ) {
1120 struct timeval msg_tv;
1122 if (msg_ptr + 4 - buf > len) {
1123 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1127 msg_len = IVAL(msg_ptr,0);
1130 if (msg_ptr + msg_len - buf > len) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1135 /* unpack messages */
1137 ZERO_STRUCT( notify );
1138 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1141 /* add to correct list in container */
1143 notify_msg_ctr_addmsg( &messages, ¬ify );
1145 /* free memory that might have been allocated by notify2_unpack_msg() */
1147 if ( notify.len != 0 )
1148 SAFE_FREE( notify.notify.data );
1151 /* process each group of messages */
1153 num_groups = notify_msg_ctr_numgroups( &messages );
1154 for ( i=0; i<num_groups; i++ )
1155 send_notify2_changes( &messages, i );
1160 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1162 notify_msg_ctr_destroy( &messages );
1167 /********************************************************************
1168 Send a message to ourself about new driver being installed
1169 so we can upgrade the information for each printer bound to this
1171 ********************************************************************/
1173 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1175 int len = strlen(drivername);
1180 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1183 message_send_pid(pid_to_procid(sys_getpid()),
1184 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1189 /**********************************************************************
1190 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1191 over all printers, upgrading ones as necessary
1192 **********************************************************************/
1194 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1198 int n_services = lp_numservices();
1200 len = MIN(len,sizeof(drivername)-1);
1201 strncpy(drivername, buf, len);
1203 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1205 /* Iterate the printer list */
1207 for (snum=0; snum<n_services; snum++)
1209 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1212 NT_PRINTER_INFO_LEVEL *printer = NULL;
1214 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1215 if (!W_ERROR_IS_OK(result))
1218 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1220 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1222 /* all we care about currently is the change_id */
1224 result = mod_a_printer(printer, 2);
1225 if (!W_ERROR_IS_OK(result)) {
1226 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1227 dos_errstr(result)));
1231 free_a_printer(&printer, 2);
1238 /********************************************************************
1239 Update the cache for all printq's with a registered client
1241 ********************************************************************/
1243 void update_monitored_printq_cache( void )
1245 Printer_entry *printer = printers_list;
1248 /* loop through all printers and update the cache where
1249 client_connected == True */
1252 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1253 && printer->notify.client_connected )
1255 snum = print_queue_snum(printer->sharename);
1256 print_queue_status( snum, NULL, NULL );
1259 printer = printer->next;
1264 /********************************************************************
1265 Send a message to ourself about new driver being installed
1266 so we can upgrade the information for each printer bound to this
1268 ********************************************************************/
1270 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1272 int len = strlen(drivername);
1277 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1280 message_send_pid(pid_to_procid(sys_getpid()),
1281 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1286 /**********************************************************************
1287 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1288 over all printers, resetting printer data as neessary
1289 **********************************************************************/
1291 void reset_all_printerdata(int msg_type, struct process_id src,
1292 void *buf, size_t len)
1296 int n_services = lp_numservices();
1298 len = MIN( len, sizeof(drivername)-1 );
1299 strncpy( drivername, buf, len );
1301 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1303 /* Iterate the printer list */
1305 for ( snum=0; snum<n_services; snum++ )
1307 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1310 NT_PRINTER_INFO_LEVEL *printer = NULL;
1312 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1313 if ( !W_ERROR_IS_OK(result) )
1317 * if the printer is bound to the driver,
1318 * then reset to the new driver initdata
1321 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1323 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1325 if ( !set_driver_init(printer, 2) ) {
1326 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1327 printer->info_2->printername, printer->info_2->drivername));
1330 result = mod_a_printer( printer, 2 );
1331 if ( !W_ERROR_IS_OK(result) ) {
1332 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1333 get_dos_error_msg(result)));
1337 free_a_printer( &printer, 2 );
1346 /********************************************************************
1347 Copy routines used by convert_to_openprinterex()
1348 *******************************************************************/
1350 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1358 DEBUG (8,("dup_devmode\n"));
1360 /* bulk copy first */
1362 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1366 /* dup the pointer members separately */
1368 len = unistrlen(devmode->devicename.buffer);
1370 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1371 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1376 len = unistrlen(devmode->formname.buffer);
1378 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1379 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1383 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1388 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1390 if (!new_ctr || !ctr)
1393 DEBUG(8,("copy_devmode_ctr\n"));
1395 new_ctr->size = ctr->size;
1396 new_ctr->devmode_ptr = ctr->devmode_ptr;
1398 if(ctr->devmode_ptr)
1399 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1402 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1404 if (!new_def || !def)
1407 DEBUG(8,("copy_printer_defaults\n"));
1409 new_def->datatype_ptr = def->datatype_ptr;
1411 if (def->datatype_ptr)
1412 copy_unistr2(&new_def->datatype, &def->datatype);
1414 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1416 new_def->access_required = def->access_required;
1419 /********************************************************************
1420 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1421 * SPOOL_Q_OPEN_PRINTER_EX structure
1422 ********************************************************************/
1424 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1426 if (!q_u_ex || !q_u)
1429 DEBUG(8,("convert_to_openprinterex\n"));
1431 if ( q_u->printername ) {
1432 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1433 if (q_u_ex->printername == NULL)
1435 copy_unistr2(q_u_ex->printername, q_u->printername);
1438 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1443 /********************************************************************
1444 * spoolss_open_printer
1446 * called from the spoolss dispatcher
1447 ********************************************************************/
1449 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1451 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1452 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1457 ZERO_STRUCT(q_u_ex);
1458 ZERO_STRUCT(r_u_ex);
1460 /* convert the OpenPrinter() call to OpenPrinterEx() */
1462 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1463 if (!W_ERROR_IS_OK(r_u_ex.status))
1464 return r_u_ex.status;
1466 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1468 /* convert back to OpenPrinter() */
1470 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1475 /********************************************************************
1476 * spoolss_open_printer
1478 * If the openprinterex rpc call contains a devmode,
1479 * it's a per-user one. This per-user devmode is derivated
1480 * from the global devmode. Openprinterex() contains a per-user
1481 * devmode for when you do EMF printing and spooling.
1482 * In the EMF case, the NT workstation is only doing half the job
1483 * of rendering the page. The other half is done by running the printer
1484 * driver on the server.
1485 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1486 * The EMF file only contains what is to be printed on the page.
1487 * So in order for the server to know how to print, the NT client sends
1488 * a devicemode attached to the openprinterex call.
1489 * But this devicemode is short lived, it's only valid for the current print job.
1491 * If Samba would have supported EMF spooling, this devicemode would
1492 * have been attached to the handle, to sent it to the driver to correctly
1493 * rasterize the EMF file.
1495 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1496 * we just act as a pass-thru between windows and the printer.
1498 * In order to know that Samba supports only RAW spooling, NT has to call
1499 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1500 * and until NT sends a RAW job, we refuse it.
1502 * But to call getprinter() or startdoc(), you first need a valid handle,
1503 * and to get an handle you have to call openprintex(). Hence why you have
1504 * a devicemode in the openprinterex() call.
1507 * Differences between NT4 and NT 2000.
1510 * On NT4, you only have a global devicemode. This global devicemode can be changed
1511 * by the administrator (or by a user with enough privs). Everytime a user
1512 * wants to print, the devicemode is resetted to the default. In Word, everytime
1513 * you print, the printer's characteristics are always reset to the global devicemode.
1517 * In W2K, there is the notion of per-user devicemode. The first time you use
1518 * a printer, a per-user devicemode is build from the global devicemode.
1519 * If you change your per-user devicemode, it is saved in the registry, under the
1520 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1521 * printer preferences available.
1523 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1524 * on the General Tab of the printer properties windows.
1526 * To change the global devicemode: it's the "Printing Defaults..." button
1527 * on the Advanced Tab of the printer properties window.
1530 ********************************************************************/
1532 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1534 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1535 POLICY_HND *handle = &r_u->handle;
1539 struct current_user user;
1540 Printer_entry *Printer=NULL;
1542 if ( !q_u->printername )
1543 return WERR_INVALID_PRINTER_NAME;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1550 DEBUGADD(3,("checking name: %s\n",name));
1552 if (!open_printer_hnd(p, handle, name, 0))
1553 return WERR_INVALID_PRINTER_NAME;
1555 Printer=find_printer_index_by_hnd(p, handle);
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name ));
1559 close_printer_handle(p,handle);
1560 return WERR_INVALID_PRINTER_NAME;
1563 get_current_user(&user, p);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1586 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1588 /* Printserver handles use global struct... */
1592 /* Map standard access rights to object specific access rights */
1594 se_map_standard(&printer_default->access_required,
1595 &printserver_std_mapping);
1597 /* Deny any object specific bits that don't apply to print
1598 servers (i.e printer and job specific bits) */
1600 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1602 if (printer_default->access_required &
1603 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1604 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1605 close_printer_handle(p, handle);
1606 return WERR_ACCESS_DENIED;
1609 /* Allow admin access */
1611 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1613 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1615 if (!lp_ms_add_printer_wizard()) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1624 && !user_has_privileges( user.nt_user_token, &se_printop )
1625 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1627 close_printer_handle(p, handle);
1628 return WERR_ACCESS_DENIED;
1631 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1635 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1638 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1639 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1641 /* We fall through to return WERR_OK */
1646 /* NT doesn't let us connect to a printer if the connecting user
1647 doesn't have print permission. */
1649 if (!get_printer_snum(p, handle, &snum)) {
1650 close_printer_handle(p, handle);
1654 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1656 /* map an empty access mask to the minimum access mask */
1657 if (printer_default->access_required == 0x0)
1658 printer_default->access_required = PRINTER_ACCESS_USE;
1661 * If we are not serving the printer driver for this printer,
1662 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1663 * will keep NT clients happy --jerry
1666 if (lp_use_client_driver(snum)
1667 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1669 printer_default->access_required = PRINTER_ACCESS_USE;
1672 /* check smb.conf parameters and the the sec_desc */
1674 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1675 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1676 return WERR_ACCESS_DENIED;
1679 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p, handle);
1682 return WERR_ACCESS_DENIED;
1685 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1692 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1694 printer_default->access_required = PRINTER_ACCESS_USE;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1701 Printer->access_granted = printer_default->access_required;
1704 * If the client sent a devmode in the OpenPrinter() call, then
1705 * save it here in case we get a job submission on this handle
1708 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1709 && q_u->printer_default.devmode_cont.devmode_ptr )
1711 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1712 &Printer->nt_devmode );
1715 #if 0 /* JERRY -- I'm doubtful this is really effective */
1716 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1717 optimization in Windows 2000 clients --jerry */
1719 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1720 && (RA_WIN2K == get_remote_arch()) )
1722 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1723 sys_usleep( 500000 );
1730 /****************************************************************************
1731 ****************************************************************************/
1733 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1734 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1740 /* allocate memory if needed. Messy because
1741 convert_printer_info is used to update an existing
1742 printer or build a new one */
1744 if ( !printer->info_2 ) {
1745 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1746 if ( !printer->info_2 ) {
1747 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1752 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1753 printer->info_2->setuptime = time(NULL);
1761 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1762 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1768 printer->info_3=NULL;
1769 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1773 printer->info_6=NULL;
1774 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1784 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1785 NT_DEVICEMODE **pp_nt_devmode)
1787 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1790 * Ensure nt_devmode is a valid pointer
1791 * as we will be overwriting it.
1794 if (nt_devmode == NULL) {
1795 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1796 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1800 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1801 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1803 nt_devmode->specversion=devmode->specversion;
1804 nt_devmode->driverversion=devmode->driverversion;
1805 nt_devmode->size=devmode->size;
1806 nt_devmode->fields=devmode->fields;
1807 nt_devmode->orientation=devmode->orientation;
1808 nt_devmode->papersize=devmode->papersize;
1809 nt_devmode->paperlength=devmode->paperlength;
1810 nt_devmode->paperwidth=devmode->paperwidth;
1811 nt_devmode->scale=devmode->scale;
1812 nt_devmode->copies=devmode->copies;
1813 nt_devmode->defaultsource=devmode->defaultsource;
1814 nt_devmode->printquality=devmode->printquality;
1815 nt_devmode->color=devmode->color;
1816 nt_devmode->duplex=devmode->duplex;
1817 nt_devmode->yresolution=devmode->yresolution;
1818 nt_devmode->ttoption=devmode->ttoption;
1819 nt_devmode->collate=devmode->collate;
1821 nt_devmode->logpixels=devmode->logpixels;
1822 nt_devmode->bitsperpel=devmode->bitsperpel;
1823 nt_devmode->pelswidth=devmode->pelswidth;
1824 nt_devmode->pelsheight=devmode->pelsheight;
1825 nt_devmode->displayflags=devmode->displayflags;
1826 nt_devmode->displayfrequency=devmode->displayfrequency;
1827 nt_devmode->icmmethod=devmode->icmmethod;
1828 nt_devmode->icmintent=devmode->icmintent;
1829 nt_devmode->mediatype=devmode->mediatype;
1830 nt_devmode->dithertype=devmode->dithertype;
1831 nt_devmode->reserved1=devmode->reserved1;
1832 nt_devmode->reserved2=devmode->reserved2;
1833 nt_devmode->panningwidth=devmode->panningwidth;
1834 nt_devmode->panningheight=devmode->panningheight;
1837 * Only change private and driverextra if the incoming devmode
1838 * has a new one. JRA.
1841 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1842 SAFE_FREE(nt_devmode->nt_dev_private);
1843 nt_devmode->driverextra=devmode->driverextra;
1844 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1846 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1849 *pp_nt_devmode = nt_devmode;
1854 /********************************************************************
1855 * _spoolss_enddocprinter_internal.
1856 ********************************************************************/
1858 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1860 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1864 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1868 if (!get_printer_snum(p, handle, &snum))
1871 Printer->document_started=False;
1872 print_job_end(snum, Printer->jobid,True);
1873 /* error codes unhandled so far ... */
1878 /********************************************************************
1879 * api_spoolss_closeprinter
1880 ********************************************************************/
1882 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1884 POLICY_HND *handle = &q_u->handle;
1886 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1888 if (Printer && Printer->document_started)
1889 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1891 if (!close_printer_handle(p, handle))
1894 /* clear the returned printer handle. Observed behavior
1895 from Win2k server. Don't think this really matters.
1896 Previous code just copied the value of the closed
1899 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1904 /********************************************************************
1905 * api_spoolss_deleteprinter
1907 ********************************************************************/
1909 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1911 POLICY_HND *handle = &q_u->handle;
1912 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1915 if (Printer && Printer->document_started)
1916 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1918 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1920 result = delete_printer_handle(p, handle);
1922 update_c_setprinter(False);
1927 /*******************************************************************
1928 * static function to lookup the version id corresponding to an
1929 * long architecture string
1930 ******************************************************************/
1932 static int get_version_id (char * arch)
1935 struct table_node archi_table[]= {
1937 {"Windows 4.0", "WIN40", 0 },
1938 {"Windows NT x86", "W32X86", 2 },
1939 {"Windows NT R4000", "W32MIPS", 2 },
1940 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1941 {"Windows NT PowerPC", "W32PPC", 2 },
1942 {"Windows IA64", "IA64", 3 },
1943 {"Windows x64", "x64", 3 },
1947 for (i=0; archi_table[i].long_archi != NULL; i++)
1949 if (strcmp(arch, archi_table[i].long_archi) == 0)
1950 return (archi_table[i].version);
1956 /********************************************************************
1957 * _spoolss_deleteprinterdriver
1958 ********************************************************************/
1960 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1964 NT_PRINTER_DRIVER_INFO_LEVEL info;
1965 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1967 struct current_user user;
1969 WERROR status_win2k = WERR_ACCESS_DENIED;
1970 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1972 get_current_user(&user, p);
1974 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1975 and not a printer admin, then fail */
1977 if ( (user.uid != 0)
1978 && !user_has_privileges(user.nt_user_token, &se_printop )
1979 && !user_in_list(uidtoname(user.uid), lp_printer_admin(-1), user.groups, user.ngroups) )
1981 return WERR_ACCESS_DENIED;
1984 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1985 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1987 /* check that we have a valid driver name first */
1989 if ((version=get_version_id(arch)) == -1)
1990 return WERR_INVALID_ENVIRONMENT;
1993 ZERO_STRUCT(info_win2k);
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1997 /* try for Win2k driver if "Windows NT x86" */
1999 if ( version == 2 ) {
2001 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2002 status = WERR_UNKNOWN_PRINTER_DRIVER;
2006 /* otherwise it was a failure */
2008 status = WERR_UNKNOWN_PRINTER_DRIVER;
2014 if (printer_driver_in_use(info.info_3)) {
2015 status = WERR_PRINTER_DRIVER_IN_USE;
2021 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2023 /* if we get to here, we now have 2 driver info structures to remove */
2024 /* remove the Win2k driver first*/
2026 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2027 free_a_printer_driver( info_win2k, 3 );
2029 /* this should not have failed---if it did, report to client */
2030 if ( !W_ERROR_IS_OK(status_win2k) )
2032 status = status_win2k;
2038 status = delete_printer_driver(info.info_3, &user, version, False);
2040 /* if at least one of the deletes succeeded return OK */
2042 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2046 free_a_printer_driver( info, 3 );
2051 /********************************************************************
2052 * spoolss_deleteprinterdriverex
2053 ********************************************************************/
2055 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2059 NT_PRINTER_DRIVER_INFO_LEVEL info;
2060 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2062 uint32 flags = q_u->delete_flags;
2064 struct current_user user;
2066 WERROR status_win2k = WERR_ACCESS_DENIED;
2067 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2069 get_current_user(&user, p);
2071 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2072 and not a printer admin, then fail */
2074 if ( (user.uid != 0)
2075 && !user_has_privileges(user.nt_user_token, &se_printop )
2076 && !user_in_list(uidtoname(user.uid), lp_printer_admin(-1), user.groups, user.ngroups) )
2078 return WERR_ACCESS_DENIED;
2081 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2082 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2084 /* check that we have a valid driver name first */
2085 if ((version=get_version_id(arch)) == -1) {
2086 /* this is what NT returns */
2087 return WERR_INVALID_ENVIRONMENT;
2090 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2091 version = q_u->version;
2094 ZERO_STRUCT(info_win2k);
2096 status = get_a_printer_driver(&info, 3, driver, arch, version);
2098 if ( !W_ERROR_IS_OK(status) )
2101 * if the client asked for a specific version,
2102 * or this is something other than Windows NT x86,
2106 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2109 /* try for Win2k driver if "Windows NT x86" */
2112 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2113 status = WERR_UNKNOWN_PRINTER_DRIVER;
2118 if ( printer_driver_in_use(info.info_3) ) {
2119 status = WERR_PRINTER_DRIVER_IN_USE;
2124 * we have a couple of cases to consider.
2125 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2126 * then the delete should fail if **any** files overlap with
2128 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2129 * non-overlapping files
2130 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2131 * is set, the do not delete any files
2132 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2135 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2137 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2139 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2140 /* no idea of the correct error here */
2141 status = WERR_ACCESS_DENIED;
2146 /* also check for W32X86/3 if necessary; maybe we already have? */
2148 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2149 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2152 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2153 /* no idea of the correct error here */
2154 free_a_printer_driver( info_win2k, 3 );
2155 status = WERR_ACCESS_DENIED;
2159 /* if we get to here, we now have 2 driver info structures to remove */
2160 /* remove the Win2k driver first*/
2162 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2163 free_a_printer_driver( info_win2k, 3 );
2165 /* this should not have failed---if it did, report to client */
2167 if ( !W_ERROR_IS_OK(status_win2k) )
2172 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2174 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2177 free_a_printer_driver( info, 3 );
2183 /****************************************************************************
2184 Internal routine for retreiving printerdata
2185 ***************************************************************************/
2187 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2188 const char *key, const char *value, uint32 *type, uint8 **data,
2189 uint32 *needed, uint32 in_size )
2191 REGISTRY_VALUE *val;
2195 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2196 return WERR_BADFILE;
2198 *type = regval_type( val );
2200 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2202 size = regval_size( val );
2204 /* copy the min(in_size, len) */
2207 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2209 /* special case for 0 length values */
2211 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2215 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2224 DEBUG(5,("get_printer_dataex: copy done\n"));
2229 /****************************************************************************
2230 Internal routine for removing printerdata
2231 ***************************************************************************/
2233 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2235 return delete_printer_data( printer->info_2, key, value );
2238 /****************************************************************************
2239 Internal routine for storing printerdata
2240 ***************************************************************************/
2242 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2243 uint32 type, uint8 *data, int real_len )
2245 /* the registry objects enforce uniqueness based on value name */
2247 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2250 /********************************************************************
2251 GetPrinterData on a printer server Handle.
2252 ********************************************************************/
2254 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2258 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2260 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2262 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2268 if (!StrCaseCmp(value, "BeepEnabled")) {
2270 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2272 SIVAL(*data, 0, 0x00);
2277 if (!StrCaseCmp(value, "EventLog")) {
2279 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2281 /* formally was 0x1b */
2282 SIVAL(*data, 0, 0x0);
2287 if (!StrCaseCmp(value, "NetPopup")) {
2289 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2291 SIVAL(*data, 0, 0x00);
2296 if (!StrCaseCmp(value, "MajorVersion")) {
2298 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2301 /* Windows NT 4.0 seems to not allow uploading of drivers
2302 to a server that reports 0x3 as the MajorVersion.
2303 need to investigate more how Win2k gets around this .
2306 if ( RA_WINNT == get_remote_arch() )
2315 if (!StrCaseCmp(value, "MinorVersion")) {
2317 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2325 * uint32 size = 0x114
2327 * uint32 minor = [0|1]
2328 * uint32 build = [2195|2600]
2329 * extra unicode string = e.g. "Service Pack 3"
2331 if (!StrCaseCmp(value, "OSVersion")) {
2335 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2338 SIVAL(*data, 0, *needed); /* size */
2339 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2341 SIVAL(*data, 12, 2195); /* build */
2343 /* leave extra string empty */
2349 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2350 const char *string="C:\\PRINTERS";
2352 *needed = 2*(strlen(string)+1);
2353 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2355 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2357 /* it's done by hand ready to go on the wire */
2358 for (i=0; i<strlen(string); i++) {
2359 (*data)[2*i]=string[i];
2360 (*data)[2*i+1]='\0';
2365 if (!StrCaseCmp(value, "Architecture")) {
2366 const char *string="Windows NT x86";
2368 *needed = 2*(strlen(string)+1);
2369 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2371 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2372 for (i=0; i<strlen(string); i++) {
2373 (*data)[2*i]=string[i];
2374 (*data)[2*i+1]='\0';
2379 if (!StrCaseCmp(value, "DsPresent")) {
2381 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2384 /* only show the publish check box if we are a
2385 memeber of a AD domain */
2387 if ( lp_security() == SEC_ADS )
2388 SIVAL(*data, 0, 0x01);
2390 SIVAL(*data, 0, 0x00);
2396 if (!StrCaseCmp(value, "DNSMachineName")) {
2399 if (!get_mydnsfullname(hostname))
2400 return WERR_BADFILE;
2402 *needed = 2*(strlen(hostname)+1);
2403 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2405 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2406 for (i=0; i<strlen(hostname); i++) {
2407 (*data)[2*i]=hostname[i];
2408 (*data)[2*i+1]='\0';
2414 return WERR_BADFILE;
2417 /********************************************************************
2418 * spoolss_getprinterdata
2419 ********************************************************************/
2421 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2423 POLICY_HND *handle = &q_u->handle;
2424 UNISTR2 *valuename = &q_u->valuename;
2425 uint32 in_size = q_u->size;
2426 uint32 *type = &r_u->type;
2427 uint32 *out_size = &r_u->size;
2428 uint8 **data = &r_u->data;
2429 uint32 *needed = &r_u->needed;
2432 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2433 NT_PRINTER_INFO_LEVEL *printer = NULL;
2437 * Reminder: when it's a string, the length is in BYTES
2438 * even if UNICODE is negociated.
2443 *out_size = in_size;
2445 /* in case of problem, return some default values */
2450 DEBUG(4,("_spoolss_getprinterdata\n"));
2453 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2454 status = WERR_BADFID;
2458 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2460 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2461 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2464 if ( !get_printer_snum(p,handle, &snum) ) {
2465 status = WERR_BADFID;
2469 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2470 if ( !W_ERROR_IS_OK(status) )
2473 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2475 if ( strequal(value, "ChangeId") ) {
2477 *needed = sizeof(uint32);
2478 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2479 status = WERR_NOMEM;
2482 SIVAL( *data, 0, printer->info_2->changeid );
2486 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2489 if (*needed > *out_size)
2490 status = WERR_MORE_DATA;
2493 if ( !W_ERROR_IS_OK(status) )
2495 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2497 /* reply this param doesn't exist */
2500 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2502 free_a_printer( &printer, 2 );
2511 /* cleanup & exit */
2514 free_a_printer( &printer, 2 );
2519 /*********************************************************
2520 Connect to the client machine.
2521 **********************************************************/
2523 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2524 struct in_addr *client_ip, const char *remote_machine)
2527 struct cli_state *the_cli;
2528 struct in_addr rm_addr;
2530 if ( is_zero_ip(*client_ip) ) {
2531 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2532 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2536 if ( ismyip( rm_addr )) {
2537 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2541 rm_addr.s_addr = client_ip->s_addr;
2542 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543 inet_ntoa(*client_ip) ));
2546 /* setup the connection */
2548 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2549 &rm_addr, 0, "IPC$", "IPC",
2553 0, lp_client_signing(), NULL );
2555 if ( !NT_STATUS_IS_OK( ret ) ) {
2556 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2561 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2562 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2563 cli_shutdown(the_cli);
2568 * Ok - we have an anonymous connection to the IPC$ share.
2569 * Now start the NT Domain stuff :-).
2572 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2573 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2574 remote_machine, nt_errstr(ret)));
2575 cli_shutdown(the_cli);
2579 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2581 (*pp_pipe)->cli = the_cli;
2586 /***************************************************************************
2587 Connect to the client.
2588 ****************************************************************************/
2590 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2591 uint32 localprinter, uint32 type,
2592 POLICY_HND *handle, struct in_addr *client_ip)
2597 * If it's the first connection, contact the client
2598 * and connect to the IPC$ share anonymously
2600 if (smb_connections==0) {
2601 fstring unix_printer;
2603 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2605 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2608 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2609 /* Tell the connections db we're now interested in printer
2610 * notify messages. */
2611 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2615 * Tell the specific printing tdb we want messages for this printer
2616 * by registering our PID.
2619 if (!print_notify_register_pid(snum))
2620 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2624 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2627 if (!W_ERROR_IS_OK(result))
2628 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2629 dos_errstr(result)));
2631 return (W_ERROR_IS_OK(result));
2634 /********************************************************************
2636 * ReplyFindFirstPrinterChangeNotifyEx
2638 * before replying OK: status=0 a rpc call is made to the workstation
2639 * asking ReplyOpenPrinter
2641 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2642 * called from api_spoolss_rffpcnex
2643 ********************************************************************/
2645 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2647 POLICY_HND *handle = &q_u->handle;
2648 uint32 flags = q_u->flags;
2649 uint32 options = q_u->options;
2650 UNISTR2 *localmachine = &q_u->localmachine;
2651 uint32 printerlocal = q_u->printerlocal;
2653 SPOOL_NOTIFY_OPTION *option = q_u->option;
2654 struct in_addr client_ip;
2656 /* store the notify value in the printer struct */
2658 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2661 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2665 Printer->notify.flags=flags;
2666 Printer->notify.options=options;
2667 Printer->notify.printerlocal=printerlocal;
2669 if (Printer->notify.option)
2670 free_spool_notify_option(&Printer->notify.option);
2672 Printer->notify.option=dup_spool_notify_option(option);
2674 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2675 sizeof(Printer->notify.localmachine)-1);
2677 /* Connect to the client machine and send a ReplyOpenPrinter */
2679 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2681 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2682 !get_printer_snum(p, handle, &snum) )
2685 client_ip.s_addr = inet_addr(p->conn->client_address);
2687 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2688 Printer->notify.printerlocal, 1,
2689 &Printer->notify.client_hnd, &client_ip))
2690 return WERR_SERVER_UNAVAILABLE;
2692 Printer->notify.client_connected=True;
2697 /*******************************************************************
2698 * fill a notify_info_data with the servername
2699 ********************************************************************/
2701 void spoolss_notify_server_name(int snum,
2702 SPOOL_NOTIFY_INFO_DATA *data,
2703 print_queue_struct *queue,
2704 NT_PRINTER_INFO_LEVEL *printer,
2705 TALLOC_CTX *mem_ctx)
2710 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2712 data->notify_data.data.length = len;
2713 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2715 if (!data->notify_data.data.string) {
2716 data->notify_data.data.length = 0;
2720 memcpy(data->notify_data.data.string, temp, len);
2723 /*******************************************************************
2724 * fill a notify_info_data with the printername (not including the servername).
2725 ********************************************************************/
2727 void spoolss_notify_printer_name(int snum,
2728 SPOOL_NOTIFY_INFO_DATA *data,
2729 print_queue_struct *queue,
2730 NT_PRINTER_INFO_LEVEL *printer,
2731 TALLOC_CTX *mem_ctx)
2736 /* the notify name should not contain the \\server\ part */
2737 char *p = strrchr(printer->info_2->printername, '\\');
2740 p = printer->info_2->printername;
2745 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2747 data->notify_data.data.length = len;
2748 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2750 if (!data->notify_data.data.string) {
2751 data->notify_data.data.length = 0;
2755 memcpy(data->notify_data.data.string, temp, len);
2758 /*******************************************************************
2759 * fill a notify_info_data with the servicename
2760 ********************************************************************/
2762 void spoolss_notify_share_name(int snum,
2763 SPOOL_NOTIFY_INFO_DATA *data,
2764 print_queue_struct *queue,
2765 NT_PRINTER_INFO_LEVEL *printer,
2766 TALLOC_CTX *mem_ctx)
2771 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2773 data->notify_data.data.length = len;
2774 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2776 if (!data->notify_data.data.string) {
2777 data->notify_data.data.length = 0;
2781 memcpy(data->notify_data.data.string, temp, len);
2784 /*******************************************************************
2785 * fill a notify_info_data with the port name
2786 ********************************************************************/
2788 void spoolss_notify_port_name(int snum,
2789 SPOOL_NOTIFY_INFO_DATA *data,
2790 print_queue_struct *queue,
2791 NT_PRINTER_INFO_LEVEL *printer,
2792 TALLOC_CTX *mem_ctx)
2797 /* even if it's strange, that's consistant in all the code */
2799 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2801 data->notify_data.data.length = len;
2802 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2804 if (!data->notify_data.data.string) {
2805 data->notify_data.data.length = 0;
2809 memcpy(data->notify_data.data.string, temp, len);
2812 /*******************************************************************
2813 * fill a notify_info_data with the printername
2814 * but it doesn't exist, have to see what to do
2815 ********************************************************************/
2817 void spoolss_notify_driver_name(int snum,
2818 SPOOL_NOTIFY_INFO_DATA *data,
2819 print_queue_struct *queue,
2820 NT_PRINTER_INFO_LEVEL *printer,
2821 TALLOC_CTX *mem_ctx)
2826 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2828 data->notify_data.data.length = len;
2829 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2831 if (!data->notify_data.data.string) {
2832 data->notify_data.data.length = 0;
2836 memcpy(data->notify_data.data.string, temp, len);
2839 /*******************************************************************
2840 * fill a notify_info_data with the comment
2841 ********************************************************************/
2843 void spoolss_notify_comment(int snum,
2844 SPOOL_NOTIFY_INFO_DATA *data,
2845 print_queue_struct *queue,
2846 NT_PRINTER_INFO_LEVEL *printer,
2847 TALLOC_CTX *mem_ctx)
2852 if (*printer->info_2->comment == '\0')
2853 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2855 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2857 data->notify_data.data.length = len;
2858 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2860 if (!data->notify_data.data.string) {
2861 data->notify_data.data.length = 0;
2865 memcpy(data->notify_data.data.string, temp, len);
2868 /*******************************************************************
2869 * fill a notify_info_data with the comment
2870 * location = "Room 1, floor 2, building 3"
2871 ********************************************************************/
2873 void spoolss_notify_location(int snum,
2874 SPOOL_NOTIFY_INFO_DATA *data,
2875 print_queue_struct *queue,
2876 NT_PRINTER_INFO_LEVEL *printer,
2877 TALLOC_CTX *mem_ctx)
2882 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2884 data->notify_data.data.length = len;
2885 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2887 if (!data->notify_data.data.string) {
2888 data->notify_data.data.length = 0;
2892 memcpy(data->notify_data.data.string, temp, len);
2895 /*******************************************************************
2896 * fill a notify_info_data with the device mode
2897 * jfm:xxxx don't to it for know but that's a real problem !!!
2898 ********************************************************************/
2900 static void spoolss_notify_devmode(int snum,
2901 SPOOL_NOTIFY_INFO_DATA *data,
2902 print_queue_struct *queue,
2903 NT_PRINTER_INFO_LEVEL *printer,
2904 TALLOC_CTX *mem_ctx)
2908 /*******************************************************************
2909 * fill a notify_info_data with the separator file name
2910 ********************************************************************/
2912 void spoolss_notify_sepfile(int snum,
2913 SPOOL_NOTIFY_INFO_DATA *data,
2914 print_queue_struct *queue,
2915 NT_PRINTER_INFO_LEVEL *printer,
2916 TALLOC_CTX *mem_ctx)
2921 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2923 data->notify_data.data.length = len;
2924 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2926 if (!data->notify_data.data.string) {
2927 data->notify_data.data.length = 0;
2931 memcpy(data->notify_data.data.string, temp, len);
2934 /*******************************************************************
2935 * fill a notify_info_data with the print processor
2936 * jfm:xxxx return always winprint to indicate we don't do anything to it
2937 ********************************************************************/
2939 void spoolss_notify_print_processor(int snum,
2940 SPOOL_NOTIFY_INFO_DATA *data,
2941 print_queue_struct *queue,
2942 NT_PRINTER_INFO_LEVEL *printer,
2943 TALLOC_CTX *mem_ctx)
2948 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2950 data->notify_data.data.length = len;
2951 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2953 if (!data->notify_data.data.string) {
2954 data->notify_data.data.length = 0;
2958 memcpy(data->notify_data.data.string, temp, len);
2961 /*******************************************************************
2962 * fill a notify_info_data with the print processor options
2963 * jfm:xxxx send an empty string
2964 ********************************************************************/
2966 void spoolss_notify_parameters(int snum,
2967 SPOOL_NOTIFY_INFO_DATA *data,
2968 print_queue_struct *queue,
2969 NT_PRINTER_INFO_LEVEL *printer,
2970 TALLOC_CTX *mem_ctx)
2975 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2977 data->notify_data.data.length = len;
2978 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2980 if (!data->notify_data.data.string) {
2981 data->notify_data.data.length = 0;
2985 memcpy(data->notify_data.data.string, temp, len);
2988 /*******************************************************************
2989 * fill a notify_info_data with the data type
2990 * jfm:xxxx always send RAW as data type
2991 ********************************************************************/
2993 void spoolss_notify_datatype(int snum,
2994 SPOOL_NOTIFY_INFO_DATA *data,
2995 print_queue_struct *queue,
2996 NT_PRINTER_INFO_LEVEL *printer,
2997 TALLOC_CTX *mem_ctx)
3002 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3004 data->notify_data.data.length = len;
3005 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3007 if (!data->notify_data.data.string) {
3008 data->notify_data.data.length = 0;
3012 memcpy(data->notify_data.data.string, temp, len);
3015 /*******************************************************************
3016 * fill a notify_info_data with the security descriptor
3017 * jfm:xxxx send an null pointer to say no security desc
3018 * have to implement security before !
3019 ********************************************************************/
3021 static void spoolss_notify_security_desc(int snum,
3022 SPOOL_NOTIFY_INFO_DATA *data,
3023 print_queue_struct *queue,
3024 NT_PRINTER_INFO_LEVEL *printer,
3025 TALLOC_CTX *mem_ctx)
3027 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3028 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3031 /*******************************************************************
3032 * fill a notify_info_data with the attributes
3033 * jfm:xxxx a samba printer is always shared
3034 ********************************************************************/
3036 void spoolss_notify_attributes(int snum,
3037 SPOOL_NOTIFY_INFO_DATA *data,
3038 print_queue_struct *queue,
3039 NT_PRINTER_INFO_LEVEL *printer,
3040 TALLOC_CTX *mem_ctx)
3042 data->notify_data.value[0] = printer->info_2->attributes;
3043 data->notify_data.value[1] = 0;
3046 /*******************************************************************
3047 * fill a notify_info_data with the priority
3048 ********************************************************************/
3050 static void spoolss_notify_priority(int snum,
3051 SPOOL_NOTIFY_INFO_DATA *data,
3052 print_queue_struct *queue,
3053 NT_PRINTER_INFO_LEVEL *printer,
3054 TALLOC_CTX *mem_ctx)
3056 data->notify_data.value[0] = printer->info_2->priority;
3057 data->notify_data.value[1] = 0;
3060 /*******************************************************************
3061 * fill a notify_info_data with the default priority
3062 ********************************************************************/
3064 static void spoolss_notify_default_priority(int snum,
3065 SPOOL_NOTIFY_INFO_DATA *data,
3066 print_queue_struct *queue,
3067 NT_PRINTER_INFO_LEVEL *printer,
3068 TALLOC_CTX *mem_ctx)
3070 data->notify_data.value[0] = printer->info_2->default_priority;
3071 data->notify_data.value[1] = 0;
3074 /*******************************************************************
3075 * fill a notify_info_data with the start time
3076 ********************************************************************/
3078 static void spoolss_notify_start_time(int snum,
3079 SPOOL_NOTIFY_INFO_DATA *data,
3080 print_queue_struct *queue,
3081 NT_PRINTER_INFO_LEVEL *printer,
3082 TALLOC_CTX *mem_ctx)
3084 data->notify_data.value[0] = printer->info_2->starttime;
3085 data->notify_data.value[1] = 0;
3088 /*******************************************************************
3089 * fill a notify_info_data with the until time
3090 ********************************************************************/
3092 static void spoolss_notify_until_time(int snum,
3093 SPOOL_NOTIFY_INFO_DATA *data,
3094 print_queue_struct *queue,
3095 NT_PRINTER_INFO_LEVEL *printer,
3096 TALLOC_CTX *mem_ctx)
3098 data->notify_data.value[0] = printer->info_2->untiltime;
3099 data->notify_data.value[1] = 0;
3102 /*******************************************************************
3103 * fill a notify_info_data with the status
3104 ********************************************************************/
3106 static void spoolss_notify_status(int snum,
3107 SPOOL_NOTIFY_INFO_DATA *data,
3108 print_queue_struct *queue,
3109 NT_PRINTER_INFO_LEVEL *printer,
3110 TALLOC_CTX *mem_ctx)
3112 print_status_struct status;
3114 print_queue_length(snum, &status);
3115 data->notify_data.value[0]=(uint32) status.status;
3116 data->notify_data.value[1] = 0;
3119 /*******************************************************************
3120 * fill a notify_info_data with the number of jobs queued
3121 ********************************************************************/
3123 void spoolss_notify_cjobs(int snum,
3124 SPOOL_NOTIFY_INFO_DATA *data,
3125 print_queue_struct *queue,
3126 NT_PRINTER_INFO_LEVEL *printer,
3127 TALLOC_CTX *mem_ctx)
3129 data->notify_data.value[0] = print_queue_length(snum, NULL);
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with the average ppm
3135 ********************************************************************/
3137 static void spoolss_notify_average_ppm(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3143 /* always respond 8 pages per minutes */
3144 /* a little hard ! */
3145 data->notify_data.value[0] = printer->info_2->averageppm;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with username
3151 ********************************************************************/
3153 static void spoolss_notify_username(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3162 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3164 data->notify_data.data.length = len;
3165 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3167 if (!data->notify_data.data.string) {
3168 data->notify_data.data.length = 0;
3172 memcpy(data->notify_data.data.string, temp, len);
3175 /*******************************************************************
3176 * fill a notify_info_data with job status
3177 ********************************************************************/
3179 static void spoolss_notify_job_status(int snum,
3180 SPOOL_NOTIFY_INFO_DATA *data,
3181 print_queue_struct *queue,
3182 NT_PRINTER_INFO_LEVEL *printer,
3183 TALLOC_CTX *mem_ctx)
3185 data->notify_data.value[0]=nt_printj_status(queue->status);
3186 data->notify_data.value[1] = 0;
3189 /*******************************************************************
3190 * fill a notify_info_data with job name
3191 ********************************************************************/
3193 static void spoolss_notify_job_name(int snum,
3194 SPOOL_NOTIFY_INFO_DATA *data,
3195 print_queue_struct *queue,
3196 NT_PRINTER_INFO_LEVEL *printer,
3197 TALLOC_CTX *mem_ctx)
3202 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3204 data->notify_data.data.length = len;
3205 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3207 if (!data->notify_data.data.string) {
3208 data->notify_data.data.length = 0;
3212 memcpy(data->notify_data.data.string, temp, len);
3215 /*******************************************************************
3216 * fill a notify_info_data with job status
3217 ********************************************************************/
3219 static void spoolss_notify_job_status_string(int snum,
3220 SPOOL_NOTIFY_INFO_DATA *data,
3221 print_queue_struct *queue,
3222 NT_PRINTER_INFO_LEVEL *printer,
3223 TALLOC_CTX *mem_ctx)
3226 * Now we're returning job status codes we just return a "" here. JRA.
3233 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3236 switch (queue->status) {
3241 p = ""; /* NT provides the paused string */
3250 #endif /* NO LONGER NEEDED. */
3252 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3254 data->notify_data.data.length = len;
3255 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3257 if (!data->notify_data.data.string) {
3258 data->notify_data.data.length = 0;
3262 memcpy(data->notify_data.data.string, temp, len);
3265 /*******************************************************************
3266 * fill a notify_info_data with job time
3267 ********************************************************************/
3269 static void spoolss_notify_job_time(int snum,
3270 SPOOL_NOTIFY_INFO_DATA *data,
3271 print_queue_struct *queue,
3272 NT_PRINTER_INFO_LEVEL *printer,
3273 TALLOC_CTX *mem_ctx)
3275 data->notify_data.value[0]=0x0;
3276 data->notify_data.value[1]=0;
3279 /*******************************************************************
3280 * fill a notify_info_data with job size
3281 ********************************************************************/
3283 static void spoolss_notify_job_size(int snum,
3284 SPOOL_NOTIFY_INFO_DATA *data,
3285 print_queue_struct *queue,
3286 NT_PRINTER_INFO_LEVEL *printer,
3287 TALLOC_CTX *mem_ctx)
3289 data->notify_data.value[0]=queue->size;
3290 data->notify_data.value[1]=0;
3293 /*******************************************************************
3294 * fill a notify_info_data with page info
3295 ********************************************************************/
3296 static void spoolss_notify_total_pages(int snum,
3297 SPOOL_NOTIFY_INFO_DATA *data,
3298 print_queue_struct *queue,
3299 NT_PRINTER_INFO_LEVEL *printer,
3300 TALLOC_CTX *mem_ctx)
3302 data->notify_data.value[0]=queue->page_count;
3303 data->notify_data.value[1]=0;
3306 /*******************************************************************
3307 * fill a notify_info_data with pages printed info.
3308 ********************************************************************/
3309 static void spoolss_notify_pages_printed(int snum,
3310 SPOOL_NOTIFY_INFO_DATA *data,
3311 print_queue_struct *queue,
3312 NT_PRINTER_INFO_LEVEL *printer,
3313 TALLOC_CTX *mem_ctx)
3315 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3316 data->notify_data.value[1]=0;
3319 /*******************************************************************
3320 Fill a notify_info_data with job position.
3321 ********************************************************************/
3323 static void spoolss_notify_job_position(int snum,
3324 SPOOL_NOTIFY_INFO_DATA *data,
3325 print_queue_struct *queue,
3326 NT_PRINTER_INFO_LEVEL *printer,
3327 TALLOC_CTX *mem_ctx)
3329 data->notify_data.value[0]=queue->job;
3330 data->notify_data.value[1]=0;
3333 /*******************************************************************
3334 Fill a notify_info_data with submitted time.
3335 ********************************************************************/
3337 static void spoolss_notify_submitted_time(int snum,
3338 SPOOL_NOTIFY_INFO_DATA *data,
3339 print_queue_struct *queue,
3340 NT_PRINTER_INFO_LEVEL *printer,
3341 TALLOC_CTX *mem_ctx)
3348 t=gmtime(&queue->time);
3350 len = sizeof(SYSTEMTIME);
3352 data->notify_data.data.length = len;
3353 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3355 if (!data->notify_data.data.string) {
3356 data->notify_data.data.length = 0;
3360 make_systemtime(&st, t);
3363 * Systemtime must be linearized as a set of UINT16's.
3364 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3367 p = (char *)data->notify_data.data.string;
3368 SSVAL(p, 0, st.year);
3369 SSVAL(p, 2, st.month);
3370 SSVAL(p, 4, st.dayofweek);
3371 SSVAL(p, 6, st.day);
3372 SSVAL(p, 8, st.hour);
3373 SSVAL(p, 10, st.minute);
3374 SSVAL(p, 12, st.second);
3375 SSVAL(p, 14, st.milliseconds);
3378 struct s_notify_info_data_table
3384 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3385 print_queue_struct *queue,
3386 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3389 /* A table describing the various print notification constants and
3390 whether the notification data is a pointer to a variable sized
3391 buffer, a one value uint32 or a two value uint32. */
3393 static const struct s_notify_info_data_table notify_info_data_table[] =
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3405 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3406 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3407 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3408 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3409 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3410 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3411 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3412 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3413 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3414 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3415 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3416 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3417 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3418 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3419 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3420 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3428 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3429 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3430 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3431 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3432 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3433 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3434 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3435 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3436 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3437 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3438 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3439 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3440 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3441 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3442 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3443 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3444 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3447 /*******************************************************************
3448 Return the size of info_data structure.
3449 ********************************************************************/
3451 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3455 for (i = 0; i < sizeof(notify_info_data_table); i++)
3457 if ( (notify_info_data_table[i].type == type)
3458 && (notify_info_data_table[i].field == field) )
3460 switch(notify_info_data_table[i].size)
3462 case NOTIFY_ONE_VALUE:
3463 case NOTIFY_TWO_VALUE:
3468 /* The only pointer notify data I have seen on
3469 the wire is the submitted time and this has
3470 the notify size set to 4. -tpot */
3472 case NOTIFY_POINTER:
3475 case NOTIFY_SECDESC:
3481 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3486 /*******************************************************************
3487 Return the type of notify_info_data.
3488 ********************************************************************/
3490 static int type_of_notify_info_data(uint16 type, uint16 field)
3494 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3495 if (notify_info_data_table[i].type == type &&
3496 notify_info_data_table[i].field == field)
3497 return notify_info_data_table[i].size;
3503 /****************************************************************************
3504 ****************************************************************************/
3506 static int search_notify(uint16 type, uint16 field, int *value)
3510 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3511 if (notify_info_data_table[i].type == type &&
3512 notify_info_data_table[i].field == field &&
3513 notify_info_data_table[i].fn != NULL) {
3522 /****************************************************************************
3523 ****************************************************************************/
3525 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3527 info_data->type = type;
3528 info_data->field = field;
3529 info_data->reserved = 0;
3531 info_data->size = size_of_notify_info_data(type, field);
3532 info_data->enc_type = type_of_notify_info_data(type, field);
3539 /*******************************************************************
3541 * fill a notify_info struct with info asked
3543 ********************************************************************/
3545 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3546 snum, SPOOL_NOTIFY_OPTION_TYPE
3547 *option_type, uint32 id,
3548 TALLOC_CTX *mem_ctx)
3554 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3555 NT_PRINTER_INFO_LEVEL *printer = NULL;
3556 print_queue_struct *queue=NULL;
3558 type=option_type->type;
3560 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3561 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3562 option_type->count, lp_servicename(snum)));
3564 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3567 for(field_num=0; field_num<option_type->count; field_num++) {
3568 field = option_type->fields[field_num];
3570 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3572 if (!search_notify(type, field, &j) )
3575 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3576 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3581 current_data = &info->data[info->count];
3583 construct_info_data(current_data, type, field, id);
3585 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3586 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3588 notify_info_data_table[j].fn(snum, current_data, queue,
3594 free_a_printer(&printer, 2);
3598 /*******************************************************************
3600 * fill a notify_info struct with info asked
3602 ********************************************************************/
3604 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3605 SPOOL_NOTIFY_INFO *info,
3606 NT_PRINTER_INFO_LEVEL *printer,
3607 int snum, SPOOL_NOTIFY_OPTION_TYPE
3608 *option_type, uint32 id,
3609 TALLOC_CTX *mem_ctx)
3615 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3617 DEBUG(4,("construct_notify_jobs_info\n"));
3619 type = option_type->type;
3621 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3622 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3623 option_type->count));
3625 for(field_num=0; field_num<option_type->count; field_num++) {
3626 field = option_type->fields[field_num];
3628 if (!search_notify(type, field, &j) )
3631 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3632 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3635 else info->data = tid;
3637 current_data=&(info->data[info->count]);
3639 construct_info_data(current_data, type, field, id);
3640 notify_info_data_table[j].fn(snum, current_data, queue,
3649 * JFM: The enumeration is not that simple, it's even non obvious.
3651 * let's take an example: I want to monitor the PRINTER SERVER for
3652 * the printer's name and the number of jobs currently queued.
3653 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3654 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3656 * I have 3 printers on the back of my server.
3658 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3661 * 1 printer 1 name 1
3662 * 2 printer 1 cjob 1
3663 * 3 printer 2 name 2
3664 * 4 printer 2 cjob 2
3665 * 5 printer 3 name 3
3666 * 6 printer 3 name 3
3668 * that's the print server case, the printer case is even worse.
3671 /*******************************************************************
3673 * enumerate all printers on the printserver
3674 * fill a notify_info struct with info asked
3676 ********************************************************************/
3678 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3679 SPOOL_NOTIFY_INFO *info,
3680 TALLOC_CTX *mem_ctx)
3683 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3684 int n_services=lp_numservices();
3686 SPOOL_NOTIFY_OPTION *option;
3687 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3689 DEBUG(4,("printserver_notify_info\n"));
3694 option=Printer->notify.option;
3699 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3700 sending a ffpcn() request first */
3705 for (i=0; i<option->count; i++) {
3706 option_type=&(option->ctr.type[i]);
3708 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3711 for (snum=0; snum<n_services; snum++)
3713 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3714 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3720 * Debugging information, don't delete.
3723 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3724 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3725 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3727 for (i=0; i<info->count; i++) {
3728 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3729 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3730 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3737 /*******************************************************************
3739 * fill a notify_info struct with info asked
3741 ********************************************************************/
3743 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3744 TALLOC_CTX *mem_ctx)
3747 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3750 SPOOL_NOTIFY_OPTION *option;
3751 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3753 print_queue_struct *queue=NULL;
3754 print_status_struct status;
3756 DEBUG(4,("printer_notify_info\n"));
3761 option=Printer->notify.option;
3767 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3768 sending a ffpcn() request first */
3773 get_printer_snum(p, hnd, &snum);
3775 for (i=0; i<option->count; i++) {
3776 option_type=&option->ctr.type[i];
3778 switch ( option_type->type ) {
3779 case PRINTER_NOTIFY_TYPE:
3780 if(construct_notify_printer_info(Printer, info, snum,
3786 case JOB_NOTIFY_TYPE: {
3787 NT_PRINTER_INFO_LEVEL *printer = NULL;
3789 count = print_queue_status(snum, &queue, &status);
3791 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3794 for (j=0; j<count; j++) {
3795 construct_notify_jobs_info(&queue[j], info,
3802 free_a_printer(&printer, 2);
3812 * Debugging information, don't delete.
3815 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3816 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3817 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3819 for (i=0; i<info->count; i++) {
3820 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3821 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3822 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3828 /********************************************************************
3830 ********************************************************************/
3832 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3834 POLICY_HND *handle = &q_u->handle;
3835 SPOOL_NOTIFY_INFO *info = &r_u->info;
3837 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3838 WERROR result = WERR_BADFID;
3840 /* we always have a NOTIFY_INFO struct */
3844 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3845 OUR_HANDLE(handle)));
3849 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3852 * We are now using the change value, and
3853 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3854 * I don't have a global notification system, I'm sending back all the
3855 * informations even when _NOTHING_ has changed.
3858 /* We need to keep track of the change value to send back in
3859 RRPCN replies otherwise our updates are ignored. */
3861 Printer->notify.fnpcn = True;
3863 if (Printer->notify.client_connected) {
3864 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3865 Printer->notify.change = q_u->change;
3868 /* just ignore the SPOOL_NOTIFY_OPTION */
3870 switch (Printer->printer_type) {
3871 case PRINTER_HANDLE_IS_PRINTSERVER:
3872 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3875 case PRINTER_HANDLE_IS_PRINTER:
3876 result = printer_notify_info(p, handle, info, p->mem_ctx);
3880 Printer->notify.fnpcn = False;
3886 /********************************************************************
3887 * construct_printer_info_0
3888 * fill a printer_info_0 struct
3889 ********************************************************************/
3891 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3895 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3896 counter_printer_0 *session_counter;
3897 uint32 global_counter;
3900 print_status_struct status;
3902 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3905 count = print_queue_length(snum, &status);
3907 /* check if we already have a counter for this printer */
3908 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3909 if (session_counter->snum == snum)
3913 /* it's the first time, add it to the list */
3914 if (session_counter==NULL) {
3915 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3916 free_a_printer(&ntprinter, 2);
3919 ZERO_STRUCTP(session_counter);
3920 session_counter->snum=snum;
3921 session_counter->counter=0;
3922 DLIST_ADD(counter_list, session_counter);
3926 session_counter->counter++;
3929 * the global_counter should be stored in a TDB as it's common to all the clients
3930 * and should be zeroed on samba startup
3932 global_counter=session_counter->counter;
3934 pstrcpy(chaine,ntprinter->info_2->printername);
3936 init_unistr(&printer->printername, chaine);
3938 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3939 init_unistr(&printer->servername, chaine);
3941 printer->cjobs = count;
3942 printer->total_jobs = 0;
3943 printer->total_bytes = 0;
3945 setuptime = (time_t)ntprinter->info_2->setuptime;
3946 t=gmtime(&setuptime);
3948 printer->year = t->tm_year+1900;
3949 printer->month = t->tm_mon+1;
3950 printer->dayofweek = t->tm_wday;
3951 printer->day = t->tm_mday;
3952 printer->hour = t->tm_hour;
3953 printer->minute = t->tm_min;
3954 printer->second = t->tm_sec;
3955 printer->milliseconds = 0;
3957 printer->global_counter = global_counter;
3958 printer->total_pages = 0;
3960 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3961 printer->major_version = 0x0005; /* NT 5 */
3962 printer->build_version = 0x0893; /* build 2195 */
3964 printer->unknown7 = 0x1;
3965 printer->unknown8 = 0x0;
3966 printer->unknown9 = 0x0;
3967 printer->session_counter = session_counter->counter;
3968 printer->unknown11 = 0x0;
3969 printer->printer_errors = 0x0; /* number of print failure */
3970 printer->unknown13 = 0x0;
3971 printer->unknown14 = 0x1;
3972 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3973 printer->unknown16 = 0x0;
3974 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3975 printer->unknown18 = 0x0;
3976 printer->status = nt_printq_status(status.status);
3977 printer->unknown20 = 0x0;
3978 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3979 printer->unknown22 = 0x0;
3980 printer->unknown23 = 0x6; /* 6 ???*/
3981 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3982 printer->unknown25 = 0;
3983 printer->unknown26 = 0;
3984 printer->unknown27 = 0;
3985 printer->unknown28 = 0;
3986 printer->unknown29 = 0;
3988 free_a_printer(&ntprinter,2);
3992 /********************************************************************
3993 * construct_printer_info_1
3994 * fill a printer_info_1 struct
3995 ********************************************************************/
3996 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4000 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4002 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4005 printer->flags=flags;
4007 if (*ntprinter->info_2->comment == '\0') {
4008 init_unistr(&printer->comment, lp_comment(snum));
4009 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4010 ntprinter->info_2->drivername, lp_comment(snum));
4013 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4014 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4015 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4018 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4020 init_unistr(&printer->description, chaine);
4021 init_unistr(&printer->name, chaine2);
4023 free_a_printer(&ntprinter,2);
4028 /****************************************************************************
4029 Free a DEVMODE struct.
4030 ****************************************************************************/
4032 static void free_dev_mode(DEVICEMODE *dev)
4037 SAFE_FREE(dev->dev_private);
4042 /****************************************************************************
4043 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4044 should be valid upon entry
4045 ****************************************************************************/
4047 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4049 if ( !devmode || !ntdevmode )
4052 init_unistr(&devmode->devicename, ntdevmode->devicename);
4054 init_unistr(&devmode->formname, ntdevmode->formname);
4056 devmode->specversion = ntdevmode->specversion;
4057 devmode->driverversion = ntdevmode->driverversion;
4058 devmode->size = ntdevmode->size;
4059 devmode->driverextra = ntdevmode->driverextra;
4060 devmode->fields = ntdevmode->fields;
4062 devmode->orientation = ntdevmode->orientation;
4063 devmode->papersize = ntdevmode->papersize;
4064 devmode->paperlength = ntdevmode->paperlength;
4065 devmode->paperwidth = ntdevmode->paperwidth;
4066 devmode->scale = ntdevmode->scale;
4067 devmode->copies = ntdevmode->copies;
4068 devmode->defaultsource = ntdevmode->defaultsource;
4069 devmode->printquality = ntdevmode->printquality;
4070 devmode->color = ntdevmode->color;
4071 devmode->duplex = ntdevmode->duplex;
4072 devmode->yresolution = ntdevmode->yresolution;
4073 devmode->ttoption = ntdevmode->ttoption;
4074 devmode->collate = ntdevmode->collate;
4075 devmode->icmmethod = ntdevmode->icmmethod;
4076 devmode->icmintent = ntdevmode->icmintent;
4077 devmode->mediatype = ntdevmode->mediatype;
4078 devmode->dithertype = ntdevmode->dithertype;
4080 if (ntdevmode->nt_dev_private != NULL) {
4081 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4088 /****************************************************************************
4089 Create a DEVMODE struct. Returns malloced memory.
4090 ****************************************************************************/
4092 DEVICEMODE *construct_dev_mode(int snum)
4094 NT_PRINTER_INFO_LEVEL *printer = NULL;
4095 DEVICEMODE *devmode = NULL;
4097 DEBUG(7,("construct_dev_mode\n"));
4099 DEBUGADD(8,("getting printer characteristics\n"));
4101 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4104 if ( !printer->info_2->devmode ) {
4105 DEBUG(5, ("BONG! There was no device mode!\n"));
4109 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4110 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4114 ZERO_STRUCTP(devmode);
4116 DEBUGADD(8,("loading DEVICEMODE\n"));
4118 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4119 free_dev_mode( devmode );
4124 free_a_printer(&printer,2);
4129 /********************************************************************
4130 * construct_printer_info_2
4131 * fill a printer_info_2 struct
4132 ********************************************************************/
4134 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4137 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4139 print_status_struct status;
4141 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4144 count = print_queue_length(snum, &status);
4146 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4147 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4148 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4149 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4150 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4152 if (*ntprinter->info_2->comment == '\0')
4153 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4155 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4157 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4158 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4159 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4160 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4161 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4163 printer->attributes = ntprinter->info_2->attributes;
4165 printer->priority = ntprinter->info_2->priority; /* priority */
4166 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4167 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4168 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4169 printer->status = nt_printq_status(status.status); /* status */
4170 printer->cjobs = count; /* jobs */
4171 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4173 if ( !(printer->devmode = construct_dev_mode(snum)) )
4174 DEBUG(8, ("Returning NULL Devicemode!\n"));
4176 printer->secdesc = NULL;
4178 if ( ntprinter->info_2->secdesc_buf
4179 && ntprinter->info_2->secdesc_buf->len != 0 )
4181 /* don't use talloc_steal() here unless you do a deep steal of all
4182 the SEC_DESC members */
4184 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4185 ntprinter->info_2->secdesc_buf->sec );
4188 free_a_printer(&ntprinter, 2);
4193 /********************************************************************
4194 * construct_printer_info_3
4195 * fill a printer_info_3 struct
4196 ********************************************************************/
4198 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4200 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4201 PRINTER_INFO_3 *printer = NULL;
4203 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4207 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4208 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4212 ZERO_STRUCTP(printer);
4214 /* These are the components of the SD we are returning. */
4216 printer->flags = 0x4;
4218 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4219 /* don't use talloc_steal() here unless you do a deep steal of all
4220 the SEC_DESC members */
4222 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4223 ntprinter->info_2->secdesc_buf->sec );
4226 free_a_printer(&ntprinter, 2);
4228 *pp_printer = printer;
4232 /********************************************************************
4233 * construct_printer_info_4
4234 * fill a printer_info_4 struct
4235 ********************************************************************/
4237 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4239 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4241 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4244 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4245 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4246 printer->attributes = ntprinter->info_2->attributes;
4248 free_a_printer(&ntprinter, 2);
4252 /********************************************************************
4253 * construct_printer_info_5
4254 * fill a printer_info_5 struct
4255 ********************************************************************/
4257 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4259 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4261 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4264 init_unistr(&printer->printername, ntprinter->info_2->printername);
4265 init_unistr(&printer->portname, ntprinter->info_2->portname);
4266 printer->attributes = ntprinter->info_2->attributes;
4268 /* these two are not used by NT+ according to MSDN */
4270 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4271 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4273 free_a_printer(&ntprinter, 2);
4278 /********************************************************************
4279 * construct_printer_info_7
4280 * fill a printer_info_7 struct
4281 ********************************************************************/
4283 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4285 char *guid_str = NULL;
4288 if (is_printer_published(print_hnd, snum, &guid)) {
4289 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4290 strupper_m(guid_str);
4291 init_unistr(&printer->guid, guid_str);
4292 printer->action = SPOOL_DS_PUBLISH;
4294 init_unistr(&printer->guid, "");
4295 printer->action = SPOOL_DS_UNPUBLISH;
4301 /********************************************************************
4302 Spoolss_enumprinters.
4303 ********************************************************************/
4305 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4309 int n_services=lp_numservices();
4310 PRINTER_INFO_1 *tp, *printers=NULL;
4311 PRINTER_INFO_1 current_prt;
4312 WERROR result = WERR_OK;
4314 DEBUG(4,("enum_all_printers_info_1\n"));
4316 for (snum=0; snum<n_services; snum++) {
4317 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4318 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4320 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4321 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4322 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4323 SAFE_FREE(printers);
4328 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4330 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4336 /* check the required size. */
4337 for (i=0; i<*returned; i++)
4338 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4340 if (*needed > offered) {
4341 result = WERR_INSUFFICIENT_BUFFER;
4345 if (!rpcbuf_alloc_size(buffer, *needed)) {
4346 result = WERR_NOMEM;
4350 /* fill the buffer with the structures */
4351 for (i=0; i<*returned; i++)
4352 smb_io_printer_info_1("", buffer, &printers[i], 0);
4357 SAFE_FREE(printers);
4359 if ( !W_ERROR_IS_OK(result) )
4365 /********************************************************************
4366 enum_all_printers_info_1_local.
4367 *********************************************************************/
4369 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4371 DEBUG(4,("enum_all_printers_info_1_local\n"));
4373 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4376 /********************************************************************
4377 enum_all_printers_info_1_name.
4378 *********************************************************************/
4380 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4384 DEBUG(4,("enum_all_printers_info_1_name\n"));
4386 if ((name[0] == '\\') && (name[1] == '\\'))
4389 if (is_myname_or_ipaddr(s)) {
4390 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4393 return WERR_INVALID_NAME;
4396 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4397 /********************************************************************
4398 enum_all_printers_info_1_remote.
4399 *********************************************************************/
4401 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4403 PRINTER_INFO_1 *printer;
4404 fstring printername;
4407 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4408 WERROR result = WERR_OK;
4410 /* JFM: currently it's more a place holder than anything else.
4411 * In the spooler world there is a notion of server registration.
4412 * the print servers are registered on the PDC (in the same domain)
4414 * We should have a TDB here. The registration is done thru an
4415 * undocumented RPC call.
4418 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4423 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4424 slprintf(desc, sizeof(desc)-1,"%s", name);
4425 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4427 init_unistr(&printer->description, desc);
4428 init_unistr(&printer->name, printername);
4429 init_unistr(&printer->comment, comment);
4430 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4432 /* check the required size. */
4433 *needed += spoolss_size_printer_info_1(printer);
4435 if (*needed > offered) {
4436 result = WERR_INSUFFICIENT_BUFFER;
4440 if (!rpcbuf_alloc_size(buffer, *needed)) {
4441 result = WERR_NOMEM;
4445 /* fill the buffer with the structures */
4446 smb_io_printer_info_1("", buffer, printer, 0);
4452 if ( !W_ERROR_IS_OK(result) )
4460 /********************************************************************
4461 enum_all_printers_info_1_network.
4462 *********************************************************************/
4464 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4468 DEBUG(4,("enum_all_printers_info_1_network\n"));
4470 /* If we respond to a enum_printers level 1 on our name with flags
4471 set to PRINTER_ENUM_REMOTE with a list of printers then these
4472 printers incorrectly appear in the APW browse list.
4473 Specifically the printers for the server appear at the workgroup
4474 level where all the other servers in the domain are
4475 listed. Windows responds to this call with a
4476 WERR_CAN_NOT_COMPLETE so we should do the same. */
4478 if (name[0] == '\\' && name[1] == '\\')
4481 if (is_myname_or_ipaddr(s))
4482 return WERR_CAN_NOT_COMPLETE;
4484 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4487 /********************************************************************
4488 * api_spoolss_enumprinters
4490 * called from api_spoolss_enumprinters (see this to understand)
4491 ********************************************************************/
4493 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4497 int n_services=lp_numservices();
4498 PRINTER_INFO_2 *tp, *printers=NULL;
4499 PRINTER_INFO_2 current_prt;
4500 WERROR result = WERR_OK;
4502 for (snum=0; snum<n_services; snum++) {
4503 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4504 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4506 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4508 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4509 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4510 SAFE_FREE(printers);
4515 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4518 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4525 /* check the required size. */
4526 for (i=0; i<*returned; i++)
4527 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4529 if (*needed > offered) {
4530 result = WERR_INSUFFICIENT_BUFFER;
4534 if (!rpcbuf_alloc_size(buffer, *needed)) {
4535 result = WERR_NOMEM;
4539 /* fill the buffer with the structures */
4540 for (i=0; i<*returned; i++)
4541 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4546 for (i=0; i<*returned; i++)
4547 free_devmode(printers[i].devmode);
4549 SAFE_FREE(printers);
4551 if ( !W_ERROR_IS_OK(result) )
4557 /********************************************************************
4558 * handle enumeration of printers at level 1
4559 ********************************************************************/
4561 static WERROR enumprinters_level1( uint32 flags, fstring name,
4562 RPC_BUFFER *buffer, uint32 offered,
4563 uint32 *needed, uint32 *returned)
4565 /* Not all the flags are equals */
4567 if (flags & PRINTER_ENUM_LOCAL)
4568 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4570 if (flags & PRINTER_ENUM_NAME)
4571 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4573 #if 0 /* JERRY - disabled for now */
4574 if (flags & PRINTER_ENUM_REMOTE)
4575 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4578 if (flags & PRINTER_ENUM_NETWORK)
4579 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4581 return WERR_OK; /* NT4sp5 does that */
4584 /********************************************************************
4585 * handle enumeration of printers at level 2
4586 ********************************************************************/
4588 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4589 RPC_BUFFER *buffer, uint32 offered,
4590 uint32 *needed, uint32 *returned)
4592 char *s = servername;
4594 if (flags & PRINTER_ENUM_LOCAL) {
4595 return enum_all_printers_info_2(buffer, offered, needed, returned);
4598 if (flags & PRINTER_ENUM_NAME) {
4599 if ((servername[0] == '\\') && (servername[1] == '\\'))
4601 if (is_myname_or_ipaddr(s))
4602 return enum_all_printers_info_2(buffer, offered, needed, returned);
4604 return WERR_INVALID_NAME;
4607 if (flags & PRINTER_ENUM_REMOTE)
4608 return WERR_UNKNOWN_LEVEL;
4613 /********************************************************************
4614 * handle enumeration of printers at level 5
4615 ********************************************************************/
4617 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4618 RPC_BUFFER *buffer, uint32 offered,
4619 uint32 *needed, uint32 *returned)
4621 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4625 /********************************************************************
4626 * api_spoolss_enumprinters
4628 * called from api_spoolss_enumprinters (see this to understand)
4629 ********************************************************************/
4631 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4633 uint32 flags = q_u->flags;
4634 UNISTR2 *servername = &q_u->servername;
4635 uint32 level = q_u->level;
4636 RPC_BUFFER *buffer = NULL;
4637 uint32 offered = q_u->offered;
4638 uint32 *needed = &r_u->needed;
4639 uint32 *returned = &r_u->returned;
4643 /* that's an [in out] buffer */
4645 if ( q_u->buffer ) {
4646 rpcbuf_move(q_u->buffer, &r_u->buffer);
4647 buffer = r_u->buffer;
4650 DEBUG(4,("_spoolss_enumprinters\n"));
4657 * flags==PRINTER_ENUM_NAME
4658 * if name=="" then enumerates all printers
4659 * if name!="" then enumerate the printer
4660 * flags==PRINTER_ENUM_REMOTE
4661 * name is NULL, enumerate printers
4662 * Level 2: name!="" enumerates printers, name can't be NULL
4663 * Level 3: doesn't exist
4664 * Level 4: does a local registry lookup
4665 * Level 5: same as Level 2
4668 unistr2_to_ascii(name, servername, sizeof(name)-1);
4673 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4675 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4677 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4682 return WERR_UNKNOWN_LEVEL;
4685 /****************************************************************************
4686 ****************************************************************************/
4688 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4690 PRINTER_INFO_0 *printer=NULL;
4691 WERROR result = WERR_OK;
4693 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4696 construct_printer_info_0(print_hnd, printer, snum);
4698 /* check the required size. */
4699 *needed += spoolss_size_printer_info_0(printer);
4701 if (*needed > offered) {
4702 result = WERR_INSUFFICIENT_BUFFER;
4706 if (!rpcbuf_alloc_size(buffer, *needed)) {
4707 result = WERR_NOMEM;
4711 /* fill the buffer with the structures */
4712 smb_io_printer_info_0("", buffer, printer, 0);
4722 /****************************************************************************
4723 ****************************************************************************/
4725 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4727 PRINTER_INFO_1 *printer=NULL;
4728 WERROR result = WERR_OK;
4730 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4733 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4735 /* check the required size. */
4736 *needed += spoolss_size_printer_info_1(printer);
4738 if (*needed > offered) {
4739 result = WERR_INSUFFICIENT_BUFFER;
4743 if (!rpcbuf_alloc_size(buffer, *needed)) {
4744 result = WERR_NOMEM;
4748 /* fill the buffer with the structures */
4749 smb_io_printer_info_1("", buffer, printer, 0);
4758 /****************************************************************************
4759 ****************************************************************************/
4761 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4763 PRINTER_INFO_2 *printer=NULL;
4764 WERROR result = WERR_OK;
4766 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4769 construct_printer_info_2(print_hnd, printer, snum);
4771 /* check the required size. */
4772 *needed += spoolss_size_printer_info_2(printer);
4774 if (*needed > offered) {
4775 result = WERR_INSUFFICIENT_BUFFER;
4779 if (!rpcbuf_alloc_size(buffer, *needed)) {
4780 result = WERR_NOMEM;
4784 /* fill the buffer with the structures */
4785 if (!smb_io_printer_info_2("", buffer, printer, 0))
4786 result = WERR_NOMEM;
4790 free_printer_info_2(printer);
4795 /****************************************************************************
4796 ****************************************************************************/
4798 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4800 PRINTER_INFO_3 *printer=NULL;
4801 WERROR result = WERR_OK;
4803 if (!construct_printer_info_3(print_hnd, &printer, snum))
4806 /* check the required size. */
4807 *needed += spoolss_size_printer_info_3(printer);
4809 if (*needed > offered) {
4810 result = WERR_INSUFFICIENT_BUFFER;
4814 if (!rpcbuf_alloc_size(buffer, *needed)) {
4815 result = WERR_NOMEM;
4819 /* fill the buffer with the structures */
4820 smb_io_printer_info_3("", buffer, printer, 0);
4824 free_printer_info_3(printer);
4829 /****************************************************************************
4830 ****************************************************************************/
4832 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4834 PRINTER_INFO_4 *printer=NULL;
4835 WERROR result = WERR_OK;
4837 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4840 if (!construct_printer_info_4(print_hnd, printer, snum))
4843 /* check the required size. */
4844 *needed += spoolss_size_printer_info_4(printer);
4846 if (*needed > offered) {
4847 result = WERR_INSUFFICIENT_BUFFER;
4851 if (!rpcbuf_alloc_size(buffer, *needed)) {
4852 result = WERR_NOMEM;
4856 /* fill the buffer with the structures */
4857 smb_io_printer_info_4("", buffer, printer, 0);
4861 free_printer_info_4(printer);
4866 /****************************************************************************
4867 ****************************************************************************/
4869 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4871 PRINTER_INFO_5 *printer=NULL;
4872 WERROR result = WERR_OK;
4874 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4877 if (!construct_printer_info_5(print_hnd, printer, snum))
4880 /* check the required size. */
4881 *needed += spoolss_size_printer_info_5(printer);
4883 if (*needed > offered) {
4884 result = WERR_INSUFFICIENT_BUFFER;
4888 if (!rpcbuf_alloc_size(buffer, *needed)) {
4889 result = WERR_NOMEM;
4893 /* fill the buffer with the structures */
4894 smb_io_printer_info_5("", buffer, printer, 0);
4898 free_printer_info_5(printer);
4903 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4905 PRINTER_INFO_7 *printer=NULL;
4906 WERROR result = WERR_OK;
4908 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4911 if (!construct_printer_info_7(print_hnd, printer, snum))
4914 /* check the required size. */
4915 *needed += spoolss_size_printer_info_7(printer);
4917 if (*needed > offered) {
4918 result = WERR_INSUFFICIENT_BUFFER;
4922 if (!rpcbuf_alloc_size(buffer, *needed)) {
4923 result = WERR_NOMEM;
4928 /* fill the buffer with the structures */
4929 smb_io_printer_info_7("", buffer, printer, 0);
4933 free_printer_info_7(printer);
4938 /****************************************************************************
4939 ****************************************************************************/
4941 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4943 POLICY_HND *handle = &q_u->handle;
4944 uint32 level = q_u->level;
4945 RPC_BUFFER *buffer = NULL;
4946 uint32 offered = q_u->offered;
4947 uint32 *needed = &r_u->needed;
4948 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4952 /* that's an [in out] buffer */
4954 if ( q_u->buffer ) {
4955 rpcbuf_move(q_u->buffer, &r_u->buffer);
4956 buffer = r_u->buffer;
4961 if (!get_printer_snum(p, handle, &snum))
4966 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4968 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4970 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4972 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4974 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4976 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4978 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4980 return WERR_UNKNOWN_LEVEL;
4983 /********************************************************************
4984 * fill a DRIVER_INFO_1 struct
4985 ********************************************************************/
4987 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4989 init_unistr( &info->name, driver.info_3->name);
4992 /********************************************************************
4993 * construct_printer_driver_info_1
4994 ********************************************************************/
4996 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4998 NT_PRINTER_INFO_LEVEL *printer = NULL;
4999 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5001 ZERO_STRUCT(driver);
5003 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5004 return WERR_INVALID_PRINTER_NAME;
5006 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5007 return WERR_UNKNOWN_PRINTER_DRIVER;
5009 fill_printer_driver_info_1(info, driver, servername, architecture);
5011 free_a_printer(&printer,2);
5016 /********************************************************************
5017 * construct_printer_driver_info_2
5018 * fill a printer_info_2 struct
5019 ********************************************************************/
5021 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5025 info->version=driver.info_3->cversion;
5027 init_unistr( &info->name, driver.info_3->name );
5028 init_unistr( &info->architecture, driver.info_3->environment );
5031 if (strlen(driver.info_3->driverpath)) {
5032 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5033 init_unistr( &info->driverpath, temp );
5035 init_unistr( &info->driverpath, "" );
5037 if (strlen(driver.info_3->datafile)) {
5038 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5039 init_unistr( &info->datafile, temp );
5041 init_unistr( &info->datafile, "" );
5043 if (strlen(driver.info_3->configfile)) {
5044 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5045 init_unistr( &info->configfile, temp );
5047 init_unistr( &info->configfile, "" );
5050 /********************************************************************
5051 * construct_printer_driver_info_2
5052 * fill a printer_info_2 struct
5053 ********************************************************************/
5055 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5057 NT_PRINTER_INFO_LEVEL *printer = NULL;
5058 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5060 ZERO_STRUCT(printer);
5061 ZERO_STRUCT(driver);
5063 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5064 return WERR_INVALID_PRINTER_NAME;
5066 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5067 return WERR_UNKNOWN_PRINTER_DRIVER;
5069 fill_printer_driver_info_2(info, driver, servername);
5071 free_a_printer(&printer,2);
5076 /********************************************************************
5077 * copy a strings array and convert to UNICODE
5079 * convert an array of ascii string to a UNICODE string
5080 ********************************************************************/
5082 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5090 DEBUG(6,("init_unistr_array\n"));
5101 v = ""; /* hack to handle null lists */
5104 /* hack to allow this to be used in places other than when generating
5105 the list of dependent files */
5108 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5112 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5114 /* add one extra unit16 for the second terminating NULL */
5116 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5117 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5125 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5130 /* special case for ""; we need to add both NULL's here */
5132 (*uni_array)[j++]=0x0000;
5133 (*uni_array)[j]=0x0000;
5136 DEBUGADD(6,("last one:done\n"));
5138 /* return size of array in uint16's */
5143 /********************************************************************
5144 * construct_printer_info_3
5145 * fill a printer_info_3 struct
5146 ********************************************************************/
5148 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5154 info->version=driver.info_3->cversion;
5156 init_unistr( &info->name, driver.info_3->name );
5157 init_unistr( &info->architecture, driver.info_3->environment );
5159 if (strlen(driver.info_3->driverpath)) {
5160 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5161 init_unistr( &info->driverpath, temp );
5163 init_unistr( &info->driverpath, "" );
5165 if (strlen(driver.info_3->datafile)) {
5166 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5167 init_unistr( &info->datafile, temp );
5169 init_unistr( &info->datafile, "" );
5171 if (strlen(driver.info_3->configfile)) {
5172 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5173 init_unistr( &info->configfile, temp );
5175 init_unistr( &info->configfile, "" );
5177 if (strlen(driver.info_3->helpfile)) {
5178 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5179 init_unistr( &info->helpfile, temp );
5181 init_unistr( &info->helpfile, "" );
5183 init_unistr( &info->monitorname, driver.info_3->monitorname );
5184 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5186 info->dependentfiles=NULL;
5187 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5190 /********************************************************************
5191 * construct_printer_info_3
5192 * fill a printer_info_3 struct
5193 ********************************************************************/
5195 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5197 NT_PRINTER_INFO_LEVEL *printer = NULL;
5198 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5200 ZERO_STRUCT(driver);
5202 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5203 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5204 if (!W_ERROR_IS_OK(status))
5205 return WERR_INVALID_PRINTER_NAME;
5207 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5208 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5213 * I put this code in during testing. Helpful when commenting out the
5214 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5215 * as win2k always queries the driver using an infor level of 6.
5216 * I've left it in (but ifdef'd out) because I'll probably
5217 * use it in experimentation again in the future. --jerry 22/01/2002
5220 if (!W_ERROR_IS_OK(status)) {
5222 * Is this a W2k client ?
5225 /* Yes - try again with a WinNT driver. */
5227 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5228 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5232 if (!W_ERROR_IS_OK(status)) {
5233 free_a_printer(&printer,2);
5234 return WERR_UNKNOWN_PRINTER_DRIVER;
5242 fill_printer_driver_info_3(info, driver, servername);
5244 free_a_printer(&printer,2);
5249 /********************************************************************
5250 * construct_printer_info_6
5251 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5252 ********************************************************************/
5254 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5260 memset(&nullstr, '\0', sizeof(fstring));
5262 info->version=driver.info_3->cversion;
5264 init_unistr( &info->name, driver.info_3->name );
5265 init_unistr( &info->architecture, driver.info_3->environment );
5267 if (strlen(driver.info_3->driverpath)) {
5268 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5269 init_unistr( &info->driverpath, temp );
5271 init_unistr( &info->driverpath, "" );
5273 if (strlen(driver.info_3->datafile)) {
5274 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5275 init_unistr( &info->datafile, temp );
5277 init_unistr( &info->datafile, "" );
5279 if (strlen(driver.info_3->configfile)) {
5280 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5281 init_unistr( &info->configfile, temp );
5283 init_unistr( &info->configfile, "" );
5285 if (strlen(driver.info_3->helpfile)) {
5286 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5287 init_unistr( &info->helpfile, temp );
5289 init_unistr( &info->helpfile, "" );
5291 init_unistr( &info->monitorname, driver.info_3->monitorname );
5292 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5294 info->dependentfiles = NULL;
5295 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5297 info->previousdrivernames=NULL;
5298 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5300 info->driver_date.low=0;
5301 info->driver_date.high=0;
5304 info->driver_version_low=0;
5305 info->driver_version_high=0;
5307 init_unistr( &info->mfgname, "");
5308 init_unistr( &info->oem_url, "");
5309 init_unistr( &info->hardware_id, "");
5310 init_unistr( &info->provider, "");
5313 /********************************************************************
5314 * construct_printer_info_6
5315 * fill a printer_info_6 struct
5316 ********************************************************************/
5318 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5319 fstring servername, fstring architecture, uint32 version)
5321 NT_PRINTER_INFO_LEVEL *printer = NULL;
5322 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5325 ZERO_STRUCT(driver);
5327 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5329 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5331 if (!W_ERROR_IS_OK(status))
5332 return WERR_INVALID_PRINTER_NAME;
5334 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5336 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5338 if (!W_ERROR_IS_OK(status))
5341 * Is this a W2k client ?
5345 free_a_printer(&printer,2);
5346 return WERR_UNKNOWN_PRINTER_DRIVER;
5349 /* Yes - try again with a WinNT driver. */
5351 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5352 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5353 if (!W_ERROR_IS_OK(status)) {
5354 free_a_printer(&printer,2);
5355 return WERR_UNKNOWN_PRINTER_DRIVER;
5359 fill_printer_driver_info_6(info, driver, servername);
5361 free_a_printer(&printer,2);
5362 free_a_printer_driver(driver, 3);
5367 /****************************************************************************
5368 ****************************************************************************/
5370 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5372 SAFE_FREE(info->dependentfiles);
5375 /****************************************************************************
5376 ****************************************************************************/
5378 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5380 SAFE_FREE(info->dependentfiles);
5383 /****************************************************************************
5384 ****************************************************************************/
5386 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5388 DRIVER_INFO_1 *info=NULL;
5391 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5394 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5395 if (!W_ERROR_IS_OK(result))
5398 /* check the required size. */
5399 *needed += spoolss_size_printer_driver_info_1(info);
5401 if (*needed > offered) {
5402 result = WERR_INSUFFICIENT_BUFFER;
5406 if (!rpcbuf_alloc_size(buffer, *needed)) {
5407 result = WERR_NOMEM;
5411 /* fill the buffer with the structures */
5412 smb_io_printer_driver_info_1("", buffer, info, 0);
5421 /****************************************************************************
5422 ****************************************************************************/
5424 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5426 DRIVER_INFO_2 *info=NULL;
5429 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5432 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5433 if (!W_ERROR_IS_OK(result))
5436 /* check the required size. */
5437 *needed += spoolss_size_printer_driver_info_2(info);
5439 if (*needed > offered) {
5440 result = WERR_INSUFFICIENT_BUFFER;
5444 if (!rpcbuf_alloc_size(buffer, *needed)) {
5445 result = WERR_NOMEM;
5449 /* fill the buffer with the structures */
5450 smb_io_printer_driver_info_2("", buffer, info, 0);
5459 /****************************************************************************
5460 ****************************************************************************/
5462 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5469 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5470 if (!W_ERROR_IS_OK(result))
5473 /* check the required size. */
5474 *needed += spoolss_size_printer_driver_info_3(&info);
5476 if (*needed > offered) {
5477 result = WERR_INSUFFICIENT_BUFFER;
5481 if (!rpcbuf_alloc_size(buffer, *needed)) {
5482 result = WERR_NOMEM;
5486 /* fill the buffer with the structures */
5487 smb_io_printer_driver_info_3("", buffer, &info, 0);
5490 free_printer_driver_info_3(&info);
5495 /****************************************************************************
5496 ****************************************************************************/
5498 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5505 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5506 if (!W_ERROR_IS_OK(result))
5509 /* check the required size. */
5510 *needed += spoolss_size_printer_driver_info_6(&info);
5512 if (*needed > offered) {
5513 result = WERR_INSUFFICIENT_BUFFER;
5517 if (!rpcbuf_alloc_size(buffer, *needed)) {
5518 result = WERR_NOMEM;
5522 /* fill the buffer with the structures */
5523 smb_io_printer_driver_info_6("", buffer, &info, 0);
5526 free_printer_driver_info_6(&info);
5531 /****************************************************************************
5532 ****************************************************************************/
5534 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5536 POLICY_HND *handle = &q_u->handle;
5537 UNISTR2 *uni_arch = &q_u->architecture;
5538 uint32 level = q_u->level;
5539 uint32 clientmajorversion = q_u->clientmajorversion;
5540 RPC_BUFFER *buffer = NULL;
5541 uint32 offered = q_u->offered;
5542 uint32 *needed = &r_u->needed;
5543 uint32 *servermajorversion = &r_u->servermajorversion;
5544 uint32 *serverminorversion = &r_u->serverminorversion;
5545 Printer_entry *printer;
5548 fstring architecture;
5551 /* that's an [in out] buffer */
5553 if ( q_u->buffer ) {
5554 rpcbuf_move(q_u->buffer, &r_u->buffer);
5555 buffer = r_u->buffer;
5558 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5560 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5561 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5562 return WERR_INVALID_PRINTER_NAME;
5566 *servermajorversion = 0;
5567 *serverminorversion = 0;
5569 fstrcpy(servername, get_server_name( printer ));
5570 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5572 if (!get_printer_snum(p, handle, &snum))
5577 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5579 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5581 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5583 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5586 /* apparently this call is the equivalent of
5587 EnumPrinterDataEx() for the DsDriver key */
5592 return WERR_UNKNOWN_LEVEL;
5595 /****************************************************************************
5596 ****************************************************************************/
5598 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5600 POLICY_HND *handle = &q_u->handle;
5602 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5605 DEBUG(3,("Error in startpageprinter printer handle\n"));
5609 Printer->page_started=True;
5613 /****************************************************************************
5614 ****************************************************************************/
5616 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5618 POLICY_HND *handle = &q_u->handle;
5621 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5624 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5628 if (!get_printer_snum(p, handle, &snum))
5631 Printer->page_started=False;
5632 print_job_endpage(snum, Printer->jobid);
5637 /********************************************************************
5638 * api_spoolss_getprinter
5639 * called from the spoolss dispatcher
5641 ********************************************************************/
5643 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5645 POLICY_HND *handle = &q_u->handle;
5646 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5647 uint32 *jobid = &r_u->jobid;
5649 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5653 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5654 struct current_user user;
5657 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5661 get_current_user(&user, p);
5664 * a nice thing with NT is it doesn't listen to what you tell it.
5665 * when asked to send _only_ RAW datas, it tries to send datas
5668 * So I add checks like in NT Server ...
5671 if (info_1->p_datatype != 0) {
5672 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5673 if (strcmp(datatype, "RAW") != 0) {
5675 return WERR_INVALID_DATATYPE;
5679 /* get the share number of the printer */
5680 if (!get_printer_snum(p, handle, &snum)) {
5684 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5686 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5688 /* An error occured in print_job_start() so return an appropriate
5691 if (Printer->jobid == -1) {
5692 return map_werror_from_unix(errno);
5695 Printer->document_started=True;
5696 (*jobid) = Printer->jobid;
5701 /********************************************************************
5702 * api_spoolss_getprinter
5703 * called from the spoolss dispatcher
5705 ********************************************************************/
5707 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5709 POLICY_HND *handle = &q_u->handle;
5711 return _spoolss_enddocprinter_internal(p, handle);
5714 /****************************************************************************
5715 ****************************************************************************/
5717 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5719 POLICY_HND *handle = &q_u->handle;
5720 uint32 buffer_size = q_u->buffer_size;
5721 uint8 *buffer = q_u->buffer;
5722 uint32 *buffer_written = &q_u->buffer_size2;
5724 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5727 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5728 r_u->buffer_written = q_u->buffer_size2;
5732 if (!get_printer_snum(p, handle, &snum))
5735 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5736 (SMB_OFF_T)-1, (size_t)buffer_size);
5737 if (*buffer_written == (uint32)-1) {
5738 r_u->buffer_written = 0;
5739 if (errno == ENOSPC)
5740 return WERR_NO_SPOOL_SPACE;
5742 return WERR_ACCESS_DENIED;
5745 r_u->buffer_written = q_u->buffer_size2;
5750 /********************************************************************
5751 * api_spoolss_getprinter
5752 * called from the spoolss dispatcher
5754 ********************************************************************/
5756 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5759 struct current_user user;
5761 WERROR errcode = WERR_BADFUNC;
5762 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5764 get_current_user(&user, p);
5767 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5771 if (!get_printer_snum(p, handle, &snum))
5775 case PRINTER_CONTROL_PAUSE:
5776 if (print_queue_pause(&user, snum, &errcode)) {
5780 case PRINTER_CONTROL_RESUME:
5781 case PRINTER_CONTROL_UNPAUSE:
5782 if (print_queue_resume(&user, snum, &errcode)) {
5786 case PRINTER_CONTROL_PURGE:
5787 if (print_queue_purge(&user, snum, &errcode)) {
5792 return WERR_UNKNOWN_LEVEL;
5798 /********************************************************************
5799 * api_spoolss_abortprinter
5800 * From MSDN: "Deletes printer's spool file if printer is configured
5802 ********************************************************************/
5804 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5806 POLICY_HND *handle = &q_u->handle;
5807 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5809 struct current_user user;
5810 WERROR errcode = WERR_OK;
5813 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5817 if (!get_printer_snum(p, handle, &snum))
5820 get_current_user( &user, p );
5822 print_job_delete( &user, snum, Printer->jobid, &errcode );
5827 /********************************************************************
5828 * called by spoolss_api_setprinter
5829 * when updating a printer description
5830 ********************************************************************/
5832 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5833 const SPOOL_PRINTER_INFO_LEVEL *info,
5834 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5836 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5840 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5842 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5843 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5844 OUR_HANDLE(handle)));
5846 result = WERR_BADFID;
5850 /* Check the user has permissions to change the security
5851 descriptor. By experimentation with two NT machines, the user
5852 requires Full Access to the printer to change security
5855 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5856 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5857 result = WERR_ACCESS_DENIED;
5861 /* NT seems to like setting the security descriptor even though
5862 nothing may have actually changed. */
5864 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5866 if (DEBUGLEVEL >= 10) {
5870 the_acl = old_secdesc_ctr->sec->dacl;
5871 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5872 PRINTERNAME(snum), the_acl->num_aces));
5874 for (i = 0; i < the_acl->num_aces; i++) {
5877 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5879 DEBUG(10, ("%s 0x%08x\n", sid_str,
5880 the_acl->ace[i].info.mask));
5883 the_acl = secdesc_ctr->sec->dacl;
5886 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5887 PRINTERNAME(snum), the_acl->num_aces));
5889 for (i = 0; i < the_acl->num_aces; i++) {
5892 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5894 DEBUG(10, ("%s 0x%08x\n", sid_str,
5895 the_acl->ace[i].info.mask));
5898 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5902 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5904 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5909 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5916 /********************************************************************
5917 Canonicalize printer info from a client
5919 ATTN: It does not matter what we set the servername to hear
5920 since we do the necessary work in get_a_printer() to set it to
5921 the correct value based on what the client sent in the
5922 _spoolss_open_printer_ex().
5923 ********************************************************************/
5925 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5927 fstring printername;
5930 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5931 "portname=%s drivername=%s comment=%s location=%s\n",
5932 info->servername, info->printername, info->sharename,
5933 info->portname, info->drivername, info->comment, info->location));
5935 /* we force some elements to "correct" values */
5936 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5937 fstrcpy(info->sharename, lp_servicename(snum));
5939 /* check to see if we allow printername != sharename */
5941 if ( lp_force_printername(snum) ) {
5942 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5943 global_myname(), info->sharename );
5946 /* make sure printername is in \\server\printername format */
5948 fstrcpy( printername, info->printername );
5950 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5951 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5955 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5956 global_myname(), p );
5959 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5960 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5967 /****************************************************************************
5968 ****************************************************************************/
5970 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5972 char *cmd = lp_addprinter_cmd();
5978 fstring remote_machine = "%m";
5979 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5980 BOOL is_print_op = False;
5982 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5984 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5985 cmd, printer->info_2->printername, printer->info_2->sharename,
5986 printer->info_2->portname, printer->info_2->drivername,
5987 printer->info_2->location, printer->info_2->comment, remote_machine);
5990 is_print_op = user_has_privileges( token, &se_printop );
5992 DEBUG(10,("Running [%s]\n", command));
5994 /********* BEGIN SePrintOperatorPrivilege **********/
5999 if ( (ret = smbrun(command, &fd)) == 0 ) {
6000 /* Tell everyone we updated smb.conf. */
6001 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6007 /********* END SePrintOperatorPrivilege **********/
6009 DEBUGADD(10,("returned [%d]\n", ret));
6017 /* reload our services immediately */
6018 reload_services( False );
6021 /* Get lines and convert them back to dos-codepage */
6022 qlines = fd_lines_load(fd, &numlines);
6023 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6026 /* Set the portname to what the script says the portname should be. */
6027 /* but don't require anything to be return from the script exit a good error code */
6030 /* Set the portname to what the script says the portname should be. */
6031 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6032 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6035 file_lines_free(qlines);
6039 /********************************************************************
6040 * Called by spoolss_api_setprinter
6041 * when updating a printer description.
6042 ********************************************************************/
6044 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6045 const SPOOL_PRINTER_INFO_LEVEL *info,
6046 DEVICEMODE *devmode)
6049 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6050 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6055 DEBUG(8,("update_printer\n"));
6060 result = WERR_BADFID;
6064 if (!get_printer_snum(p, handle, &snum)) {
6065 result = WERR_BADFID;
6069 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6070 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6071 result = WERR_BADFID;
6075 DEBUGADD(8,("Converting info_2 struct\n"));
6078 * convert_printer_info converts the incoming
6079 * info from the client and overwrites the info
6080 * just read from the tdb in the pointer 'printer'.
6083 if (!convert_printer_info(info, printer, level)) {
6084 result = WERR_NOMEM;
6089 /* we have a valid devmode
6090 convert it and link it*/
6092 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6093 if (!convert_devicemode(printer->info_2->printername, devmode,
6094 &printer->info_2->devmode)) {
6095 result = WERR_NOMEM;
6100 /* Do sanity check on the requested changes for Samba */
6102 if (!check_printer_ok(printer->info_2, snum)) {
6103 result = WERR_INVALID_PARAM;
6107 /* FIXME!!! If the driver has changed we really should verify that
6108 it is installed before doing much else --jerry */
6110 /* Check calling user has permission to update printer description */
6112 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6113 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6114 result = WERR_ACCESS_DENIED;
6118 /* Call addprinter hook */
6119 /* Check changes to see if this is really needed */
6121 if ( *lp_addprinter_cmd()
6122 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6123 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6124 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6125 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6127 /* add_printer_hook() will call reload_services() */
6129 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6130 result = WERR_ACCESS_DENIED;
6136 * When a *new* driver is bound to a printer, the drivername is used to
6137 * lookup previously saved driver initialization info, which is then
6138 * bound to the printer, simulating what happens in the Windows arch.
6140 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6142 if (!set_driver_init(printer, 2))
6144 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6145 printer->info_2->drivername));
6148 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6149 printer->info_2->drivername));
6151 notify_printer_driver(snum, printer->info_2->drivername);
6155 * flag which changes actually occured. This is a small subset of
6156 * all the possible changes. We also have to update things in the
6160 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6161 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6162 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6163 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6165 notify_printer_comment(snum, printer->info_2->comment);
6168 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6169 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 notify_printer_sharename(snum, printer->info_2->sharename);
6176 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6179 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6182 pname = printer->info_2->printername;
6185 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6186 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6187 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6189 notify_printer_printername( snum, pname );
6192 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6193 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6194 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6195 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6197 notify_printer_port(snum, printer->info_2->portname);
6200 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6201 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6202 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6203 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6205 notify_printer_location(snum, printer->info_2->location);
6208 /* here we need to update some more DsSpooler keys */
6209 /* uNCName, serverName, shortServerName */
6211 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6212 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6213 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6214 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6215 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6217 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6218 global_myname(), printer->info_2->sharename );
6219 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6220 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6221 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6223 /* Update printer info */
6224 result = mod_a_printer(printer, 2);
6227 free_a_printer(&printer, 2);
6228 free_a_printer(&old_printer, 2);
6234 /****************************************************************************
6235 ****************************************************************************/
6236 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6237 const SPOOL_PRINTER_INFO_LEVEL *info)
6240 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6242 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6244 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6249 if (!get_printer_snum(p, handle, &snum))
6252 nt_printer_publish(Printer, snum, info7->action);
6256 return WERR_UNKNOWN_LEVEL;
6259 /****************************************************************************
6260 ****************************************************************************/
6262 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6264 POLICY_HND *handle = &q_u->handle;
6265 uint32 level = q_u->level;
6266 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6267 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6268 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6269 uint32 command = q_u->command;
6272 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6275 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6279 /* check the level */
6282 return control_printer(handle, command, p);
6284 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6285 if (!W_ERROR_IS_OK(result))
6288 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6291 return update_printer_sec(handle, level, info, p,
6294 return publish_or_unpublish_printer(p, handle, info);
6296 return WERR_UNKNOWN_LEVEL;
6300 /****************************************************************************
6301 ****************************************************************************/
6303 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6305 POLICY_HND *handle = &q_u->handle;
6306 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6309 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6313 if (Printer->notify.client_connected==True) {
6316 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6318 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6319 !get_printer_snum(p, handle, &snum) )
6322 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6325 Printer->notify.flags=0;
6326 Printer->notify.options=0;
6327 Printer->notify.localmachine[0]='\0';
6328 Printer->notify.printerlocal=0;
6329 if (Printer->notify.option)
6330 free_spool_notify_option(&Printer->notify.option);
6331 Printer->notify.client_connected=False;
6336 /****************************************************************************
6337 ****************************************************************************/
6339 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6341 /* that's an [in out] buffer */
6344 rpcbuf_move(q_u->buffer, &r_u->buffer);
6347 return WERR_INVALID_PARAM; /* this is what a NT server
6348 returns for AddJob. AddJob
6349 must fail on non-local
6353 /****************************************************************************
6354 ****************************************************************************/
6356 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6357 int position, int snum,
6358 NT_PRINTER_INFO_LEVEL *ntprinter)
6362 t=gmtime(&queue->time);
6364 job_info->jobid=queue->job;
6365 init_unistr(&job_info->printername, lp_servicename(snum));
6366 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6367 init_unistr(&job_info->username, queue->fs_user);
6368 init_unistr(&job_info->document, queue->fs_file);
6369 init_unistr(&job_info->datatype, "RAW");
6370 init_unistr(&job_info->text_status, "");
6371 job_info->status=nt_printj_status(queue->status);
6372 job_info->priority=queue->priority;
6373 job_info->position=position;
6374 job_info->totalpages=queue->page_count;
6375 job_info->pagesprinted=0;
6377 make_systemtime(&job_info->submitted, t);
6380 /****************************************************************************
6381 ****************************************************************************/
6383 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6384 int position, int snum,
6385 NT_PRINTER_INFO_LEVEL *ntprinter,
6386 DEVICEMODE *devmode)
6390 t=gmtime(&queue->time);
6392 job_info->jobid=queue->job;
6394 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6396 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6397 init_unistr(&job_info->username, queue->fs_user);
6398 init_unistr(&job_info->document, queue->fs_file);
6399 init_unistr(&job_info->notifyname, queue->fs_user);
6400 init_unistr(&job_info->datatype, "RAW");
6401 init_unistr(&job_info->printprocessor, "winprint");
6402 init_unistr(&job_info->parameters, "");
6403 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6404 init_unistr(&job_info->text_status, "");
6406 /* and here the security descriptor */
6408 job_info->status=nt_printj_status(queue->status);
6409 job_info->priority=queue->priority;
6410 job_info->position=position;
6411 job_info->starttime=0;
6412 job_info->untiltime=0;
6413 job_info->totalpages=queue->page_count;
6414 job_info->size=queue->size;
6415 make_systemtime(&(job_info->submitted), t);
6416 job_info->timeelapsed=0;
6417 job_info->pagesprinted=0;
6419 job_info->devmode = devmode;
6424 /****************************************************************************
6425 Enumjobs at level 1.
6426 ****************************************************************************/
6428 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6429 NT_PRINTER_INFO_LEVEL *ntprinter,
6430 RPC_BUFFER *buffer, uint32 offered,
6431 uint32 *needed, uint32 *returned)
6435 WERROR result = WERR_OK;
6437 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6444 for (i=0; i<*returned; i++)
6445 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6449 /* check the required size. */
6450 for (i=0; i<*returned; i++)
6451 (*needed) += spoolss_size_job_info_1(&info[i]);
6453 if (*needed > offered) {
6454 result = WERR_INSUFFICIENT_BUFFER;
6458 if (!rpcbuf_alloc_size(buffer, *needed)) {
6459 result = WERR_NOMEM;
6463 /* fill the buffer with the structures */
6464 for (i=0; i<*returned; i++)
6465 smb_io_job_info_1("", buffer, &info[i], 0);
6471 if ( !W_ERROR_IS_OK(result) )
6477 /****************************************************************************
6478 Enumjobs at level 2.
6479 ****************************************************************************/
6481 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6482 NT_PRINTER_INFO_LEVEL *ntprinter,
6483 RPC_BUFFER *buffer, uint32 offered,
6484 uint32 *needed, uint32 *returned)
6486 JOB_INFO_2 *info = NULL;
6488 WERROR result = WERR_OK;
6489 DEVICEMODE *devmode = NULL;
6491 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6496 /* this should not be a failure condition if the devmode is NULL */
6498 devmode = construct_dev_mode(snum);
6500 for (i=0; i<*returned; i++)
6501 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6503 free_a_printer(&ntprinter, 2);
6506 /* check the required size. */
6507 for (i=0; i<*returned; i++)
6508 (*needed) += spoolss_size_job_info_2(&info[i]);
6510 if (*needed > offered) {
6511 result = WERR_INSUFFICIENT_BUFFER;
6515 if (!rpcbuf_alloc_size(buffer, *needed)) {
6516 result = WERR_NOMEM;
6520 /* fill the buffer with the structures */
6521 for (i=0; i<*returned; i++)
6522 smb_io_job_info_2("", buffer, &info[i], 0);
6525 free_devmode(devmode);
6528 if ( !W_ERROR_IS_OK(result) )
6535 /****************************************************************************
6537 ****************************************************************************/
6539 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6541 POLICY_HND *handle = &q_u->handle;
6542 uint32 level = q_u->level;
6543 RPC_BUFFER *buffer = NULL;
6544 uint32 offered = q_u->offered;
6545 uint32 *needed = &r_u->needed;
6546 uint32 *returned = &r_u->returned;
6548 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6550 print_status_struct prt_status;
6551 print_queue_struct *queue=NULL;
6553 /* that's an [in out] buffer */
6555 if ( q_u->buffer ) {
6556 rpcbuf_move(q_u->buffer, &r_u->buffer);
6557 buffer = r_u->buffer;
6560 DEBUG(4,("_spoolss_enumjobs\n"));
6565 /* lookup the printer snum and tdb entry */
6567 if (!get_printer_snum(p, handle, &snum))
6570 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6571 if ( !W_ERROR_IS_OK(wret) )
6574 *returned = print_queue_status(snum, &queue, &prt_status);
6575 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6577 if (*returned == 0) {
6584 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6587 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6592 wret = WERR_UNKNOWN_LEVEL;
6595 free_a_printer( &ntprinter, 2 );
6599 /****************************************************************************
6600 ****************************************************************************/
6602 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6607 /****************************************************************************
6608 ****************************************************************************/
6610 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6612 POLICY_HND *handle = &q_u->handle;
6613 uint32 jobid = q_u->jobid;
6614 uint32 command = q_u->command;
6616 struct current_user user;
6618 WERROR errcode = WERR_BADFUNC;
6620 if (!get_printer_snum(p, handle, &snum)) {
6624 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6625 return WERR_INVALID_PRINTER_NAME;
6628 get_current_user(&user, p);
6631 case JOB_CONTROL_CANCEL:
6632 case JOB_CONTROL_DELETE:
6633 if (print_job_delete(&user, snum, jobid, &errcode)) {
6637 case JOB_CONTROL_PAUSE:
6638 if (print_job_pause(&user, snum, jobid, &errcode)) {
6642 case JOB_CONTROL_RESTART:
6643 case JOB_CONTROL_RESUME:
6644 if (print_job_resume(&user, snum, jobid, &errcode)) {
6649 return WERR_UNKNOWN_LEVEL;
6655 /****************************************************************************
6656 Enumerates all printer drivers at level 1.
6657 ****************************************************************************/
6659 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6664 fstring *list = NULL;
6665 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6666 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6667 WERROR result = WERR_OK;
6671 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6673 ndrivers=get_ntdrivers(&list, architecture, version);
6674 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6680 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6681 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6682 SAFE_FREE(driver_info_1);
6686 else driver_info_1 = tdi1;
6689 for (i=0; i<ndrivers; i++) {
6691 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6692 ZERO_STRUCT(driver);
6693 status = get_a_printer_driver(&driver, 3, list[i],
6694 architecture, version);
6695 if (!W_ERROR_IS_OK(status)) {
6699 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6700 free_a_printer_driver(driver, 3);
6703 *returned+=ndrivers;
6707 /* check the required size. */
6708 for (i=0; i<*returned; i++) {
6709 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6710 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6713 if (*needed > offered) {
6714 result = WERR_INSUFFICIENT_BUFFER;
6718 if (!rpcbuf_alloc_size(buffer, *needed)) {
6719 result = WERR_NOMEM;
6723 /* fill the buffer with the driver structures */
6724 for (i=0; i<*returned; i++) {
6725 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6726 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6730 SAFE_FREE(driver_info_1);
6732 if ( !W_ERROR_IS_OK(result) )
6738 /****************************************************************************
6739 Enumerates all printer drivers at level 2.
6740 ****************************************************************************/
6742 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6747 fstring *list = NULL;
6748 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6749 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6750 WERROR result = WERR_OK;
6754 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6756 ndrivers=get_ntdrivers(&list, architecture, version);
6757 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6763 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6764 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6765 SAFE_FREE(driver_info_2);
6769 else driver_info_2 = tdi2;
6772 for (i=0; i<ndrivers; i++) {
6775 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6776 ZERO_STRUCT(driver);
6777 status = get_a_printer_driver(&driver, 3, list[i],
6778 architecture, version);
6779 if (!W_ERROR_IS_OK(status)) {
6783 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6784 free_a_printer_driver(driver, 3);
6787 *returned+=ndrivers;
6791 /* check the required size. */
6792 for (i=0; i<*returned; i++) {
6793 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6794 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6797 if (*needed > offered) {
6798 result = WERR_INSUFFICIENT_BUFFER;
6802 if (!rpcbuf_alloc_size(buffer, *needed)) {
6803 result = WERR_NOMEM;
6807 /* fill the buffer with the form structures */
6808 for (i=0; i<*returned; i++) {
6809 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6810 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6814 SAFE_FREE(driver_info_2);
6816 if ( !W_ERROR_IS_OK(result) )
6822 /****************************************************************************
6823 Enumerates all printer drivers at level 3.
6824 ****************************************************************************/
6826 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6831 fstring *list = NULL;
6832 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6833 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6834 WERROR result = WERR_OK;
6838 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6840 ndrivers=get_ntdrivers(&list, architecture, version);
6841 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6847 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6848 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6849 SAFE_FREE(driver_info_3);
6853 else driver_info_3 = tdi3;
6856 for (i=0; i<ndrivers; i++) {
6859 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6860 ZERO_STRUCT(driver);
6861 status = get_a_printer_driver(&driver, 3, list[i],
6862 architecture, version);
6863 if (!W_ERROR_IS_OK(status)) {
6867 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6868 free_a_printer_driver(driver, 3);
6871 *returned+=ndrivers;
6875 /* check the required size. */
6876 for (i=0; i<*returned; i++) {
6877 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6878 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6881 if (*needed > offered) {
6882 result = WERR_INSUFFICIENT_BUFFER;
6886 if (!rpcbuf_alloc_size(buffer, *needed)) {
6887 result = WERR_NOMEM;
6891 /* fill the buffer with the driver structures */
6892 for (i=0; i<*returned; i++) {
6893 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6894 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6898 for (i=0; i<*returned; i++)
6899 SAFE_FREE(driver_info_3[i].dependentfiles);
6901 SAFE_FREE(driver_info_3);
6903 if ( !W_ERROR_IS_OK(result) )
6909 /****************************************************************************
6910 Enumerates all printer drivers.
6911 ****************************************************************************/
6913 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6915 uint32 level = q_u->level;
6916 RPC_BUFFER *buffer = NULL;
6917 uint32 offered = q_u->offered;
6918 uint32 *needed = &r_u->needed;
6919 uint32 *returned = &r_u->returned;
6922 fstring architecture;
6924 /* that's an [in out] buffer */
6926 if ( q_u->buffer ) {
6927 rpcbuf_move(q_u->buffer, &r_u->buffer);
6928 buffer = r_u->buffer;
6931 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6936 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6937 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6939 if ( !is_myname_or_ipaddr( servername ) )
6940 return WERR_UNKNOWN_PRINTER_DRIVER;
6944 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6946 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6948 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6950 return WERR_UNKNOWN_LEVEL;
6954 /****************************************************************************
6955 ****************************************************************************/
6957 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6959 form->flag=list->flag;
6960 init_unistr(&form->name, list->name);
6961 form->width=list->width;
6962 form->length=list->length;
6963 form->left=list->left;
6964 form->top=list->top;
6965 form->right=list->right;
6966 form->bottom=list->bottom;
6969 /****************************************************************************
6970 ****************************************************************************/
6972 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6974 uint32 level = q_u->level;
6975 RPC_BUFFER *buffer = NULL;
6976 uint32 offered = q_u->offered;
6977 uint32 *needed = &r_u->needed;
6978 uint32 *numofforms = &r_u->numofforms;
6979 uint32 numbuiltinforms;
6981 nt_forms_struct *list=NULL;
6982 nt_forms_struct *builtinlist=NULL;
6987 /* that's an [in out] buffer */
6989 if ( q_u->buffer ) {
6990 rpcbuf_move(q_u->buffer, &r_u->buffer);
6991 buffer = r_u->buffer;
6994 DEBUG(4,("_spoolss_enumforms\n"));
6995 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6996 DEBUGADD(5,("Info level [%d]\n", level));
6998 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6999 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7000 *numofforms = get_ntforms(&list);
7001 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7002 *numofforms += numbuiltinforms;
7004 if (*numofforms == 0)
7005 return WERR_NO_MORE_ITEMS;
7009 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7014 /* construct the list of form structures */
7015 for (i=0; i<numbuiltinforms; i++) {
7016 DEBUGADD(6,("Filling form number [%d]\n",i));
7017 fill_form_1(&forms_1[i], &builtinlist[i]);
7020 SAFE_FREE(builtinlist);
7022 for (; i<*numofforms; i++) {
7023 DEBUGADD(6,("Filling form number [%d]\n",i));
7024 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7029 /* check the required size. */
7030 for (i=0; i<numbuiltinforms; i++) {
7031 DEBUGADD(6,("adding form [%d]'s size\n",i));
7032 buffer_size += spoolss_size_form_1(&forms_1[i]);
7034 for (; i<*numofforms; i++) {
7035 DEBUGADD(6,("adding form [%d]'s size\n",i));
7036 buffer_size += spoolss_size_form_1(&forms_1[i]);
7039 *needed=buffer_size;
7041 if (*needed > offered) {
7044 return WERR_INSUFFICIENT_BUFFER;
7047 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7053 /* fill the buffer with the form structures */
7054 for (i=0; i<numbuiltinforms; i++) {
7055 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7056 smb_io_form_1("", buffer, &forms_1[i], 0);
7058 for (; i<*numofforms; i++) {
7059 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7060 smb_io_form_1("", buffer, &forms_1[i], 0);
7069 SAFE_FREE(builtinlist);
7070 return WERR_UNKNOWN_LEVEL;
7075 /****************************************************************************
7076 ****************************************************************************/
7078 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7080 uint32 level = q_u->level;
7081 UNISTR2 *uni_formname = &q_u->formname;
7082 RPC_BUFFER *buffer = NULL;
7083 uint32 offered = q_u->offered;
7084 uint32 *needed = &r_u->needed;
7086 nt_forms_struct *list=NULL;
7087 nt_forms_struct builtin_form;
7092 int numofforms=0, i=0;
7094 /* that's an [in out] buffer */
7096 if ( q_u->buffer ) {
7097 rpcbuf_move(q_u->buffer, &r_u->buffer);
7098 buffer = r_u->buffer;
7101 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7103 DEBUG(4,("_spoolss_getform\n"));
7104 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7105 DEBUGADD(5,("Info level [%d]\n", level));
7107 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7108 if (!foundBuiltin) {
7109 numofforms = get_ntforms(&list);
7110 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7112 if (numofforms == 0)
7119 fill_form_1(&form_1, &builtin_form);
7122 /* Check if the requested name is in the list of form structures */
7123 for (i=0; i<numofforms; i++) {
7125 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7127 if (strequal(form_name, list[i].name)) {
7128 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7129 fill_form_1(&form_1, &list[i]);
7135 if (i == numofforms) {
7139 /* check the required size. */
7141 *needed=spoolss_size_form_1(&form_1);
7143 if (*needed > offered)
7144 return WERR_INSUFFICIENT_BUFFER;
7146 if (!rpcbuf_alloc_size(buffer, buffer_size))
7149 /* fill the buffer with the form structures */
7150 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7151 smb_io_form_1("", buffer, &form_1, 0);
7157 return WERR_UNKNOWN_LEVEL;
7161 /****************************************************************************
7162 ****************************************************************************/
7164 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7166 init_unistr(&port->port_name, name);
7169 /****************************************************************************
7170 ****************************************************************************/
7172 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7174 init_unistr(&port->port_name, name);
7175 init_unistr(&port->monitor_name, "Local Monitor");
7176 init_unistr(&port->description, "Local Port");
7177 port->port_type=PORT_TYPE_WRITE;
7182 /****************************************************************************
7183 wrapper around the enumer ports command
7184 ****************************************************************************/
7186 WERROR enumports_hook( int *count, char ***lines )
7188 char *cmd = lp_enumports_cmd();
7196 /* if no hook then just fill in the default port */
7199 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7200 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7205 /* we have a valid enumport command */
7207 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7209 DEBUG(10,("Running [%s]\n", command));
7210 ret = smbrun(command, &fd);
7211 DEBUG(10,("Returned [%d]\n", ret));
7216 return WERR_ACCESS_DENIED;
7220 qlines = fd_lines_load(fd, &numlines);
7221 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7231 /****************************************************************************
7233 ****************************************************************************/
7235 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7237 PORT_INFO_1 *ports=NULL;
7239 WERROR result = WERR_OK;
7243 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7247 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7248 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7249 dos_errstr(WERR_NOMEM)));
7250 file_lines_free(qlines);
7254 for (i=0; i<numlines; i++) {
7255 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7256 fill_port_1(&ports[i], qlines[i]);
7259 file_lines_free(qlines);
7262 *returned = numlines;
7264 /* check the required size. */
7265 for (i=0; i<*returned; i++) {
7266 DEBUGADD(6,("adding port [%d]'s size\n", i));
7267 *needed += spoolss_size_port_info_1(&ports[i]);
7270 if (*needed > offered) {
7271 result = WERR_INSUFFICIENT_BUFFER;
7275 if (!rpcbuf_alloc_size(buffer, *needed)) {
7276 result = WERR_NOMEM;
7280 /* fill the buffer with the ports structures */
7281 for (i=0; i<*returned; i++) {
7282 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7283 smb_io_port_1("", buffer, &ports[i], 0);
7289 if ( !W_ERROR_IS_OK(result) )
7295 /****************************************************************************
7297 ****************************************************************************/
7299 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7301 PORT_INFO_2 *ports=NULL;
7303 WERROR result = WERR_OK;
7307 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7312 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7313 file_lines_free(qlines);
7317 for (i=0; i<numlines; i++) {
7318 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7319 fill_port_2(&(ports[i]), qlines[i]);
7322 file_lines_free(qlines);
7325 *returned = numlines;
7327 /* check the required size. */
7328 for (i=0; i<*returned; i++) {
7329 DEBUGADD(6,("adding port [%d]'s size\n", i));
7330 *needed += spoolss_size_port_info_2(&ports[i]);
7333 if (*needed > offered) {
7334 result = WERR_INSUFFICIENT_BUFFER;
7338 if (!rpcbuf_alloc_size(buffer, *needed)) {
7339 result = WERR_NOMEM;
7343 /* fill the buffer with the ports structures */
7344 for (i=0; i<*returned; i++) {
7345 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7346 smb_io_port_2("", buffer, &ports[i], 0);
7352 if ( !W_ERROR_IS_OK(result) )
7358 /****************************************************************************
7360 ****************************************************************************/
7362 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7364 uint32 level = q_u->level;
7365 RPC_BUFFER *buffer = NULL;
7366 uint32 offered = q_u->offered;
7367 uint32 *needed = &r_u->needed;
7368 uint32 *returned = &r_u->returned;
7370 /* that's an [in out] buffer */
7372 if ( q_u->buffer ) {
7373 rpcbuf_move(q_u->buffer, &r_u->buffer);
7374 buffer = r_u->buffer;
7377 DEBUG(4,("_spoolss_enumports\n"));
7384 return enumports_level_1(buffer, offered, needed, returned);
7386 return enumports_level_2(buffer, offered, needed, returned);
7388 return WERR_UNKNOWN_LEVEL;
7392 /****************************************************************************
7393 ****************************************************************************/
7395 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7396 const SPOOL_PRINTER_INFO_LEVEL *info,
7397 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7398 uint32 user_switch, const SPOOL_USER_CTR *user,
7401 NT_PRINTER_INFO_LEVEL *printer = NULL;
7404 WERROR err = WERR_OK;
7406 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7407 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7411 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7412 if (!convert_printer_info(info, printer, 2)) {
7413 free_a_printer(&printer, 2);
7417 /* check to see if the printer already exists */
7419 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7420 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7421 printer->info_2->sharename));
7422 free_a_printer(&printer, 2);
7423 return WERR_PRINTER_ALREADY_EXISTS;
7426 /* FIXME!!! smbd should check to see if the driver is installed before
7427 trying to add a printer like this --jerry */
7429 if (*lp_addprinter_cmd() ) {
7430 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7431 free_a_printer(&printer,2);
7432 return WERR_ACCESS_DENIED;
7435 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7436 "smb.conf parameter \"addprinter command\" is defined. This"
7437 "parameter must exist for this call to succeed\n",
7438 printer->info_2->sharename ));
7441 /* use our primary netbios name since get_a_printer() will convert
7442 it to what the client expects on a case by case basis */
7444 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7445 printer->info_2->sharename);
7448 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7449 free_a_printer(&printer,2);
7450 return WERR_ACCESS_DENIED;
7453 /* you must be a printer admin to add a new printer */
7454 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7455 free_a_printer(&printer,2);
7456 return WERR_ACCESS_DENIED;
7460 * Do sanity check on the requested changes for Samba.
7463 if (!check_printer_ok(printer->info_2, snum)) {
7464 free_a_printer(&printer,2);
7465 return WERR_INVALID_PARAM;
7469 * When a printer is created, the drivername bound to the printer is used
7470 * to lookup previously saved driver initialization info, which is then
7471 * bound to the new printer, simulating what happens in the Windows arch.
7476 set_driver_init(printer, 2);
7480 /* A valid devmode was included, convert and link it
7482 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7484 if (!convert_devicemode(printer->info_2->printername, devmode,
7485 &printer->info_2->devmode))
7489 /* write the ASCII on disk */
7490 err = mod_a_printer(printer, 2);
7491 if (!W_ERROR_IS_OK(err)) {
7492 free_a_printer(&printer,2);
7496 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7497 /* Handle open failed - remove addition. */
7498 del_a_printer(printer->info_2->sharename);
7499 free_a_printer(&printer,2);
7500 return WERR_ACCESS_DENIED;
7503 update_c_setprinter(False);
7504 free_a_printer(&printer,2);
7509 /****************************************************************************
7510 ****************************************************************************/
7512 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7514 UNISTR2 *uni_srv_name = q_u->server_name;
7515 uint32 level = q_u->level;
7516 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7517 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7518 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7519 uint32 user_switch = q_u->user_switch;
7520 SPOOL_USER_CTR *user = &q_u->user_ctr;
7521 POLICY_HND *handle = &r_u->handle;
7525 /* we don't handle yet */
7526 /* but I know what to do ... */
7527 return WERR_UNKNOWN_LEVEL;
7529 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7531 user_switch, user, handle);
7533 return WERR_UNKNOWN_LEVEL;
7537 /****************************************************************************
7538 ****************************************************************************/
7540 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7542 uint32 level = q_u->level;
7543 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7544 WERROR err = WERR_OK;
7545 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7546 struct current_user user;
7547 fstring driver_name;
7550 ZERO_STRUCT(driver);
7552 get_current_user(&user, p);
7554 if (!convert_printer_driver_info(info, &driver, level)) {
7559 DEBUG(5,("Cleaning driver's information\n"));
7560 err = clean_up_driver_struct(driver, level, &user);
7561 if (!W_ERROR_IS_OK(err))
7564 DEBUG(5,("Moving driver to final destination\n"));
7565 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7569 if (add_a_printer_driver(driver, level)!=0) {
7570 err = WERR_ACCESS_DENIED;
7574 /* BEGIN_ADMIN_LOG */
7577 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7578 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7579 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7582 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7583 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7584 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7590 * I think this is where he DrvUpgradePrinter() hook would be
7591 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7592 * server. Right now, we just need to send ourselves a message
7593 * to update each printer bound to this driver. --jerry
7596 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7597 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7602 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7603 * decide if the driver init data should be deleted. The rules are:
7604 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7605 * 2) delete init data only if there is no 2k/Xp driver
7606 * 3) always delete init data
7607 * The generalized rule is always use init data from the highest order driver.
7608 * It is necessary to follow the driver install by an initialization step to
7609 * finish off this process.
7612 version = driver.info_3->cversion;
7613 else if (level == 6)
7614 version = driver.info_6->version;
7619 * 9x printer driver - never delete init data
7622 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7627 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7628 * there is no 2k/Xp driver init data for this driver name.
7632 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7634 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7636 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7638 if (!del_driver_init(driver_name))
7639 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7642 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7644 free_a_printer_driver(driver1,3);
7645 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7652 * 2k or Xp printer driver - always delete init data
7655 if (!del_driver_init(driver_name))
7656 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7660 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7666 free_a_printer_driver(driver, level);
7670 /********************************************************************
7671 * spoolss_addprinterdriverex
7672 ********************************************************************/
7674 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7676 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7677 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7680 * we only support the semantics of AddPrinterDriver()
7681 * i.e. only copy files that are newer than existing ones
7684 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7685 return WERR_ACCESS_DENIED;
7687 ZERO_STRUCT(q_u_local);
7688 ZERO_STRUCT(r_u_local);
7690 /* just pass the information off to _spoolss_addprinterdriver() */
7691 q_u_local.server_name_ptr = q_u->server_name_ptr;
7692 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7693 q_u_local.level = q_u->level;
7694 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7696 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7699 /****************************************************************************
7700 ****************************************************************************/
7702 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7704 init_unistr(&info->name, name);
7707 /****************************************************************************
7708 ****************************************************************************/
7710 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7716 const char *short_archi;
7717 DRIVER_DIRECTORY_1 *info=NULL;
7718 WERROR result = WERR_OK;
7720 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7721 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7723 /* check for beginning double '\'s and that the server
7726 pservername = servername;
7727 if ( *pservername == '\\' && strlen(servername)>2 ) {
7731 if ( !is_myname_or_ipaddr( pservername ) )
7732 return WERR_INVALID_PARAM;
7734 if (!(short_archi = get_short_archi(long_archi)))
7735 return WERR_INVALID_ENVIRONMENT;
7737 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7740 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7742 DEBUG(4,("printer driver directory: [%s]\n", path));
7744 fill_driverdir_1(info, path);
7746 *needed += spoolss_size_driverdir_info_1(info);
7748 if (*needed > offered) {
7749 result = WERR_INSUFFICIENT_BUFFER;
7753 if (!rpcbuf_alloc_size(buffer, *needed)) {
7754 result = WERR_NOMEM;
7758 smb_io_driverdir_1("", buffer, info, 0);
7766 /****************************************************************************
7767 ****************************************************************************/
7769 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7771 UNISTR2 *name = &q_u->name;
7772 UNISTR2 *uni_environment = &q_u->environment;
7773 uint32 level = q_u->level;
7774 RPC_BUFFER *buffer = NULL;
7775 uint32 offered = q_u->offered;
7776 uint32 *needed = &r_u->needed;
7778 /* that's an [in out] buffer */
7780 if ( q_u->buffer ) {
7781 rpcbuf_move(q_u->buffer, &r_u->buffer);
7782 buffer = r_u->buffer;
7785 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7791 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7793 return WERR_UNKNOWN_LEVEL;
7797 /****************************************************************************
7798 ****************************************************************************/
7800 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7802 POLICY_HND *handle = &q_u->handle;
7803 uint32 idx = q_u->index;
7804 uint32 in_value_len = q_u->valuesize;
7805 uint32 in_data_len = q_u->datasize;
7806 uint32 *out_max_value_len = &r_u->valuesize;
7807 uint16 **out_value = &r_u->value;
7808 uint32 *out_value_len = &r_u->realvaluesize;
7809 uint32 *out_type = &r_u->type;
7810 uint32 *out_max_data_len = &r_u->datasize;
7811 uint8 **data_out = &r_u->data;
7812 uint32 *out_data_len = &r_u->realdatasize;
7814 NT_PRINTER_INFO_LEVEL *printer = NULL;
7816 uint32 biggest_valuesize;
7817 uint32 biggest_datasize;
7819 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7822 REGISTRY_VALUE *val = NULL;
7823 NT_PRINTER_DATA *p_data;
7824 int i, key_index, num_values;
7829 *out_max_data_len = 0;
7833 DEBUG(5,("spoolss_enumprinterdata\n"));
7836 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7840 if (!get_printer_snum(p,handle, &snum))
7843 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7844 if (!W_ERROR_IS_OK(result))
7847 p_data = printer->info_2->data;
7848 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7853 * The NT machine wants to know the biggest size of value and data
7855 * cf: MSDN EnumPrinterData remark section
7858 if ( !in_value_len && !in_data_len && (key_index != -1) )
7860 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7862 biggest_valuesize = 0;
7863 biggest_datasize = 0;
7865 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7867 for ( i=0; i<num_values; i++ )
7869 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7871 name_length = strlen(val->valuename);
7872 if ( strlen(val->valuename) > biggest_valuesize )
7873 biggest_valuesize = name_length;
7875 if ( val->size > biggest_datasize )
7876 biggest_datasize = val->size;
7878 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7882 /* the value is an UNICODE string but real_value_size is the length
7883 in bytes including the trailing 0 */
7885 *out_value_len = 2 * (1+biggest_valuesize);
7886 *out_data_len = biggest_datasize;
7888 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7894 * the value len is wrong in NT sp3
7895 * that's the number of bytes not the number of unicode chars
7898 if ( key_index != -1 )
7899 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7904 /* out_value should default to "" or else NT4 has
7905 problems unmarshalling the response */
7907 *out_max_value_len=(in_value_len/sizeof(uint16));
7909 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7911 result = WERR_NOMEM;
7915 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7917 /* the data is counted in bytes */
7919 *out_max_data_len = in_data_len;
7920 *out_data_len = in_data_len;
7922 /* only allocate when given a non-zero data_len */
7924 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7926 result = WERR_NOMEM;
7930 result = WERR_NO_MORE_ITEMS;
7936 * - counted in bytes in the request
7937 * - counted in UNICODE chars in the max reply
7938 * - counted in bytes in the real size
7940 * take a pause *before* coding not *during* coding
7944 *out_max_value_len=(in_value_len/sizeof(uint16));
7945 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7947 result = WERR_NOMEM;
7951 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7955 *out_type = regval_type( val );
7957 /* data - counted in bytes */
7959 *out_max_data_len = in_data_len;
7960 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7962 result = WERR_NOMEM;
7965 data_len = regval_size(val);
7967 memcpy( *data_out, regval_data_p(val), data_len );
7968 *out_data_len = data_len;
7972 free_a_printer(&printer, 2);
7976 /****************************************************************************
7977 ****************************************************************************/
7979 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7981 POLICY_HND *handle = &q_u->handle;
7982 UNISTR2 *value = &q_u->value;
7983 uint32 type = q_u->type;
7984 uint8 *data = q_u->data;
7985 uint32 real_len = q_u->real_len;
7987 NT_PRINTER_INFO_LEVEL *printer = NULL;
7989 WERROR status = WERR_OK;
7990 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7993 DEBUG(5,("spoolss_setprinterdata\n"));
7996 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8000 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8001 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8002 return WERR_INVALID_PARAM;
8005 if (!get_printer_snum(p,handle, &snum))
8009 * Access check : NT returns "access denied" if you make a
8010 * SetPrinterData call without the necessary privildge.
8011 * we were originally returning OK if nothing changed
8012 * which made Win2k issue **a lot** of SetPrinterData
8013 * when connecting to a printer --jerry
8016 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8018 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8019 status = WERR_ACCESS_DENIED;
8023 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8024 if (!W_ERROR_IS_OK(status))
8027 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8030 * When client side code sets a magic printer data key, detect it and save
8031 * the current printer data and the magic key's data (its the DEVMODE) for
8032 * future printer/driver initializations.
8034 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8036 /* Set devmode and printer initialization info */
8037 status = save_driver_init( printer, 2, data, real_len );
8039 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8043 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8044 type, data, real_len );
8045 if ( W_ERROR_IS_OK(status) )
8046 status = mod_a_printer(printer, 2);
8050 free_a_printer(&printer, 2);
8055 /****************************************************************************
8056 ****************************************************************************/
8058 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8060 POLICY_HND *handle = &q_u->handle;
8061 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8064 DEBUG(5,("_spoolss_resetprinter\n"));
8067 * All we do is to check to see if the handle and queue is valid.
8068 * This call really doesn't mean anything to us because we only
8069 * support RAW printing. --jerry
8073 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8077 if (!get_printer_snum(p,handle, &snum))
8081 /* blindly return success */
8086 /****************************************************************************
8087 ****************************************************************************/
8089 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8091 POLICY_HND *handle = &q_u->handle;
8092 UNISTR2 *value = &q_u->valuename;
8094 NT_PRINTER_INFO_LEVEL *printer = NULL;
8096 WERROR status = WERR_OK;
8097 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8100 DEBUG(5,("spoolss_deleteprinterdata\n"));
8103 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8107 if (!get_printer_snum(p, handle, &snum))
8110 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8111 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8112 return WERR_ACCESS_DENIED;
8115 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8116 if (!W_ERROR_IS_OK(status))
8119 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8121 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8123 if ( W_ERROR_IS_OK(status) )
8124 mod_a_printer( printer, 2 );
8126 free_a_printer(&printer, 2);
8131 /****************************************************************************
8132 ****************************************************************************/
8134 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8136 POLICY_HND *handle = &q_u->handle;
8137 FORM *form = &q_u->form;
8138 nt_forms_struct tmpForm;
8140 WERROR status = WERR_OK;
8141 NT_PRINTER_INFO_LEVEL *printer = NULL;
8144 nt_forms_struct *list=NULL;
8145 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8147 DEBUG(5,("spoolss_addform\n"));
8150 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8155 /* forms can be added on printer of on the print server handle */
8157 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8159 if (!get_printer_snum(p,handle, &snum))
8162 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8163 if (!W_ERROR_IS_OK(status))
8167 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8168 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8169 status = WERR_ACCESS_DENIED;
8173 /* can't add if builtin */
8175 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8176 status = WERR_ALREADY_EXISTS;
8180 count = get_ntforms(&list);
8182 if(!add_a_form(&list, form, &count)) {
8183 status = WERR_NOMEM;
8187 write_ntforms(&list, count);
8190 * ChangeID must always be set if this is a printer
8193 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8194 status = mod_a_printer(printer, 2);
8198 free_a_printer(&printer, 2);
8204 /****************************************************************************
8205 ****************************************************************************/
8207 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8209 POLICY_HND *handle = &q_u->handle;
8210 UNISTR2 *form_name = &q_u->name;
8211 nt_forms_struct tmpForm;
8213 nt_forms_struct *list=NULL;
8214 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8216 WERROR status = WERR_OK;
8217 NT_PRINTER_INFO_LEVEL *printer = NULL;
8219 DEBUG(5,("spoolss_deleteform\n"));
8222 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8226 /* forms can be deleted on printer of on the print server handle */
8228 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8230 if (!get_printer_snum(p,handle, &snum))
8233 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8234 if (!W_ERROR_IS_OK(status))
8238 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8239 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8240 status = WERR_ACCESS_DENIED;
8244 /* can't delete if builtin */
8246 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8247 status = WERR_INVALID_PARAM;
8251 count = get_ntforms(&list);
8253 if ( !delete_a_form(&list, form_name, &count, &status ))
8257 * ChangeID must always be set if this is a printer
8260 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8261 status = mod_a_printer(printer, 2);
8265 free_a_printer(&printer, 2);
8271 /****************************************************************************
8272 ****************************************************************************/
8274 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8276 POLICY_HND *handle = &q_u->handle;
8277 FORM *form = &q_u->form;
8278 nt_forms_struct tmpForm;
8280 WERROR status = WERR_OK;
8281 NT_PRINTER_INFO_LEVEL *printer = NULL;
8284 nt_forms_struct *list=NULL;
8285 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8287 DEBUG(5,("spoolss_setform\n"));
8290 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8294 /* forms can be modified on printer of on the print server handle */
8296 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8298 if (!get_printer_snum(p,handle, &snum))
8301 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8302 if (!W_ERROR_IS_OK(status))
8306 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8307 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8308 status = WERR_ACCESS_DENIED;
8312 /* can't set if builtin */
8313 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8314 status = WERR_INVALID_PARAM;
8318 count = get_ntforms(&list);
8319 update_a_form(&list, form, count);
8320 write_ntforms(&list, count);
8323 * ChangeID must always be set if this is a printer
8326 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8327 status = mod_a_printer(printer, 2);
8332 free_a_printer(&printer, 2);
8338 /****************************************************************************
8339 enumprintprocessors level 1.
8340 ****************************************************************************/
8342 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8344 PRINTPROCESSOR_1 *info_1=NULL;
8345 WERROR result = WERR_OK;
8347 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8352 init_unistr(&info_1->name, "winprint");
8354 *needed += spoolss_size_printprocessor_info_1(info_1);
8356 if (*needed > offered) {
8357 result = WERR_INSUFFICIENT_BUFFER;
8361 if (!rpcbuf_alloc_size(buffer, *needed)) {
8362 result = WERR_NOMEM;
8366 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8371 if ( !W_ERROR_IS_OK(result) )
8377 /****************************************************************************
8378 ****************************************************************************/
8380 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8382 uint32 level = q_u->level;
8383 RPC_BUFFER *buffer = NULL;
8384 uint32 offered = q_u->offered;
8385 uint32 *needed = &r_u->needed;
8386 uint32 *returned = &r_u->returned;
8388 /* that's an [in out] buffer */
8390 if ( q_u->buffer ) {
8391 rpcbuf_move(q_u->buffer, &r_u->buffer);
8392 buffer = r_u->buffer;
8395 DEBUG(5,("spoolss_enumprintprocessors\n"));
8398 * Enumerate the print processors ...
8400 * Just reply with "winprint", to keep NT happy
8401 * and I can use my nice printer checker.
8409 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8411 return WERR_UNKNOWN_LEVEL;
8415 /****************************************************************************
8416 enumprintprocdatatypes level 1.
8417 ****************************************************************************/
8419 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8421 PRINTPROCDATATYPE_1 *info_1=NULL;
8422 WERROR result = WERR_NOMEM;
8424 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8429 init_unistr(&info_1->name, "RAW");
8431 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8433 if (*needed > offered) {
8434 result = WERR_INSUFFICIENT_BUFFER;
8438 if (!rpcbuf_alloc_size(buffer, *needed)) {
8439 result = WERR_NOMEM;
8443 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8448 if ( !W_ERROR_IS_OK(result) )
8454 /****************************************************************************
8455 ****************************************************************************/
8457 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8459 uint32 level = q_u->level;
8460 RPC_BUFFER *buffer = NULL;
8461 uint32 offered = q_u->offered;
8462 uint32 *needed = &r_u->needed;
8463 uint32 *returned = &r_u->returned;
8465 /* that's an [in out] buffer */
8467 if ( q_u->buffer ) {
8468 rpcbuf_move(q_u->buffer, &r_u->buffer);
8469 buffer = r_u->buffer;
8472 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8479 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8481 return WERR_UNKNOWN_LEVEL;
8485 /****************************************************************************
8486 enumprintmonitors level 1.
8487 ****************************************************************************/
8489 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8491 PRINTMONITOR_1 *info_1=NULL;
8492 WERROR result = WERR_OK;
8494 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8499 init_unistr(&info_1->name, "Local Port");
8501 *needed += spoolss_size_printmonitor_info_1(info_1);
8503 if (*needed > offered) {
8504 result = WERR_INSUFFICIENT_BUFFER;
8508 if (!rpcbuf_alloc_size(buffer, *needed)) {
8509 result = WERR_NOMEM;
8513 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8518 if ( !W_ERROR_IS_OK(result) )
8524 /****************************************************************************
8525 enumprintmonitors level 2.
8526 ****************************************************************************/
8528 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8530 PRINTMONITOR_2 *info_2=NULL;
8531 WERROR result = WERR_OK;
8533 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8538 init_unistr(&info_2->name, "Local Port");
8539 init_unistr(&info_2->environment, "Windows NT X86");
8540 init_unistr(&info_2->dll_name, "localmon.dll");
8542 *needed += spoolss_size_printmonitor_info_2(info_2);
8544 if (*needed > offered) {
8545 result = WERR_INSUFFICIENT_BUFFER;
8549 if (!rpcbuf_alloc_size(buffer, *needed)) {
8550 result = WERR_NOMEM;
8554 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8559 if ( !W_ERROR_IS_OK(result) )
8565 /****************************************************************************
8566 ****************************************************************************/
8568 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8570 uint32 level = q_u->level;
8571 RPC_BUFFER *buffer = NULL;
8572 uint32 offered = q_u->offered;
8573 uint32 *needed = &r_u->needed;
8574 uint32 *returned = &r_u->returned;
8576 /* that's an [in out] buffer */
8578 if ( q_u->buffer ) {
8579 rpcbuf_move(q_u->buffer, &r_u->buffer);
8580 buffer = r_u->buffer;
8583 DEBUG(5,("spoolss_enumprintmonitors\n"));
8586 * Enumerate the print monitors ...
8588 * Just reply with "Local Port", to keep NT happy
8589 * and I can use my nice printer checker.
8597 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8599 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8601 return WERR_UNKNOWN_LEVEL;
8605 /****************************************************************************
8606 ****************************************************************************/
8608 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8609 NT_PRINTER_INFO_LEVEL *ntprinter,
8610 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8615 JOB_INFO_1 *info_1=NULL;
8616 WERROR result = WERR_OK;
8618 info_1=SMB_MALLOC_P(JOB_INFO_1);
8620 if (info_1 == NULL) {
8624 for (i=0; i<count && found==False; i++) {
8625 if ((*queue)[i].job==(int)jobid)
8631 /* NT treats not found as bad param... yet another bad choice */
8632 return WERR_INVALID_PARAM;
8635 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8637 *needed += spoolss_size_job_info_1(info_1);
8639 if (*needed > offered) {
8640 result = WERR_INSUFFICIENT_BUFFER;
8644 if (!rpcbuf_alloc_size(buffer, *needed)) {
8645 result = WERR_NOMEM;
8649 smb_io_job_info_1("", buffer, info_1, 0);
8657 /****************************************************************************
8658 ****************************************************************************/
8660 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8661 NT_PRINTER_INFO_LEVEL *ntprinter,
8662 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8669 DEVICEMODE *devmode = NULL;
8670 NT_DEVICEMODE *nt_devmode = NULL;
8672 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8675 ZERO_STRUCTP(info_2);
8677 for ( i=0; i<count && found==False; i++ )
8679 if ((*queue)[i].job == (int)jobid)
8684 /* NT treats not found as bad param... yet another bad
8686 result = WERR_INVALID_PARAM;
8691 * if the print job does not have a DEVMODE associated with it,
8692 * just use the one for the printer. A NULL devicemode is not
8693 * a failure condition
8696 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8697 devmode = construct_dev_mode(snum);
8699 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8700 ZERO_STRUCTP( devmode );
8701 convert_nt_devicemode( devmode, nt_devmode );
8705 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8707 *needed += spoolss_size_job_info_2(info_2);
8709 if (*needed > offered) {
8710 result = WERR_INSUFFICIENT_BUFFER;
8714 if (!rpcbuf_alloc_size(buffer, *needed)) {
8715 result = WERR_NOMEM;
8719 smb_io_job_info_2("", buffer, info_2, 0);
8724 /* Cleanup allocated memory */
8726 free_job_info_2(info_2); /* Also frees devmode */
8732 /****************************************************************************
8733 ****************************************************************************/
8735 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8737 POLICY_HND *handle = &q_u->handle;
8738 uint32 jobid = q_u->jobid;
8739 uint32 level = q_u->level;
8740 RPC_BUFFER *buffer = NULL;
8741 uint32 offered = q_u->offered;
8742 uint32 *needed = &r_u->needed;
8743 WERROR wstatus = WERR_OK;
8744 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8747 print_queue_struct *queue = NULL;
8748 print_status_struct prt_status;
8750 /* that's an [in out] buffer */
8752 if ( q_u->buffer ) {
8753 rpcbuf_move(q_u->buffer, &r_u->buffer);
8754 buffer = r_u->buffer;
8757 DEBUG(5,("spoolss_getjob\n"));
8761 if (!get_printer_snum(p, handle, &snum))
8764 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8765 if ( !W_ERROR_IS_OK(wstatus) )
8768 count = print_queue_status(snum, &queue, &prt_status);
8770 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8771 count, prt_status.status, prt_status.message));
8775 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8776 buffer, offered, needed);
8779 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8780 buffer, offered, needed);
8783 wstatus = WERR_UNKNOWN_LEVEL;
8788 free_a_printer( &ntprinter, 2 );
8793 /********************************************************************
8794 spoolss_getprinterdataex
8796 From MSDN documentation of GetPrinterDataEx: pass request
8797 to GetPrinterData if key is "PrinterDriverData".
8798 ********************************************************************/
8800 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8802 POLICY_HND *handle = &q_u->handle;
8803 uint32 in_size = q_u->size;
8804 uint32 *type = &r_u->type;
8805 uint32 *out_size = &r_u->size;
8806 uint8 **data = &r_u->data;
8807 uint32 *needed = &r_u->needed;
8808 fstring keyname, valuename;
8810 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8812 NT_PRINTER_INFO_LEVEL *printer = NULL;
8814 WERROR status = WERR_OK;
8816 DEBUG(4,("_spoolss_getprinterdataex\n"));
8818 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8819 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8821 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8822 keyname, valuename));
8824 /* in case of problem, return some default values */
8828 *out_size = in_size;
8831 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8832 status = WERR_BADFID;
8836 /* Is the handle to a printer or to the server? */
8838 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8839 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8840 status = WERR_INVALID_PARAM;
8844 if ( !get_printer_snum(p,handle, &snum) )
8847 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8848 if ( !W_ERROR_IS_OK(status) )
8851 /* check to see if the keyname is valid */
8852 if ( !strlen(keyname) ) {
8853 status = WERR_INVALID_PARAM;
8857 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8858 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8859 free_a_printer( &printer, 2 );
8860 status = WERR_BADFILE;
8864 /* When given a new keyname, we should just create it */
8866 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8868 if (*needed > *out_size)
8869 status = WERR_MORE_DATA;
8872 if ( !W_ERROR_IS_OK(status) )
8874 DEBUG(5, ("error: allocating %d\n", *out_size));
8876 /* reply this param doesn't exist */
8880 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8881 status = WERR_NOMEM;
8891 free_a_printer( &printer, 2 );
8896 /********************************************************************
8897 * spoolss_setprinterdataex
8898 ********************************************************************/
8900 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8902 POLICY_HND *handle = &q_u->handle;
8903 uint32 type = q_u->type;
8904 uint8 *data = q_u->data;
8905 uint32 real_len = q_u->real_len;
8907 NT_PRINTER_INFO_LEVEL *printer = NULL;
8909 WERROR status = WERR_OK;
8910 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8915 DEBUG(4,("_spoolss_setprinterdataex\n"));
8917 /* From MSDN documentation of SetPrinterDataEx: pass request to
8918 SetPrinterData if key is "PrinterDriverData" */
8921 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8925 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8926 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8927 return WERR_INVALID_PARAM;
8930 if ( !get_printer_snum(p,handle, &snum) )
8934 * Access check : NT returns "access denied" if you make a
8935 * SetPrinterData call without the necessary privildge.
8936 * we were originally returning OK if nothing changed
8937 * which made Win2k issue **a lot** of SetPrinterData
8938 * when connecting to a printer --jerry
8941 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8943 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8944 return WERR_ACCESS_DENIED;
8947 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8948 if (!W_ERROR_IS_OK(status))
8951 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8952 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8954 /* check for OID in valuename */
8956 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8962 /* save the registry data */
8964 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8966 if ( W_ERROR_IS_OK(status) )
8968 /* save the OID if one was specified */
8970 fstrcat( keyname, "\\" );
8971 fstrcat( keyname, SPOOL_OID_KEY );
8974 * I'm not checking the status here on purpose. Don't know
8975 * if this is right, but I'm returning the status from the
8976 * previous set_printer_dataex() call. I have no idea if
8977 * this is right. --jerry
8980 set_printer_dataex( printer, keyname, valuename,
8981 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8984 status = mod_a_printer(printer, 2);
8987 free_a_printer(&printer, 2);
8993 /********************************************************************
8994 * spoolss_deleteprinterdataex
8995 ********************************************************************/
8997 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8999 POLICY_HND *handle = &q_u->handle;
9000 UNISTR2 *value = &q_u->valuename;
9001 UNISTR2 *key = &q_u->keyname;
9003 NT_PRINTER_INFO_LEVEL *printer = NULL;
9005 WERROR status = WERR_OK;
9006 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9007 pstring valuename, keyname;
9009 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9012 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9016 if (!get_printer_snum(p, handle, &snum))
9019 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9020 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9021 return WERR_ACCESS_DENIED;
9024 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9025 if (!W_ERROR_IS_OK(status))
9028 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9029 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9031 status = delete_printer_dataex( printer, keyname, valuename );
9033 if ( W_ERROR_IS_OK(status) )
9034 mod_a_printer( printer, 2 );
9036 free_a_printer(&printer, 2);
9041 /********************************************************************
9042 * spoolss_enumprinterkey
9043 ********************************************************************/
9046 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9049 fstring *keynames = NULL;
9050 uint16 *enumkeys = NULL;
9053 POLICY_HND *handle = &q_u->handle;
9054 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9055 NT_PRINTER_DATA *data;
9056 NT_PRINTER_INFO_LEVEL *printer = NULL;
9058 WERROR status = WERR_BADFILE;
9061 DEBUG(4,("_spoolss_enumprinterkey\n"));
9064 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9068 if ( !get_printer_snum(p,handle, &snum) )
9071 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9072 if (!W_ERROR_IS_OK(status))
9075 /* get the list of subkey names */
9077 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9078 data = printer->info_2->data;
9080 num_keys = get_printer_subkeys( data, key, &keynames );
9082 if ( num_keys == -1 ) {
9083 status = WERR_BADFILE;
9087 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9089 r_u->needed = printerkey_len*2;
9091 if ( q_u->size < r_u->needed ) {
9092 status = WERR_MORE_DATA;
9096 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9097 status = WERR_NOMEM;
9103 if ( q_u->size < r_u->needed )
9104 status = WERR_MORE_DATA;
9107 free_a_printer( &printer, 2 );
9108 SAFE_FREE( keynames );
9113 /********************************************************************
9114 * spoolss_deleteprinterkey
9115 ********************************************************************/
9117 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9119 POLICY_HND *handle = &q_u->handle;
9120 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9122 NT_PRINTER_INFO_LEVEL *printer = NULL;
9126 DEBUG(5,("spoolss_deleteprinterkey\n"));
9129 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9133 /* if keyname == NULL, return error */
9135 if ( !q_u->keyname.buffer )
9136 return WERR_INVALID_PARAM;
9138 if (!get_printer_snum(p, handle, &snum))
9141 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9142 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9143 return WERR_ACCESS_DENIED;
9146 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9147 if (!W_ERROR_IS_OK(status))
9150 /* delete the key and all subneys */
9152 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9154 status = delete_all_printer_data( printer->info_2, key );
9156 if ( W_ERROR_IS_OK(status) )
9157 status = mod_a_printer(printer, 2);
9159 free_a_printer( &printer, 2 );
9165 /********************************************************************
9166 * spoolss_enumprinterdataex
9167 ********************************************************************/
9169 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9171 POLICY_HND *handle = &q_u->handle;
9172 uint32 in_size = q_u->size;
9175 NT_PRINTER_INFO_LEVEL *printer = NULL;
9176 PRINTER_ENUM_VALUES *enum_values = NULL;
9177 NT_PRINTER_DATA *p_data;
9179 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9184 REGISTRY_VALUE *val;
9189 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9192 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9197 * first check for a keyname of NULL or "". Win2k seems to send
9198 * this a lot and we should send back WERR_INVALID_PARAM
9199 * no need to spend time looking up the printer in this case.
9203 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9204 if ( !strlen(key) ) {
9205 result = WERR_INVALID_PARAM;
9209 /* get the printer off of disk */
9211 if (!get_printer_snum(p,handle, &snum))
9214 ZERO_STRUCT(printer);
9215 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9216 if (!W_ERROR_IS_OK(result))
9219 /* now look for a match on the key name */
9221 p_data = printer->info_2->data;
9223 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9224 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9226 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9227 result = WERR_INVALID_PARAM;
9234 /* allocate the memory for the array of pointers -- if necessary */
9236 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9239 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9241 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9242 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9243 result = WERR_NOMEM;
9247 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9251 * loop through all params and build the array to pass
9252 * back to the client
9255 for ( i=0; i<num_entries; i++ )
9257 /* lookup the registry value */
9259 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9260 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9264 value_name = regval_name( val );
9265 init_unistr( &enum_values[i].valuename, value_name );
9266 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9267 enum_values[i].type = regval_type( val );
9269 data_len = regval_size( val );
9271 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9273 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9275 result = WERR_NOMEM;
9279 enum_values[i].data_len = data_len;
9281 /* keep track of the size of the array in bytes */
9283 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9286 /* housekeeping information in the reply */
9288 r_u->needed = needed;
9289 r_u->returned = num_entries;
9291 if (needed > in_size) {
9292 result = WERR_MORE_DATA;
9296 /* copy data into the reply */
9298 r_u->ctr.size = r_u->needed;
9299 r_u->ctr.size_of_array = r_u->returned;
9300 r_u->ctr.values = enum_values;
9306 free_a_printer(&printer, 2);
9311 /****************************************************************************
9312 ****************************************************************************/
9314 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9316 init_unistr(&info->name, name);
9319 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9320 UNISTR2 *environment,
9327 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9328 WERROR result = WERR_OK;
9330 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9332 if (!get_short_archi(long_archi))
9333 return WERR_INVALID_ENVIRONMENT;
9335 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9338 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9340 fill_printprocessordirectory_1(info, path);
9342 *needed += spoolss_size_printprocessordirectory_info_1(info);
9344 if (*needed > offered) {
9345 result = WERR_INSUFFICIENT_BUFFER;
9349 if (!rpcbuf_alloc_size(buffer, *needed)) {
9350 result = WERR_INSUFFICIENT_BUFFER;
9354 smb_io_printprocessordirectory_1("", buffer, info, 0);
9362 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9364 uint32 level = q_u->level;
9365 RPC_BUFFER *buffer = NULL;
9366 uint32 offered = q_u->offered;
9367 uint32 *needed = &r_u->needed;
9370 /* that's an [in out] buffer */
9372 if ( q_u->buffer ) {
9373 rpcbuf_move(q_u->buffer, &r_u->buffer);
9374 buffer = r_u->buffer;
9377 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9383 result = getprintprocessordirectory_level_1
9384 (&q_u->name, &q_u->environment, buffer, offered, needed);
9387 result = WERR_UNKNOWN_LEVEL;
9395 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9396 SPOOL_R_REPLYOPENPRINTER *r_u)
9398 DEBUG(5,("_spoolss_replyopenprinter\n"));
9400 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9405 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9406 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9408 DEBUG(5,("_spoolss_replycloseprinter\n"));