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 **)&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 */
484 snum = find_service(aprinter);
486 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
488 fstrcpy( sname, aprinter );
491 /* do another loop to look for printernames */
493 for (snum=0; !found && snum<n_services; snum++) {
495 /* no point in checking if this is not a printer or
496 we aren't allowing printername != sharename */
498 if ( !(lp_snum_ok(snum)
500 && !lp_force_printername(snum)) )
505 fstrcpy(sname, lp_servicename(snum));
508 result = get_a_printer( NULL, &printer, 2, sname );
509 if ( !W_ERROR_IS_OK(result) ) {
510 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
511 sname, dos_errstr(result)));
515 /* printername is always returned as \\server\printername */
516 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
517 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
518 printer->info_2->printername));
519 free_a_printer( &printer, 2);
525 if ( strequal(printername, aprinter) ) {
529 DEBUGADD(10, ("printername: %s\n", printername));
531 free_a_printer( &printer, 2);
535 DEBUGADD(4,("Printer not found\n"));
539 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
541 fstrcpy(Printer->sharename, sname);
546 /****************************************************************************
547 Find first available printer slot. creates a printer handle for you.
548 ****************************************************************************/
550 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
552 Printer_entry *new_printer;
554 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
556 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
559 ZERO_STRUCTP(new_printer);
561 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
562 SAFE_FREE(new_printer);
566 /* Add to the internal list. */
567 DLIST_ADD(printers_list, new_printer);
569 new_printer->notify.option=NULL;
571 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
572 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
573 close_printer_handle(p, hnd);
577 if (!set_printer_hnd_printertype(new_printer, name)) {
578 close_printer_handle(p, hnd);
582 if (!set_printer_hnd_name(new_printer, name)) {
583 close_printer_handle(p, hnd);
587 new_printer->access_granted = access_granted;
589 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
594 /***************************************************************************
595 check to see if the client motify handle is monitoring the notification
596 given by (notify_type, notify_field).
597 **************************************************************************/
599 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
605 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
608 SPOOL_NOTIFY_OPTION *option = p->notify.option;
612 * Flags should always be zero when the change notify
613 * is registered by the client's spooler. A user Win32 app
614 * might use the flags though instead of the NOTIFY_OPTION_INFO
623 return is_monitoring_event_flags(
624 p->notify.flags, notify_type, notify_field);
626 for (i = 0; i < option->count; i++) {
628 /* Check match for notify_type */
630 if (option->ctr.type[i].type != notify_type)
633 /* Check match for field */
635 for (j = 0; j < option->ctr.type[i].count; j++) {
636 if (option->ctr.type[i].fields[j] == notify_field) {
642 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
643 p->servername, p->sharename, notify_type, notify_field));
648 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
650 static void notify_one_value(struct spoolss_notify_msg *msg,
651 SPOOL_NOTIFY_INFO_DATA *data,
654 data->notify_data.value[0] = msg->notify.value[0];
655 data->notify_data.value[1] = 0;
658 static void notify_string(struct spoolss_notify_msg *msg,
659 SPOOL_NOTIFY_INFO_DATA *data,
664 /* The length of the message includes the trailing \0 */
666 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
668 data->notify_data.data.length = msg->len * 2;
669 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
671 if (!data->notify_data.data.string) {
672 data->notify_data.data.length = 0;
676 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
679 static void notify_system_time(struct spoolss_notify_msg *msg,
680 SPOOL_NOTIFY_INFO_DATA *data,
686 if (msg->len != sizeof(time_t)) {
687 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
692 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
693 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
697 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
698 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
702 if (!spoolss_io_system_time("", &ps, 0, &systime))
705 data->notify_data.data.length = prs_offset(&ps);
706 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
708 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
713 struct notify2_message_table {
715 void (*fn)(struct spoolss_notify_msg *msg,
716 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
719 static struct notify2_message_table printer_notify_table[] = {
720 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
721 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
722 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
723 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
724 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
725 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
726 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
727 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
728 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
729 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
730 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
731 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
732 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
733 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
734 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
735 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
736 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
737 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
738 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
741 static struct notify2_message_table job_notify_table[] = {
742 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
743 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
744 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
745 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
746 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
747 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
748 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
749 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
750 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
751 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
752 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
753 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
754 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
755 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
756 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
757 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
758 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
759 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
760 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
761 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
762 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
763 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
764 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
765 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
769 /***********************************************************************
770 Allocate talloc context for container object
771 **********************************************************************/
773 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
778 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
783 /***********************************************************************
784 release all allocated memory and zero out structure
785 **********************************************************************/
787 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
793 talloc_destroy(ctr->ctx);
800 /***********************************************************************
801 **********************************************************************/
803 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
811 /***********************************************************************
812 **********************************************************************/
814 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
816 if ( !ctr || !ctr->msg_groups )
819 if ( idx >= ctr->num_groups )
822 return &ctr->msg_groups[idx];
826 /***********************************************************************
827 How many groups of change messages do we have ?
828 **********************************************************************/
830 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
835 return ctr->num_groups;
838 /***********************************************************************
839 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
840 **********************************************************************/
842 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
844 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
845 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
846 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
852 /* loop over all groups looking for a matching printer name */
854 for ( i=0; i<ctr->num_groups; i++ ) {
855 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
859 /* add a new group? */
861 if ( i == ctr->num_groups ) {
864 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
865 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
868 ctr->msg_groups = groups;
870 /* clear the new entry and set the printer name */
872 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
873 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
876 /* add the change messages; 'i' is the correct index now regardless */
878 msg_grp = &ctr->msg_groups[i];
882 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
883 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
886 msg_grp->msgs = msg_list;
888 new_slot = msg_grp->num_msgs-1;
889 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
891 /* need to allocate own copy of data */
894 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
896 return ctr->num_groups;
899 /***********************************************************************
900 Send a change notication message on all handles which have a call
902 **********************************************************************/
904 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
907 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
908 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
909 SPOOLSS_NOTIFY_MSG *messages;
910 int sending_msg_count;
913 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
917 messages = msg_group->msgs;
920 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
924 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
926 /* loop over all printers */
928 for (p = printers_list; p; p = p->next) {
929 SPOOL_NOTIFY_INFO_DATA *data;
934 /* Is there notification on this handle? */
936 if ( !p->notify.client_connected )
939 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
941 /* For this printer? Print servers always receive
944 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
945 ( !strequal(msg_group->printername, p->sharename) ) )
948 DEBUG(10,("Our printer\n"));
950 /* allocate the max entries possible */
952 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
955 /* build the array of change notifications */
957 sending_msg_count = 0;
959 for ( i=0; i<msg_group->num_msgs; i++ ) {
960 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
962 /* Are we monitoring this event? */
964 if (!is_monitoring_event(p, msg->type, msg->field))
970 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
971 msg->type, msg->field, p->sharename));
974 * if the is a printer notification handle and not a job notification
975 * type, then set the id to 0. Other wise just use what was specified
978 * When registering change notification on a print server handle
979 * we always need to send back the id (snum) matching the printer
980 * for which the change took place. For change notify registered
981 * on a printer handle, this does not matter and the id should be 0.
986 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
992 /* Convert unix jobid to smb jobid */
994 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
995 id = sysjob_to_jobid(msg->id);
998 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1003 construct_info_data( &data[data_len], msg->type, msg->field, id );
1006 case PRINTER_NOTIFY_TYPE:
1007 if ( printer_notify_table[msg->field].fn )
1008 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1011 case JOB_NOTIFY_TYPE:
1012 if ( job_notify_table[msg->field].fn )
1013 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1017 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1024 if ( sending_msg_count ) {
1025 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1026 data_len, data, p->notify.change, 0 );
1031 DEBUG(8,("send_notify2_changes: Exit...\n"));
1035 /***********************************************************************
1036 **********************************************************************/
1038 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1041 uint32 tv_sec, tv_usec;
1044 /* Unpack message */
1046 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1049 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1051 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1054 tdb_unpack((char *)buf + offset, len - offset, "dd",
1055 &msg->notify.value[0], &msg->notify.value[1]);
1057 tdb_unpack((char *)buf + offset, len - offset, "B",
1058 &msg->len, &msg->notify.data);
1060 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1061 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1063 tv->tv_sec = tv_sec;
1064 tv->tv_usec = tv_usec;
1067 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1068 msg->notify.value[1]));
1070 dump_data(3, msg->notify.data, msg->len);
1075 /********************************************************************
1076 Receive a notify2 message list
1077 ********************************************************************/
1079 static void receive_notify2_message_list(int msg_type, struct process_id src,
1080 void *msg, size_t len)
1082 size_t msg_count, i;
1083 char *buf = (char *)msg;
1086 SPOOLSS_NOTIFY_MSG notify;
1087 SPOOLSS_NOTIFY_MSG_CTR messages;
1091 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1095 msg_count = IVAL(buf, 0);
1098 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1100 if (msg_count == 0) {
1101 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1105 /* initialize the container */
1107 ZERO_STRUCT( messages );
1108 notify_msg_ctr_init( &messages );
1111 * build message groups for each printer identified
1112 * in a change_notify msg. Remember that a PCN message
1113 * includes the handle returned for the srv_spoolss_replyopenprinter()
1114 * call. Therefore messages are grouped according to printer handle.
1117 for ( i=0; i<msg_count; i++ ) {
1118 struct timeval msg_tv;
1120 if (msg_ptr + 4 - buf > len) {
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1125 msg_len = IVAL(msg_ptr,0);
1128 if (msg_ptr + msg_len - buf > len) {
1129 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1133 /* unpack messages */
1135 ZERO_STRUCT( notify );
1136 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1139 /* add to correct list in container */
1141 notify_msg_ctr_addmsg( &messages, ¬ify );
1143 /* free memory that might have been allocated by notify2_unpack_msg() */
1145 if ( notify.len != 0 )
1146 SAFE_FREE( notify.notify.data );
1149 /* process each group of messages */
1151 num_groups = notify_msg_ctr_numgroups( &messages );
1152 for ( i=0; i<num_groups; i++ )
1153 send_notify2_changes( &messages, i );
1158 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1160 notify_msg_ctr_destroy( &messages );
1165 /********************************************************************
1166 Send a message to ourself about new driver being installed
1167 so we can upgrade the information for each printer bound to this
1169 ********************************************************************/
1171 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1173 int len = strlen(drivername);
1178 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1181 message_send_pid(pid_to_procid(sys_getpid()),
1182 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1187 /**********************************************************************
1188 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1189 over all printers, upgrading ones as necessary
1190 **********************************************************************/
1192 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1196 int n_services = lp_numservices();
1198 len = MIN(len,sizeof(drivername)-1);
1199 strncpy(drivername, buf, len);
1201 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1203 /* Iterate the printer list */
1205 for (snum=0; snum<n_services; snum++)
1207 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1210 NT_PRINTER_INFO_LEVEL *printer = NULL;
1212 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1213 if (!W_ERROR_IS_OK(result))
1216 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1218 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1220 /* all we care about currently is the change_id */
1222 result = mod_a_printer(printer, 2);
1223 if (!W_ERROR_IS_OK(result)) {
1224 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1225 dos_errstr(result)));
1229 free_a_printer(&printer, 2);
1236 /********************************************************************
1237 Update the cache for all printq's with a registered client
1239 ********************************************************************/
1241 void update_monitored_printq_cache( void )
1243 Printer_entry *printer = printers_list;
1246 /* loop through all printers and update the cache where
1247 client_connected == True */
1250 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1251 && printer->notify.client_connected )
1253 snum = print_queue_snum(printer->sharename);
1254 print_queue_status( snum, NULL, NULL );
1257 printer = printer->next;
1262 /********************************************************************
1263 Send a message to ourself about new driver being installed
1264 so we can upgrade the information for each printer bound to this
1266 ********************************************************************/
1268 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1270 int len = strlen(drivername);
1275 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1278 message_send_pid(pid_to_procid(sys_getpid()),
1279 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1284 /**********************************************************************
1285 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1286 over all printers, resetting printer data as neessary
1287 **********************************************************************/
1289 void reset_all_printerdata(int msg_type, struct process_id src,
1290 void *buf, size_t len)
1294 int n_services = lp_numservices();
1296 len = MIN( len, sizeof(drivername)-1 );
1297 strncpy( drivername, buf, len );
1299 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1301 /* Iterate the printer list */
1303 for ( snum=0; snum<n_services; snum++ )
1305 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1308 NT_PRINTER_INFO_LEVEL *printer = NULL;
1310 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1311 if ( !W_ERROR_IS_OK(result) )
1315 * if the printer is bound to the driver,
1316 * then reset to the new driver initdata
1319 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1321 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1323 if ( !set_driver_init(printer, 2) ) {
1324 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1325 printer->info_2->printername, printer->info_2->drivername));
1328 result = mod_a_printer( printer, 2 );
1329 if ( !W_ERROR_IS_OK(result) ) {
1330 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1331 get_dos_error_msg(result)));
1335 free_a_printer( &printer, 2 );
1344 /********************************************************************
1345 Copy routines used by convert_to_openprinterex()
1346 *******************************************************************/
1348 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1356 DEBUG (8,("dup_devmode\n"));
1358 /* bulk copy first */
1360 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1364 /* dup the pointer members separately */
1366 len = unistrlen(devmode->devicename.buffer);
1368 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1369 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1374 len = unistrlen(devmode->formname.buffer);
1376 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1377 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1381 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1386 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1388 if (!new_ctr || !ctr)
1391 DEBUG(8,("copy_devmode_ctr\n"));
1393 new_ctr->size = ctr->size;
1394 new_ctr->devmode_ptr = ctr->devmode_ptr;
1396 if(ctr->devmode_ptr)
1397 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1400 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1402 if (!new_def || !def)
1405 DEBUG(8,("copy_printer_defaults\n"));
1407 new_def->datatype_ptr = def->datatype_ptr;
1409 if (def->datatype_ptr)
1410 copy_unistr2(&new_def->datatype, &def->datatype);
1412 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1414 new_def->access_required = def->access_required;
1417 /********************************************************************
1418 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1419 * SPOOL_Q_OPEN_PRINTER_EX structure
1420 ********************************************************************/
1422 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1424 if (!q_u_ex || !q_u)
1427 DEBUG(8,("convert_to_openprinterex\n"));
1429 if ( q_u->printername ) {
1430 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1431 if (q_u_ex->printername == NULL)
1433 copy_unistr2(q_u_ex->printername, q_u->printername);
1436 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1441 /********************************************************************
1442 * spoolss_open_printer
1444 * called from the spoolss dispatcher
1445 ********************************************************************/
1447 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1449 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1450 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1455 ZERO_STRUCT(q_u_ex);
1456 ZERO_STRUCT(r_u_ex);
1458 /* convert the OpenPrinter() call to OpenPrinterEx() */
1460 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1461 if (!W_ERROR_IS_OK(r_u_ex.status))
1462 return r_u_ex.status;
1464 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1466 /* convert back to OpenPrinter() */
1468 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1473 /********************************************************************
1474 * spoolss_open_printer
1476 * If the openprinterex rpc call contains a devmode,
1477 * it's a per-user one. This per-user devmode is derivated
1478 * from the global devmode. Openprinterex() contains a per-user
1479 * devmode for when you do EMF printing and spooling.
1480 * In the EMF case, the NT workstation is only doing half the job
1481 * of rendering the page. The other half is done by running the printer
1482 * driver on the server.
1483 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1484 * The EMF file only contains what is to be printed on the page.
1485 * So in order for the server to know how to print, the NT client sends
1486 * a devicemode attached to the openprinterex call.
1487 * But this devicemode is short lived, it's only valid for the current print job.
1489 * If Samba would have supported EMF spooling, this devicemode would
1490 * have been attached to the handle, to sent it to the driver to correctly
1491 * rasterize the EMF file.
1493 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1494 * we just act as a pass-thru between windows and the printer.
1496 * In order to know that Samba supports only RAW spooling, NT has to call
1497 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1498 * and until NT sends a RAW job, we refuse it.
1500 * But to call getprinter() or startdoc(), you first need a valid handle,
1501 * and to get an handle you have to call openprintex(). Hence why you have
1502 * a devicemode in the openprinterex() call.
1505 * Differences between NT4 and NT 2000.
1508 * On NT4, you only have a global devicemode. This global devicemode can be changed
1509 * by the administrator (or by a user with enough privs). Everytime a user
1510 * wants to print, the devicemode is resetted to the default. In Word, everytime
1511 * you print, the printer's characteristics are always reset to the global devicemode.
1515 * In W2K, there is the notion of per-user devicemode. The first time you use
1516 * a printer, a per-user devicemode is build from the global devicemode.
1517 * If you change your per-user devicemode, it is saved in the registry, under the
1518 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1519 * printer preferences available.
1521 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1522 * on the General Tab of the printer properties windows.
1524 * To change the global devicemode: it's the "Printing Defaults..." button
1525 * on the Advanced Tab of the printer properties window.
1528 ********************************************************************/
1530 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1532 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1533 POLICY_HND *handle = &r_u->handle;
1537 struct current_user user;
1538 Printer_entry *Printer=NULL;
1540 if ( !q_u->printername )
1541 return WERR_INVALID_PRINTER_NAME;
1543 /* some sanity check because you can open a printer or a print server */
1544 /* aka: \\server\printer or \\server */
1546 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1548 DEBUGADD(3,("checking name: %s\n",name));
1550 if (!open_printer_hnd(p, handle, name, 0))
1551 return WERR_INVALID_PRINTER_NAME;
1553 Printer=find_printer_index_by_hnd(p, handle);
1555 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1556 "handle we created for printer %s\n", name ));
1557 close_printer_handle(p,handle);
1558 return WERR_INVALID_PRINTER_NAME;
1561 get_current_user(&user, p);
1564 * First case: the user is opening the print server:
1566 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1567 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1569 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1570 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1571 * or if the user is listed in the smb.conf printer admin parameter.
1573 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1574 * client view printer folder, but does not show the MSAPW.
1576 * Note: this test needs code to check access rights here too. Jeremy
1577 * could you look at this?
1579 * Second case: the user is opening a printer:
1580 * NT doesn't let us connect to a printer if the connecting user
1581 * doesn't have print permission.
1584 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1586 /* Printserver handles use global struct... */
1590 /* Map standard access rights to object specific access rights */
1592 se_map_standard(&printer_default->access_required,
1593 &printserver_std_mapping);
1595 /* Deny any object specific bits that don't apply to print
1596 servers (i.e printer and job specific bits) */
1598 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1600 if (printer_default->access_required &
1601 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1602 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1603 close_printer_handle(p, handle);
1604 return WERR_ACCESS_DENIED;
1607 /* Allow admin access */
1609 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1611 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1613 if (!lp_ms_add_printer_wizard()) {
1614 close_printer_handle(p, handle);
1615 return WERR_ACCESS_DENIED;
1618 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1619 and not a printer admin, then fail */
1622 && !user_has_privileges( user.nt_user_token, &se_printop )
1623 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1625 close_printer_handle(p, handle);
1626 return WERR_ACCESS_DENIED;
1629 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1633 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1636 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1637 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1639 /* We fall through to return WERR_OK */
1644 /* NT doesn't let us connect to a printer if the connecting user
1645 doesn't have print permission. */
1647 if (!get_printer_snum(p, handle, &snum)) {
1648 close_printer_handle(p, handle);
1652 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1654 /* map an empty access mask to the minimum access mask */
1655 if (printer_default->access_required == 0x0)
1656 printer_default->access_required = PRINTER_ACCESS_USE;
1659 * If we are not serving the printer driver for this printer,
1660 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1661 * will keep NT clients happy --jerry
1664 if (lp_use_client_driver(snum)
1665 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1667 printer_default->access_required = PRINTER_ACCESS_USE;
1670 /* check smb.conf parameters and the the sec_desc */
1672 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1673 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1674 return WERR_ACCESS_DENIED;
1677 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1678 DEBUG(3, ("access DENIED for printer open\n"));
1679 close_printer_handle(p, handle);
1680 return WERR_ACCESS_DENIED;
1683 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1684 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1685 close_printer_handle(p, handle);
1686 return WERR_ACCESS_DENIED;
1689 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1690 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1692 printer_default->access_required = PRINTER_ACCESS_USE;
1694 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1695 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1699 Printer->access_granted = printer_default->access_required;
1702 * If the client sent a devmode in the OpenPrinter() call, then
1703 * save it here in case we get a job submission on this handle
1706 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1707 && q_u->printer_default.devmode_cont.devmode_ptr )
1709 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1710 &Printer->nt_devmode );
1713 #if 0 /* JERRY -- I'm doubtful this is really effective */
1714 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1715 optimization in Windows 2000 clients --jerry */
1717 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1718 && (RA_WIN2K == get_remote_arch()) )
1720 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1721 sys_usleep( 500000 );
1728 /****************************************************************************
1729 ****************************************************************************/
1731 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1732 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1738 /* allocate memory if needed. Messy because
1739 convert_printer_info is used to update an existing
1740 printer or build a new one */
1742 if ( !printer->info_2 ) {
1743 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1744 if ( !printer->info_2 ) {
1745 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1750 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1751 printer->info_2->setuptime = time(NULL);
1759 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1760 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1766 printer->info_3=NULL;
1767 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1771 printer->info_6=NULL;
1772 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1782 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1783 NT_DEVICEMODE **pp_nt_devmode)
1785 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1788 * Ensure nt_devmode is a valid pointer
1789 * as we will be overwriting it.
1792 if (nt_devmode == NULL) {
1793 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1794 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1798 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1799 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1801 nt_devmode->specversion=devmode->specversion;
1802 nt_devmode->driverversion=devmode->driverversion;
1803 nt_devmode->size=devmode->size;
1804 nt_devmode->fields=devmode->fields;
1805 nt_devmode->orientation=devmode->orientation;
1806 nt_devmode->papersize=devmode->papersize;
1807 nt_devmode->paperlength=devmode->paperlength;
1808 nt_devmode->paperwidth=devmode->paperwidth;
1809 nt_devmode->scale=devmode->scale;
1810 nt_devmode->copies=devmode->copies;
1811 nt_devmode->defaultsource=devmode->defaultsource;
1812 nt_devmode->printquality=devmode->printquality;
1813 nt_devmode->color=devmode->color;
1814 nt_devmode->duplex=devmode->duplex;
1815 nt_devmode->yresolution=devmode->yresolution;
1816 nt_devmode->ttoption=devmode->ttoption;
1817 nt_devmode->collate=devmode->collate;
1819 nt_devmode->logpixels=devmode->logpixels;
1820 nt_devmode->bitsperpel=devmode->bitsperpel;
1821 nt_devmode->pelswidth=devmode->pelswidth;
1822 nt_devmode->pelsheight=devmode->pelsheight;
1823 nt_devmode->displayflags=devmode->displayflags;
1824 nt_devmode->displayfrequency=devmode->displayfrequency;
1825 nt_devmode->icmmethod=devmode->icmmethod;
1826 nt_devmode->icmintent=devmode->icmintent;
1827 nt_devmode->mediatype=devmode->mediatype;
1828 nt_devmode->dithertype=devmode->dithertype;
1829 nt_devmode->reserved1=devmode->reserved1;
1830 nt_devmode->reserved2=devmode->reserved2;
1831 nt_devmode->panningwidth=devmode->panningwidth;
1832 nt_devmode->panningheight=devmode->panningheight;
1835 * Only change private and driverextra if the incoming devmode
1836 * has a new one. JRA.
1839 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1840 SAFE_FREE(nt_devmode->nt_dev_private);
1841 nt_devmode->driverextra=devmode->driverextra;
1842 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1844 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1847 *pp_nt_devmode = nt_devmode;
1852 /********************************************************************
1853 * _spoolss_enddocprinter_internal.
1854 ********************************************************************/
1856 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1858 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1862 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1866 if (!get_printer_snum(p, handle, &snum))
1869 Printer->document_started=False;
1870 print_job_end(snum, Printer->jobid,True);
1871 /* error codes unhandled so far ... */
1876 /********************************************************************
1877 * api_spoolss_closeprinter
1878 ********************************************************************/
1880 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1882 POLICY_HND *handle = &q_u->handle;
1884 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1886 if (Printer && Printer->document_started)
1887 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1889 if (!close_printer_handle(p, handle))
1892 /* clear the returned printer handle. Observed behavior
1893 from Win2k server. Don't think this really matters.
1894 Previous code just copied the value of the closed
1897 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1902 /********************************************************************
1903 * api_spoolss_deleteprinter
1905 ********************************************************************/
1907 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1909 POLICY_HND *handle = &q_u->handle;
1910 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1913 if (Printer && Printer->document_started)
1914 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1916 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1918 result = delete_printer_handle(p, handle);
1920 update_c_setprinter(False);
1925 /*******************************************************************
1926 * static function to lookup the version id corresponding to an
1927 * long architecture string
1928 ******************************************************************/
1930 static int get_version_id (char * arch)
1933 struct table_node archi_table[]= {
1935 {"Windows 4.0", "WIN40", 0 },
1936 {"Windows NT x86", "W32X86", 2 },
1937 {"Windows NT R4000", "W32MIPS", 2 },
1938 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1939 {"Windows NT PowerPC", "W32PPC", 2 },
1940 {"Windows IA64", "IA64", 3 },
1941 {"Windows x64", "x64", 3 },
1945 for (i=0; archi_table[i].long_archi != NULL; i++)
1947 if (strcmp(arch, archi_table[i].long_archi) == 0)
1948 return (archi_table[i].version);
1954 /********************************************************************
1955 * _spoolss_deleteprinterdriver
1956 ********************************************************************/
1958 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1962 NT_PRINTER_DRIVER_INFO_LEVEL info;
1963 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1965 struct current_user user;
1967 WERROR status_win2k = WERR_ACCESS_DENIED;
1969 get_current_user(&user, p);
1971 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1972 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1974 /* check that we have a valid driver name first */
1976 if ((version=get_version_id(arch)) == -1)
1977 return WERR_INVALID_ENVIRONMENT;
1980 ZERO_STRUCT(info_win2k);
1982 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1984 /* try for Win2k driver if "Windows NT x86" */
1986 if ( version == 2 ) {
1988 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1989 status = WERR_UNKNOWN_PRINTER_DRIVER;
1993 /* otherwise it was a failure */
1995 status = WERR_UNKNOWN_PRINTER_DRIVER;
2001 if (printer_driver_in_use(info.info_3)) {
2002 status = WERR_PRINTER_DRIVER_IN_USE;
2008 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2010 /* if we get to here, we now have 2 driver info structures to remove */
2011 /* remove the Win2k driver first*/
2013 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2014 free_a_printer_driver( info_win2k, 3 );
2016 /* this should not have failed---if it did, report to client */
2017 if ( !W_ERROR_IS_OK(status_win2k) )
2019 status = status_win2k;
2025 status = delete_printer_driver(info.info_3, &user, version, False);
2027 /* if at least one of the deletes succeeded return OK */
2029 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2033 free_a_printer_driver( info, 3 );
2038 /********************************************************************
2039 * spoolss_deleteprinterdriverex
2040 ********************************************************************/
2042 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2046 NT_PRINTER_DRIVER_INFO_LEVEL info;
2047 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2049 uint32 flags = q_u->delete_flags;
2051 struct current_user user;
2053 WERROR status_win2k = WERR_ACCESS_DENIED;
2055 get_current_user(&user, p);
2057 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2058 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2060 /* check that we have a valid driver name first */
2061 if ((version=get_version_id(arch)) == -1) {
2062 /* this is what NT returns */
2063 return WERR_INVALID_ENVIRONMENT;
2066 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2067 version = q_u->version;
2070 ZERO_STRUCT(info_win2k);
2072 status = get_a_printer_driver(&info, 3, driver, arch, version);
2074 if ( !W_ERROR_IS_OK(status) )
2077 * if the client asked for a specific version,
2078 * or this is something other than Windows NT x86,
2082 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2085 /* try for Win2k driver if "Windows NT x86" */
2088 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2089 status = WERR_UNKNOWN_PRINTER_DRIVER;
2094 if ( printer_driver_in_use(info.info_3) ) {
2095 status = WERR_PRINTER_DRIVER_IN_USE;
2100 * we have a couple of cases to consider.
2101 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2102 * then the delete should fail if **any** files overlap with
2104 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2105 * non-overlapping files
2106 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2107 * is set, the do not delete any files
2108 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2111 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2113 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2115 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2116 /* no idea of the correct error here */
2117 status = WERR_ACCESS_DENIED;
2122 /* also check for W32X86/3 if necessary; maybe we already have? */
2124 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2125 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2128 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2129 /* no idea of the correct error here */
2130 free_a_printer_driver( info_win2k, 3 );
2131 status = WERR_ACCESS_DENIED;
2135 /* if we get to here, we now have 2 driver info structures to remove */
2136 /* remove the Win2k driver first*/
2138 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2139 free_a_printer_driver( info_win2k, 3 );
2141 /* this should not have failed---if it did, report to client */
2143 if ( !W_ERROR_IS_OK(status_win2k) )
2148 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2150 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2153 free_a_printer_driver( info, 3 );
2159 /****************************************************************************
2160 Internal routine for retreiving printerdata
2161 ***************************************************************************/
2163 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2164 const char *key, const char *value, uint32 *type, uint8 **data,
2165 uint32 *needed, uint32 in_size )
2167 REGISTRY_VALUE *val;
2171 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2172 return WERR_BADFILE;
2174 *type = regval_type( val );
2176 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2178 size = regval_size( val );
2180 /* copy the min(in_size, len) */
2183 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2185 /* special case for 0 length values */
2187 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2191 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2200 DEBUG(5,("get_printer_dataex: copy done\n"));
2205 /****************************************************************************
2206 Internal routine for removing printerdata
2207 ***************************************************************************/
2209 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2211 return delete_printer_data( printer->info_2, key, value );
2214 /****************************************************************************
2215 Internal routine for storing printerdata
2216 ***************************************************************************/
2218 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2219 uint32 type, uint8 *data, int real_len )
2221 /* the registry objects enforce uniqueness based on value name */
2223 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2226 /********************************************************************
2227 GetPrinterData on a printer server Handle.
2228 ********************************************************************/
2230 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2234 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2236 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2238 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2244 if (!StrCaseCmp(value, "BeepEnabled")) {
2246 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2248 SIVAL(*data, 0, 0x00);
2253 if (!StrCaseCmp(value, "EventLog")) {
2255 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2257 /* formally was 0x1b */
2258 SIVAL(*data, 0, 0x0);
2263 if (!StrCaseCmp(value, "NetPopup")) {
2265 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2267 SIVAL(*data, 0, 0x00);
2272 if (!StrCaseCmp(value, "MajorVersion")) {
2274 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2277 /* Windows NT 4.0 seems to not allow uploading of drivers
2278 to a server that reports 0x3 as the MajorVersion.
2279 need to investigate more how Win2k gets around this .
2282 if ( RA_WINNT == get_remote_arch() )
2291 if (!StrCaseCmp(value, "MinorVersion")) {
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2301 * uint32 size = 0x114
2303 * uint32 minor = [0|1]
2304 * uint32 build = [2195|2600]
2305 * extra unicode string = e.g. "Service Pack 3"
2307 if (!StrCaseCmp(value, "OSVersion")) {
2311 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2314 SIVAL(*data, 0, *needed); /* size */
2315 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2317 SIVAL(*data, 12, 2195); /* build */
2319 /* leave extra string empty */
2325 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2326 const char *string="C:\\PRINTERS";
2328 *needed = 2*(strlen(string)+1);
2329 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2331 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2333 /* it's done by hand ready to go on the wire */
2334 for (i=0; i<strlen(string); i++) {
2335 (*data)[2*i]=string[i];
2336 (*data)[2*i+1]='\0';
2341 if (!StrCaseCmp(value, "Architecture")) {
2342 const char *string="Windows NT x86";
2344 *needed = 2*(strlen(string)+1);
2345 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2347 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2348 for (i=0; i<strlen(string); i++) {
2349 (*data)[2*i]=string[i];
2350 (*data)[2*i+1]='\0';
2355 if (!StrCaseCmp(value, "DsPresent")) {
2357 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2360 /* only show the publish check box if we are a
2361 memeber of a AD domain */
2363 if ( lp_security() == SEC_ADS )
2364 SIVAL(*data, 0, 0x01);
2366 SIVAL(*data, 0, 0x00);
2372 if (!StrCaseCmp(value, "DNSMachineName")) {
2375 if (!get_mydnsfullname(hostname))
2376 return WERR_BADFILE;
2378 *needed = 2*(strlen(hostname)+1);
2379 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2381 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2382 for (i=0; i<strlen(hostname); i++) {
2383 (*data)[2*i]=hostname[i];
2384 (*data)[2*i+1]='\0';
2390 return WERR_BADFILE;
2393 /********************************************************************
2394 * spoolss_getprinterdata
2395 ********************************************************************/
2397 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2399 POLICY_HND *handle = &q_u->handle;
2400 UNISTR2 *valuename = &q_u->valuename;
2401 uint32 in_size = q_u->size;
2402 uint32 *type = &r_u->type;
2403 uint32 *out_size = &r_u->size;
2404 uint8 **data = &r_u->data;
2405 uint32 *needed = &r_u->needed;
2408 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2409 NT_PRINTER_INFO_LEVEL *printer = NULL;
2413 * Reminder: when it's a string, the length is in BYTES
2414 * even if UNICODE is negociated.
2419 *out_size = in_size;
2421 /* in case of problem, return some default values */
2426 DEBUG(4,("_spoolss_getprinterdata\n"));
2429 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2430 status = WERR_BADFID;
2434 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2436 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2437 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2440 if ( !get_printer_snum(p,handle, &snum) ) {
2441 status = WERR_BADFID;
2445 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2446 if ( !W_ERROR_IS_OK(status) )
2449 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2451 if ( strequal(value, "ChangeId") ) {
2453 *needed = sizeof(uint32);
2454 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2455 status = WERR_NOMEM;
2458 SIVAL( *data, 0, printer->info_2->changeid );
2462 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2465 if (*needed > *out_size)
2466 status = WERR_MORE_DATA;
2469 if ( !W_ERROR_IS_OK(status) )
2471 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2473 /* reply this param doesn't exist */
2476 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2478 free_a_printer( &printer, 2 );
2487 /* cleanup & exit */
2490 free_a_printer( &printer, 2 );
2495 /*********************************************************
2496 Connect to the client machine.
2497 **********************************************************/
2499 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2500 struct in_addr *client_ip, const char *remote_machine)
2503 struct cli_state *the_cli;
2504 struct in_addr rm_addr;
2506 if ( is_zero_ip(*client_ip) ) {
2507 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2508 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2512 if ( ismyip( rm_addr )) {
2513 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2517 rm_addr.s_addr = client_ip->s_addr;
2518 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2519 inet_ntoa(*client_ip) ));
2522 /* setup the connection */
2524 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2525 &rm_addr, 0, "IPC$", "IPC",
2529 0, lp_client_signing(), NULL );
2531 if ( !NT_STATUS_IS_OK( ret ) ) {
2532 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2537 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2538 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2539 cli_shutdown(the_cli);
2544 * Ok - we have an anonymous connection to the IPC$ share.
2545 * Now start the NT Domain stuff :-).
2548 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2549 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2550 remote_machine, nt_errstr(ret)));
2551 cli_shutdown(the_cli);
2555 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2557 (*pp_pipe)->cli = the_cli;
2562 /***************************************************************************
2563 Connect to the client.
2564 ****************************************************************************/
2566 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2567 uint32 localprinter, uint32 type,
2568 POLICY_HND *handle, struct in_addr *client_ip)
2573 * If it's the first connection, contact the client
2574 * and connect to the IPC$ share anonymously
2576 if (smb_connections==0) {
2577 fstring unix_printer;
2579 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2581 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2584 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2585 /* Tell the connections db we're now interested in printer
2586 * notify messages. */
2587 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2591 * Tell the specific printing tdb we want messages for this printer
2592 * by registering our PID.
2595 if (!print_notify_register_pid(snum))
2596 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2600 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2603 if (!W_ERROR_IS_OK(result))
2604 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2605 dos_errstr(result)));
2607 return (W_ERROR_IS_OK(result));
2610 /********************************************************************
2612 * ReplyFindFirstPrinterChangeNotifyEx
2614 * before replying OK: status=0 a rpc call is made to the workstation
2615 * asking ReplyOpenPrinter
2617 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2618 * called from api_spoolss_rffpcnex
2619 ********************************************************************/
2621 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2623 POLICY_HND *handle = &q_u->handle;
2624 uint32 flags = q_u->flags;
2625 uint32 options = q_u->options;
2626 UNISTR2 *localmachine = &q_u->localmachine;
2627 uint32 printerlocal = q_u->printerlocal;
2629 SPOOL_NOTIFY_OPTION *option = q_u->option;
2630 struct in_addr client_ip;
2632 /* store the notify value in the printer struct */
2634 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2637 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2641 Printer->notify.flags=flags;
2642 Printer->notify.options=options;
2643 Printer->notify.printerlocal=printerlocal;
2645 if (Printer->notify.option)
2646 free_spool_notify_option(&Printer->notify.option);
2648 Printer->notify.option=dup_spool_notify_option(option);
2650 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2651 sizeof(Printer->notify.localmachine)-1);
2653 /* Connect to the client machine and send a ReplyOpenPrinter */
2655 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2657 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2658 !get_printer_snum(p, handle, &snum) )
2661 client_ip.s_addr = inet_addr(p->conn->client_address);
2663 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2664 Printer->notify.printerlocal, 1,
2665 &Printer->notify.client_hnd, &client_ip))
2666 return WERR_SERVER_UNAVAILABLE;
2668 Printer->notify.client_connected=True;
2673 /*******************************************************************
2674 * fill a notify_info_data with the servername
2675 ********************************************************************/
2677 void spoolss_notify_server_name(int snum,
2678 SPOOL_NOTIFY_INFO_DATA *data,
2679 print_queue_struct *queue,
2680 NT_PRINTER_INFO_LEVEL *printer,
2681 TALLOC_CTX *mem_ctx)
2686 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2688 data->notify_data.data.length = len;
2689 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2691 if (!data->notify_data.data.string) {
2692 data->notify_data.data.length = 0;
2696 memcpy(data->notify_data.data.string, temp, len);
2699 /*******************************************************************
2700 * fill a notify_info_data with the printername (not including the servername).
2701 ********************************************************************/
2703 void spoolss_notify_printer_name(int snum,
2704 SPOOL_NOTIFY_INFO_DATA *data,
2705 print_queue_struct *queue,
2706 NT_PRINTER_INFO_LEVEL *printer,
2707 TALLOC_CTX *mem_ctx)
2712 /* the notify name should not contain the \\server\ part */
2713 char *p = strrchr(printer->info_2->printername, '\\');
2716 p = printer->info_2->printername;
2721 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2723 data->notify_data.data.length = len;
2724 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2726 if (!data->notify_data.data.string) {
2727 data->notify_data.data.length = 0;
2731 memcpy(data->notify_data.data.string, temp, len);
2734 /*******************************************************************
2735 * fill a notify_info_data with the servicename
2736 ********************************************************************/
2738 void spoolss_notify_share_name(int snum,
2739 SPOOL_NOTIFY_INFO_DATA *data,
2740 print_queue_struct *queue,
2741 NT_PRINTER_INFO_LEVEL *printer,
2742 TALLOC_CTX *mem_ctx)
2747 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2749 data->notify_data.data.length = len;
2750 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2752 if (!data->notify_data.data.string) {
2753 data->notify_data.data.length = 0;
2757 memcpy(data->notify_data.data.string, temp, len);
2760 /*******************************************************************
2761 * fill a notify_info_data with the port name
2762 ********************************************************************/
2764 void spoolss_notify_port_name(int snum,
2765 SPOOL_NOTIFY_INFO_DATA *data,
2766 print_queue_struct *queue,
2767 NT_PRINTER_INFO_LEVEL *printer,
2768 TALLOC_CTX *mem_ctx)
2773 /* even if it's strange, that's consistant in all the code */
2775 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2777 data->notify_data.data.length = len;
2778 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2780 if (!data->notify_data.data.string) {
2781 data->notify_data.data.length = 0;
2785 memcpy(data->notify_data.data.string, temp, len);
2788 /*******************************************************************
2789 * fill a notify_info_data with the printername
2790 * but it doesn't exist, have to see what to do
2791 ********************************************************************/
2793 void spoolss_notify_driver_name(int snum,
2794 SPOOL_NOTIFY_INFO_DATA *data,
2795 print_queue_struct *queue,
2796 NT_PRINTER_INFO_LEVEL *printer,
2797 TALLOC_CTX *mem_ctx)
2802 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2804 data->notify_data.data.length = len;
2805 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2807 if (!data->notify_data.data.string) {
2808 data->notify_data.data.length = 0;
2812 memcpy(data->notify_data.data.string, temp, len);
2815 /*******************************************************************
2816 * fill a notify_info_data with the comment
2817 ********************************************************************/
2819 void spoolss_notify_comment(int snum,
2820 SPOOL_NOTIFY_INFO_DATA *data,
2821 print_queue_struct *queue,
2822 NT_PRINTER_INFO_LEVEL *printer,
2823 TALLOC_CTX *mem_ctx)
2828 if (*printer->info_2->comment == '\0')
2829 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2831 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2833 data->notify_data.data.length = len;
2834 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2836 if (!data->notify_data.data.string) {
2837 data->notify_data.data.length = 0;
2841 memcpy(data->notify_data.data.string, temp, len);
2844 /*******************************************************************
2845 * fill a notify_info_data with the comment
2846 * location = "Room 1, floor 2, building 3"
2847 ********************************************************************/
2849 void spoolss_notify_location(int snum,
2850 SPOOL_NOTIFY_INFO_DATA *data,
2851 print_queue_struct *queue,
2852 NT_PRINTER_INFO_LEVEL *printer,
2853 TALLOC_CTX *mem_ctx)
2858 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2860 data->notify_data.data.length = len;
2861 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2863 if (!data->notify_data.data.string) {
2864 data->notify_data.data.length = 0;
2868 memcpy(data->notify_data.data.string, temp, len);
2871 /*******************************************************************
2872 * fill a notify_info_data with the device mode
2873 * jfm:xxxx don't to it for know but that's a real problem !!!
2874 ********************************************************************/
2876 static void spoolss_notify_devmode(int snum,
2877 SPOOL_NOTIFY_INFO_DATA *data,
2878 print_queue_struct *queue,
2879 NT_PRINTER_INFO_LEVEL *printer,
2880 TALLOC_CTX *mem_ctx)
2884 /*******************************************************************
2885 * fill a notify_info_data with the separator file name
2886 ********************************************************************/
2888 void spoolss_notify_sepfile(int snum,
2889 SPOOL_NOTIFY_INFO_DATA *data,
2890 print_queue_struct *queue,
2891 NT_PRINTER_INFO_LEVEL *printer,
2892 TALLOC_CTX *mem_ctx)
2897 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2899 data->notify_data.data.length = len;
2900 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2902 if (!data->notify_data.data.string) {
2903 data->notify_data.data.length = 0;
2907 memcpy(data->notify_data.data.string, temp, len);
2910 /*******************************************************************
2911 * fill a notify_info_data with the print processor
2912 * jfm:xxxx return always winprint to indicate we don't do anything to it
2913 ********************************************************************/
2915 void spoolss_notify_print_processor(int snum,
2916 SPOOL_NOTIFY_INFO_DATA *data,
2917 print_queue_struct *queue,
2918 NT_PRINTER_INFO_LEVEL *printer,
2919 TALLOC_CTX *mem_ctx)
2924 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2926 data->notify_data.data.length = len;
2927 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2929 if (!data->notify_data.data.string) {
2930 data->notify_data.data.length = 0;
2934 memcpy(data->notify_data.data.string, temp, len);
2937 /*******************************************************************
2938 * fill a notify_info_data with the print processor options
2939 * jfm:xxxx send an empty string
2940 ********************************************************************/
2942 void spoolss_notify_parameters(int snum,
2943 SPOOL_NOTIFY_INFO_DATA *data,
2944 print_queue_struct *queue,
2945 NT_PRINTER_INFO_LEVEL *printer,
2946 TALLOC_CTX *mem_ctx)
2951 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2953 data->notify_data.data.length = len;
2954 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2956 if (!data->notify_data.data.string) {
2957 data->notify_data.data.length = 0;
2961 memcpy(data->notify_data.data.string, temp, len);
2964 /*******************************************************************
2965 * fill a notify_info_data with the data type
2966 * jfm:xxxx always send RAW as data type
2967 ********************************************************************/
2969 void spoolss_notify_datatype(int snum,
2970 SPOOL_NOTIFY_INFO_DATA *data,
2971 print_queue_struct *queue,
2972 NT_PRINTER_INFO_LEVEL *printer,
2973 TALLOC_CTX *mem_ctx)
2978 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2980 data->notify_data.data.length = len;
2981 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2983 if (!data->notify_data.data.string) {
2984 data->notify_data.data.length = 0;
2988 memcpy(data->notify_data.data.string, temp, len);
2991 /*******************************************************************
2992 * fill a notify_info_data with the security descriptor
2993 * jfm:xxxx send an null pointer to say no security desc
2994 * have to implement security before !
2995 ********************************************************************/
2997 static void spoolss_notify_security_desc(int snum,
2998 SPOOL_NOTIFY_INFO_DATA *data,
2999 print_queue_struct *queue,
3000 NT_PRINTER_INFO_LEVEL *printer,
3001 TALLOC_CTX *mem_ctx)
3003 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3004 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3007 /*******************************************************************
3008 * fill a notify_info_data with the attributes
3009 * jfm:xxxx a samba printer is always shared
3010 ********************************************************************/
3012 void spoolss_notify_attributes(int snum,
3013 SPOOL_NOTIFY_INFO_DATA *data,
3014 print_queue_struct *queue,
3015 NT_PRINTER_INFO_LEVEL *printer,
3016 TALLOC_CTX *mem_ctx)
3018 data->notify_data.value[0] = printer->info_2->attributes;
3019 data->notify_data.value[1] = 0;
3022 /*******************************************************************
3023 * fill a notify_info_data with the priority
3024 ********************************************************************/
3026 static void spoolss_notify_priority(int snum,
3027 SPOOL_NOTIFY_INFO_DATA *data,
3028 print_queue_struct *queue,
3029 NT_PRINTER_INFO_LEVEL *printer,
3030 TALLOC_CTX *mem_ctx)
3032 data->notify_data.value[0] = printer->info_2->priority;
3033 data->notify_data.value[1] = 0;
3036 /*******************************************************************
3037 * fill a notify_info_data with the default priority
3038 ********************************************************************/
3040 static void spoolss_notify_default_priority(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 data->notify_data.value[0] = printer->info_2->default_priority;
3047 data->notify_data.value[1] = 0;
3050 /*******************************************************************
3051 * fill a notify_info_data with the start time
3052 ********************************************************************/
3054 static void spoolss_notify_start_time(int snum,
3055 SPOOL_NOTIFY_INFO_DATA *data,
3056 print_queue_struct *queue,
3057 NT_PRINTER_INFO_LEVEL *printer,
3058 TALLOC_CTX *mem_ctx)
3060 data->notify_data.value[0] = printer->info_2->starttime;
3061 data->notify_data.value[1] = 0;
3064 /*******************************************************************
3065 * fill a notify_info_data with the until time
3066 ********************************************************************/
3068 static void spoolss_notify_until_time(int snum,
3069 SPOOL_NOTIFY_INFO_DATA *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 data->notify_data.value[0] = printer->info_2->untiltime;
3075 data->notify_data.value[1] = 0;
3078 /*******************************************************************
3079 * fill a notify_info_data with the status
3080 ********************************************************************/
3082 static void spoolss_notify_status(int snum,
3083 SPOOL_NOTIFY_INFO_DATA *data,
3084 print_queue_struct *queue,
3085 NT_PRINTER_INFO_LEVEL *printer,
3086 TALLOC_CTX *mem_ctx)
3088 print_status_struct status;
3090 print_queue_length(snum, &status);
3091 data->notify_data.value[0]=(uint32) status.status;
3092 data->notify_data.value[1] = 0;
3095 /*******************************************************************
3096 * fill a notify_info_data with the number of jobs queued
3097 ********************************************************************/
3099 void spoolss_notify_cjobs(int snum,
3100 SPOOL_NOTIFY_INFO_DATA *data,
3101 print_queue_struct *queue,
3102 NT_PRINTER_INFO_LEVEL *printer,
3103 TALLOC_CTX *mem_ctx)
3105 data->notify_data.value[0] = print_queue_length(snum, NULL);
3106 data->notify_data.value[1] = 0;
3109 /*******************************************************************
3110 * fill a notify_info_data with the average ppm
3111 ********************************************************************/
3113 static void spoolss_notify_average_ppm(int snum,
3114 SPOOL_NOTIFY_INFO_DATA *data,
3115 print_queue_struct *queue,
3116 NT_PRINTER_INFO_LEVEL *printer,
3117 TALLOC_CTX *mem_ctx)
3119 /* always respond 8 pages per minutes */
3120 /* a little hard ! */
3121 data->notify_data.value[0] = printer->info_2->averageppm;
3122 data->notify_data.value[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with username
3127 ********************************************************************/
3129 static void spoolss_notify_username(int snum,
3130 SPOOL_NOTIFY_INFO_DATA *data,
3131 print_queue_struct *queue,
3132 NT_PRINTER_INFO_LEVEL *printer,
3133 TALLOC_CTX *mem_ctx)
3138 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3140 data->notify_data.data.length = len;
3141 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3143 if (!data->notify_data.data.string) {
3144 data->notify_data.data.length = 0;
3148 memcpy(data->notify_data.data.string, temp, len);
3151 /*******************************************************************
3152 * fill a notify_info_data with job status
3153 ********************************************************************/
3155 static void spoolss_notify_job_status(int snum,
3156 SPOOL_NOTIFY_INFO_DATA *data,
3157 print_queue_struct *queue,
3158 NT_PRINTER_INFO_LEVEL *printer,
3159 TALLOC_CTX *mem_ctx)
3161 data->notify_data.value[0]=nt_printj_status(queue->status);
3162 data->notify_data.value[1] = 0;
3165 /*******************************************************************
3166 * fill a notify_info_data with job name
3167 ********************************************************************/
3169 static void spoolss_notify_job_name(int snum,
3170 SPOOL_NOTIFY_INFO_DATA *data,
3171 print_queue_struct *queue,
3172 NT_PRINTER_INFO_LEVEL *printer,
3173 TALLOC_CTX *mem_ctx)
3178 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3180 data->notify_data.data.length = len;
3181 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3183 if (!data->notify_data.data.string) {
3184 data->notify_data.data.length = 0;
3188 memcpy(data->notify_data.data.string, temp, len);
3191 /*******************************************************************
3192 * fill a notify_info_data with job status
3193 ********************************************************************/
3195 static void spoolss_notify_job_status_string(int snum,
3196 SPOOL_NOTIFY_INFO_DATA *data,
3197 print_queue_struct *queue,
3198 NT_PRINTER_INFO_LEVEL *printer,
3199 TALLOC_CTX *mem_ctx)
3202 * Now we're returning job status codes we just return a "" here. JRA.
3209 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3212 switch (queue->status) {
3217 p = ""; /* NT provides the paused string */
3226 #endif /* NO LONGER NEEDED. */
3228 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3230 data->notify_data.data.length = len;
3231 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3233 if (!data->notify_data.data.string) {
3234 data->notify_data.data.length = 0;
3238 memcpy(data->notify_data.data.string, temp, len);
3241 /*******************************************************************
3242 * fill a notify_info_data with job time
3243 ********************************************************************/
3245 static void spoolss_notify_job_time(int snum,
3246 SPOOL_NOTIFY_INFO_DATA *data,
3247 print_queue_struct *queue,
3248 NT_PRINTER_INFO_LEVEL *printer,
3249 TALLOC_CTX *mem_ctx)
3251 data->notify_data.value[0]=0x0;
3252 data->notify_data.value[1]=0;
3255 /*******************************************************************
3256 * fill a notify_info_data with job size
3257 ********************************************************************/
3259 static void spoolss_notify_job_size(int snum,
3260 SPOOL_NOTIFY_INFO_DATA *data,
3261 print_queue_struct *queue,
3262 NT_PRINTER_INFO_LEVEL *printer,
3263 TALLOC_CTX *mem_ctx)
3265 data->notify_data.value[0]=queue->size;
3266 data->notify_data.value[1]=0;
3269 /*******************************************************************
3270 * fill a notify_info_data with page info
3271 ********************************************************************/
3272 static void spoolss_notify_total_pages(int snum,
3273 SPOOL_NOTIFY_INFO_DATA *data,
3274 print_queue_struct *queue,
3275 NT_PRINTER_INFO_LEVEL *printer,
3276 TALLOC_CTX *mem_ctx)
3278 data->notify_data.value[0]=queue->page_count;
3279 data->notify_data.value[1]=0;
3282 /*******************************************************************
3283 * fill a notify_info_data with pages printed info.
3284 ********************************************************************/
3285 static void spoolss_notify_pages_printed(int snum,
3286 SPOOL_NOTIFY_INFO_DATA *data,
3287 print_queue_struct *queue,
3288 NT_PRINTER_INFO_LEVEL *printer,
3289 TALLOC_CTX *mem_ctx)
3291 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3292 data->notify_data.value[1]=0;
3295 /*******************************************************************
3296 Fill a notify_info_data with job position.
3297 ********************************************************************/
3299 static void spoolss_notify_job_position(int snum,
3300 SPOOL_NOTIFY_INFO_DATA *data,
3301 print_queue_struct *queue,
3302 NT_PRINTER_INFO_LEVEL *printer,
3303 TALLOC_CTX *mem_ctx)
3305 data->notify_data.value[0]=queue->job;
3306 data->notify_data.value[1]=0;
3309 /*******************************************************************
3310 Fill a notify_info_data with submitted time.
3311 ********************************************************************/
3313 static void spoolss_notify_submitted_time(int snum,
3314 SPOOL_NOTIFY_INFO_DATA *data,
3315 print_queue_struct *queue,
3316 NT_PRINTER_INFO_LEVEL *printer,
3317 TALLOC_CTX *mem_ctx)
3324 t=gmtime(&queue->time);
3326 len = sizeof(SYSTEMTIME);
3328 data->notify_data.data.length = len;
3329 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3331 if (!data->notify_data.data.string) {
3332 data->notify_data.data.length = 0;
3336 make_systemtime(&st, t);
3339 * Systemtime must be linearized as a set of UINT16's.
3340 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3343 p = (char *)data->notify_data.data.string;
3344 SSVAL(p, 0, st.year);
3345 SSVAL(p, 2, st.month);
3346 SSVAL(p, 4, st.dayofweek);
3347 SSVAL(p, 6, st.day);
3348 SSVAL(p, 8, st.hour);
3349 SSVAL(p, 10, st.minute);
3350 SSVAL(p, 12, st.second);
3351 SSVAL(p, 14, st.milliseconds);
3354 struct s_notify_info_data_table
3360 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3361 print_queue_struct *queue,
3362 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3365 /* A table describing the various print notification constants and
3366 whether the notification data is a pointer to a variable sized
3367 buffer, a one value uint32 or a two value uint32. */
3369 static const struct s_notify_info_data_table notify_info_data_table[] =
3371 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3372 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3373 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3374 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3375 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3376 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3377 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3378 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3397 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3398 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3399 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3400 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3401 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3402 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3403 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3404 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3420 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3423 /*******************************************************************
3424 Return the size of info_data structure.
3425 ********************************************************************/
3427 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3431 for (i = 0; i < sizeof(notify_info_data_table); i++)
3433 if ( (notify_info_data_table[i].type == type)
3434 && (notify_info_data_table[i].field == field) )
3436 switch(notify_info_data_table[i].size)
3438 case NOTIFY_ONE_VALUE:
3439 case NOTIFY_TWO_VALUE:
3444 /* The only pointer notify data I have seen on
3445 the wire is the submitted time and this has
3446 the notify size set to 4. -tpot */
3448 case NOTIFY_POINTER:
3451 case NOTIFY_SECDESC:
3457 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3462 /*******************************************************************
3463 Return the type of notify_info_data.
3464 ********************************************************************/
3466 static int type_of_notify_info_data(uint16 type, uint16 field)
3470 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3471 if (notify_info_data_table[i].type == type &&
3472 notify_info_data_table[i].field == field)
3473 return notify_info_data_table[i].size;
3479 /****************************************************************************
3480 ****************************************************************************/
3482 static int search_notify(uint16 type, uint16 field, int *value)
3486 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3487 if (notify_info_data_table[i].type == type &&
3488 notify_info_data_table[i].field == field &&
3489 notify_info_data_table[i].fn != NULL) {
3498 /****************************************************************************
3499 ****************************************************************************/
3501 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3503 info_data->type = type;
3504 info_data->field = field;
3505 info_data->reserved = 0;
3507 info_data->size = size_of_notify_info_data(type, field);
3508 info_data->enc_type = type_of_notify_info_data(type, field);
3515 /*******************************************************************
3517 * fill a notify_info struct with info asked
3519 ********************************************************************/
3521 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3522 snum, SPOOL_NOTIFY_OPTION_TYPE
3523 *option_type, uint32 id,
3524 TALLOC_CTX *mem_ctx)
3530 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3531 NT_PRINTER_INFO_LEVEL *printer = NULL;
3532 print_queue_struct *queue=NULL;
3534 type=option_type->type;
3536 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3537 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3538 option_type->count, lp_servicename(snum)));
3540 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3543 for(field_num=0; field_num<option_type->count; field_num++) {
3544 field = option_type->fields[field_num];
3546 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3548 if (!search_notify(type, field, &j) )
3551 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3552 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3557 current_data = &info->data[info->count];
3559 construct_info_data(current_data, type, field, id);
3561 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3562 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3564 notify_info_data_table[j].fn(snum, current_data, queue,
3570 free_a_printer(&printer, 2);
3574 /*******************************************************************
3576 * fill a notify_info struct with info asked
3578 ********************************************************************/
3580 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3581 SPOOL_NOTIFY_INFO *info,
3582 NT_PRINTER_INFO_LEVEL *printer,
3583 int snum, SPOOL_NOTIFY_OPTION_TYPE
3584 *option_type, uint32 id,
3585 TALLOC_CTX *mem_ctx)
3591 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3593 DEBUG(4,("construct_notify_jobs_info\n"));
3595 type = option_type->type;
3597 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3598 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3599 option_type->count));
3601 for(field_num=0; field_num<option_type->count; field_num++) {
3602 field = option_type->fields[field_num];
3604 if (!search_notify(type, field, &j) )
3607 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3608 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3611 else info->data = tid;
3613 current_data=&(info->data[info->count]);
3615 construct_info_data(current_data, type, field, id);
3616 notify_info_data_table[j].fn(snum, current_data, queue,
3625 * JFM: The enumeration is not that simple, it's even non obvious.
3627 * let's take an example: I want to monitor the PRINTER SERVER for
3628 * the printer's name and the number of jobs currently queued.
3629 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3630 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3632 * I have 3 printers on the back of my server.
3634 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3637 * 1 printer 1 name 1
3638 * 2 printer 1 cjob 1
3639 * 3 printer 2 name 2
3640 * 4 printer 2 cjob 2
3641 * 5 printer 3 name 3
3642 * 6 printer 3 name 3
3644 * that's the print server case, the printer case is even worse.
3647 /*******************************************************************
3649 * enumerate all printers on the printserver
3650 * fill a notify_info struct with info asked
3652 ********************************************************************/
3654 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3655 SPOOL_NOTIFY_INFO *info,
3656 TALLOC_CTX *mem_ctx)
3659 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3660 int n_services=lp_numservices();
3662 SPOOL_NOTIFY_OPTION *option;
3663 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3665 DEBUG(4,("printserver_notify_info\n"));
3670 option=Printer->notify.option;
3675 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3676 sending a ffpcn() request first */
3681 for (i=0; i<option->count; i++) {
3682 option_type=&(option->ctr.type[i]);
3684 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3687 for (snum=0; snum<n_services; snum++)
3689 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3690 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3696 * Debugging information, don't delete.
3699 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3700 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3701 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3703 for (i=0; i<info->count; i++) {
3704 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3705 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3706 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3713 /*******************************************************************
3715 * fill a notify_info struct with info asked
3717 ********************************************************************/
3719 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3720 TALLOC_CTX *mem_ctx)
3723 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3726 SPOOL_NOTIFY_OPTION *option;
3727 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3729 print_queue_struct *queue=NULL;
3730 print_status_struct status;
3732 DEBUG(4,("printer_notify_info\n"));
3737 option=Printer->notify.option;
3743 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3744 sending a ffpcn() request first */
3749 get_printer_snum(p, hnd, &snum);
3751 for (i=0; i<option->count; i++) {
3752 option_type=&option->ctr.type[i];
3754 switch ( option_type->type ) {
3755 case PRINTER_NOTIFY_TYPE:
3756 if(construct_notify_printer_info(Printer, info, snum,
3762 case JOB_NOTIFY_TYPE: {
3763 NT_PRINTER_INFO_LEVEL *printer = NULL;
3765 count = print_queue_status(snum, &queue, &status);
3767 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3770 for (j=0; j<count; j++) {
3771 construct_notify_jobs_info(&queue[j], info,
3778 free_a_printer(&printer, 2);
3788 * Debugging information, don't delete.
3791 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3792 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3793 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3795 for (i=0; i<info->count; i++) {
3796 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3797 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3798 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3804 /********************************************************************
3806 ********************************************************************/
3808 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3810 POLICY_HND *handle = &q_u->handle;
3811 SPOOL_NOTIFY_INFO *info = &r_u->info;
3813 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3814 WERROR result = WERR_BADFID;
3816 /* we always have a NOTIFY_INFO struct */
3820 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3821 OUR_HANDLE(handle)));
3825 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3828 * We are now using the change value, and
3829 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3830 * I don't have a global notification system, I'm sending back all the
3831 * informations even when _NOTHING_ has changed.
3834 /* We need to keep track of the change value to send back in
3835 RRPCN replies otherwise our updates are ignored. */
3837 Printer->notify.fnpcn = True;
3839 if (Printer->notify.client_connected) {
3840 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3841 Printer->notify.change = q_u->change;
3844 /* just ignore the SPOOL_NOTIFY_OPTION */
3846 switch (Printer->printer_type) {
3847 case PRINTER_HANDLE_IS_PRINTSERVER:
3848 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3851 case PRINTER_HANDLE_IS_PRINTER:
3852 result = printer_notify_info(p, handle, info, p->mem_ctx);
3856 Printer->notify.fnpcn = False;
3862 /********************************************************************
3863 * construct_printer_info_0
3864 * fill a printer_info_0 struct
3865 ********************************************************************/
3867 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3871 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3872 counter_printer_0 *session_counter;
3873 uint32 global_counter;
3876 print_status_struct status;
3878 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3881 count = print_queue_length(snum, &status);
3883 /* check if we already have a counter for this printer */
3884 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3885 if (session_counter->snum == snum)
3889 /* it's the first time, add it to the list */
3890 if (session_counter==NULL) {
3891 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3892 free_a_printer(&ntprinter, 2);
3895 ZERO_STRUCTP(session_counter);
3896 session_counter->snum=snum;
3897 session_counter->counter=0;
3898 DLIST_ADD(counter_list, session_counter);
3902 session_counter->counter++;
3905 * the global_counter should be stored in a TDB as it's common to all the clients
3906 * and should be zeroed on samba startup
3908 global_counter=session_counter->counter;
3910 pstrcpy(chaine,ntprinter->info_2->printername);
3912 init_unistr(&printer->printername, chaine);
3914 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3915 init_unistr(&printer->servername, chaine);
3917 printer->cjobs = count;
3918 printer->total_jobs = 0;
3919 printer->total_bytes = 0;
3921 setuptime = (time_t)ntprinter->info_2->setuptime;
3922 t=gmtime(&setuptime);
3924 printer->year = t->tm_year+1900;
3925 printer->month = t->tm_mon+1;
3926 printer->dayofweek = t->tm_wday;
3927 printer->day = t->tm_mday;
3928 printer->hour = t->tm_hour;
3929 printer->minute = t->tm_min;
3930 printer->second = t->tm_sec;
3931 printer->milliseconds = 0;
3933 printer->global_counter = global_counter;
3934 printer->total_pages = 0;
3936 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3937 printer->major_version = 0x0005; /* NT 5 */
3938 printer->build_version = 0x0893; /* build 2195 */
3940 printer->unknown7 = 0x1;
3941 printer->unknown8 = 0x0;
3942 printer->unknown9 = 0x0;
3943 printer->session_counter = session_counter->counter;
3944 printer->unknown11 = 0x0;
3945 printer->printer_errors = 0x0; /* number of print failure */
3946 printer->unknown13 = 0x0;
3947 printer->unknown14 = 0x1;
3948 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3949 printer->unknown16 = 0x0;
3950 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3951 printer->unknown18 = 0x0;
3952 printer->status = nt_printq_status(status.status);
3953 printer->unknown20 = 0x0;
3954 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3955 printer->unknown22 = 0x0;
3956 printer->unknown23 = 0x6; /* 6 ???*/
3957 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3958 printer->unknown25 = 0;
3959 printer->unknown26 = 0;
3960 printer->unknown27 = 0;
3961 printer->unknown28 = 0;
3962 printer->unknown29 = 0;
3964 free_a_printer(&ntprinter,2);
3968 /********************************************************************
3969 * construct_printer_info_1
3970 * fill a printer_info_1 struct
3971 ********************************************************************/
3972 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3976 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3978 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3981 printer->flags=flags;
3983 if (*ntprinter->info_2->comment == '\0') {
3984 init_unistr(&printer->comment, lp_comment(snum));
3985 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3986 ntprinter->info_2->drivername, lp_comment(snum));
3989 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3990 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3991 ntprinter->info_2->drivername, ntprinter->info_2->comment);
3994 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
3996 init_unistr(&printer->description, chaine);
3997 init_unistr(&printer->name, chaine2);
3999 free_a_printer(&ntprinter,2);
4004 /****************************************************************************
4005 Free a DEVMODE struct.
4006 ****************************************************************************/
4008 static void free_dev_mode(DEVICEMODE *dev)
4013 SAFE_FREE(dev->dev_private);
4018 /****************************************************************************
4019 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4020 should be valid upon entry
4021 ****************************************************************************/
4023 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4025 if ( !devmode || !ntdevmode )
4028 init_unistr(&devmode->devicename, ntdevmode->devicename);
4030 init_unistr(&devmode->formname, ntdevmode->formname);
4032 devmode->specversion = ntdevmode->specversion;
4033 devmode->driverversion = ntdevmode->driverversion;
4034 devmode->size = ntdevmode->size;
4035 devmode->driverextra = ntdevmode->driverextra;
4036 devmode->fields = ntdevmode->fields;
4038 devmode->orientation = ntdevmode->orientation;
4039 devmode->papersize = ntdevmode->papersize;
4040 devmode->paperlength = ntdevmode->paperlength;
4041 devmode->paperwidth = ntdevmode->paperwidth;
4042 devmode->scale = ntdevmode->scale;
4043 devmode->copies = ntdevmode->copies;
4044 devmode->defaultsource = ntdevmode->defaultsource;
4045 devmode->printquality = ntdevmode->printquality;
4046 devmode->color = ntdevmode->color;
4047 devmode->duplex = ntdevmode->duplex;
4048 devmode->yresolution = ntdevmode->yresolution;
4049 devmode->ttoption = ntdevmode->ttoption;
4050 devmode->collate = ntdevmode->collate;
4051 devmode->icmmethod = ntdevmode->icmmethod;
4052 devmode->icmintent = ntdevmode->icmintent;
4053 devmode->mediatype = ntdevmode->mediatype;
4054 devmode->dithertype = ntdevmode->dithertype;
4056 if (ntdevmode->nt_dev_private != NULL) {
4057 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4064 /****************************************************************************
4065 Create a DEVMODE struct. Returns malloced memory.
4066 ****************************************************************************/
4068 DEVICEMODE *construct_dev_mode(int snum)
4070 NT_PRINTER_INFO_LEVEL *printer = NULL;
4071 DEVICEMODE *devmode = NULL;
4073 DEBUG(7,("construct_dev_mode\n"));
4075 DEBUGADD(8,("getting printer characteristics\n"));
4077 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4080 if ( !printer->info_2->devmode ) {
4081 DEBUG(5, ("BONG! There was no device mode!\n"));
4085 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4086 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4090 ZERO_STRUCTP(devmode);
4092 DEBUGADD(8,("loading DEVICEMODE\n"));
4094 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4095 free_dev_mode( devmode );
4100 free_a_printer(&printer,2);
4105 /********************************************************************
4106 * construct_printer_info_2
4107 * fill a printer_info_2 struct
4108 ********************************************************************/
4110 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4113 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4115 print_status_struct status;
4117 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4120 count = print_queue_length(snum, &status);
4122 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4123 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4124 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4125 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4126 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4128 if (*ntprinter->info_2->comment == '\0')
4129 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4131 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4133 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4134 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4135 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4136 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4137 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4139 printer->attributes = ntprinter->info_2->attributes;
4141 printer->priority = ntprinter->info_2->priority; /* priority */
4142 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4143 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4144 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4145 printer->status = nt_printq_status(status.status); /* status */
4146 printer->cjobs = count; /* jobs */
4147 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4149 if ( !(printer->devmode = construct_dev_mode(snum)) )
4150 DEBUG(8, ("Returning NULL Devicemode!\n"));
4152 printer->secdesc = NULL;
4154 if ( ntprinter->info_2->secdesc_buf
4155 && ntprinter->info_2->secdesc_buf->len != 0 )
4157 /* don't use talloc_steal() here unless you do a deep steal of all
4158 the SEC_DESC members */
4160 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4161 ntprinter->info_2->secdesc_buf->sec );
4164 free_a_printer(&ntprinter, 2);
4169 /********************************************************************
4170 * construct_printer_info_3
4171 * fill a printer_info_3 struct
4172 ********************************************************************/
4174 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4176 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4177 PRINTER_INFO_3 *printer = NULL;
4179 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4183 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4184 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4188 ZERO_STRUCTP(printer);
4190 /* These are the components of the SD we are returning. */
4192 printer->flags = 0x4;
4194 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4195 /* don't use talloc_steal() here unless you do a deep steal of all
4196 the SEC_DESC members */
4198 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4199 ntprinter->info_2->secdesc_buf->sec );
4202 free_a_printer(&ntprinter, 2);
4204 *pp_printer = printer;
4208 /********************************************************************
4209 * construct_printer_info_4
4210 * fill a printer_info_4 struct
4211 ********************************************************************/
4213 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4215 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4217 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4220 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4221 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4222 printer->attributes = ntprinter->info_2->attributes;
4224 free_a_printer(&ntprinter, 2);
4228 /********************************************************************
4229 * construct_printer_info_5
4230 * fill a printer_info_5 struct
4231 ********************************************************************/
4233 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4235 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4237 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4240 init_unistr(&printer->printername, ntprinter->info_2->printername);
4241 init_unistr(&printer->portname, ntprinter->info_2->portname);
4242 printer->attributes = ntprinter->info_2->attributes;
4244 /* these two are not used by NT+ according to MSDN */
4246 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4247 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4249 free_a_printer(&ntprinter, 2);
4254 /********************************************************************
4255 * construct_printer_info_7
4256 * fill a printer_info_7 struct
4257 ********************************************************************/
4259 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4261 char *guid_str = NULL;
4264 if (is_printer_published(print_hnd, snum, &guid)) {
4265 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4266 strupper_m(guid_str);
4267 init_unistr(&printer->guid, guid_str);
4268 printer->action = SPOOL_DS_PUBLISH;
4270 init_unistr(&printer->guid, "");
4271 printer->action = SPOOL_DS_UNPUBLISH;
4277 /********************************************************************
4278 Spoolss_enumprinters.
4279 ********************************************************************/
4281 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4285 int n_services=lp_numservices();
4286 PRINTER_INFO_1 *tp, *printers=NULL;
4287 PRINTER_INFO_1 current_prt;
4288 WERROR result = WERR_OK;
4290 DEBUG(4,("enum_all_printers_info_1\n"));
4292 for (snum=0; snum<n_services; snum++) {
4293 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4294 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4296 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4297 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4298 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4299 SAFE_FREE(printers);
4304 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4306 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4312 /* check the required size. */
4313 for (i=0; i<*returned; i++)
4314 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4316 if (*needed > offered) {
4317 result = WERR_INSUFFICIENT_BUFFER;
4321 if (!rpcbuf_alloc_size(buffer, *needed)) {
4322 result = WERR_NOMEM;
4326 /* fill the buffer with the structures */
4327 for (i=0; i<*returned; i++)
4328 smb_io_printer_info_1("", buffer, &printers[i], 0);
4333 SAFE_FREE(printers);
4335 if ( !W_ERROR_IS_OK(result) )
4341 /********************************************************************
4342 enum_all_printers_info_1_local.
4343 *********************************************************************/
4345 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4347 DEBUG(4,("enum_all_printers_info_1_local\n"));
4349 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4352 /********************************************************************
4353 enum_all_printers_info_1_name.
4354 *********************************************************************/
4356 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4360 DEBUG(4,("enum_all_printers_info_1_name\n"));
4362 if ((name[0] == '\\') && (name[1] == '\\'))
4365 if (is_myname_or_ipaddr(s)) {
4366 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4369 return WERR_INVALID_NAME;
4372 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4373 /********************************************************************
4374 enum_all_printers_info_1_remote.
4375 *********************************************************************/
4377 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4379 PRINTER_INFO_1 *printer;
4380 fstring printername;
4383 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4384 WERROR result = WERR_OK;
4386 /* JFM: currently it's more a place holder than anything else.
4387 * In the spooler world there is a notion of server registration.
4388 * the print servers are registered on the PDC (in the same domain)
4390 * We should have a TDB here. The registration is done thru an
4391 * undocumented RPC call.
4394 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4399 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4400 slprintf(desc, sizeof(desc)-1,"%s", name);
4401 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4403 init_unistr(&printer->description, desc);
4404 init_unistr(&printer->name, printername);
4405 init_unistr(&printer->comment, comment);
4406 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4408 /* check the required size. */
4409 *needed += spoolss_size_printer_info_1(printer);
4411 if (*needed > offered) {
4412 result = WERR_INSUFFICIENT_BUFFER;
4416 if (!rpcbuf_alloc_size(buffer, *needed)) {
4417 result = WERR_NOMEM;
4421 /* fill the buffer with the structures */
4422 smb_io_printer_info_1("", buffer, printer, 0);
4428 if ( !W_ERROR_IS_OK(result) )
4436 /********************************************************************
4437 enum_all_printers_info_1_network.
4438 *********************************************************************/
4440 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4444 DEBUG(4,("enum_all_printers_info_1_network\n"));
4446 /* If we respond to a enum_printers level 1 on our name with flags
4447 set to PRINTER_ENUM_REMOTE with a list of printers then these
4448 printers incorrectly appear in the APW browse list.
4449 Specifically the printers for the server appear at the workgroup
4450 level where all the other servers in the domain are
4451 listed. Windows responds to this call with a
4452 WERR_CAN_NOT_COMPLETE so we should do the same. */
4454 if (name[0] == '\\' && name[1] == '\\')
4457 if (is_myname_or_ipaddr(s))
4458 return WERR_CAN_NOT_COMPLETE;
4460 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4463 /********************************************************************
4464 * api_spoolss_enumprinters
4466 * called from api_spoolss_enumprinters (see this to understand)
4467 ********************************************************************/
4469 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4473 int n_services=lp_numservices();
4474 PRINTER_INFO_2 *tp, *printers=NULL;
4475 PRINTER_INFO_2 current_prt;
4476 WERROR result = WERR_OK;
4478 for (snum=0; snum<n_services; snum++) {
4479 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4480 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4482 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4484 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4485 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4486 SAFE_FREE(printers);
4491 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4494 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4501 /* check the required size. */
4502 for (i=0; i<*returned; i++)
4503 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4505 if (*needed > offered) {
4506 result = WERR_INSUFFICIENT_BUFFER;
4510 if (!rpcbuf_alloc_size(buffer, *needed)) {
4511 result = WERR_NOMEM;
4515 /* fill the buffer with the structures */
4516 for (i=0; i<*returned; i++)
4517 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4522 for (i=0; i<*returned; i++)
4523 free_devmode(printers[i].devmode);
4525 SAFE_FREE(printers);
4527 if ( !W_ERROR_IS_OK(result) )
4533 /********************************************************************
4534 * handle enumeration of printers at level 1
4535 ********************************************************************/
4537 static WERROR enumprinters_level1( uint32 flags, fstring name,
4538 RPC_BUFFER *buffer, uint32 offered,
4539 uint32 *needed, uint32 *returned)
4541 /* Not all the flags are equals */
4543 if (flags & PRINTER_ENUM_LOCAL)
4544 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4546 if (flags & PRINTER_ENUM_NAME)
4547 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4549 #if 0 /* JERRY - disabled for now */
4550 if (flags & PRINTER_ENUM_REMOTE)
4551 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4554 if (flags & PRINTER_ENUM_NETWORK)
4555 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4557 return WERR_OK; /* NT4sp5 does that */
4560 /********************************************************************
4561 * handle enumeration of printers at level 2
4562 ********************************************************************/
4564 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4565 RPC_BUFFER *buffer, uint32 offered,
4566 uint32 *needed, uint32 *returned)
4568 char *s = servername;
4570 if (flags & PRINTER_ENUM_LOCAL) {
4571 return enum_all_printers_info_2(buffer, offered, needed, returned);
4574 if (flags & PRINTER_ENUM_NAME) {
4575 if ((servername[0] == '\\') && (servername[1] == '\\'))
4577 if (is_myname_or_ipaddr(s))
4578 return enum_all_printers_info_2(buffer, offered, needed, returned);
4580 return WERR_INVALID_NAME;
4583 if (flags & PRINTER_ENUM_REMOTE)
4584 return WERR_UNKNOWN_LEVEL;
4589 /********************************************************************
4590 * handle enumeration of printers at level 5
4591 ********************************************************************/
4593 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4594 RPC_BUFFER *buffer, uint32 offered,
4595 uint32 *needed, uint32 *returned)
4597 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4601 /********************************************************************
4602 * api_spoolss_enumprinters
4604 * called from api_spoolss_enumprinters (see this to understand)
4605 ********************************************************************/
4607 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4609 uint32 flags = q_u->flags;
4610 UNISTR2 *servername = &q_u->servername;
4611 uint32 level = q_u->level;
4612 RPC_BUFFER *buffer = NULL;
4613 uint32 offered = q_u->offered;
4614 uint32 *needed = &r_u->needed;
4615 uint32 *returned = &r_u->returned;
4619 /* that's an [in out] buffer */
4621 if ( q_u->buffer ) {
4622 rpcbuf_move(q_u->buffer, &r_u->buffer);
4623 buffer = r_u->buffer;
4626 DEBUG(4,("_spoolss_enumprinters\n"));
4633 * flags==PRINTER_ENUM_NAME
4634 * if name=="" then enumerates all printers
4635 * if name!="" then enumerate the printer
4636 * flags==PRINTER_ENUM_REMOTE
4637 * name is NULL, enumerate printers
4638 * Level 2: name!="" enumerates printers, name can't be NULL
4639 * Level 3: doesn't exist
4640 * Level 4: does a local registry lookup
4641 * Level 5: same as Level 2
4644 unistr2_to_ascii(name, servername, sizeof(name)-1);
4649 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4651 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4653 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4658 return WERR_UNKNOWN_LEVEL;
4661 /****************************************************************************
4662 ****************************************************************************/
4664 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4666 PRINTER_INFO_0 *printer=NULL;
4667 WERROR result = WERR_OK;
4669 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4672 construct_printer_info_0(print_hnd, printer, snum);
4674 /* check the required size. */
4675 *needed += spoolss_size_printer_info_0(printer);
4677 if (*needed > offered) {
4678 result = WERR_INSUFFICIENT_BUFFER;
4682 if (!rpcbuf_alloc_size(buffer, *needed)) {
4683 result = WERR_NOMEM;
4687 /* fill the buffer with the structures */
4688 smb_io_printer_info_0("", buffer, printer, 0);
4698 /****************************************************************************
4699 ****************************************************************************/
4701 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4703 PRINTER_INFO_1 *printer=NULL;
4704 WERROR result = WERR_OK;
4706 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4709 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4711 /* check the required size. */
4712 *needed += spoolss_size_printer_info_1(printer);
4714 if (*needed > offered) {
4715 result = WERR_INSUFFICIENT_BUFFER;
4719 if (!rpcbuf_alloc_size(buffer, *needed)) {
4720 result = WERR_NOMEM;
4724 /* fill the buffer with the structures */
4725 smb_io_printer_info_1("", buffer, printer, 0);
4734 /****************************************************************************
4735 ****************************************************************************/
4737 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4739 PRINTER_INFO_2 *printer=NULL;
4740 WERROR result = WERR_OK;
4742 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4745 construct_printer_info_2(print_hnd, printer, snum);
4747 /* check the required size. */
4748 *needed += spoolss_size_printer_info_2(printer);
4750 if (*needed > offered) {
4751 result = WERR_INSUFFICIENT_BUFFER;
4755 if (!rpcbuf_alloc_size(buffer, *needed)) {
4756 result = WERR_NOMEM;
4760 /* fill the buffer with the structures */
4761 if (!smb_io_printer_info_2("", buffer, printer, 0))
4762 result = WERR_NOMEM;
4766 free_printer_info_2(printer);
4771 /****************************************************************************
4772 ****************************************************************************/
4774 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4776 PRINTER_INFO_3 *printer=NULL;
4777 WERROR result = WERR_OK;
4779 if (!construct_printer_info_3(print_hnd, &printer, snum))
4782 /* check the required size. */
4783 *needed += spoolss_size_printer_info_3(printer);
4785 if (*needed > offered) {
4786 result = WERR_INSUFFICIENT_BUFFER;
4790 if (!rpcbuf_alloc_size(buffer, *needed)) {
4791 result = WERR_NOMEM;
4795 /* fill the buffer with the structures */
4796 smb_io_printer_info_3("", buffer, printer, 0);
4800 free_printer_info_3(printer);
4805 /****************************************************************************
4806 ****************************************************************************/
4808 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4810 PRINTER_INFO_4 *printer=NULL;
4811 WERROR result = WERR_OK;
4813 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4816 if (!construct_printer_info_4(print_hnd, printer, snum))
4819 /* check the required size. */
4820 *needed += spoolss_size_printer_info_4(printer);
4822 if (*needed > offered) {
4823 result = WERR_INSUFFICIENT_BUFFER;
4827 if (!rpcbuf_alloc_size(buffer, *needed)) {
4828 result = WERR_NOMEM;
4832 /* fill the buffer with the structures */
4833 smb_io_printer_info_4("", buffer, printer, 0);
4837 free_printer_info_4(printer);
4842 /****************************************************************************
4843 ****************************************************************************/
4845 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4847 PRINTER_INFO_5 *printer=NULL;
4848 WERROR result = WERR_OK;
4850 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4853 if (!construct_printer_info_5(print_hnd, printer, snum))
4856 /* check the required size. */
4857 *needed += spoolss_size_printer_info_5(printer);
4859 if (*needed > offered) {
4860 result = WERR_INSUFFICIENT_BUFFER;
4864 if (!rpcbuf_alloc_size(buffer, *needed)) {
4865 result = WERR_NOMEM;
4869 /* fill the buffer with the structures */
4870 smb_io_printer_info_5("", buffer, printer, 0);
4874 free_printer_info_5(printer);
4879 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4881 PRINTER_INFO_7 *printer=NULL;
4882 WERROR result = WERR_OK;
4884 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4887 if (!construct_printer_info_7(print_hnd, printer, snum))
4890 /* check the required size. */
4891 *needed += spoolss_size_printer_info_7(printer);
4893 if (*needed > offered) {
4894 result = WERR_INSUFFICIENT_BUFFER;
4898 if (!rpcbuf_alloc_size(buffer, *needed)) {
4899 result = WERR_NOMEM;
4904 /* fill the buffer with the structures */
4905 smb_io_printer_info_7("", buffer, printer, 0);
4909 free_printer_info_7(printer);
4914 /****************************************************************************
4915 ****************************************************************************/
4917 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4919 POLICY_HND *handle = &q_u->handle;
4920 uint32 level = q_u->level;
4921 RPC_BUFFER *buffer = NULL;
4922 uint32 offered = q_u->offered;
4923 uint32 *needed = &r_u->needed;
4924 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4928 /* that's an [in out] buffer */
4930 if ( q_u->buffer ) {
4931 rpcbuf_move(q_u->buffer, &r_u->buffer);
4932 buffer = r_u->buffer;
4937 if (!get_printer_snum(p, handle, &snum))
4942 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4944 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4946 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4948 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4950 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4954 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4956 return WERR_UNKNOWN_LEVEL;
4959 /********************************************************************
4960 * fill a DRIVER_INFO_1 struct
4961 ********************************************************************/
4963 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4965 init_unistr( &info->name, driver.info_3->name);
4968 /********************************************************************
4969 * construct_printer_driver_info_1
4970 ********************************************************************/
4972 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4974 NT_PRINTER_INFO_LEVEL *printer = NULL;
4975 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4977 ZERO_STRUCT(driver);
4979 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4980 return WERR_INVALID_PRINTER_NAME;
4982 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4983 return WERR_UNKNOWN_PRINTER_DRIVER;
4985 fill_printer_driver_info_1(info, driver, servername, architecture);
4987 free_a_printer(&printer,2);
4992 /********************************************************************
4993 * construct_printer_driver_info_2
4994 * fill a printer_info_2 struct
4995 ********************************************************************/
4997 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5001 info->version=driver.info_3->cversion;
5003 init_unistr( &info->name, driver.info_3->name );
5004 init_unistr( &info->architecture, driver.info_3->environment );
5007 if (strlen(driver.info_3->driverpath)) {
5008 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5009 init_unistr( &info->driverpath, temp );
5011 init_unistr( &info->driverpath, "" );
5013 if (strlen(driver.info_3->datafile)) {
5014 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5015 init_unistr( &info->datafile, temp );
5017 init_unistr( &info->datafile, "" );
5019 if (strlen(driver.info_3->configfile)) {
5020 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5021 init_unistr( &info->configfile, temp );
5023 init_unistr( &info->configfile, "" );
5026 /********************************************************************
5027 * construct_printer_driver_info_2
5028 * fill a printer_info_2 struct
5029 ********************************************************************/
5031 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5033 NT_PRINTER_INFO_LEVEL *printer = NULL;
5034 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5036 ZERO_STRUCT(printer);
5037 ZERO_STRUCT(driver);
5039 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5040 return WERR_INVALID_PRINTER_NAME;
5042 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5043 return WERR_UNKNOWN_PRINTER_DRIVER;
5045 fill_printer_driver_info_2(info, driver, servername);
5047 free_a_printer(&printer,2);
5052 /********************************************************************
5053 * copy a strings array and convert to UNICODE
5055 * convert an array of ascii string to a UNICODE string
5056 ********************************************************************/
5058 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5066 DEBUG(6,("init_unistr_array\n"));
5077 v = ""; /* hack to handle null lists */
5080 /* hack to allow this to be used in places other than when generating
5081 the list of dependent files */
5084 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5088 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5090 /* add one extra unit16 for the second terminating NULL */
5092 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5093 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5101 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5106 /* special case for ""; we need to add both NULL's here */
5108 (*uni_array)[j++]=0x0000;
5109 (*uni_array)[j]=0x0000;
5112 DEBUGADD(6,("last one:done\n"));
5114 /* return size of array in uint16's */
5119 /********************************************************************
5120 * construct_printer_info_3
5121 * fill a printer_info_3 struct
5122 ********************************************************************/
5124 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5130 info->version=driver.info_3->cversion;
5132 init_unistr( &info->name, driver.info_3->name );
5133 init_unistr( &info->architecture, driver.info_3->environment );
5135 if (strlen(driver.info_3->driverpath)) {
5136 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5137 init_unistr( &info->driverpath, temp );
5139 init_unistr( &info->driverpath, "" );
5141 if (strlen(driver.info_3->datafile)) {
5142 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5143 init_unistr( &info->datafile, temp );
5145 init_unistr( &info->datafile, "" );
5147 if (strlen(driver.info_3->configfile)) {
5148 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5149 init_unistr( &info->configfile, temp );
5151 init_unistr( &info->configfile, "" );
5153 if (strlen(driver.info_3->helpfile)) {
5154 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5155 init_unistr( &info->helpfile, temp );
5157 init_unistr( &info->helpfile, "" );
5159 init_unistr( &info->monitorname, driver.info_3->monitorname );
5160 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5162 info->dependentfiles=NULL;
5163 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5166 /********************************************************************
5167 * construct_printer_info_3
5168 * fill a printer_info_3 struct
5169 ********************************************************************/
5171 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5173 NT_PRINTER_INFO_LEVEL *printer = NULL;
5174 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5176 ZERO_STRUCT(driver);
5178 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5179 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5180 if (!W_ERROR_IS_OK(status))
5181 return WERR_INVALID_PRINTER_NAME;
5183 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5184 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5189 * I put this code in during testing. Helpful when commenting out the
5190 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5191 * as win2k always queries the driver using an infor level of 6.
5192 * I've left it in (but ifdef'd out) because I'll probably
5193 * use it in experimentation again in the future. --jerry 22/01/2002
5196 if (!W_ERROR_IS_OK(status)) {
5198 * Is this a W2k client ?
5201 /* Yes - try again with a WinNT driver. */
5203 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5204 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5208 if (!W_ERROR_IS_OK(status)) {
5209 free_a_printer(&printer,2);
5210 return WERR_UNKNOWN_PRINTER_DRIVER;
5218 fill_printer_driver_info_3(info, driver, servername);
5220 free_a_printer(&printer,2);
5225 /********************************************************************
5226 * construct_printer_info_6
5227 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5228 ********************************************************************/
5230 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5236 memset(&nullstr, '\0', sizeof(fstring));
5238 info->version=driver.info_3->cversion;
5240 init_unistr( &info->name, driver.info_3->name );
5241 init_unistr( &info->architecture, driver.info_3->environment );
5243 if (strlen(driver.info_3->driverpath)) {
5244 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5245 init_unistr( &info->driverpath, temp );
5247 init_unistr( &info->driverpath, "" );
5249 if (strlen(driver.info_3->datafile)) {
5250 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5251 init_unistr( &info->datafile, temp );
5253 init_unistr( &info->datafile, "" );
5255 if (strlen(driver.info_3->configfile)) {
5256 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5257 init_unistr( &info->configfile, temp );
5259 init_unistr( &info->configfile, "" );
5261 if (strlen(driver.info_3->helpfile)) {
5262 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5263 init_unistr( &info->helpfile, temp );
5265 init_unistr( &info->helpfile, "" );
5267 init_unistr( &info->monitorname, driver.info_3->monitorname );
5268 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5270 info->dependentfiles = NULL;
5271 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5273 info->previousdrivernames=NULL;
5274 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5276 info->driver_date.low=0;
5277 info->driver_date.high=0;
5280 info->driver_version_low=0;
5281 info->driver_version_high=0;
5283 init_unistr( &info->mfgname, "");
5284 init_unistr( &info->oem_url, "");
5285 init_unistr( &info->hardware_id, "");
5286 init_unistr( &info->provider, "");
5289 /********************************************************************
5290 * construct_printer_info_6
5291 * fill a printer_info_6 struct
5292 ********************************************************************/
5294 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5295 fstring servername, fstring architecture, uint32 version)
5297 NT_PRINTER_INFO_LEVEL *printer = NULL;
5298 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5301 ZERO_STRUCT(driver);
5303 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5305 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5307 if (!W_ERROR_IS_OK(status))
5308 return WERR_INVALID_PRINTER_NAME;
5310 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5312 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5314 if (!W_ERROR_IS_OK(status))
5317 * Is this a W2k client ?
5321 free_a_printer(&printer,2);
5322 return WERR_UNKNOWN_PRINTER_DRIVER;
5325 /* Yes - try again with a WinNT driver. */
5327 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5328 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5329 if (!W_ERROR_IS_OK(status)) {
5330 free_a_printer(&printer,2);
5331 return WERR_UNKNOWN_PRINTER_DRIVER;
5335 fill_printer_driver_info_6(info, driver, servername);
5337 free_a_printer(&printer,2);
5338 free_a_printer_driver(driver, 3);
5343 /****************************************************************************
5344 ****************************************************************************/
5346 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5348 SAFE_FREE(info->dependentfiles);
5351 /****************************************************************************
5352 ****************************************************************************/
5354 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5356 SAFE_FREE(info->dependentfiles);
5359 /****************************************************************************
5360 ****************************************************************************/
5362 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5364 DRIVER_INFO_1 *info=NULL;
5367 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5370 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5371 if (!W_ERROR_IS_OK(result))
5374 /* check the required size. */
5375 *needed += spoolss_size_printer_driver_info_1(info);
5377 if (*needed > offered) {
5378 result = WERR_INSUFFICIENT_BUFFER;
5382 if (!rpcbuf_alloc_size(buffer, *needed)) {
5383 result = WERR_NOMEM;
5387 /* fill the buffer with the structures */
5388 smb_io_printer_driver_info_1("", buffer, info, 0);
5397 /****************************************************************************
5398 ****************************************************************************/
5400 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5402 DRIVER_INFO_2 *info=NULL;
5405 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5408 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5409 if (!W_ERROR_IS_OK(result))
5412 /* check the required size. */
5413 *needed += spoolss_size_printer_driver_info_2(info);
5415 if (*needed > offered) {
5416 result = WERR_INSUFFICIENT_BUFFER;
5420 if (!rpcbuf_alloc_size(buffer, *needed)) {
5421 result = WERR_NOMEM;
5425 /* fill the buffer with the structures */
5426 smb_io_printer_driver_info_2("", buffer, info, 0);
5435 /****************************************************************************
5436 ****************************************************************************/
5438 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5445 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5446 if (!W_ERROR_IS_OK(result))
5449 /* check the required size. */
5450 *needed += spoolss_size_printer_driver_info_3(&info);
5452 if (*needed > offered) {
5453 result = WERR_INSUFFICIENT_BUFFER;
5457 if (!rpcbuf_alloc_size(buffer, *needed)) {
5458 result = WERR_NOMEM;
5462 /* fill the buffer with the structures */
5463 smb_io_printer_driver_info_3("", buffer, &info, 0);
5466 free_printer_driver_info_3(&info);
5471 /****************************************************************************
5472 ****************************************************************************/
5474 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5481 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5482 if (!W_ERROR_IS_OK(result))
5485 /* check the required size. */
5486 *needed += spoolss_size_printer_driver_info_6(&info);
5488 if (*needed > offered) {
5489 result = WERR_INSUFFICIENT_BUFFER;
5493 if (!rpcbuf_alloc_size(buffer, *needed)) {
5494 result = WERR_NOMEM;
5498 /* fill the buffer with the structures */
5499 smb_io_printer_driver_info_6("", buffer, &info, 0);
5502 free_printer_driver_info_6(&info);
5507 /****************************************************************************
5508 ****************************************************************************/
5510 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5512 POLICY_HND *handle = &q_u->handle;
5513 UNISTR2 *uni_arch = &q_u->architecture;
5514 uint32 level = q_u->level;
5515 uint32 clientmajorversion = q_u->clientmajorversion;
5516 RPC_BUFFER *buffer = NULL;
5517 uint32 offered = q_u->offered;
5518 uint32 *needed = &r_u->needed;
5519 uint32 *servermajorversion = &r_u->servermajorversion;
5520 uint32 *serverminorversion = &r_u->serverminorversion;
5521 Printer_entry *printer;
5524 fstring architecture;
5527 /* that's an [in out] buffer */
5529 if ( q_u->buffer ) {
5530 rpcbuf_move(q_u->buffer, &r_u->buffer);
5531 buffer = r_u->buffer;
5534 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5536 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5537 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5538 return WERR_INVALID_PRINTER_NAME;
5542 *servermajorversion = 0;
5543 *serverminorversion = 0;
5545 fstrcpy(servername, get_server_name( printer ));
5546 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5548 if (!get_printer_snum(p, handle, &snum))
5553 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5555 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5557 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5559 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5562 /* apparently this call is the equivalent of
5563 EnumPrinterDataEx() for the DsDriver key */
5568 return WERR_UNKNOWN_LEVEL;
5571 /****************************************************************************
5572 ****************************************************************************/
5574 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5576 POLICY_HND *handle = &q_u->handle;
5578 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5581 DEBUG(3,("Error in startpageprinter printer handle\n"));
5585 Printer->page_started=True;
5589 /****************************************************************************
5590 ****************************************************************************/
5592 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5594 POLICY_HND *handle = &q_u->handle;
5597 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5600 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5604 if (!get_printer_snum(p, handle, &snum))
5607 Printer->page_started=False;
5608 print_job_endpage(snum, Printer->jobid);
5613 /********************************************************************
5614 * api_spoolss_getprinter
5615 * called from the spoolss dispatcher
5617 ********************************************************************/
5619 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5621 POLICY_HND *handle = &q_u->handle;
5622 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5623 uint32 *jobid = &r_u->jobid;
5625 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5629 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5630 struct current_user user;
5633 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5637 get_current_user(&user, p);
5640 * a nice thing with NT is it doesn't listen to what you tell it.
5641 * when asked to send _only_ RAW datas, it tries to send datas
5644 * So I add checks like in NT Server ...
5647 if (info_1->p_datatype != 0) {
5648 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5649 if (strcmp(datatype, "RAW") != 0) {
5651 return WERR_INVALID_DATATYPE;
5655 /* get the share number of the printer */
5656 if (!get_printer_snum(p, handle, &snum)) {
5660 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5662 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5664 /* An error occured in print_job_start() so return an appropriate
5667 if (Printer->jobid == -1) {
5668 return map_werror_from_unix(errno);
5671 Printer->document_started=True;
5672 (*jobid) = Printer->jobid;
5677 /********************************************************************
5678 * api_spoolss_getprinter
5679 * called from the spoolss dispatcher
5681 ********************************************************************/
5683 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5685 POLICY_HND *handle = &q_u->handle;
5687 return _spoolss_enddocprinter_internal(p, handle);
5690 /****************************************************************************
5691 ****************************************************************************/
5693 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5695 POLICY_HND *handle = &q_u->handle;
5696 uint32 buffer_size = q_u->buffer_size;
5697 uint8 *buffer = q_u->buffer;
5698 uint32 *buffer_written = &q_u->buffer_size2;
5700 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5703 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5704 r_u->buffer_written = q_u->buffer_size2;
5708 if (!get_printer_snum(p, handle, &snum))
5711 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5712 (SMB_OFF_T)-1, (size_t)buffer_size);
5713 if (*buffer_written == (uint32)-1) {
5714 r_u->buffer_written = 0;
5715 if (errno == ENOSPC)
5716 return WERR_NO_SPOOL_SPACE;
5718 return WERR_ACCESS_DENIED;
5721 r_u->buffer_written = q_u->buffer_size2;
5726 /********************************************************************
5727 * api_spoolss_getprinter
5728 * called from the spoolss dispatcher
5730 ********************************************************************/
5732 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5735 struct current_user user;
5737 WERROR errcode = WERR_BADFUNC;
5738 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5740 get_current_user(&user, p);
5743 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5747 if (!get_printer_snum(p, handle, &snum))
5751 case PRINTER_CONTROL_PAUSE:
5752 if (print_queue_pause(&user, snum, &errcode)) {
5756 case PRINTER_CONTROL_RESUME:
5757 case PRINTER_CONTROL_UNPAUSE:
5758 if (print_queue_resume(&user, snum, &errcode)) {
5762 case PRINTER_CONTROL_PURGE:
5763 if (print_queue_purge(&user, snum, &errcode)) {
5768 return WERR_UNKNOWN_LEVEL;
5774 /********************************************************************
5775 * api_spoolss_abortprinter
5776 * From MSDN: "Deletes printer's spool file if printer is configured
5778 ********************************************************************/
5780 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5782 POLICY_HND *handle = &q_u->handle;
5783 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5785 struct current_user user;
5786 WERROR errcode = WERR_OK;
5789 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5793 if (!get_printer_snum(p, handle, &snum))
5796 get_current_user( &user, p );
5798 print_job_delete( &user, snum, Printer->jobid, &errcode );
5803 /********************************************************************
5804 * called by spoolss_api_setprinter
5805 * when updating a printer description
5806 ********************************************************************/
5808 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5809 const SPOOL_PRINTER_INFO_LEVEL *info,
5810 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5812 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5816 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5818 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5819 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5820 OUR_HANDLE(handle)));
5822 result = WERR_BADFID;
5826 /* Check the user has permissions to change the security
5827 descriptor. By experimentation with two NT machines, the user
5828 requires Full Access to the printer to change security
5831 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5832 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5833 result = WERR_ACCESS_DENIED;
5837 /* NT seems to like setting the security descriptor even though
5838 nothing may have actually changed. */
5840 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5842 if (DEBUGLEVEL >= 10) {
5846 the_acl = old_secdesc_ctr->sec->dacl;
5847 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5848 PRINTERNAME(snum), the_acl->num_aces));
5850 for (i = 0; i < the_acl->num_aces; i++) {
5853 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5855 DEBUG(10, ("%s 0x%08x\n", sid_str,
5856 the_acl->ace[i].info.mask));
5859 the_acl = secdesc_ctr->sec->dacl;
5862 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5863 PRINTERNAME(snum), the_acl->num_aces));
5865 for (i = 0; i < the_acl->num_aces; i++) {
5868 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5870 DEBUG(10, ("%s 0x%08x\n", sid_str,
5871 the_acl->ace[i].info.mask));
5874 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5878 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5880 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5885 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5892 /********************************************************************
5893 Canonicalize printer info from a client
5895 ATTN: It does not matter what we set the servername to hear
5896 since we do the necessary work in get_a_printer() to set it to
5897 the correct value based on what the client sent in the
5898 _spoolss_open_printer_ex().
5899 ********************************************************************/
5901 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5903 fstring printername;
5906 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5907 "portname=%s drivername=%s comment=%s location=%s\n",
5908 info->servername, info->printername, info->sharename,
5909 info->portname, info->drivername, info->comment, info->location));
5911 /* we force some elements to "correct" values */
5912 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5913 fstrcpy(info->sharename, lp_servicename(snum));
5915 /* check to see if we allow printername != sharename */
5917 if ( lp_force_printername(snum) ) {
5918 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5919 global_myname(), info->sharename );
5922 /* make sure printername is in \\server\printername format */
5924 fstrcpy( printername, info->printername );
5926 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5927 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5931 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5932 global_myname(), p );
5935 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5936 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5943 /****************************************************************************
5944 ****************************************************************************/
5946 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5948 char *cmd = lp_addprinter_cmd();
5954 fstring remote_machine = "%m";
5955 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5956 BOOL is_print_op = False;
5958 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5960 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5961 cmd, printer->info_2->printername, printer->info_2->sharename,
5962 printer->info_2->portname, printer->info_2->drivername,
5963 printer->info_2->location, printer->info_2->comment, remote_machine);
5966 is_print_op = user_has_privileges( token, &se_printop );
5968 DEBUG(10,("Running [%s]\n", command));
5970 /********* BEGIN SePrintOperatorPrivilege **********/
5975 if ( (ret = smbrun(command, &fd)) == 0 ) {
5976 /* Tell everyone we updated smb.conf. */
5977 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5983 /********* END SePrintOperatorPrivilege **********/
5985 DEBUGADD(10,("returned [%d]\n", ret));
5993 /* reload our services immediately */
5994 reload_services( False );
5997 /* Get lines and convert them back to dos-codepage */
5998 qlines = fd_lines_load(fd, &numlines);
5999 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6002 /* Set the portname to what the script says the portname should be. */
6003 /* but don't require anything to be return from the script exit a good error code */
6006 /* Set the portname to what the script says the portname should be. */
6007 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6008 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6011 file_lines_free(qlines);
6015 /********************************************************************
6016 * Called by spoolss_api_setprinter
6017 * when updating a printer description.
6018 ********************************************************************/
6020 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6021 const SPOOL_PRINTER_INFO_LEVEL *info,
6022 DEVICEMODE *devmode)
6025 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6026 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6031 DEBUG(8,("update_printer\n"));
6036 result = WERR_BADFID;
6040 if (!get_printer_snum(p, handle, &snum)) {
6041 result = WERR_BADFID;
6045 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6046 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6047 result = WERR_BADFID;
6051 DEBUGADD(8,("Converting info_2 struct\n"));
6054 * convert_printer_info converts the incoming
6055 * info from the client and overwrites the info
6056 * just read from the tdb in the pointer 'printer'.
6059 if (!convert_printer_info(info, printer, level)) {
6060 result = WERR_NOMEM;
6065 /* we have a valid devmode
6066 convert it and link it*/
6068 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6069 if (!convert_devicemode(printer->info_2->printername, devmode,
6070 &printer->info_2->devmode)) {
6071 result = WERR_NOMEM;
6076 /* Do sanity check on the requested changes for Samba */
6078 if (!check_printer_ok(printer->info_2, snum)) {
6079 result = WERR_INVALID_PARAM;
6083 /* FIXME!!! If the driver has changed we really should verify that
6084 it is installed before doing much else --jerry */
6086 /* Check calling user has permission to update printer description */
6088 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6089 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6090 result = WERR_ACCESS_DENIED;
6094 /* Call addprinter hook */
6095 /* Check changes to see if this is really needed */
6097 if ( *lp_addprinter_cmd()
6098 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6099 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6100 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6101 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6103 /* add_printer_hook() will call reload_services() */
6105 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6106 result = WERR_ACCESS_DENIED;
6112 * When a *new* driver is bound to a printer, the drivername is used to
6113 * lookup previously saved driver initialization info, which is then
6114 * bound to the printer, simulating what happens in the Windows arch.
6116 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6118 if (!set_driver_init(printer, 2))
6120 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6121 printer->info_2->drivername));
6124 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6125 printer->info_2->drivername));
6127 notify_printer_driver(snum, printer->info_2->drivername);
6131 * flag which changes actually occured. This is a small subset of
6132 * all the possible changes. We also have to update things in the
6136 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6137 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6138 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6139 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6141 notify_printer_comment(snum, printer->info_2->comment);
6144 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6145 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6146 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6147 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6149 notify_printer_sharename(snum, printer->info_2->sharename);
6152 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6155 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6158 pname = printer->info_2->printername;
6161 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6162 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6163 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6165 notify_printer_printername( snum, pname );
6168 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6169 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 notify_printer_port(snum, printer->info_2->portname);
6176 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6177 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6178 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6179 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6181 notify_printer_location(snum, printer->info_2->location);
6184 /* here we need to update some more DsSpooler keys */
6185 /* uNCName, serverName, shortServerName */
6187 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6188 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6189 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6190 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6191 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6193 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6194 global_myname(), printer->info_2->sharename );
6195 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6196 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6197 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6199 /* Update printer info */
6200 result = mod_a_printer(printer, 2);
6203 free_a_printer(&printer, 2);
6204 free_a_printer(&old_printer, 2);
6210 /****************************************************************************
6211 ****************************************************************************/
6212 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6213 const SPOOL_PRINTER_INFO_LEVEL *info)
6216 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6218 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6220 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6225 if (!get_printer_snum(p, handle, &snum))
6228 nt_printer_publish(Printer, snum, info7->action);
6232 return WERR_UNKNOWN_LEVEL;
6235 /****************************************************************************
6236 ****************************************************************************/
6238 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6240 POLICY_HND *handle = &q_u->handle;
6241 uint32 level = q_u->level;
6242 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6243 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6244 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6245 uint32 command = q_u->command;
6248 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6251 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6255 /* check the level */
6258 return control_printer(handle, command, p);
6260 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6261 if (!W_ERROR_IS_OK(result))
6264 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6267 return update_printer_sec(handle, level, info, p,
6270 return publish_or_unpublish_printer(p, handle, info);
6272 return WERR_UNKNOWN_LEVEL;
6276 /****************************************************************************
6277 ****************************************************************************/
6279 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6281 POLICY_HND *handle = &q_u->handle;
6282 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6285 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6289 if (Printer->notify.client_connected==True) {
6292 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6294 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6295 !get_printer_snum(p, handle, &snum) )
6298 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6301 Printer->notify.flags=0;
6302 Printer->notify.options=0;
6303 Printer->notify.localmachine[0]='\0';
6304 Printer->notify.printerlocal=0;
6305 if (Printer->notify.option)
6306 free_spool_notify_option(&Printer->notify.option);
6307 Printer->notify.client_connected=False;
6312 /****************************************************************************
6313 ****************************************************************************/
6315 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6317 /* that's an [in out] buffer */
6320 rpcbuf_move(q_u->buffer, &r_u->buffer);
6323 return WERR_INVALID_PARAM; /* this is what a NT server
6324 returns for AddJob. AddJob
6325 must fail on non-local
6329 /****************************************************************************
6330 ****************************************************************************/
6332 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6333 int position, int snum,
6334 NT_PRINTER_INFO_LEVEL *ntprinter)
6338 t=gmtime(&queue->time);
6340 job_info->jobid=queue->job;
6341 init_unistr(&job_info->printername, lp_servicename(snum));
6342 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6343 init_unistr(&job_info->username, queue->fs_user);
6344 init_unistr(&job_info->document, queue->fs_file);
6345 init_unistr(&job_info->datatype, "RAW");
6346 init_unistr(&job_info->text_status, "");
6347 job_info->status=nt_printj_status(queue->status);
6348 job_info->priority=queue->priority;
6349 job_info->position=position;
6350 job_info->totalpages=queue->page_count;
6351 job_info->pagesprinted=0;
6353 make_systemtime(&job_info->submitted, t);
6356 /****************************************************************************
6357 ****************************************************************************/
6359 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6360 int position, int snum,
6361 NT_PRINTER_INFO_LEVEL *ntprinter,
6362 DEVICEMODE *devmode)
6366 t=gmtime(&queue->time);
6368 job_info->jobid=queue->job;
6370 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6372 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6373 init_unistr(&job_info->username, queue->fs_user);
6374 init_unistr(&job_info->document, queue->fs_file);
6375 init_unistr(&job_info->notifyname, queue->fs_user);
6376 init_unistr(&job_info->datatype, "RAW");
6377 init_unistr(&job_info->printprocessor, "winprint");
6378 init_unistr(&job_info->parameters, "");
6379 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6380 init_unistr(&job_info->text_status, "");
6382 /* and here the security descriptor */
6384 job_info->status=nt_printj_status(queue->status);
6385 job_info->priority=queue->priority;
6386 job_info->position=position;
6387 job_info->starttime=0;
6388 job_info->untiltime=0;
6389 job_info->totalpages=queue->page_count;
6390 job_info->size=queue->size;
6391 make_systemtime(&(job_info->submitted), t);
6392 job_info->timeelapsed=0;
6393 job_info->pagesprinted=0;
6395 job_info->devmode = devmode;
6400 /****************************************************************************
6401 Enumjobs at level 1.
6402 ****************************************************************************/
6404 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6405 NT_PRINTER_INFO_LEVEL *ntprinter,
6406 RPC_BUFFER *buffer, uint32 offered,
6407 uint32 *needed, uint32 *returned)
6411 WERROR result = WERR_OK;
6413 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6420 for (i=0; i<*returned; i++)
6421 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6425 /* check the required size. */
6426 for (i=0; i<*returned; i++)
6427 (*needed) += spoolss_size_job_info_1(&info[i]);
6429 if (*needed > offered) {
6430 result = WERR_INSUFFICIENT_BUFFER;
6434 if (!rpcbuf_alloc_size(buffer, *needed)) {
6435 result = WERR_NOMEM;
6439 /* fill the buffer with the structures */
6440 for (i=0; i<*returned; i++)
6441 smb_io_job_info_1("", buffer, &info[i], 0);
6447 if ( !W_ERROR_IS_OK(result) )
6453 /****************************************************************************
6454 Enumjobs at level 2.
6455 ****************************************************************************/
6457 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6458 NT_PRINTER_INFO_LEVEL *ntprinter,
6459 RPC_BUFFER *buffer, uint32 offered,
6460 uint32 *needed, uint32 *returned)
6462 JOB_INFO_2 *info = NULL;
6464 WERROR result = WERR_OK;
6465 DEVICEMODE *devmode = NULL;
6467 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6472 /* this should not be a failure condition if the devmode is NULL */
6474 devmode = construct_dev_mode(snum);
6476 for (i=0; i<*returned; i++)
6477 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6479 free_a_printer(&ntprinter, 2);
6482 /* check the required size. */
6483 for (i=0; i<*returned; i++)
6484 (*needed) += spoolss_size_job_info_2(&info[i]);
6486 if (*needed > offered) {
6487 result = WERR_INSUFFICIENT_BUFFER;
6491 if (!rpcbuf_alloc_size(buffer, *needed)) {
6492 result = WERR_NOMEM;
6496 /* fill the buffer with the structures */
6497 for (i=0; i<*returned; i++)
6498 smb_io_job_info_2("", buffer, &info[i], 0);
6501 free_devmode(devmode);
6504 if ( !W_ERROR_IS_OK(result) )
6511 /****************************************************************************
6513 ****************************************************************************/
6515 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6517 POLICY_HND *handle = &q_u->handle;
6518 uint32 level = q_u->level;
6519 RPC_BUFFER *buffer = NULL;
6520 uint32 offered = q_u->offered;
6521 uint32 *needed = &r_u->needed;
6522 uint32 *returned = &r_u->returned;
6524 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6526 print_status_struct prt_status;
6527 print_queue_struct *queue=NULL;
6529 /* that's an [in out] buffer */
6531 if ( q_u->buffer ) {
6532 rpcbuf_move(q_u->buffer, &r_u->buffer);
6533 buffer = r_u->buffer;
6536 DEBUG(4,("_spoolss_enumjobs\n"));
6541 /* lookup the printer snum and tdb entry */
6543 if (!get_printer_snum(p, handle, &snum))
6546 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6547 if ( !W_ERROR_IS_OK(wret) )
6550 *returned = print_queue_status(snum, &queue, &prt_status);
6551 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6553 if (*returned == 0) {
6560 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6563 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6568 wret = WERR_UNKNOWN_LEVEL;
6571 free_a_printer( &ntprinter, 2 );
6575 /****************************************************************************
6576 ****************************************************************************/
6578 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6583 /****************************************************************************
6584 ****************************************************************************/
6586 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6588 POLICY_HND *handle = &q_u->handle;
6589 uint32 jobid = q_u->jobid;
6590 uint32 command = q_u->command;
6592 struct current_user user;
6594 WERROR errcode = WERR_BADFUNC;
6596 if (!get_printer_snum(p, handle, &snum)) {
6600 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6601 return WERR_INVALID_PRINTER_NAME;
6604 get_current_user(&user, p);
6607 case JOB_CONTROL_CANCEL:
6608 case JOB_CONTROL_DELETE:
6609 if (print_job_delete(&user, snum, jobid, &errcode)) {
6613 case JOB_CONTROL_PAUSE:
6614 if (print_job_pause(&user, snum, jobid, &errcode)) {
6618 case JOB_CONTROL_RESTART:
6619 case JOB_CONTROL_RESUME:
6620 if (print_job_resume(&user, snum, jobid, &errcode)) {
6625 return WERR_UNKNOWN_LEVEL;
6631 /****************************************************************************
6632 Enumerates all printer drivers at level 1.
6633 ****************************************************************************/
6635 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6640 fstring *list = NULL;
6641 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6642 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6643 WERROR result = WERR_OK;
6647 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6649 ndrivers=get_ntdrivers(&list, architecture, version);
6650 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6656 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6657 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6658 SAFE_FREE(driver_info_1);
6662 else driver_info_1 = tdi1;
6665 for (i=0; i<ndrivers; i++) {
6667 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6668 ZERO_STRUCT(driver);
6669 status = get_a_printer_driver(&driver, 3, list[i],
6670 architecture, version);
6671 if (!W_ERROR_IS_OK(status)) {
6675 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6676 free_a_printer_driver(driver, 3);
6679 *returned+=ndrivers;
6683 /* check the required size. */
6684 for (i=0; i<*returned; i++) {
6685 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6686 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6689 if (*needed > offered) {
6690 result = WERR_INSUFFICIENT_BUFFER;
6694 if (!rpcbuf_alloc_size(buffer, *needed)) {
6695 result = WERR_NOMEM;
6699 /* fill the buffer with the driver structures */
6700 for (i=0; i<*returned; i++) {
6701 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6702 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6706 SAFE_FREE(driver_info_1);
6708 if ( !W_ERROR_IS_OK(result) )
6714 /****************************************************************************
6715 Enumerates all printer drivers at level 2.
6716 ****************************************************************************/
6718 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6723 fstring *list = NULL;
6724 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6725 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6726 WERROR result = WERR_OK;
6730 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6732 ndrivers=get_ntdrivers(&list, architecture, version);
6733 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6739 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6740 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6741 SAFE_FREE(driver_info_2);
6745 else driver_info_2 = tdi2;
6748 for (i=0; i<ndrivers; i++) {
6751 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6752 ZERO_STRUCT(driver);
6753 status = get_a_printer_driver(&driver, 3, list[i],
6754 architecture, version);
6755 if (!W_ERROR_IS_OK(status)) {
6759 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6760 free_a_printer_driver(driver, 3);
6763 *returned+=ndrivers;
6767 /* check the required size. */
6768 for (i=0; i<*returned; i++) {
6769 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6770 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6773 if (*needed > offered) {
6774 result = WERR_INSUFFICIENT_BUFFER;
6778 if (!rpcbuf_alloc_size(buffer, *needed)) {
6779 result = WERR_NOMEM;
6783 /* fill the buffer with the form structures */
6784 for (i=0; i<*returned; i++) {
6785 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6786 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6790 SAFE_FREE(driver_info_2);
6792 if ( !W_ERROR_IS_OK(result) )
6798 /****************************************************************************
6799 Enumerates all printer drivers at level 3.
6800 ****************************************************************************/
6802 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6807 fstring *list = NULL;
6808 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6809 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6810 WERROR result = WERR_OK;
6814 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6816 ndrivers=get_ntdrivers(&list, architecture, version);
6817 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6823 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6824 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6825 SAFE_FREE(driver_info_3);
6829 else driver_info_3 = tdi3;
6832 for (i=0; i<ndrivers; i++) {
6835 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6836 ZERO_STRUCT(driver);
6837 status = get_a_printer_driver(&driver, 3, list[i],
6838 architecture, version);
6839 if (!W_ERROR_IS_OK(status)) {
6843 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6844 free_a_printer_driver(driver, 3);
6847 *returned+=ndrivers;
6851 /* check the required size. */
6852 for (i=0; i<*returned; i++) {
6853 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6854 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6857 if (*needed > offered) {
6858 result = WERR_INSUFFICIENT_BUFFER;
6862 if (!rpcbuf_alloc_size(buffer, *needed)) {
6863 result = WERR_NOMEM;
6867 /* fill the buffer with the driver structures */
6868 for (i=0; i<*returned; i++) {
6869 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6870 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6874 for (i=0; i<*returned; i++)
6875 SAFE_FREE(driver_info_3[i].dependentfiles);
6877 SAFE_FREE(driver_info_3);
6879 if ( !W_ERROR_IS_OK(result) )
6885 /****************************************************************************
6886 Enumerates all printer drivers.
6887 ****************************************************************************/
6889 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6891 uint32 level = q_u->level;
6892 RPC_BUFFER *buffer = NULL;
6893 uint32 offered = q_u->offered;
6894 uint32 *needed = &r_u->needed;
6895 uint32 *returned = &r_u->returned;
6898 fstring architecture;
6900 /* that's an [in out] buffer */
6902 if ( q_u->buffer ) {
6903 rpcbuf_move(q_u->buffer, &r_u->buffer);
6904 buffer = r_u->buffer;
6907 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6912 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6913 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6915 if ( !is_myname_or_ipaddr( servername ) )
6916 return WERR_UNKNOWN_PRINTER_DRIVER;
6920 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6922 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6924 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6926 return WERR_UNKNOWN_LEVEL;
6930 /****************************************************************************
6931 ****************************************************************************/
6933 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6935 form->flag=list->flag;
6936 init_unistr(&form->name, list->name);
6937 form->width=list->width;
6938 form->length=list->length;
6939 form->left=list->left;
6940 form->top=list->top;
6941 form->right=list->right;
6942 form->bottom=list->bottom;
6945 /****************************************************************************
6946 ****************************************************************************/
6948 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6950 uint32 level = q_u->level;
6951 RPC_BUFFER *buffer = NULL;
6952 uint32 offered = q_u->offered;
6953 uint32 *needed = &r_u->needed;
6954 uint32 *numofforms = &r_u->numofforms;
6955 uint32 numbuiltinforms;
6957 nt_forms_struct *list=NULL;
6958 nt_forms_struct *builtinlist=NULL;
6963 /* that's an [in out] buffer */
6965 if ( q_u->buffer ) {
6966 rpcbuf_move(q_u->buffer, &r_u->buffer);
6967 buffer = r_u->buffer;
6970 DEBUG(4,("_spoolss_enumforms\n"));
6971 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6972 DEBUGADD(5,("Info level [%d]\n", level));
6974 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6975 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6976 *numofforms = get_ntforms(&list);
6977 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6978 *numofforms += numbuiltinforms;
6980 if (*numofforms == 0)
6981 return WERR_NO_MORE_ITEMS;
6985 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6990 /* construct the list of form structures */
6991 for (i=0; i<numbuiltinforms; i++) {
6992 DEBUGADD(6,("Filling form number [%d]\n",i));
6993 fill_form_1(&forms_1[i], &builtinlist[i]);
6996 SAFE_FREE(builtinlist);
6998 for (; i<*numofforms; i++) {
6999 DEBUGADD(6,("Filling form number [%d]\n",i));
7000 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7005 /* check the required size. */
7006 for (i=0; i<numbuiltinforms; i++) {
7007 DEBUGADD(6,("adding form [%d]'s size\n",i));
7008 buffer_size += spoolss_size_form_1(&forms_1[i]);
7010 for (; i<*numofforms; i++) {
7011 DEBUGADD(6,("adding form [%d]'s size\n",i));
7012 buffer_size += spoolss_size_form_1(&forms_1[i]);
7015 *needed=buffer_size;
7017 if (*needed > offered) {
7020 return WERR_INSUFFICIENT_BUFFER;
7023 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7029 /* fill the buffer with the form structures */
7030 for (i=0; i<numbuiltinforms; i++) {
7031 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7032 smb_io_form_1("", buffer, &forms_1[i], 0);
7034 for (; i<*numofforms; i++) {
7035 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7036 smb_io_form_1("", buffer, &forms_1[i], 0);
7045 SAFE_FREE(builtinlist);
7046 return WERR_UNKNOWN_LEVEL;
7051 /****************************************************************************
7052 ****************************************************************************/
7054 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7056 uint32 level = q_u->level;
7057 UNISTR2 *uni_formname = &q_u->formname;
7058 RPC_BUFFER *buffer = NULL;
7059 uint32 offered = q_u->offered;
7060 uint32 *needed = &r_u->needed;
7062 nt_forms_struct *list=NULL;
7063 nt_forms_struct builtin_form;
7068 int numofforms=0, i=0;
7070 /* that's an [in out] buffer */
7072 if ( q_u->buffer ) {
7073 rpcbuf_move(q_u->buffer, &r_u->buffer);
7074 buffer = r_u->buffer;
7077 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7079 DEBUG(4,("_spoolss_getform\n"));
7080 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7081 DEBUGADD(5,("Info level [%d]\n", level));
7083 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7084 if (!foundBuiltin) {
7085 numofforms = get_ntforms(&list);
7086 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7088 if (numofforms == 0)
7095 fill_form_1(&form_1, &builtin_form);
7098 /* Check if the requested name is in the list of form structures */
7099 for (i=0; i<numofforms; i++) {
7101 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7103 if (strequal(form_name, list[i].name)) {
7104 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7105 fill_form_1(&form_1, &list[i]);
7111 if (i == numofforms) {
7115 /* check the required size. */
7117 *needed=spoolss_size_form_1(&form_1);
7119 if (*needed > offered)
7120 return WERR_INSUFFICIENT_BUFFER;
7122 if (!rpcbuf_alloc_size(buffer, buffer_size))
7125 /* fill the buffer with the form structures */
7126 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7127 smb_io_form_1("", buffer, &form_1, 0);
7133 return WERR_UNKNOWN_LEVEL;
7137 /****************************************************************************
7138 ****************************************************************************/
7140 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7142 init_unistr(&port->port_name, name);
7145 /****************************************************************************
7146 ****************************************************************************/
7148 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7150 init_unistr(&port->port_name, name);
7151 init_unistr(&port->monitor_name, "Local Monitor");
7152 init_unistr(&port->description, "Local Port");
7153 port->port_type=PORT_TYPE_WRITE;
7158 /****************************************************************************
7159 wrapper around the enumer ports command
7160 ****************************************************************************/
7162 WERROR enumports_hook( int *count, char ***lines )
7164 char *cmd = lp_enumports_cmd();
7172 /* if no hook then just fill in the default port */
7175 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7176 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7181 /* we have a valid enumport command */
7183 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7185 DEBUG(10,("Running [%s]\n", command));
7186 ret = smbrun(command, &fd);
7187 DEBUG(10,("Returned [%d]\n", ret));
7192 return WERR_ACCESS_DENIED;
7196 qlines = fd_lines_load(fd, &numlines);
7197 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7207 /****************************************************************************
7209 ****************************************************************************/
7211 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7213 PORT_INFO_1 *ports=NULL;
7215 WERROR result = WERR_OK;
7219 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7223 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7224 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7225 dos_errstr(WERR_NOMEM)));
7226 file_lines_free(qlines);
7230 for (i=0; i<numlines; i++) {
7231 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7232 fill_port_1(&ports[i], qlines[i]);
7235 file_lines_free(qlines);
7238 *returned = numlines;
7240 /* check the required size. */
7241 for (i=0; i<*returned; i++) {
7242 DEBUGADD(6,("adding port [%d]'s size\n", i));
7243 *needed += spoolss_size_port_info_1(&ports[i]);
7246 if (*needed > offered) {
7247 result = WERR_INSUFFICIENT_BUFFER;
7251 if (!rpcbuf_alloc_size(buffer, *needed)) {
7252 result = WERR_NOMEM;
7256 /* fill the buffer with the ports structures */
7257 for (i=0; i<*returned; i++) {
7258 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7259 smb_io_port_1("", buffer, &ports[i], 0);
7265 if ( !W_ERROR_IS_OK(result) )
7271 /****************************************************************************
7273 ****************************************************************************/
7275 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7277 PORT_INFO_2 *ports=NULL;
7279 WERROR result = WERR_OK;
7283 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7288 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7289 file_lines_free(qlines);
7293 for (i=0; i<numlines; i++) {
7294 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7295 fill_port_2(&(ports[i]), qlines[i]);
7298 file_lines_free(qlines);
7301 *returned = numlines;
7303 /* check the required size. */
7304 for (i=0; i<*returned; i++) {
7305 DEBUGADD(6,("adding port [%d]'s size\n", i));
7306 *needed += spoolss_size_port_info_2(&ports[i]);
7309 if (*needed > offered) {
7310 result = WERR_INSUFFICIENT_BUFFER;
7314 if (!rpcbuf_alloc_size(buffer, *needed)) {
7315 result = WERR_NOMEM;
7319 /* fill the buffer with the ports structures */
7320 for (i=0; i<*returned; i++) {
7321 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7322 smb_io_port_2("", buffer, &ports[i], 0);
7328 if ( !W_ERROR_IS_OK(result) )
7334 /****************************************************************************
7336 ****************************************************************************/
7338 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7340 uint32 level = q_u->level;
7341 RPC_BUFFER *buffer = NULL;
7342 uint32 offered = q_u->offered;
7343 uint32 *needed = &r_u->needed;
7344 uint32 *returned = &r_u->returned;
7346 /* that's an [in out] buffer */
7348 if ( q_u->buffer ) {
7349 rpcbuf_move(q_u->buffer, &r_u->buffer);
7350 buffer = r_u->buffer;
7353 DEBUG(4,("_spoolss_enumports\n"));
7360 return enumports_level_1(buffer, offered, needed, returned);
7362 return enumports_level_2(buffer, offered, needed, returned);
7364 return WERR_UNKNOWN_LEVEL;
7368 /****************************************************************************
7369 ****************************************************************************/
7371 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7372 const SPOOL_PRINTER_INFO_LEVEL *info,
7373 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7374 uint32 user_switch, const SPOOL_USER_CTR *user,
7377 NT_PRINTER_INFO_LEVEL *printer = NULL;
7380 WERROR err = WERR_OK;
7382 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7383 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7387 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7388 if (!convert_printer_info(info, printer, 2)) {
7389 free_a_printer(&printer, 2);
7393 /* check to see if the printer already exists */
7395 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7396 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7397 printer->info_2->sharename));
7398 free_a_printer(&printer, 2);
7399 return WERR_PRINTER_ALREADY_EXISTS;
7402 /* FIXME!!! smbd should check to see if the driver is installed before
7403 trying to add a printer like this --jerry */
7405 if (*lp_addprinter_cmd() ) {
7406 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7407 free_a_printer(&printer,2);
7408 return WERR_ACCESS_DENIED;
7411 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7412 "smb.conf parameter \"addprinter command\" is defined. This"
7413 "parameter must exist for this call to succeed\n",
7414 printer->info_2->sharename ));
7417 /* use our primary netbios name since get_a_printer() will convert
7418 it to what the client expects on a case by case basis */
7420 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7421 printer->info_2->sharename);
7424 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7425 free_a_printer(&printer,2);
7426 return WERR_ACCESS_DENIED;
7429 /* you must be a printer admin to add a new printer */
7430 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7431 free_a_printer(&printer,2);
7432 return WERR_ACCESS_DENIED;
7436 * Do sanity check on the requested changes for Samba.
7439 if (!check_printer_ok(printer->info_2, snum)) {
7440 free_a_printer(&printer,2);
7441 return WERR_INVALID_PARAM;
7445 * When a printer is created, the drivername bound to the printer is used
7446 * to lookup previously saved driver initialization info, which is then
7447 * bound to the new printer, simulating what happens in the Windows arch.
7452 set_driver_init(printer, 2);
7456 /* A valid devmode was included, convert and link it
7458 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7460 if (!convert_devicemode(printer->info_2->printername, devmode,
7461 &printer->info_2->devmode))
7465 /* write the ASCII on disk */
7466 err = mod_a_printer(printer, 2);
7467 if (!W_ERROR_IS_OK(err)) {
7468 free_a_printer(&printer,2);
7472 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7473 /* Handle open failed - remove addition. */
7474 del_a_printer(printer->info_2->sharename);
7475 free_a_printer(&printer,2);
7476 return WERR_ACCESS_DENIED;
7479 update_c_setprinter(False);
7480 free_a_printer(&printer,2);
7485 /****************************************************************************
7486 ****************************************************************************/
7488 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7490 UNISTR2 *uni_srv_name = q_u->server_name;
7491 uint32 level = q_u->level;
7492 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7493 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7494 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7495 uint32 user_switch = q_u->user_switch;
7496 SPOOL_USER_CTR *user = &q_u->user_ctr;
7497 POLICY_HND *handle = &r_u->handle;
7501 /* we don't handle yet */
7502 /* but I know what to do ... */
7503 return WERR_UNKNOWN_LEVEL;
7505 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7507 user_switch, user, handle);
7509 return WERR_UNKNOWN_LEVEL;
7513 /****************************************************************************
7514 ****************************************************************************/
7516 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7518 uint32 level = q_u->level;
7519 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7520 WERROR err = WERR_OK;
7521 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7522 struct current_user user;
7523 fstring driver_name;
7526 ZERO_STRUCT(driver);
7528 get_current_user(&user, p);
7530 if (!convert_printer_driver_info(info, &driver, level)) {
7535 DEBUG(5,("Cleaning driver's information\n"));
7536 err = clean_up_driver_struct(driver, level, &user);
7537 if (!W_ERROR_IS_OK(err))
7540 DEBUG(5,("Moving driver to final destination\n"));
7541 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7545 if (add_a_printer_driver(driver, level)!=0) {
7546 err = WERR_ACCESS_DENIED;
7550 /* BEGIN_ADMIN_LOG */
7553 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7554 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7555 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7558 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7559 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7560 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7566 * I think this is where he DrvUpgradePrinter() hook would be
7567 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7568 * server. Right now, we just need to send ourselves a message
7569 * to update each printer bound to this driver. --jerry
7572 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7573 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7578 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7579 * decide if the driver init data should be deleted. The rules are:
7580 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7581 * 2) delete init data only if there is no 2k/Xp driver
7582 * 3) always delete init data
7583 * The generalized rule is always use init data from the highest order driver.
7584 * It is necessary to follow the driver install by an initialization step to
7585 * finish off this process.
7588 version = driver.info_3->cversion;
7589 else if (level == 6)
7590 version = driver.info_6->version;
7595 * 9x printer driver - never delete init data
7598 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7603 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7604 * there is no 2k/Xp driver init data for this driver name.
7608 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7610 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7612 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7614 if (!del_driver_init(driver_name))
7615 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7618 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7620 free_a_printer_driver(driver1,3);
7621 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7628 * 2k or Xp printer driver - always delete init data
7631 if (!del_driver_init(driver_name))
7632 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7636 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7642 free_a_printer_driver(driver, level);
7646 /********************************************************************
7647 * spoolss_addprinterdriverex
7648 ********************************************************************/
7650 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7652 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7653 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7656 * we only support the semantics of AddPrinterDriver()
7657 * i.e. only copy files that are newer than existing ones
7660 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7661 return WERR_ACCESS_DENIED;
7663 ZERO_STRUCT(q_u_local);
7664 ZERO_STRUCT(r_u_local);
7666 /* just pass the information off to _spoolss_addprinterdriver() */
7667 q_u_local.server_name_ptr = q_u->server_name_ptr;
7668 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7669 q_u_local.level = q_u->level;
7670 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7672 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7675 /****************************************************************************
7676 ****************************************************************************/
7678 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7680 init_unistr(&info->name, name);
7683 /****************************************************************************
7684 ****************************************************************************/
7686 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7692 const char *short_archi;
7693 DRIVER_DIRECTORY_1 *info=NULL;
7694 WERROR result = WERR_OK;
7696 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7697 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7699 /* check for beginning double '\'s and that the server
7702 pservername = servername;
7703 if ( *pservername == '\\' && strlen(servername)>2 ) {
7707 if ( !is_myname_or_ipaddr( pservername ) )
7708 return WERR_INVALID_PARAM;
7710 if (!(short_archi = get_short_archi(long_archi)))
7711 return WERR_INVALID_ENVIRONMENT;
7713 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7716 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7718 DEBUG(4,("printer driver directory: [%s]\n", path));
7720 fill_driverdir_1(info, path);
7722 *needed += spoolss_size_driverdir_info_1(info);
7724 if (*needed > offered) {
7725 result = WERR_INSUFFICIENT_BUFFER;
7729 if (!rpcbuf_alloc_size(buffer, *needed)) {
7730 result = WERR_NOMEM;
7734 smb_io_driverdir_1("", buffer, info, 0);
7742 /****************************************************************************
7743 ****************************************************************************/
7745 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7747 UNISTR2 *name = &q_u->name;
7748 UNISTR2 *uni_environment = &q_u->environment;
7749 uint32 level = q_u->level;
7750 RPC_BUFFER *buffer = NULL;
7751 uint32 offered = q_u->offered;
7752 uint32 *needed = &r_u->needed;
7754 /* that's an [in out] buffer */
7756 if ( q_u->buffer ) {
7757 rpcbuf_move(q_u->buffer, &r_u->buffer);
7758 buffer = r_u->buffer;
7761 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7767 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7769 return WERR_UNKNOWN_LEVEL;
7773 /****************************************************************************
7774 ****************************************************************************/
7776 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7778 POLICY_HND *handle = &q_u->handle;
7779 uint32 idx = q_u->index;
7780 uint32 in_value_len = q_u->valuesize;
7781 uint32 in_data_len = q_u->datasize;
7782 uint32 *out_max_value_len = &r_u->valuesize;
7783 uint16 **out_value = &r_u->value;
7784 uint32 *out_value_len = &r_u->realvaluesize;
7785 uint32 *out_type = &r_u->type;
7786 uint32 *out_max_data_len = &r_u->datasize;
7787 uint8 **data_out = &r_u->data;
7788 uint32 *out_data_len = &r_u->realdatasize;
7790 NT_PRINTER_INFO_LEVEL *printer = NULL;
7792 uint32 biggest_valuesize;
7793 uint32 biggest_datasize;
7795 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7798 REGISTRY_VALUE *val = NULL;
7799 NT_PRINTER_DATA *p_data;
7800 int i, key_index, num_values;
7805 *out_max_data_len = 0;
7809 DEBUG(5,("spoolss_enumprinterdata\n"));
7812 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7816 if (!get_printer_snum(p,handle, &snum))
7819 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7820 if (!W_ERROR_IS_OK(result))
7823 p_data = printer->info_2->data;
7824 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7829 * The NT machine wants to know the biggest size of value and data
7831 * cf: MSDN EnumPrinterData remark section
7834 if ( !in_value_len && !in_data_len && (key_index != -1) )
7836 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7838 biggest_valuesize = 0;
7839 biggest_datasize = 0;
7841 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7843 for ( i=0; i<num_values; i++ )
7845 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7847 name_length = strlen(val->valuename);
7848 if ( strlen(val->valuename) > biggest_valuesize )
7849 biggest_valuesize = name_length;
7851 if ( val->size > biggest_datasize )
7852 biggest_datasize = val->size;
7854 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7858 /* the value is an UNICODE string but real_value_size is the length
7859 in bytes including the trailing 0 */
7861 *out_value_len = 2 * (1+biggest_valuesize);
7862 *out_data_len = biggest_datasize;
7864 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7870 * the value len is wrong in NT sp3
7871 * that's the number of bytes not the number of unicode chars
7874 if ( key_index != -1 )
7875 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7880 /* out_value should default to "" or else NT4 has
7881 problems unmarshalling the response */
7883 *out_max_value_len=(in_value_len/sizeof(uint16));
7885 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7887 result = WERR_NOMEM;
7891 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7893 /* the data is counted in bytes */
7895 *out_max_data_len = in_data_len;
7896 *out_data_len = in_data_len;
7898 /* only allocate when given a non-zero data_len */
7900 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7902 result = WERR_NOMEM;
7906 result = WERR_NO_MORE_ITEMS;
7912 * - counted in bytes in the request
7913 * - counted in UNICODE chars in the max reply
7914 * - counted in bytes in the real size
7916 * take a pause *before* coding not *during* coding
7920 *out_max_value_len=(in_value_len/sizeof(uint16));
7921 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7923 result = WERR_NOMEM;
7927 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7931 *out_type = regval_type( val );
7933 /* data - counted in bytes */
7935 *out_max_data_len = in_data_len;
7936 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7938 result = WERR_NOMEM;
7941 data_len = regval_size(val);
7943 memcpy( *data_out, regval_data_p(val), data_len );
7944 *out_data_len = data_len;
7948 free_a_printer(&printer, 2);
7952 /****************************************************************************
7953 ****************************************************************************/
7955 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7957 POLICY_HND *handle = &q_u->handle;
7958 UNISTR2 *value = &q_u->value;
7959 uint32 type = q_u->type;
7960 uint8 *data = q_u->data;
7961 uint32 real_len = q_u->real_len;
7963 NT_PRINTER_INFO_LEVEL *printer = NULL;
7965 WERROR status = WERR_OK;
7966 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7969 DEBUG(5,("spoolss_setprinterdata\n"));
7972 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7976 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7977 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7978 return WERR_INVALID_PARAM;
7981 if (!get_printer_snum(p,handle, &snum))
7985 * Access check : NT returns "access denied" if you make a
7986 * SetPrinterData call without the necessary privildge.
7987 * we were originally returning OK if nothing changed
7988 * which made Win2k issue **a lot** of SetPrinterData
7989 * when connecting to a printer --jerry
7992 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
7994 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7995 status = WERR_ACCESS_DENIED;
7999 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8000 if (!W_ERROR_IS_OK(status))
8003 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8006 * When client side code sets a magic printer data key, detect it and save
8007 * the current printer data and the magic key's data (its the DEVMODE) for
8008 * future printer/driver initializations.
8010 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8012 /* Set devmode and printer initialization info */
8013 status = save_driver_init( printer, 2, data, real_len );
8015 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8019 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8020 type, data, real_len );
8021 if ( W_ERROR_IS_OK(status) )
8022 status = mod_a_printer(printer, 2);
8026 free_a_printer(&printer, 2);
8031 /****************************************************************************
8032 ****************************************************************************/
8034 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8036 POLICY_HND *handle = &q_u->handle;
8037 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8040 DEBUG(5,("_spoolss_resetprinter\n"));
8043 * All we do is to check to see if the handle and queue is valid.
8044 * This call really doesn't mean anything to us because we only
8045 * support RAW printing. --jerry
8049 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8053 if (!get_printer_snum(p,handle, &snum))
8057 /* blindly return success */
8062 /****************************************************************************
8063 ****************************************************************************/
8065 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8067 POLICY_HND *handle = &q_u->handle;
8068 UNISTR2 *value = &q_u->valuename;
8070 NT_PRINTER_INFO_LEVEL *printer = NULL;
8072 WERROR status = WERR_OK;
8073 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8076 DEBUG(5,("spoolss_deleteprinterdata\n"));
8079 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8083 if (!get_printer_snum(p, handle, &snum))
8086 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8087 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8088 return WERR_ACCESS_DENIED;
8091 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8092 if (!W_ERROR_IS_OK(status))
8095 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8097 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8099 if ( W_ERROR_IS_OK(status) )
8100 mod_a_printer( printer, 2 );
8102 free_a_printer(&printer, 2);
8107 /****************************************************************************
8108 ****************************************************************************/
8110 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8112 POLICY_HND *handle = &q_u->handle;
8113 FORM *form = &q_u->form;
8114 nt_forms_struct tmpForm;
8116 WERROR status = WERR_OK;
8117 NT_PRINTER_INFO_LEVEL *printer = NULL;
8120 nt_forms_struct *list=NULL;
8121 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8123 DEBUG(5,("spoolss_addform\n"));
8126 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8131 /* forms can be added on printer of on the print server handle */
8133 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8135 if (!get_printer_snum(p,handle, &snum))
8138 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8139 if (!W_ERROR_IS_OK(status))
8143 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8144 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8145 status = WERR_ACCESS_DENIED;
8149 /* can't add if builtin */
8151 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8152 status = WERR_ALREADY_EXISTS;
8156 count = get_ntforms(&list);
8158 if(!add_a_form(&list, form, &count)) {
8159 status = WERR_NOMEM;
8163 write_ntforms(&list, count);
8166 * ChangeID must always be set if this is a printer
8169 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8170 status = mod_a_printer(printer, 2);
8174 free_a_printer(&printer, 2);
8180 /****************************************************************************
8181 ****************************************************************************/
8183 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8185 POLICY_HND *handle = &q_u->handle;
8186 UNISTR2 *form_name = &q_u->name;
8187 nt_forms_struct tmpForm;
8189 nt_forms_struct *list=NULL;
8190 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8192 WERROR status = WERR_OK;
8193 NT_PRINTER_INFO_LEVEL *printer = NULL;
8195 DEBUG(5,("spoolss_deleteform\n"));
8198 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8202 /* forms can be deleted on printer of on the print server handle */
8204 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8206 if (!get_printer_snum(p,handle, &snum))
8209 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8210 if (!W_ERROR_IS_OK(status))
8214 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8215 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8216 status = WERR_ACCESS_DENIED;
8220 /* can't delete if builtin */
8222 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8223 status = WERR_INVALID_PARAM;
8227 count = get_ntforms(&list);
8229 if ( !delete_a_form(&list, form_name, &count, &status ))
8233 * ChangeID must always be set if this is a printer
8236 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8237 status = mod_a_printer(printer, 2);
8241 free_a_printer(&printer, 2);
8247 /****************************************************************************
8248 ****************************************************************************/
8250 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8252 POLICY_HND *handle = &q_u->handle;
8253 FORM *form = &q_u->form;
8254 nt_forms_struct tmpForm;
8256 WERROR status = WERR_OK;
8257 NT_PRINTER_INFO_LEVEL *printer = NULL;
8260 nt_forms_struct *list=NULL;
8261 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8263 DEBUG(5,("spoolss_setform\n"));
8266 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8270 /* forms can be modified on printer of on the print server handle */
8272 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8274 if (!get_printer_snum(p,handle, &snum))
8277 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8278 if (!W_ERROR_IS_OK(status))
8282 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8283 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8284 status = WERR_ACCESS_DENIED;
8288 /* can't set if builtin */
8289 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8290 status = WERR_INVALID_PARAM;
8294 count = get_ntforms(&list);
8295 update_a_form(&list, form, count);
8296 write_ntforms(&list, count);
8299 * ChangeID must always be set if this is a printer
8302 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8303 status = mod_a_printer(printer, 2);
8308 free_a_printer(&printer, 2);
8314 /****************************************************************************
8315 enumprintprocessors level 1.
8316 ****************************************************************************/
8318 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8320 PRINTPROCESSOR_1 *info_1=NULL;
8321 WERROR result = WERR_OK;
8323 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8328 init_unistr(&info_1->name, "winprint");
8330 *needed += spoolss_size_printprocessor_info_1(info_1);
8332 if (*needed > offered) {
8333 result = WERR_INSUFFICIENT_BUFFER;
8337 if (!rpcbuf_alloc_size(buffer, *needed)) {
8338 result = WERR_NOMEM;
8342 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8347 if ( !W_ERROR_IS_OK(result) )
8353 /****************************************************************************
8354 ****************************************************************************/
8356 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8358 uint32 level = q_u->level;
8359 RPC_BUFFER *buffer = NULL;
8360 uint32 offered = q_u->offered;
8361 uint32 *needed = &r_u->needed;
8362 uint32 *returned = &r_u->returned;
8364 /* that's an [in out] buffer */
8366 if ( q_u->buffer ) {
8367 rpcbuf_move(q_u->buffer, &r_u->buffer);
8368 buffer = r_u->buffer;
8371 DEBUG(5,("spoolss_enumprintprocessors\n"));
8374 * Enumerate the print processors ...
8376 * Just reply with "winprint", to keep NT happy
8377 * and I can use my nice printer checker.
8385 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8387 return WERR_UNKNOWN_LEVEL;
8391 /****************************************************************************
8392 enumprintprocdatatypes level 1.
8393 ****************************************************************************/
8395 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8397 PRINTPROCDATATYPE_1 *info_1=NULL;
8398 WERROR result = WERR_NOMEM;
8400 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8405 init_unistr(&info_1->name, "RAW");
8407 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8409 if (*needed > offered) {
8410 result = WERR_INSUFFICIENT_BUFFER;
8414 if (!rpcbuf_alloc_size(buffer, *needed)) {
8415 result = WERR_NOMEM;
8419 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8424 if ( !W_ERROR_IS_OK(result) )
8430 /****************************************************************************
8431 ****************************************************************************/
8433 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8435 uint32 level = q_u->level;
8436 RPC_BUFFER *buffer = NULL;
8437 uint32 offered = q_u->offered;
8438 uint32 *needed = &r_u->needed;
8439 uint32 *returned = &r_u->returned;
8441 /* that's an [in out] buffer */
8443 if ( q_u->buffer ) {
8444 rpcbuf_move(q_u->buffer, &r_u->buffer);
8445 buffer = r_u->buffer;
8448 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8455 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8457 return WERR_UNKNOWN_LEVEL;
8461 /****************************************************************************
8462 enumprintmonitors level 1.
8463 ****************************************************************************/
8465 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8467 PRINTMONITOR_1 *info_1=NULL;
8468 WERROR result = WERR_OK;
8470 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8475 init_unistr(&info_1->name, "Local Port");
8477 *needed += spoolss_size_printmonitor_info_1(info_1);
8479 if (*needed > offered) {
8480 result = WERR_INSUFFICIENT_BUFFER;
8484 if (!rpcbuf_alloc_size(buffer, *needed)) {
8485 result = WERR_NOMEM;
8489 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8494 if ( !W_ERROR_IS_OK(result) )
8500 /****************************************************************************
8501 enumprintmonitors level 2.
8502 ****************************************************************************/
8504 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8506 PRINTMONITOR_2 *info_2=NULL;
8507 WERROR result = WERR_OK;
8509 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8514 init_unistr(&info_2->name, "Local Port");
8515 init_unistr(&info_2->environment, "Windows NT X86");
8516 init_unistr(&info_2->dll_name, "localmon.dll");
8518 *needed += spoolss_size_printmonitor_info_2(info_2);
8520 if (*needed > offered) {
8521 result = WERR_INSUFFICIENT_BUFFER;
8525 if (!rpcbuf_alloc_size(buffer, *needed)) {
8526 result = WERR_NOMEM;
8530 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8535 if ( !W_ERROR_IS_OK(result) )
8541 /****************************************************************************
8542 ****************************************************************************/
8544 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8546 uint32 level = q_u->level;
8547 RPC_BUFFER *buffer = NULL;
8548 uint32 offered = q_u->offered;
8549 uint32 *needed = &r_u->needed;
8550 uint32 *returned = &r_u->returned;
8552 /* that's an [in out] buffer */
8554 if ( q_u->buffer ) {
8555 rpcbuf_move(q_u->buffer, &r_u->buffer);
8556 buffer = r_u->buffer;
8559 DEBUG(5,("spoolss_enumprintmonitors\n"));
8562 * Enumerate the print monitors ...
8564 * Just reply with "Local Port", to keep NT happy
8565 * and I can use my nice printer checker.
8573 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8575 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8577 return WERR_UNKNOWN_LEVEL;
8581 /****************************************************************************
8582 ****************************************************************************/
8584 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8585 NT_PRINTER_INFO_LEVEL *ntprinter,
8586 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8591 JOB_INFO_1 *info_1=NULL;
8592 WERROR result = WERR_OK;
8594 info_1=SMB_MALLOC_P(JOB_INFO_1);
8596 if (info_1 == NULL) {
8600 for (i=0; i<count && found==False; i++) {
8601 if ((*queue)[i].job==(int)jobid)
8607 /* NT treats not found as bad param... yet another bad choice */
8608 return WERR_INVALID_PARAM;
8611 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8613 *needed += spoolss_size_job_info_1(info_1);
8615 if (*needed > offered) {
8616 result = WERR_INSUFFICIENT_BUFFER;
8620 if (!rpcbuf_alloc_size(buffer, *needed)) {
8621 result = WERR_NOMEM;
8625 smb_io_job_info_1("", buffer, info_1, 0);
8633 /****************************************************************************
8634 ****************************************************************************/
8636 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8637 NT_PRINTER_INFO_LEVEL *ntprinter,
8638 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8645 DEVICEMODE *devmode = NULL;
8646 NT_DEVICEMODE *nt_devmode = NULL;
8648 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8651 ZERO_STRUCTP(info_2);
8653 for ( i=0; i<count && found==False; i++ )
8655 if ((*queue)[i].job == (int)jobid)
8660 /* NT treats not found as bad param... yet another bad
8662 result = WERR_INVALID_PARAM;
8667 * if the print job does not have a DEVMODE associated with it,
8668 * just use the one for the printer. A NULL devicemode is not
8669 * a failure condition
8672 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8673 devmode = construct_dev_mode(snum);
8675 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8676 ZERO_STRUCTP( devmode );
8677 convert_nt_devicemode( devmode, nt_devmode );
8681 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8683 *needed += spoolss_size_job_info_2(info_2);
8685 if (*needed > offered) {
8686 result = WERR_INSUFFICIENT_BUFFER;
8690 if (!rpcbuf_alloc_size(buffer, *needed)) {
8691 result = WERR_NOMEM;
8695 smb_io_job_info_2("", buffer, info_2, 0);
8700 /* Cleanup allocated memory */
8702 free_job_info_2(info_2); /* Also frees devmode */
8708 /****************************************************************************
8709 ****************************************************************************/
8711 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8713 POLICY_HND *handle = &q_u->handle;
8714 uint32 jobid = q_u->jobid;
8715 uint32 level = q_u->level;
8716 RPC_BUFFER *buffer = NULL;
8717 uint32 offered = q_u->offered;
8718 uint32 *needed = &r_u->needed;
8719 WERROR wstatus = WERR_OK;
8720 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8723 print_queue_struct *queue = NULL;
8724 print_status_struct prt_status;
8726 /* that's an [in out] buffer */
8728 if ( q_u->buffer ) {
8729 rpcbuf_move(q_u->buffer, &r_u->buffer);
8730 buffer = r_u->buffer;
8733 DEBUG(5,("spoolss_getjob\n"));
8737 if (!get_printer_snum(p, handle, &snum))
8740 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8741 if ( !W_ERROR_IS_OK(wstatus) )
8744 count = print_queue_status(snum, &queue, &prt_status);
8746 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8747 count, prt_status.status, prt_status.message));
8751 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8752 buffer, offered, needed);
8755 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8756 buffer, offered, needed);
8759 wstatus = WERR_UNKNOWN_LEVEL;
8764 free_a_printer( &ntprinter, 2 );
8769 /********************************************************************
8770 spoolss_getprinterdataex
8772 From MSDN documentation of GetPrinterDataEx: pass request
8773 to GetPrinterData if key is "PrinterDriverData".
8774 ********************************************************************/
8776 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8778 POLICY_HND *handle = &q_u->handle;
8779 uint32 in_size = q_u->size;
8780 uint32 *type = &r_u->type;
8781 uint32 *out_size = &r_u->size;
8782 uint8 **data = &r_u->data;
8783 uint32 *needed = &r_u->needed;
8784 fstring keyname, valuename;
8786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8788 NT_PRINTER_INFO_LEVEL *printer = NULL;
8790 WERROR status = WERR_OK;
8792 DEBUG(4,("_spoolss_getprinterdataex\n"));
8794 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8795 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8797 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8798 keyname, valuename));
8800 /* in case of problem, return some default values */
8804 *out_size = in_size;
8807 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8808 status = WERR_BADFID;
8812 /* Is the handle to a printer or to the server? */
8814 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8815 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8816 status = WERR_INVALID_PARAM;
8820 if ( !get_printer_snum(p,handle, &snum) )
8823 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8824 if ( !W_ERROR_IS_OK(status) )
8827 /* check to see if the keyname is valid */
8828 if ( !strlen(keyname) ) {
8829 status = WERR_INVALID_PARAM;
8833 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8834 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8835 free_a_printer( &printer, 2 );
8836 status = WERR_BADFILE;
8840 /* When given a new keyname, we should just create it */
8842 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8844 if (*needed > *out_size)
8845 status = WERR_MORE_DATA;
8848 if ( !W_ERROR_IS_OK(status) )
8850 DEBUG(5, ("error: allocating %d\n", *out_size));
8852 /* reply this param doesn't exist */
8856 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8857 status = WERR_NOMEM;
8867 free_a_printer( &printer, 2 );
8872 /********************************************************************
8873 * spoolss_setprinterdataex
8874 ********************************************************************/
8876 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8878 POLICY_HND *handle = &q_u->handle;
8879 uint32 type = q_u->type;
8880 uint8 *data = q_u->data;
8881 uint32 real_len = q_u->real_len;
8883 NT_PRINTER_INFO_LEVEL *printer = NULL;
8885 WERROR status = WERR_OK;
8886 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8891 DEBUG(4,("_spoolss_setprinterdataex\n"));
8893 /* From MSDN documentation of SetPrinterDataEx: pass request to
8894 SetPrinterData if key is "PrinterDriverData" */
8897 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8901 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8902 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8903 return WERR_INVALID_PARAM;
8906 if ( !get_printer_snum(p,handle, &snum) )
8910 * Access check : NT returns "access denied" if you make a
8911 * SetPrinterData call without the necessary privildge.
8912 * we were originally returning OK if nothing changed
8913 * which made Win2k issue **a lot** of SetPrinterData
8914 * when connecting to a printer --jerry
8917 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8919 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8920 return WERR_ACCESS_DENIED;
8923 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8924 if (!W_ERROR_IS_OK(status))
8927 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8928 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8930 /* check for OID in valuename */
8932 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8938 /* save the registry data */
8940 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8942 if ( W_ERROR_IS_OK(status) )
8944 /* save the OID if one was specified */
8946 fstrcat( keyname, "\\" );
8947 fstrcat( keyname, SPOOL_OID_KEY );
8950 * I'm not checking the status here on purpose. Don't know
8951 * if this is right, but I'm returning the status from the
8952 * previous set_printer_dataex() call. I have no idea if
8953 * this is right. --jerry
8956 set_printer_dataex( printer, keyname, valuename,
8957 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8960 status = mod_a_printer(printer, 2);
8963 free_a_printer(&printer, 2);
8969 /********************************************************************
8970 * spoolss_deleteprinterdataex
8971 ********************************************************************/
8973 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8975 POLICY_HND *handle = &q_u->handle;
8976 UNISTR2 *value = &q_u->valuename;
8977 UNISTR2 *key = &q_u->keyname;
8979 NT_PRINTER_INFO_LEVEL *printer = NULL;
8981 WERROR status = WERR_OK;
8982 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8983 pstring valuename, keyname;
8985 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8988 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8992 if (!get_printer_snum(p, handle, &snum))
8995 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8996 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8997 return WERR_ACCESS_DENIED;
9000 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9001 if (!W_ERROR_IS_OK(status))
9004 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9005 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9007 status = delete_printer_dataex( printer, keyname, valuename );
9009 if ( W_ERROR_IS_OK(status) )
9010 mod_a_printer( printer, 2 );
9012 free_a_printer(&printer, 2);
9017 /********************************************************************
9018 * spoolss_enumprinterkey
9019 ********************************************************************/
9022 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9025 fstring *keynames = NULL;
9026 uint16 *enumkeys = NULL;
9029 POLICY_HND *handle = &q_u->handle;
9030 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9031 NT_PRINTER_DATA *data;
9032 NT_PRINTER_INFO_LEVEL *printer = NULL;
9034 WERROR status = WERR_BADFILE;
9037 DEBUG(4,("_spoolss_enumprinterkey\n"));
9040 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9044 if ( !get_printer_snum(p,handle, &snum) )
9047 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9048 if (!W_ERROR_IS_OK(status))
9051 /* get the list of subkey names */
9053 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9054 data = printer->info_2->data;
9056 num_keys = get_printer_subkeys( data, key, &keynames );
9058 if ( num_keys == -1 ) {
9059 status = WERR_BADFILE;
9063 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9065 r_u->needed = printerkey_len*2;
9067 if ( q_u->size < r_u->needed ) {
9068 status = WERR_MORE_DATA;
9072 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9073 status = WERR_NOMEM;
9079 if ( q_u->size < r_u->needed )
9080 status = WERR_MORE_DATA;
9083 free_a_printer( &printer, 2 );
9084 SAFE_FREE( keynames );
9089 /********************************************************************
9090 * spoolss_deleteprinterkey
9091 ********************************************************************/
9093 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9095 POLICY_HND *handle = &q_u->handle;
9096 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9098 NT_PRINTER_INFO_LEVEL *printer = NULL;
9102 DEBUG(5,("spoolss_deleteprinterkey\n"));
9105 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9109 /* if keyname == NULL, return error */
9111 if ( !q_u->keyname.buffer )
9112 return WERR_INVALID_PARAM;
9114 if (!get_printer_snum(p, handle, &snum))
9117 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9118 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9119 return WERR_ACCESS_DENIED;
9122 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9123 if (!W_ERROR_IS_OK(status))
9126 /* delete the key and all subneys */
9128 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9130 status = delete_all_printer_data( printer->info_2, key );
9132 if ( W_ERROR_IS_OK(status) )
9133 status = mod_a_printer(printer, 2);
9135 free_a_printer( &printer, 2 );
9141 /********************************************************************
9142 * spoolss_enumprinterdataex
9143 ********************************************************************/
9145 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9147 POLICY_HND *handle = &q_u->handle;
9148 uint32 in_size = q_u->size;
9151 NT_PRINTER_INFO_LEVEL *printer = NULL;
9152 PRINTER_ENUM_VALUES *enum_values = NULL;
9153 NT_PRINTER_DATA *p_data;
9155 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9160 REGISTRY_VALUE *val;
9165 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9168 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9173 * first check for a keyname of NULL or "". Win2k seems to send
9174 * this a lot and we should send back WERR_INVALID_PARAM
9175 * no need to spend time looking up the printer in this case.
9179 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9180 if ( !strlen(key) ) {
9181 result = WERR_INVALID_PARAM;
9185 /* get the printer off of disk */
9187 if (!get_printer_snum(p,handle, &snum))
9190 ZERO_STRUCT(printer);
9191 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9192 if (!W_ERROR_IS_OK(result))
9195 /* now look for a match on the key name */
9197 p_data = printer->info_2->data;
9199 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9200 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9202 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9203 result = WERR_INVALID_PARAM;
9210 /* allocate the memory for the array of pointers -- if necessary */
9212 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9215 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9217 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9218 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9219 result = WERR_NOMEM;
9223 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9227 * loop through all params and build the array to pass
9228 * back to the client
9231 for ( i=0; i<num_entries; i++ )
9233 /* lookup the registry value */
9235 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9236 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9240 value_name = regval_name( val );
9241 init_unistr( &enum_values[i].valuename, value_name );
9242 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9243 enum_values[i].type = regval_type( val );
9245 data_len = regval_size( val );
9247 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9249 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9251 result = WERR_NOMEM;
9255 enum_values[i].data_len = data_len;
9257 /* keep track of the size of the array in bytes */
9259 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9262 /* housekeeping information in the reply */
9264 r_u->needed = needed;
9265 r_u->returned = num_entries;
9267 if (needed > in_size) {
9268 result = WERR_MORE_DATA;
9272 /* copy data into the reply */
9274 r_u->ctr.size = r_u->needed;
9275 r_u->ctr.size_of_array = r_u->returned;
9276 r_u->ctr.values = enum_values;
9282 free_a_printer(&printer, 2);
9287 /****************************************************************************
9288 ****************************************************************************/
9290 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9292 init_unistr(&info->name, name);
9295 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9296 UNISTR2 *environment,
9303 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9304 WERROR result = WERR_OK;
9306 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9308 if (!get_short_archi(long_archi))
9309 return WERR_INVALID_ENVIRONMENT;
9311 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9314 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9316 fill_printprocessordirectory_1(info, path);
9318 *needed += spoolss_size_printprocessordirectory_info_1(info);
9320 if (*needed > offered) {
9321 result = WERR_INSUFFICIENT_BUFFER;
9325 if (!rpcbuf_alloc_size(buffer, *needed)) {
9326 result = WERR_INSUFFICIENT_BUFFER;
9330 smb_io_printprocessordirectory_1("", buffer, info, 0);
9338 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9340 uint32 level = q_u->level;
9341 RPC_BUFFER *buffer = NULL;
9342 uint32 offered = q_u->offered;
9343 uint32 *needed = &r_u->needed;
9346 /* that's an [in out] buffer */
9348 if ( q_u->buffer ) {
9349 rpcbuf_move(q_u->buffer, &r_u->buffer);
9350 buffer = r_u->buffer;
9353 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9359 result = getprintprocessordirectory_level_1
9360 (&q_u->name, &q_u->environment, buffer, offered, needed);
9363 result = WERR_UNKNOWN_LEVEL;
9371 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9372 SPOOL_R_REPLYOPENPRINTER *r_u)
9374 DEBUG(5,("_spoolss_replyopenprinter\n"));
9376 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9381 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9382 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9384 DEBUG(5,("_spoolss_replycloseprinter\n"));