2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver)
55 if (ver < 0 || ver > 3)
57 return drv_ver_to_os[ver];
61 const char *long_archi;
62 const char *short_archi;
66 static Printer_entry *printers_list;
68 typedef struct _counter_printer_0 {
69 struct _counter_printer_0 *next;
70 struct _counter_printer_0 *prev;
76 static counter_printer_0 *counter_list;
78 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v)
96 return JOB_STATUS_PAUSED;
98 return JOB_STATUS_SPOOLING;
100 return JOB_STATUS_PRINTING;
102 return JOB_STATUS_ERROR;
104 return JOB_STATUS_DELETING;
106 return JOB_STATUS_OFFLINE;
108 return JOB_STATUS_PAPEROUT;
110 return JOB_STATUS_PRINTED;
112 return JOB_STATUS_DELETED;
114 return JOB_STATUS_BLOCKED;
115 case LPQ_USER_INTERVENTION:
116 return JOB_STATUS_USER_INTERVENTION;
121 static int nt_printq_status(int v)
125 return PRINTER_STATUS_PAUSED;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
143 SAFE_FREE((*pp)->ctr.type);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
171 if (!W_ERROR_IS_OK(result))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections==1) {
178 cli_shutdown( notify_cli_pipe->cli );
179 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr)
198 Printer_entry *Printer = (Printer_entry *)ptr;
200 if (Printer->notify.client_connected==True) {
203 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
205 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
206 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
207 snum = print_queue_snum(Printer->sharename);
209 srv_spoolss_replycloseprinter(snum,
210 &Printer->notify.client_hnd);
214 Printer->notify.flags=0;
215 Printer->notify.options=0;
216 Printer->notify.localmachine[0]='\0';
217 Printer->notify.printerlocal=0;
218 free_spool_notify_option(&Printer->notify.option);
219 Printer->notify.option=NULL;
220 Printer->notify.client_connected=False;
222 free_nt_devicemode( &Printer->nt_devmode );
223 free_a_printer( &Printer->printer_info, 2 );
225 talloc_destroy( Printer->ctx );
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list, Printer);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
239 SPOOL_NOTIFY_OPTION *new_sp = NULL;
244 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
251 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
253 if (!new_sp->ctr.type) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
268 Printer_entry *find_printer = NULL;
270 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
284 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
291 close_policy_hnd(p, hnd);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR delete_printer_hook( NT_USER_TOKEN *token, const char *sharename )
301 char *cmd = lp_deleteprinter_cmd();
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 BOOL is_print_op = False;
307 /* can't fail if we don't try */
312 pstr_sprintf(command, "%s \"%s\"", cmd, sharename);
315 is_print_op = user_has_privileges( token, &se_printop );
317 DEBUG(10,("Running [%s]\n", command));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret = smbrun(command, NULL)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret));
337 return WERR_BADFID; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False );
342 if ( lp_servicenumber( sharename ) < 0 )
343 return WERR_ACCESS_DENIED;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
354 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer->sharename ) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
381 return delete_printer_hook( p->pipe_user.nt_user_token, Printer->sharename );
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
390 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
397 switch (Printer->printer_type) {
398 case PRINTER_HANDLE_IS_PRINTER:
399 DEBUG(4,("short name:%s\n", Printer->sharename));
400 *number = print_queue_snum(Printer->sharename);
401 return (*number != -1);
402 case PRINTER_HANDLE_IS_PRINTSERVER:
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
416 DEBUG(3,("Setting printer type=%s\n", handlename));
418 if ( strlen(handlename) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
423 /* it's a print server */
424 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
437 /****************************************************************************
438 Set printer handle name.
439 ****************************************************************************/
441 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
444 int n_services=lp_numservices();
445 char *aprinter, *printername;
446 const char *servername;
449 NT_PRINTER_INFO_LEVEL *printer;
452 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
454 aprinter = handlename;
455 if ( *handlename == '\\' ) {
456 servername = handlename + 2;
457 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
466 /* save the servername to fill in replies on this handle */
468 if ( !is_myname_or_ipaddr( servername ) )
471 fstrcpy( Printer->servername, servername );
473 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
476 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
479 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
481 /* Search all sharenames first as this is easier than pulling
482 the printer_info_2 off of disk. Don't use find_service() since
483 that calls out to map_username() */
485 /* do another loop to look for printernames */
487 for (snum=0; !found && snum<n_services; snum++) {
489 /* no point going on if this is not a printer */
491 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
494 fstrcpy(sname, lp_servicename(snum));
495 if ( strequal( aprinter, sname ) ) {
500 /* no point looking up the printer object if
501 we aren't allowing printername != sharename */
503 if ( lp_force_printername(snum) )
506 fstrcpy(sname, lp_servicename(snum));
509 result = get_a_printer( NULL, &printer, 2, sname );
510 if ( !W_ERROR_IS_OK(result) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname, dos_errstr(result)));
516 /* printername is always returned as \\server\printername */
517 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer->info_2->printername));
520 free_a_printer( &printer, 2);
526 if ( strequal(printername, aprinter) ) {
531 DEBUGADD(10, ("printername: %s\n", printername));
533 free_a_printer( &printer, 2);
537 DEBUGADD(4,("Printer not found\n"));
541 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
543 fstrcpy(Printer->sharename, sname);
548 /****************************************************************************
549 Find first available printer slot. creates a printer handle for you.
550 ****************************************************************************/
552 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
554 Printer_entry *new_printer;
556 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
558 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
561 ZERO_STRUCTP(new_printer);
563 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
564 SAFE_FREE(new_printer);
568 /* Add to the internal list. */
569 DLIST_ADD(printers_list, new_printer);
571 new_printer->notify.option=NULL;
573 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
574 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
575 close_printer_handle(p, hnd);
579 if (!set_printer_hnd_printertype(new_printer, name)) {
580 close_printer_handle(p, hnd);
584 if (!set_printer_hnd_name(new_printer, name)) {
585 close_printer_handle(p, hnd);
589 new_printer->access_granted = access_granted;
591 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
607 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
610 SPOOL_NOTIFY_OPTION *option = p->notify.option;
614 * Flags should always be zero when the change notify
615 * is registered by the client's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
625 return is_monitoring_event_flags(
626 p->notify.flags, notify_type, notify_field);
628 for (i = 0; i < option->count; i++) {
630 /* Check match for notify_type */
632 if (option->ctr.type[i].type != notify_type)
635 /* Check match for field */
637 for (j = 0; j < option->ctr.type[i].count; j++) {
638 if (option->ctr.type[i].fields[j] == notify_field) {
644 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645 p->servername, p->sharename, notify_type, notify_field));
650 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
652 static void notify_one_value(struct spoolss_notify_msg *msg,
653 SPOOL_NOTIFY_INFO_DATA *data,
656 data->notify_data.value[0] = msg->notify.value[0];
657 data->notify_data.value[1] = 0;
660 static void notify_string(struct spoolss_notify_msg *msg,
661 SPOOL_NOTIFY_INFO_DATA *data,
666 /* The length of the message includes the trailing \0 */
668 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
670 data->notify_data.data.length = msg->len * 2;
671 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
673 if (!data->notify_data.data.string) {
674 data->notify_data.data.length = 0;
678 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
681 static void notify_system_time(struct spoolss_notify_msg *msg,
682 SPOOL_NOTIFY_INFO_DATA *data,
688 if (msg->len != sizeof(time_t)) {
689 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
694 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
695 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
699 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
700 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
704 if (!spoolss_io_system_time("", &ps, 0, &systime))
707 data->notify_data.data.length = prs_offset(&ps);
708 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
710 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
715 struct notify2_message_table {
717 void (*fn)(struct spoolss_notify_msg *msg,
718 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
721 static struct notify2_message_table printer_notify_table[] = {
722 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
723 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
724 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
725 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
726 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
727 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
728 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
729 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
730 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
731 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
732 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
733 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
734 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
735 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
736 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
737 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
738 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
739 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
740 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
743 static struct notify2_message_table job_notify_table[] = {
744 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
745 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
746 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
747 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
748 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
749 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
750 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
751 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
752 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
753 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
754 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
755 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
756 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
757 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
758 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
759 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
760 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
761 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
762 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
763 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
764 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
765 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
766 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
767 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
771 /***********************************************************************
772 Allocate talloc context for container object
773 **********************************************************************/
775 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
780 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
785 /***********************************************************************
786 release all allocated memory and zero out structure
787 **********************************************************************/
789 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
795 talloc_destroy(ctr->ctx);
802 /***********************************************************************
803 **********************************************************************/
805 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
813 /***********************************************************************
814 **********************************************************************/
816 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
818 if ( !ctr || !ctr->msg_groups )
821 if ( idx >= ctr->num_groups )
824 return &ctr->msg_groups[idx];
828 /***********************************************************************
829 How many groups of change messages do we have ?
830 **********************************************************************/
832 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
837 return ctr->num_groups;
840 /***********************************************************************
841 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
842 **********************************************************************/
844 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
846 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
847 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
848 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
854 /* loop over all groups looking for a matching printer name */
856 for ( i=0; i<ctr->num_groups; i++ ) {
857 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
861 /* add a new group? */
863 if ( i == ctr->num_groups ) {
866 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 ctr->msg_groups = groups;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
875 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp = &ctr->msg_groups[i];
884 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
888 msg_grp->msgs = msg_list;
890 new_slot = msg_grp->num_msgs-1;
891 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
893 /* need to allocate own copy of data */
896 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
898 return ctr->num_groups;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
909 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
910 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
911 SPOOLSS_NOTIFY_MSG *messages;
912 int sending_msg_count;
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 messages = msg_group->msgs;
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
928 /* loop over all printers */
930 for (p = printers_list; p; p = p->next) {
931 SPOOL_NOTIFY_INFO_DATA *data;
936 /* Is there notification on this handle? */
938 if ( !p->notify.client_connected )
941 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
943 /* For this printer? Print servers always receive
946 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
947 ( !strequal(msg_group->printername, p->sharename) ) )
950 DEBUG(10,("Our printer\n"));
952 /* allocate the max entries possible */
954 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
957 /* build the array of change notifications */
959 sending_msg_count = 0;
961 for ( i=0; i<msg_group->num_msgs; i++ ) {
962 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p, msg->type, msg->field))
972 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
973 msg->type, msg->field, p->sharename));
976 * if the is a printer notification handle and not a job notification
977 * type, then set the id to 0. Other wise just use what was specified
980 * When registering change notification on a print server handle
981 * we always need to send back the id (snum) matching the printer
982 * for which the change took place. For change notify registered
983 * on a printer handle, this does not matter and the id should be 0.
988 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
994 /* Convert unix jobid to smb jobid */
996 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
997 id = sysjob_to_jobid(msg->id);
1000 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1005 construct_info_data( &data[data_len], msg->type, msg->field, id );
1008 case PRINTER_NOTIFY_TYPE:
1009 if ( printer_notify_table[msg->field].fn )
1010 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1013 case JOB_NOTIFY_TYPE:
1014 if ( job_notify_table[msg->field].fn )
1015 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1019 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1026 if ( sending_msg_count ) {
1027 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1028 data_len, data, p->notify.change, 0 );
1033 DEBUG(8,("send_notify2_changes: Exit...\n"));
1037 /***********************************************************************
1038 **********************************************************************/
1040 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1043 uint32 tv_sec, tv_usec;
1046 /* Unpack message */
1048 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1051 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1053 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1056 tdb_unpack((char *)buf + offset, len - offset, "dd",
1057 &msg->notify.value[0], &msg->notify.value[1]);
1059 tdb_unpack((char *)buf + offset, len - offset, "B",
1060 &msg->len, &msg->notify.data);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1063 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1065 tv->tv_sec = tv_sec;
1066 tv->tv_usec = tv_usec;
1069 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1070 msg->notify.value[1]));
1072 dump_data(3, msg->notify.data, msg->len);
1077 /********************************************************************
1078 Receive a notify2 message list
1079 ********************************************************************/
1081 static void receive_notify2_message_list(int msg_type, struct process_id src,
1082 void *msg, size_t len)
1084 size_t msg_count, i;
1085 char *buf = (char *)msg;
1088 SPOOLSS_NOTIFY_MSG notify;
1089 SPOOLSS_NOTIFY_MSG_CTR messages;
1093 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1097 msg_count = IVAL(buf, 0);
1100 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1102 if (msg_count == 0) {
1103 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1107 /* initialize the container */
1109 ZERO_STRUCT( messages );
1110 notify_msg_ctr_init( &messages );
1113 * build message groups for each printer identified
1114 * in a change_notify msg. Remember that a PCN message
1115 * includes the handle returned for the srv_spoolss_replyopenprinter()
1116 * call. Therefore messages are grouped according to printer handle.
1119 for ( i=0; i<msg_count; i++ ) {
1120 struct timeval msg_tv;
1122 if (msg_ptr + 4 - buf > len) {
1123 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1127 msg_len = IVAL(msg_ptr,0);
1130 if (msg_ptr + msg_len - buf > len) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1135 /* unpack messages */
1137 ZERO_STRUCT( notify );
1138 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1141 /* add to correct list in container */
1143 notify_msg_ctr_addmsg( &messages, ¬ify );
1145 /* free memory that might have been allocated by notify2_unpack_msg() */
1147 if ( notify.len != 0 )
1148 SAFE_FREE( notify.notify.data );
1151 /* process each group of messages */
1153 num_groups = notify_msg_ctr_numgroups( &messages );
1154 for ( i=0; i<num_groups; i++ )
1155 send_notify2_changes( &messages, i );
1160 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1162 notify_msg_ctr_destroy( &messages );
1167 /********************************************************************
1168 Send a message to ourself about new driver being installed
1169 so we can upgrade the information for each printer bound to this
1171 ********************************************************************/
1173 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1175 int len = strlen(drivername);
1180 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1183 message_send_pid(pid_to_procid(sys_getpid()),
1184 MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1189 /**********************************************************************
1190 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1191 over all printers, upgrading ones as necessary
1192 **********************************************************************/
1194 void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
1198 int n_services = lp_numservices();
1200 len = MIN(len,sizeof(drivername)-1);
1201 strncpy(drivername, buf, len);
1203 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1205 /* Iterate the printer list */
1207 for (snum=0; snum<n_services; snum++)
1209 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1212 NT_PRINTER_INFO_LEVEL *printer = NULL;
1214 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1215 if (!W_ERROR_IS_OK(result))
1218 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1220 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1222 /* all we care about currently is the change_id */
1224 result = mod_a_printer(printer, 2);
1225 if (!W_ERROR_IS_OK(result)) {
1226 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1227 dos_errstr(result)));
1231 free_a_printer(&printer, 2);
1238 /********************************************************************
1239 Update the cache for all printq's with a registered client
1241 ********************************************************************/
1243 void update_monitored_printq_cache( void )
1245 Printer_entry *printer = printers_list;
1248 /* loop through all printers and update the cache where
1249 client_connected == True */
1252 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1253 && printer->notify.client_connected )
1255 snum = print_queue_snum(printer->sharename);
1256 print_queue_status( snum, NULL, NULL );
1259 printer = printer->next;
1264 /********************************************************************
1265 Send a message to ourself about new driver being installed
1266 so we can upgrade the information for each printer bound to this
1268 ********************************************************************/
1270 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1272 int len = strlen(drivername);
1277 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1280 message_send_pid(pid_to_procid(sys_getpid()),
1281 MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1286 /**********************************************************************
1287 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1288 over all printers, resetting printer data as neessary
1289 **********************************************************************/
1291 void reset_all_printerdata(int msg_type, struct process_id src,
1292 void *buf, size_t len)
1296 int n_services = lp_numservices();
1298 len = MIN( len, sizeof(drivername)-1 );
1299 strncpy( drivername, buf, len );
1301 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1303 /* Iterate the printer list */
1305 for ( snum=0; snum<n_services; snum++ )
1307 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1310 NT_PRINTER_INFO_LEVEL *printer = NULL;
1312 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1313 if ( !W_ERROR_IS_OK(result) )
1317 * if the printer is bound to the driver,
1318 * then reset to the new driver initdata
1321 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1323 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1325 if ( !set_driver_init(printer, 2) ) {
1326 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1327 printer->info_2->printername, printer->info_2->drivername));
1330 result = mod_a_printer( printer, 2 );
1331 if ( !W_ERROR_IS_OK(result) ) {
1332 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1333 get_dos_error_msg(result)));
1337 free_a_printer( &printer, 2 );
1346 /********************************************************************
1347 Copy routines used by convert_to_openprinterex()
1348 *******************************************************************/
1350 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1358 DEBUG (8,("dup_devmode\n"));
1360 /* bulk copy first */
1362 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1366 /* dup the pointer members separately */
1368 len = unistrlen(devmode->devicename.buffer);
1370 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1371 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1376 len = unistrlen(devmode->formname.buffer);
1378 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1379 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1383 d->dev_private = TALLOC_MEMDUP(ctx, devmode->dev_private, devmode->driverextra);
1388 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1390 if (!new_ctr || !ctr)
1393 DEBUG(8,("copy_devmode_ctr\n"));
1395 new_ctr->size = ctr->size;
1396 new_ctr->devmode_ptr = ctr->devmode_ptr;
1398 if(ctr->devmode_ptr)
1399 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1402 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1404 if (!new_def || !def)
1407 DEBUG(8,("copy_printer_defaults\n"));
1409 new_def->datatype_ptr = def->datatype_ptr;
1411 if (def->datatype_ptr)
1412 copy_unistr2(&new_def->datatype, &def->datatype);
1414 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1416 new_def->access_required = def->access_required;
1419 /********************************************************************
1420 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1421 * SPOOL_Q_OPEN_PRINTER_EX structure
1422 ********************************************************************/
1424 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1426 if (!q_u_ex || !q_u)
1429 DEBUG(8,("convert_to_openprinterex\n"));
1431 if ( q_u->printername ) {
1432 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1433 if (q_u_ex->printername == NULL)
1435 copy_unistr2(q_u_ex->printername, q_u->printername);
1438 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1443 /********************************************************************
1444 * spoolss_open_printer
1446 * called from the spoolss dispatcher
1447 ********************************************************************/
1449 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1451 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1452 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1457 ZERO_STRUCT(q_u_ex);
1458 ZERO_STRUCT(r_u_ex);
1460 /* convert the OpenPrinter() call to OpenPrinterEx() */
1462 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1463 if (!W_ERROR_IS_OK(r_u_ex.status))
1464 return r_u_ex.status;
1466 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1468 /* convert back to OpenPrinter() */
1470 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1475 /********************************************************************
1476 * spoolss_open_printer
1478 * If the openprinterex rpc call contains a devmode,
1479 * it's a per-user one. This per-user devmode is derivated
1480 * from the global devmode. Openprinterex() contains a per-user
1481 * devmode for when you do EMF printing and spooling.
1482 * In the EMF case, the NT workstation is only doing half the job
1483 * of rendering the page. The other half is done by running the printer
1484 * driver on the server.
1485 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1486 * The EMF file only contains what is to be printed on the page.
1487 * So in order for the server to know how to print, the NT client sends
1488 * a devicemode attached to the openprinterex call.
1489 * But this devicemode is short lived, it's only valid for the current print job.
1491 * If Samba would have supported EMF spooling, this devicemode would
1492 * have been attached to the handle, to sent it to the driver to correctly
1493 * rasterize the EMF file.
1495 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1496 * we just act as a pass-thru between windows and the printer.
1498 * In order to know that Samba supports only RAW spooling, NT has to call
1499 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1500 * and until NT sends a RAW job, we refuse it.
1502 * But to call getprinter() or startdoc(), you first need a valid handle,
1503 * and to get an handle you have to call openprintex(). Hence why you have
1504 * a devicemode in the openprinterex() call.
1507 * Differences between NT4 and NT 2000.
1510 * On NT4, you only have a global devicemode. This global devicemode can be changed
1511 * by the administrator (or by a user with enough privs). Everytime a user
1512 * wants to print, the devicemode is resetted to the default. In Word, everytime
1513 * you print, the printer's characteristics are always reset to the global devicemode.
1517 * In W2K, there is the notion of per-user devicemode. The first time you use
1518 * a printer, a per-user devicemode is build from the global devicemode.
1519 * If you change your per-user devicemode, it is saved in the registry, under the
1520 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1521 * printer preferences available.
1523 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1524 * on the General Tab of the printer properties windows.
1526 * To change the global devicemode: it's the "Printing Defaults..." button
1527 * on the Advanced Tab of the printer properties window.
1530 ********************************************************************/
1532 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1534 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1535 POLICY_HND *handle = &r_u->handle;
1539 struct current_user user;
1540 Printer_entry *Printer=NULL;
1542 if ( !q_u->printername )
1543 return WERR_INVALID_PRINTER_NAME;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name, q_u->printername, sizeof(name)-1);
1550 DEBUGADD(3,("checking name: %s\n",name));
1552 if (!open_printer_hnd(p, handle, name, 0))
1553 return WERR_INVALID_PRINTER_NAME;
1555 Printer=find_printer_index_by_hnd(p, handle);
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name ));
1559 close_printer_handle(p,handle);
1560 return WERR_INVALID_PRINTER_NAME;
1563 get_current_user(&user, p);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1586 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1588 /* Printserver handles use global struct... */
1592 /* Map standard access rights to object specific access rights */
1594 se_map_standard(&printer_default->access_required,
1595 &printserver_std_mapping);
1597 /* Deny any object specific bits that don't apply to print
1598 servers (i.e printer and job specific bits) */
1600 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1602 if (printer_default->access_required &
1603 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1604 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1605 close_printer_handle(p, handle);
1606 return WERR_ACCESS_DENIED;
1609 /* Allow admin access */
1611 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1613 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1615 if (!lp_ms_add_printer_wizard()) {
1616 close_printer_handle(p, handle);
1617 return WERR_ACCESS_DENIED;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1623 if ((user.ut.uid != 0) &&
1624 !user_has_privileges(user.nt_user_token,
1626 !token_contains_name_in_list(
1627 uidtoname(user.ut.uid), NULL,
1629 lp_printer_admin(snum))) {
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1638 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1641 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1642 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1644 /* We fall through to return WERR_OK */
1649 /* NT doesn't let us connect to a printer if the connecting user
1650 doesn't have print permission. */
1652 if (!get_printer_snum(p, handle, &snum)) {
1653 close_printer_handle(p, handle);
1657 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1659 /* map an empty access mask to the minimum access mask */
1660 if (printer_default->access_required == 0x0)
1661 printer_default->access_required = PRINTER_ACCESS_USE;
1664 * If we are not serving the printer driver for this printer,
1665 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1666 * will keep NT clients happy --jerry
1669 if (lp_use_client_driver(snum)
1670 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1672 printer_default->access_required = PRINTER_ACCESS_USE;
1675 /* check smb.conf parameters and the the sec_desc */
1677 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1678 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1679 return WERR_ACCESS_DENIED;
1682 if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
1684 !print_access_check(&user, snum,
1685 printer_default->access_required)) {
1686 DEBUG(3, ("access DENIED for printer open\n"));
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1692 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1693 close_printer_handle(p, handle);
1694 return WERR_ACCESS_DENIED;
1697 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1698 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1700 printer_default->access_required = PRINTER_ACCESS_USE;
1702 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1703 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1707 Printer->access_granted = printer_default->access_required;
1710 * If the client sent a devmode in the OpenPrinter() call, then
1711 * save it here in case we get a job submission on this handle
1714 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1715 && q_u->printer_default.devmode_cont.devmode_ptr )
1717 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1718 &Printer->nt_devmode );
1721 #if 0 /* JERRY -- I'm doubtful this is really effective */
1722 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1723 optimization in Windows 2000 clients --jerry */
1725 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1726 && (RA_WIN2K == get_remote_arch()) )
1728 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1729 sys_usleep( 500000 );
1736 /****************************************************************************
1737 ****************************************************************************/
1739 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1740 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1746 /* allocate memory if needed. Messy because
1747 convert_printer_info is used to update an existing
1748 printer or build a new one */
1750 if ( !printer->info_2 ) {
1751 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1752 if ( !printer->info_2 ) {
1753 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1758 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1759 printer->info_2->setuptime = time(NULL);
1767 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1768 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1774 printer->info_3=NULL;
1775 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1779 printer->info_6=NULL;
1780 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1790 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1791 NT_DEVICEMODE **pp_nt_devmode)
1793 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1796 * Ensure nt_devmode is a valid pointer
1797 * as we will be overwriting it.
1800 if (nt_devmode == NULL) {
1801 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1802 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1806 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1807 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1809 nt_devmode->specversion=devmode->specversion;
1810 nt_devmode->driverversion=devmode->driverversion;
1811 nt_devmode->size=devmode->size;
1812 nt_devmode->fields=devmode->fields;
1813 nt_devmode->orientation=devmode->orientation;
1814 nt_devmode->papersize=devmode->papersize;
1815 nt_devmode->paperlength=devmode->paperlength;
1816 nt_devmode->paperwidth=devmode->paperwidth;
1817 nt_devmode->scale=devmode->scale;
1818 nt_devmode->copies=devmode->copies;
1819 nt_devmode->defaultsource=devmode->defaultsource;
1820 nt_devmode->printquality=devmode->printquality;
1821 nt_devmode->color=devmode->color;
1822 nt_devmode->duplex=devmode->duplex;
1823 nt_devmode->yresolution=devmode->yresolution;
1824 nt_devmode->ttoption=devmode->ttoption;
1825 nt_devmode->collate=devmode->collate;
1827 nt_devmode->logpixels=devmode->logpixels;
1828 nt_devmode->bitsperpel=devmode->bitsperpel;
1829 nt_devmode->pelswidth=devmode->pelswidth;
1830 nt_devmode->pelsheight=devmode->pelsheight;
1831 nt_devmode->displayflags=devmode->displayflags;
1832 nt_devmode->displayfrequency=devmode->displayfrequency;
1833 nt_devmode->icmmethod=devmode->icmmethod;
1834 nt_devmode->icmintent=devmode->icmintent;
1835 nt_devmode->mediatype=devmode->mediatype;
1836 nt_devmode->dithertype=devmode->dithertype;
1837 nt_devmode->reserved1=devmode->reserved1;
1838 nt_devmode->reserved2=devmode->reserved2;
1839 nt_devmode->panningwidth=devmode->panningwidth;
1840 nt_devmode->panningheight=devmode->panningheight;
1843 * Only change private and driverextra if the incoming devmode
1844 * has a new one. JRA.
1847 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1848 SAFE_FREE(nt_devmode->nt_dev_private);
1849 nt_devmode->driverextra=devmode->driverextra;
1850 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1852 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1855 *pp_nt_devmode = nt_devmode;
1860 /********************************************************************
1861 * _spoolss_enddocprinter_internal.
1862 ********************************************************************/
1864 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1866 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1870 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1874 if (!get_printer_snum(p, handle, &snum))
1877 Printer->document_started=False;
1878 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1879 /* error codes unhandled so far ... */
1884 /********************************************************************
1885 * api_spoolss_closeprinter
1886 ********************************************************************/
1888 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1890 POLICY_HND *handle = &q_u->handle;
1892 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1894 if (Printer && Printer->document_started)
1895 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1897 if (!close_printer_handle(p, handle))
1900 /* clear the returned printer handle. Observed behavior
1901 from Win2k server. Don't think this really matters.
1902 Previous code just copied the value of the closed
1905 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1910 /********************************************************************
1911 * api_spoolss_deleteprinter
1913 ********************************************************************/
1915 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1917 POLICY_HND *handle = &q_u->handle;
1918 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1921 if (Printer && Printer->document_started)
1922 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1924 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1926 result = delete_printer_handle(p, handle);
1928 update_c_setprinter(False);
1933 /*******************************************************************
1934 * static function to lookup the version id corresponding to an
1935 * long architecture string
1936 ******************************************************************/
1938 static int get_version_id (char * arch)
1941 struct table_node archi_table[]= {
1943 {"Windows 4.0", "WIN40", 0 },
1944 {"Windows NT x86", "W32X86", 2 },
1945 {"Windows NT R4000", "W32MIPS", 2 },
1946 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1947 {"Windows NT PowerPC", "W32PPC", 2 },
1948 {"Windows IA64", "IA64", 3 },
1949 {"Windows x64", "x64", 3 },
1953 for (i=0; archi_table[i].long_archi != NULL; i++)
1955 if (strcmp(arch, archi_table[i].long_archi) == 0)
1956 return (archi_table[i].version);
1962 /********************************************************************
1963 * _spoolss_deleteprinterdriver
1964 ********************************************************************/
1966 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1970 NT_PRINTER_DRIVER_INFO_LEVEL info;
1971 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
1973 struct current_user user;
1975 WERROR status_win2k = WERR_ACCESS_DENIED;
1977 get_current_user(&user, p);
1979 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
1980 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
1982 /* check that we have a valid driver name first */
1984 if ((version=get_version_id(arch)) == -1)
1985 return WERR_INVALID_ENVIRONMENT;
1988 ZERO_STRUCT(info_win2k);
1990 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
1992 /* try for Win2k driver if "Windows NT x86" */
1994 if ( version == 2 ) {
1996 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
1997 status = WERR_UNKNOWN_PRINTER_DRIVER;
2001 /* otherwise it was a failure */
2003 status = WERR_UNKNOWN_PRINTER_DRIVER;
2009 if (printer_driver_in_use(info.info_3)) {
2010 status = WERR_PRINTER_DRIVER_IN_USE;
2016 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2018 /* if we get to here, we now have 2 driver info structures to remove */
2019 /* remove the Win2k driver first*/
2021 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2022 free_a_printer_driver( info_win2k, 3 );
2024 /* this should not have failed---if it did, report to client */
2025 if ( !W_ERROR_IS_OK(status_win2k) )
2027 status = status_win2k;
2033 status = delete_printer_driver(info.info_3, &user, version, False);
2035 /* if at least one of the deletes succeeded return OK */
2037 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2041 free_a_printer_driver( info, 3 );
2046 /********************************************************************
2047 * spoolss_deleteprinterdriverex
2048 ********************************************************************/
2050 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2054 NT_PRINTER_DRIVER_INFO_LEVEL info;
2055 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2057 uint32 flags = q_u->delete_flags;
2059 struct current_user user;
2061 WERROR status_win2k = WERR_ACCESS_DENIED;
2063 get_current_user(&user, p);
2065 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2066 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2068 /* check that we have a valid driver name first */
2069 if ((version=get_version_id(arch)) == -1) {
2070 /* this is what NT returns */
2071 return WERR_INVALID_ENVIRONMENT;
2074 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2075 version = q_u->version;
2078 ZERO_STRUCT(info_win2k);
2080 status = get_a_printer_driver(&info, 3, driver, arch, version);
2082 if ( !W_ERROR_IS_OK(status) )
2085 * if the client asked for a specific version,
2086 * or this is something other than Windows NT x86,
2090 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2093 /* try for Win2k driver if "Windows NT x86" */
2096 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2097 status = WERR_UNKNOWN_PRINTER_DRIVER;
2102 if ( printer_driver_in_use(info.info_3) ) {
2103 status = WERR_PRINTER_DRIVER_IN_USE;
2108 * we have a couple of cases to consider.
2109 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2110 * then the delete should fail if **any** files overlap with
2112 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2113 * non-overlapping files
2114 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2115 * is set, the do not delete any files
2116 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2119 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2121 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2123 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2124 /* no idea of the correct error here */
2125 status = WERR_ACCESS_DENIED;
2130 /* also check for W32X86/3 if necessary; maybe we already have? */
2132 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2133 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2136 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2137 /* no idea of the correct error here */
2138 free_a_printer_driver( info_win2k, 3 );
2139 status = WERR_ACCESS_DENIED;
2143 /* if we get to here, we now have 2 driver info structures to remove */
2144 /* remove the Win2k driver first*/
2146 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2147 free_a_printer_driver( info_win2k, 3 );
2149 /* this should not have failed---if it did, report to client */
2151 if ( !W_ERROR_IS_OK(status_win2k) )
2156 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2158 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2161 free_a_printer_driver( info, 3 );
2167 /****************************************************************************
2168 Internal routine for retreiving printerdata
2169 ***************************************************************************/
2171 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2172 const char *key, const char *value, uint32 *type, uint8 **data,
2173 uint32 *needed, uint32 in_size )
2175 REGISTRY_VALUE *val;
2179 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2180 return WERR_BADFILE;
2182 *type = regval_type( val );
2184 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2186 size = regval_size( val );
2188 /* copy the min(in_size, len) */
2191 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2193 /* special case for 0 length values */
2195 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2199 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2208 DEBUG(5,("get_printer_dataex: copy done\n"));
2213 /****************************************************************************
2214 Internal routine for removing printerdata
2215 ***************************************************************************/
2217 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2219 return delete_printer_data( printer->info_2, key, value );
2222 /****************************************************************************
2223 Internal routine for storing printerdata
2224 ***************************************************************************/
2226 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2227 uint32 type, uint8 *data, int real_len )
2229 /* the registry objects enforce uniqueness based on value name */
2231 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2234 /********************************************************************
2235 GetPrinterData on a printer server Handle.
2236 ********************************************************************/
2238 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2242 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2244 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2246 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2252 if (!StrCaseCmp(value, "BeepEnabled")) {
2254 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2256 SIVAL(*data, 0, 0x00);
2261 if (!StrCaseCmp(value, "EventLog")) {
2263 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2265 /* formally was 0x1b */
2266 SIVAL(*data, 0, 0x0);
2271 if (!StrCaseCmp(value, "NetPopup")) {
2273 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2275 SIVAL(*data, 0, 0x00);
2280 if (!StrCaseCmp(value, "MajorVersion")) {
2282 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2285 /* Windows NT 4.0 seems to not allow uploading of drivers
2286 to a server that reports 0x3 as the MajorVersion.
2287 need to investigate more how Win2k gets around this .
2290 if ( RA_WINNT == get_remote_arch() )
2299 if (!StrCaseCmp(value, "MinorVersion")) {
2301 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2309 * uint32 size = 0x114
2311 * uint32 minor = [0|1]
2312 * uint32 build = [2195|2600]
2313 * extra unicode string = e.g. "Service Pack 3"
2315 if (!StrCaseCmp(value, "OSVersion")) {
2319 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2322 SIVAL(*data, 0, *needed); /* size */
2323 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2325 SIVAL(*data, 12, 2195); /* build */
2327 /* leave extra string empty */
2333 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2334 const char *string="C:\\PRINTERS";
2336 *needed = 2*(strlen(string)+1);
2337 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2339 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2341 /* it's done by hand ready to go on the wire */
2342 for (i=0; i<strlen(string); i++) {
2343 (*data)[2*i]=string[i];
2344 (*data)[2*i+1]='\0';
2349 if (!StrCaseCmp(value, "Architecture")) {
2350 const char *string="Windows NT x86";
2352 *needed = 2*(strlen(string)+1);
2353 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2355 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2356 for (i=0; i<strlen(string); i++) {
2357 (*data)[2*i]=string[i];
2358 (*data)[2*i+1]='\0';
2363 if (!StrCaseCmp(value, "DsPresent")) {
2365 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2368 /* only show the publish check box if we are a
2369 memeber of a AD domain */
2371 if ( lp_security() == SEC_ADS )
2372 SIVAL(*data, 0, 0x01);
2374 SIVAL(*data, 0, 0x00);
2380 if (!StrCaseCmp(value, "DNSMachineName")) {
2383 if (!get_mydnsfullname(hostname))
2384 return WERR_BADFILE;
2386 *needed = 2*(strlen(hostname)+1);
2387 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2390 for (i=0; i<strlen(hostname); i++) {
2391 (*data)[2*i]=hostname[i];
2392 (*data)[2*i+1]='\0';
2398 return WERR_BADFILE;
2401 /********************************************************************
2402 * spoolss_getprinterdata
2403 ********************************************************************/
2405 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2407 POLICY_HND *handle = &q_u->handle;
2408 UNISTR2 *valuename = &q_u->valuename;
2409 uint32 in_size = q_u->size;
2410 uint32 *type = &r_u->type;
2411 uint32 *out_size = &r_u->size;
2412 uint8 **data = &r_u->data;
2413 uint32 *needed = &r_u->needed;
2416 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2417 NT_PRINTER_INFO_LEVEL *printer = NULL;
2421 * Reminder: when it's a string, the length is in BYTES
2422 * even if UNICODE is negociated.
2427 *out_size = in_size;
2429 /* in case of problem, return some default values */
2434 DEBUG(4,("_spoolss_getprinterdata\n"));
2437 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2438 status = WERR_BADFID;
2442 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2444 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2445 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2448 if ( !get_printer_snum(p,handle, &snum) ) {
2449 status = WERR_BADFID;
2453 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2454 if ( !W_ERROR_IS_OK(status) )
2457 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2459 if ( strequal(value, "ChangeId") ) {
2461 *needed = sizeof(uint32);
2462 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2463 status = WERR_NOMEM;
2466 SIVAL( *data, 0, printer->info_2->changeid );
2470 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2473 if (*needed > *out_size)
2474 status = WERR_MORE_DATA;
2477 if ( !W_ERROR_IS_OK(status) )
2479 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2481 /* reply this param doesn't exist */
2484 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2486 free_a_printer( &printer, 2 );
2495 /* cleanup & exit */
2498 free_a_printer( &printer, 2 );
2503 /*********************************************************
2504 Connect to the client machine.
2505 **********************************************************/
2507 static BOOL spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2508 struct in_addr *client_ip, const char *remote_machine)
2511 struct cli_state *the_cli;
2512 struct in_addr rm_addr;
2514 if ( is_zero_ip(*client_ip) ) {
2515 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2516 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2520 if ( ismyip( rm_addr )) {
2521 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2525 rm_addr.s_addr = client_ip->s_addr;
2526 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2527 inet_ntoa(*client_ip) ));
2530 /* setup the connection */
2532 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2533 &rm_addr, 0, "IPC$", "IPC",
2537 0, lp_client_signing(), NULL );
2539 if ( !NT_STATUS_IS_OK( ret ) ) {
2540 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2545 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2546 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2547 cli_shutdown(the_cli);
2552 * Ok - we have an anonymous connection to the IPC$ share.
2553 * Now start the NT Domain stuff :-).
2556 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2557 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2558 remote_machine, nt_errstr(ret)));
2559 cli_shutdown(the_cli);
2563 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2565 (*pp_pipe)->cli = the_cli;
2570 /***************************************************************************
2571 Connect to the client.
2572 ****************************************************************************/
2574 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2575 uint32 localprinter, uint32 type,
2576 POLICY_HND *handle, struct in_addr *client_ip)
2581 * If it's the first connection, contact the client
2582 * and connect to the IPC$ share anonymously
2584 if (smb_connections==0) {
2585 fstring unix_printer;
2587 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2589 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ip, unix_printer ))
2592 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2593 /* Tell the connections db we're now interested in printer
2594 * notify messages. */
2595 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2599 * Tell the specific printing tdb we want messages for this printer
2600 * by registering our PID.
2603 if (!print_notify_register_pid(snum))
2604 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2608 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter,
2611 if (!W_ERROR_IS_OK(result))
2612 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2613 dos_errstr(result)));
2615 return (W_ERROR_IS_OK(result));
2618 /********************************************************************
2620 * ReplyFindFirstPrinterChangeNotifyEx
2622 * before replying OK: status=0 a rpc call is made to the workstation
2623 * asking ReplyOpenPrinter
2625 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2626 * called from api_spoolss_rffpcnex
2627 ********************************************************************/
2629 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2631 POLICY_HND *handle = &q_u->handle;
2632 uint32 flags = q_u->flags;
2633 uint32 options = q_u->options;
2634 UNISTR2 *localmachine = &q_u->localmachine;
2635 uint32 printerlocal = q_u->printerlocal;
2637 SPOOL_NOTIFY_OPTION *option = q_u->option;
2638 struct in_addr client_ip;
2640 /* store the notify value in the printer struct */
2642 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2645 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2649 Printer->notify.flags=flags;
2650 Printer->notify.options=options;
2651 Printer->notify.printerlocal=printerlocal;
2653 if (Printer->notify.option)
2654 free_spool_notify_option(&Printer->notify.option);
2656 Printer->notify.option=dup_spool_notify_option(option);
2658 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2659 sizeof(Printer->notify.localmachine)-1);
2661 /* Connect to the client machine and send a ReplyOpenPrinter */
2663 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2665 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2666 !get_printer_snum(p, handle, &snum) )
2669 client_ip.s_addr = inet_addr(p->conn->client_address);
2671 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2672 Printer->notify.printerlocal, 1,
2673 &Printer->notify.client_hnd, &client_ip))
2674 return WERR_SERVER_UNAVAILABLE;
2676 Printer->notify.client_connected=True;
2681 /*******************************************************************
2682 * fill a notify_info_data with the servername
2683 ********************************************************************/
2685 void spoolss_notify_server_name(int snum,
2686 SPOOL_NOTIFY_INFO_DATA *data,
2687 print_queue_struct *queue,
2688 NT_PRINTER_INFO_LEVEL *printer,
2689 TALLOC_CTX *mem_ctx)
2694 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2696 data->notify_data.data.length = len;
2697 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2699 if (!data->notify_data.data.string) {
2700 data->notify_data.data.length = 0;
2704 memcpy(data->notify_data.data.string, temp, len);
2707 /*******************************************************************
2708 * fill a notify_info_data with the printername (not including the servername).
2709 ********************************************************************/
2711 void spoolss_notify_printer_name(int snum,
2712 SPOOL_NOTIFY_INFO_DATA *data,
2713 print_queue_struct *queue,
2714 NT_PRINTER_INFO_LEVEL *printer,
2715 TALLOC_CTX *mem_ctx)
2720 /* the notify name should not contain the \\server\ part */
2721 char *p = strrchr(printer->info_2->printername, '\\');
2724 p = printer->info_2->printername;
2729 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2731 data->notify_data.data.length = len;
2732 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2734 if (!data->notify_data.data.string) {
2735 data->notify_data.data.length = 0;
2739 memcpy(data->notify_data.data.string, temp, len);
2742 /*******************************************************************
2743 * fill a notify_info_data with the servicename
2744 ********************************************************************/
2746 void spoolss_notify_share_name(int snum,
2747 SPOOL_NOTIFY_INFO_DATA *data,
2748 print_queue_struct *queue,
2749 NT_PRINTER_INFO_LEVEL *printer,
2750 TALLOC_CTX *mem_ctx)
2755 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2757 data->notify_data.data.length = len;
2758 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2760 if (!data->notify_data.data.string) {
2761 data->notify_data.data.length = 0;
2765 memcpy(data->notify_data.data.string, temp, len);
2768 /*******************************************************************
2769 * fill a notify_info_data with the port name
2770 ********************************************************************/
2772 void spoolss_notify_port_name(int snum,
2773 SPOOL_NOTIFY_INFO_DATA *data,
2774 print_queue_struct *queue,
2775 NT_PRINTER_INFO_LEVEL *printer,
2776 TALLOC_CTX *mem_ctx)
2781 /* even if it's strange, that's consistant in all the code */
2783 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2785 data->notify_data.data.length = len;
2786 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2788 if (!data->notify_data.data.string) {
2789 data->notify_data.data.length = 0;
2793 memcpy(data->notify_data.data.string, temp, len);
2796 /*******************************************************************
2797 * fill a notify_info_data with the printername
2798 * but it doesn't exist, have to see what to do
2799 ********************************************************************/
2801 void spoolss_notify_driver_name(int snum,
2802 SPOOL_NOTIFY_INFO_DATA *data,
2803 print_queue_struct *queue,
2804 NT_PRINTER_INFO_LEVEL *printer,
2805 TALLOC_CTX *mem_ctx)
2810 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2812 data->notify_data.data.length = len;
2813 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2815 if (!data->notify_data.data.string) {
2816 data->notify_data.data.length = 0;
2820 memcpy(data->notify_data.data.string, temp, len);
2823 /*******************************************************************
2824 * fill a notify_info_data with the comment
2825 ********************************************************************/
2827 void spoolss_notify_comment(int snum,
2828 SPOOL_NOTIFY_INFO_DATA *data,
2829 print_queue_struct *queue,
2830 NT_PRINTER_INFO_LEVEL *printer,
2831 TALLOC_CTX *mem_ctx)
2836 if (*printer->info_2->comment == '\0')
2837 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2839 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2841 data->notify_data.data.length = len;
2842 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2844 if (!data->notify_data.data.string) {
2845 data->notify_data.data.length = 0;
2849 memcpy(data->notify_data.data.string, temp, len);
2852 /*******************************************************************
2853 * fill a notify_info_data with the comment
2854 * location = "Room 1, floor 2, building 3"
2855 ********************************************************************/
2857 void spoolss_notify_location(int snum,
2858 SPOOL_NOTIFY_INFO_DATA *data,
2859 print_queue_struct *queue,
2860 NT_PRINTER_INFO_LEVEL *printer,
2861 TALLOC_CTX *mem_ctx)
2866 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2868 data->notify_data.data.length = len;
2869 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2871 if (!data->notify_data.data.string) {
2872 data->notify_data.data.length = 0;
2876 memcpy(data->notify_data.data.string, temp, len);
2879 /*******************************************************************
2880 * fill a notify_info_data with the device mode
2881 * jfm:xxxx don't to it for know but that's a real problem !!!
2882 ********************************************************************/
2884 static void spoolss_notify_devmode(int snum,
2885 SPOOL_NOTIFY_INFO_DATA *data,
2886 print_queue_struct *queue,
2887 NT_PRINTER_INFO_LEVEL *printer,
2888 TALLOC_CTX *mem_ctx)
2892 /*******************************************************************
2893 * fill a notify_info_data with the separator file name
2894 ********************************************************************/
2896 void spoolss_notify_sepfile(int snum,
2897 SPOOL_NOTIFY_INFO_DATA *data,
2898 print_queue_struct *queue,
2899 NT_PRINTER_INFO_LEVEL *printer,
2900 TALLOC_CTX *mem_ctx)
2905 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2907 data->notify_data.data.length = len;
2908 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2910 if (!data->notify_data.data.string) {
2911 data->notify_data.data.length = 0;
2915 memcpy(data->notify_data.data.string, temp, len);
2918 /*******************************************************************
2919 * fill a notify_info_data with the print processor
2920 * jfm:xxxx return always winprint to indicate we don't do anything to it
2921 ********************************************************************/
2923 void spoolss_notify_print_processor(int snum,
2924 SPOOL_NOTIFY_INFO_DATA *data,
2925 print_queue_struct *queue,
2926 NT_PRINTER_INFO_LEVEL *printer,
2927 TALLOC_CTX *mem_ctx)
2932 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
2934 data->notify_data.data.length = len;
2935 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2937 if (!data->notify_data.data.string) {
2938 data->notify_data.data.length = 0;
2942 memcpy(data->notify_data.data.string, temp, len);
2945 /*******************************************************************
2946 * fill a notify_info_data with the print processor options
2947 * jfm:xxxx send an empty string
2948 ********************************************************************/
2950 void spoolss_notify_parameters(int snum,
2951 SPOOL_NOTIFY_INFO_DATA *data,
2952 print_queue_struct *queue,
2953 NT_PRINTER_INFO_LEVEL *printer,
2954 TALLOC_CTX *mem_ctx)
2959 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
2961 data->notify_data.data.length = len;
2962 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2964 if (!data->notify_data.data.string) {
2965 data->notify_data.data.length = 0;
2969 memcpy(data->notify_data.data.string, temp, len);
2972 /*******************************************************************
2973 * fill a notify_info_data with the data type
2974 * jfm:xxxx always send RAW as data type
2975 ********************************************************************/
2977 void spoolss_notify_datatype(int snum,
2978 SPOOL_NOTIFY_INFO_DATA *data,
2979 print_queue_struct *queue,
2980 NT_PRINTER_INFO_LEVEL *printer,
2981 TALLOC_CTX *mem_ctx)
2986 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
2988 data->notify_data.data.length = len;
2989 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2991 if (!data->notify_data.data.string) {
2992 data->notify_data.data.length = 0;
2996 memcpy(data->notify_data.data.string, temp, len);
2999 /*******************************************************************
3000 * fill a notify_info_data with the security descriptor
3001 * jfm:xxxx send an null pointer to say no security desc
3002 * have to implement security before !
3003 ********************************************************************/
3005 static void spoolss_notify_security_desc(int snum,
3006 SPOOL_NOTIFY_INFO_DATA *data,
3007 print_queue_struct *queue,
3008 NT_PRINTER_INFO_LEVEL *printer,
3009 TALLOC_CTX *mem_ctx)
3011 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3012 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3015 /*******************************************************************
3016 * fill a notify_info_data with the attributes
3017 * jfm:xxxx a samba printer is always shared
3018 ********************************************************************/
3020 void spoolss_notify_attributes(int snum,
3021 SPOOL_NOTIFY_INFO_DATA *data,
3022 print_queue_struct *queue,
3023 NT_PRINTER_INFO_LEVEL *printer,
3024 TALLOC_CTX *mem_ctx)
3026 data->notify_data.value[0] = printer->info_2->attributes;
3027 data->notify_data.value[1] = 0;
3030 /*******************************************************************
3031 * fill a notify_info_data with the priority
3032 ********************************************************************/
3034 static void spoolss_notify_priority(int snum,
3035 SPOOL_NOTIFY_INFO_DATA *data,
3036 print_queue_struct *queue,
3037 NT_PRINTER_INFO_LEVEL *printer,
3038 TALLOC_CTX *mem_ctx)
3040 data->notify_data.value[0] = printer->info_2->priority;
3041 data->notify_data.value[1] = 0;
3044 /*******************************************************************
3045 * fill a notify_info_data with the default priority
3046 ********************************************************************/
3048 static void spoolss_notify_default_priority(int snum,
3049 SPOOL_NOTIFY_INFO_DATA *data,
3050 print_queue_struct *queue,
3051 NT_PRINTER_INFO_LEVEL *printer,
3052 TALLOC_CTX *mem_ctx)
3054 data->notify_data.value[0] = printer->info_2->default_priority;
3055 data->notify_data.value[1] = 0;
3058 /*******************************************************************
3059 * fill a notify_info_data with the start time
3060 ********************************************************************/
3062 static void spoolss_notify_start_time(int snum,
3063 SPOOL_NOTIFY_INFO_DATA *data,
3064 print_queue_struct *queue,
3065 NT_PRINTER_INFO_LEVEL *printer,
3066 TALLOC_CTX *mem_ctx)
3068 data->notify_data.value[0] = printer->info_2->starttime;
3069 data->notify_data.value[1] = 0;
3072 /*******************************************************************
3073 * fill a notify_info_data with the until time
3074 ********************************************************************/
3076 static void spoolss_notify_until_time(int snum,
3077 SPOOL_NOTIFY_INFO_DATA *data,
3078 print_queue_struct *queue,
3079 NT_PRINTER_INFO_LEVEL *printer,
3080 TALLOC_CTX *mem_ctx)
3082 data->notify_data.value[0] = printer->info_2->untiltime;
3083 data->notify_data.value[1] = 0;
3086 /*******************************************************************
3087 * fill a notify_info_data with the status
3088 ********************************************************************/
3090 static void spoolss_notify_status(int snum,
3091 SPOOL_NOTIFY_INFO_DATA *data,
3092 print_queue_struct *queue,
3093 NT_PRINTER_INFO_LEVEL *printer,
3094 TALLOC_CTX *mem_ctx)
3096 print_status_struct status;
3098 print_queue_length(snum, &status);
3099 data->notify_data.value[0]=(uint32) status.status;
3100 data->notify_data.value[1] = 0;
3103 /*******************************************************************
3104 * fill a notify_info_data with the number of jobs queued
3105 ********************************************************************/
3107 void spoolss_notify_cjobs(int snum,
3108 SPOOL_NOTIFY_INFO_DATA *data,
3109 print_queue_struct *queue,
3110 NT_PRINTER_INFO_LEVEL *printer,
3111 TALLOC_CTX *mem_ctx)
3113 data->notify_data.value[0] = print_queue_length(snum, NULL);
3114 data->notify_data.value[1] = 0;
3117 /*******************************************************************
3118 * fill a notify_info_data with the average ppm
3119 ********************************************************************/
3121 static void spoolss_notify_average_ppm(int snum,
3122 SPOOL_NOTIFY_INFO_DATA *data,
3123 print_queue_struct *queue,
3124 NT_PRINTER_INFO_LEVEL *printer,
3125 TALLOC_CTX *mem_ctx)
3127 /* always respond 8 pages per minutes */
3128 /* a little hard ! */
3129 data->notify_data.value[0] = printer->info_2->averageppm;
3130 data->notify_data.value[1] = 0;
3133 /*******************************************************************
3134 * fill a notify_info_data with username
3135 ********************************************************************/
3137 static void spoolss_notify_username(int snum,
3138 SPOOL_NOTIFY_INFO_DATA *data,
3139 print_queue_struct *queue,
3140 NT_PRINTER_INFO_LEVEL *printer,
3141 TALLOC_CTX *mem_ctx)
3146 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3148 data->notify_data.data.length = len;
3149 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3151 if (!data->notify_data.data.string) {
3152 data->notify_data.data.length = 0;
3156 memcpy(data->notify_data.data.string, temp, len);
3159 /*******************************************************************
3160 * fill a notify_info_data with job status
3161 ********************************************************************/
3163 static void spoolss_notify_job_status(int snum,
3164 SPOOL_NOTIFY_INFO_DATA *data,
3165 print_queue_struct *queue,
3166 NT_PRINTER_INFO_LEVEL *printer,
3167 TALLOC_CTX *mem_ctx)
3169 data->notify_data.value[0]=nt_printj_status(queue->status);
3170 data->notify_data.value[1] = 0;
3173 /*******************************************************************
3174 * fill a notify_info_data with job name
3175 ********************************************************************/
3177 static void spoolss_notify_job_name(int snum,
3178 SPOOL_NOTIFY_INFO_DATA *data,
3179 print_queue_struct *queue,
3180 NT_PRINTER_INFO_LEVEL *printer,
3181 TALLOC_CTX *mem_ctx)
3186 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3188 data->notify_data.data.length = len;
3189 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3191 if (!data->notify_data.data.string) {
3192 data->notify_data.data.length = 0;
3196 memcpy(data->notify_data.data.string, temp, len);
3199 /*******************************************************************
3200 * fill a notify_info_data with job status
3201 ********************************************************************/
3203 static void spoolss_notify_job_status_string(int snum,
3204 SPOOL_NOTIFY_INFO_DATA *data,
3205 print_queue_struct *queue,
3206 NT_PRINTER_INFO_LEVEL *printer,
3207 TALLOC_CTX *mem_ctx)
3210 * Now we're returning job status codes we just return a "" here. JRA.
3217 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3220 switch (queue->status) {
3225 p = ""; /* NT provides the paused string */
3234 #endif /* NO LONGER NEEDED. */
3236 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3238 data->notify_data.data.length = len;
3239 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3241 if (!data->notify_data.data.string) {
3242 data->notify_data.data.length = 0;
3246 memcpy(data->notify_data.data.string, temp, len);
3249 /*******************************************************************
3250 * fill a notify_info_data with job time
3251 ********************************************************************/
3253 static void spoolss_notify_job_time(int snum,
3254 SPOOL_NOTIFY_INFO_DATA *data,
3255 print_queue_struct *queue,
3256 NT_PRINTER_INFO_LEVEL *printer,
3257 TALLOC_CTX *mem_ctx)
3259 data->notify_data.value[0]=0x0;
3260 data->notify_data.value[1]=0;
3263 /*******************************************************************
3264 * fill a notify_info_data with job size
3265 ********************************************************************/
3267 static void spoolss_notify_job_size(int snum,
3268 SPOOL_NOTIFY_INFO_DATA *data,
3269 print_queue_struct *queue,
3270 NT_PRINTER_INFO_LEVEL *printer,
3271 TALLOC_CTX *mem_ctx)
3273 data->notify_data.value[0]=queue->size;
3274 data->notify_data.value[1]=0;
3277 /*******************************************************************
3278 * fill a notify_info_data with page info
3279 ********************************************************************/
3280 static void spoolss_notify_total_pages(int snum,
3281 SPOOL_NOTIFY_INFO_DATA *data,
3282 print_queue_struct *queue,
3283 NT_PRINTER_INFO_LEVEL *printer,
3284 TALLOC_CTX *mem_ctx)
3286 data->notify_data.value[0]=queue->page_count;
3287 data->notify_data.value[1]=0;
3290 /*******************************************************************
3291 * fill a notify_info_data with pages printed info.
3292 ********************************************************************/
3293 static void spoolss_notify_pages_printed(int snum,
3294 SPOOL_NOTIFY_INFO_DATA *data,
3295 print_queue_struct *queue,
3296 NT_PRINTER_INFO_LEVEL *printer,
3297 TALLOC_CTX *mem_ctx)
3299 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3300 data->notify_data.value[1]=0;
3303 /*******************************************************************
3304 Fill a notify_info_data with job position.
3305 ********************************************************************/
3307 static void spoolss_notify_job_position(int snum,
3308 SPOOL_NOTIFY_INFO_DATA *data,
3309 print_queue_struct *queue,
3310 NT_PRINTER_INFO_LEVEL *printer,
3311 TALLOC_CTX *mem_ctx)
3313 data->notify_data.value[0]=queue->job;
3314 data->notify_data.value[1]=0;
3317 /*******************************************************************
3318 Fill a notify_info_data with submitted time.
3319 ********************************************************************/
3321 static void spoolss_notify_submitted_time(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3332 t=gmtime(&queue->time);
3334 len = sizeof(SYSTEMTIME);
3336 data->notify_data.data.length = len;
3337 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3339 if (!data->notify_data.data.string) {
3340 data->notify_data.data.length = 0;
3344 make_systemtime(&st, t);
3347 * Systemtime must be linearized as a set of UINT16's.
3348 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3351 p = (char *)data->notify_data.data.string;
3352 SSVAL(p, 0, st.year);
3353 SSVAL(p, 2, st.month);
3354 SSVAL(p, 4, st.dayofweek);
3355 SSVAL(p, 6, st.day);
3356 SSVAL(p, 8, st.hour);
3357 SSVAL(p, 10, st.minute);
3358 SSVAL(p, 12, st.second);
3359 SSVAL(p, 14, st.milliseconds);
3362 struct s_notify_info_data_table
3368 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3369 print_queue_struct *queue,
3370 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3373 /* A table describing the various print notification constants and
3374 whether the notification data is a pointer to a variable sized
3375 buffer, a one value uint32 or a two value uint32. */
3377 static const struct s_notify_info_data_table notify_info_data_table[] =
3379 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3380 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3381 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3382 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3383 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3384 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3385 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3386 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3387 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3388 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3389 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3390 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3391 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3392 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3393 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3394 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3395 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3396 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3397 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3398 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3399 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3400 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3401 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3402 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3403 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3404 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3405 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3406 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3407 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3408 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3409 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3410 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3411 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3412 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3413 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3414 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3415 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3416 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3417 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3418 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3419 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3420 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3421 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3422 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3423 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3424 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3425 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3426 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3427 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3428 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3431 /*******************************************************************
3432 Return the size of info_data structure.
3433 ********************************************************************/
3435 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3439 for (i = 0; i < sizeof(notify_info_data_table); i++)
3441 if ( (notify_info_data_table[i].type == type)
3442 && (notify_info_data_table[i].field == field) )
3444 switch(notify_info_data_table[i].size)
3446 case NOTIFY_ONE_VALUE:
3447 case NOTIFY_TWO_VALUE:
3452 /* The only pointer notify data I have seen on
3453 the wire is the submitted time and this has
3454 the notify size set to 4. -tpot */
3456 case NOTIFY_POINTER:
3459 case NOTIFY_SECDESC:
3465 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3470 /*******************************************************************
3471 Return the type of notify_info_data.
3472 ********************************************************************/
3474 static int type_of_notify_info_data(uint16 type, uint16 field)
3478 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3479 if (notify_info_data_table[i].type == type &&
3480 notify_info_data_table[i].field == field)
3481 return notify_info_data_table[i].size;
3487 /****************************************************************************
3488 ****************************************************************************/
3490 static int search_notify(uint16 type, uint16 field, int *value)
3494 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3495 if (notify_info_data_table[i].type == type &&
3496 notify_info_data_table[i].field == field &&
3497 notify_info_data_table[i].fn != NULL) {
3506 /****************************************************************************
3507 ****************************************************************************/
3509 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3511 info_data->type = type;
3512 info_data->field = field;
3513 info_data->reserved = 0;
3515 info_data->size = size_of_notify_info_data(type, field);
3516 info_data->enc_type = type_of_notify_info_data(type, field);
3523 /*******************************************************************
3525 * fill a notify_info struct with info asked
3527 ********************************************************************/
3529 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3530 snum, SPOOL_NOTIFY_OPTION_TYPE
3531 *option_type, uint32 id,
3532 TALLOC_CTX *mem_ctx)
3538 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3539 NT_PRINTER_INFO_LEVEL *printer = NULL;
3540 print_queue_struct *queue=NULL;
3542 type=option_type->type;
3544 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3545 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3546 option_type->count, lp_servicename(snum)));
3548 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3551 for(field_num=0; field_num<option_type->count; field_num++) {
3552 field = option_type->fields[field_num];
3554 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3556 if (!search_notify(type, field, &j) )
3559 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3560 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3565 current_data = &info->data[info->count];
3567 construct_info_data(current_data, type, field, id);
3569 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3570 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3572 notify_info_data_table[j].fn(snum, current_data, queue,
3578 free_a_printer(&printer, 2);
3582 /*******************************************************************
3584 * fill a notify_info struct with info asked
3586 ********************************************************************/
3588 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3589 SPOOL_NOTIFY_INFO *info,
3590 NT_PRINTER_INFO_LEVEL *printer,
3591 int snum, SPOOL_NOTIFY_OPTION_TYPE
3592 *option_type, uint32 id,
3593 TALLOC_CTX *mem_ctx)
3599 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3601 DEBUG(4,("construct_notify_jobs_info\n"));
3603 type = option_type->type;
3605 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3606 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3607 option_type->count));
3609 for(field_num=0; field_num<option_type->count; field_num++) {
3610 field = option_type->fields[field_num];
3612 if (!search_notify(type, field, &j) )
3615 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3616 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3619 else info->data = tid;
3621 current_data=&(info->data[info->count]);
3623 construct_info_data(current_data, type, field, id);
3624 notify_info_data_table[j].fn(snum, current_data, queue,
3633 * JFM: The enumeration is not that simple, it's even non obvious.
3635 * let's take an example: I want to monitor the PRINTER SERVER for
3636 * the printer's name and the number of jobs currently queued.
3637 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3638 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3640 * I have 3 printers on the back of my server.
3642 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3645 * 1 printer 1 name 1
3646 * 2 printer 1 cjob 1
3647 * 3 printer 2 name 2
3648 * 4 printer 2 cjob 2
3649 * 5 printer 3 name 3
3650 * 6 printer 3 name 3
3652 * that's the print server case, the printer case is even worse.
3655 /*******************************************************************
3657 * enumerate all printers on the printserver
3658 * fill a notify_info struct with info asked
3660 ********************************************************************/
3662 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3663 SPOOL_NOTIFY_INFO *info,
3664 TALLOC_CTX *mem_ctx)
3667 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3668 int n_services=lp_numservices();
3670 SPOOL_NOTIFY_OPTION *option;
3671 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3673 DEBUG(4,("printserver_notify_info\n"));
3678 option=Printer->notify.option;
3683 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3684 sending a ffpcn() request first */
3689 for (i=0; i<option->count; i++) {
3690 option_type=&(option->ctr.type[i]);
3692 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3695 for (snum=0; snum<n_services; snum++)
3697 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3698 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3704 * Debugging information, don't delete.
3707 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3708 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3709 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3711 for (i=0; i<info->count; i++) {
3712 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3713 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3714 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 /*******************************************************************
3723 * fill a notify_info struct with info asked
3725 ********************************************************************/
3727 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3728 TALLOC_CTX *mem_ctx)
3731 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3734 SPOOL_NOTIFY_OPTION *option;
3735 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3737 print_queue_struct *queue=NULL;
3738 print_status_struct status;
3740 DEBUG(4,("printer_notify_info\n"));
3745 option=Printer->notify.option;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3757 get_printer_snum(p, hnd, &snum);
3759 for (i=0; i<option->count; i++) {
3760 option_type=&option->ctr.type[i];
3762 switch ( option_type->type ) {
3763 case PRINTER_NOTIFY_TYPE:
3764 if(construct_notify_printer_info(Printer, info, snum,
3770 case JOB_NOTIFY_TYPE: {
3771 NT_PRINTER_INFO_LEVEL *printer = NULL;
3773 count = print_queue_status(snum, &queue, &status);
3775 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3778 for (j=0; j<count; j++) {
3779 construct_notify_jobs_info(&queue[j], info,
3786 free_a_printer(&printer, 2);
3796 * Debugging information, don't delete.
3799 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3800 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3801 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3803 for (i=0; i<info->count; i++) {
3804 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3805 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3806 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3812 /********************************************************************
3814 ********************************************************************/
3816 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3818 POLICY_HND *handle = &q_u->handle;
3819 SPOOL_NOTIFY_INFO *info = &r_u->info;
3821 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3822 WERROR result = WERR_BADFID;
3824 /* we always have a NOTIFY_INFO struct */
3828 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3829 OUR_HANDLE(handle)));
3833 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3836 * We are now using the change value, and
3837 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3838 * I don't have a global notification system, I'm sending back all the
3839 * informations even when _NOTHING_ has changed.
3842 /* We need to keep track of the change value to send back in
3843 RRPCN replies otherwise our updates are ignored. */
3845 Printer->notify.fnpcn = True;
3847 if (Printer->notify.client_connected) {
3848 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3849 Printer->notify.change = q_u->change;
3852 /* just ignore the SPOOL_NOTIFY_OPTION */
3854 switch (Printer->printer_type) {
3855 case PRINTER_HANDLE_IS_PRINTSERVER:
3856 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3859 case PRINTER_HANDLE_IS_PRINTER:
3860 result = printer_notify_info(p, handle, info, p->mem_ctx);
3864 Printer->notify.fnpcn = False;
3870 /********************************************************************
3871 * construct_printer_info_0
3872 * fill a printer_info_0 struct
3873 ********************************************************************/
3875 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3879 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3880 counter_printer_0 *session_counter;
3881 uint32 global_counter;
3884 print_status_struct status;
3886 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3889 count = print_queue_length(snum, &status);
3891 /* check if we already have a counter for this printer */
3892 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3893 if (session_counter->snum == snum)
3897 /* it's the first time, add it to the list */
3898 if (session_counter==NULL) {
3899 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3900 free_a_printer(&ntprinter, 2);
3903 ZERO_STRUCTP(session_counter);
3904 session_counter->snum=snum;
3905 session_counter->counter=0;
3906 DLIST_ADD(counter_list, session_counter);
3910 session_counter->counter++;
3913 * the global_counter should be stored in a TDB as it's common to all the clients
3914 * and should be zeroed on samba startup
3916 global_counter=session_counter->counter;
3918 pstrcpy(chaine,ntprinter->info_2->printername);
3920 init_unistr(&printer->printername, chaine);
3922 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3923 init_unistr(&printer->servername, chaine);
3925 printer->cjobs = count;
3926 printer->total_jobs = 0;
3927 printer->total_bytes = 0;
3929 setuptime = (time_t)ntprinter->info_2->setuptime;
3930 t=gmtime(&setuptime);
3932 printer->year = t->tm_year+1900;
3933 printer->month = t->tm_mon+1;
3934 printer->dayofweek = t->tm_wday;
3935 printer->day = t->tm_mday;
3936 printer->hour = t->tm_hour;
3937 printer->minute = t->tm_min;
3938 printer->second = t->tm_sec;
3939 printer->milliseconds = 0;
3941 printer->global_counter = global_counter;
3942 printer->total_pages = 0;
3944 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3945 printer->major_version = 0x0005; /* NT 5 */
3946 printer->build_version = 0x0893; /* build 2195 */
3948 printer->unknown7 = 0x1;
3949 printer->unknown8 = 0x0;
3950 printer->unknown9 = 0x0;
3951 printer->session_counter = session_counter->counter;
3952 printer->unknown11 = 0x0;
3953 printer->printer_errors = 0x0; /* number of print failure */
3954 printer->unknown13 = 0x0;
3955 printer->unknown14 = 0x1;
3956 printer->unknown15 = 0x024a; /* 586 Pentium ? */
3957 printer->unknown16 = 0x0;
3958 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
3959 printer->unknown18 = 0x0;
3960 printer->status = nt_printq_status(status.status);
3961 printer->unknown20 = 0x0;
3962 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3963 printer->unknown22 = 0x0;
3964 printer->unknown23 = 0x6; /* 6 ???*/
3965 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
3966 printer->unknown25 = 0;
3967 printer->unknown26 = 0;
3968 printer->unknown27 = 0;
3969 printer->unknown28 = 0;
3970 printer->unknown29 = 0;
3972 free_a_printer(&ntprinter,2);
3976 /********************************************************************
3977 * construct_printer_info_1
3978 * fill a printer_info_1 struct
3979 ********************************************************************/
3980 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
3984 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3986 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3989 printer->flags=flags;
3991 if (*ntprinter->info_2->comment == '\0') {
3992 init_unistr(&printer->comment, lp_comment(snum));
3993 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3994 ntprinter->info_2->drivername, lp_comment(snum));
3997 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
3998 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
3999 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4002 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4004 init_unistr(&printer->description, chaine);
4005 init_unistr(&printer->name, chaine2);
4007 free_a_printer(&ntprinter,2);
4012 /****************************************************************************
4013 Free a DEVMODE struct.
4014 ****************************************************************************/
4016 static void free_dev_mode(DEVICEMODE *dev)
4021 SAFE_FREE(dev->dev_private);
4026 /****************************************************************************
4027 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4028 should be valid upon entry
4029 ****************************************************************************/
4031 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4033 if ( !devmode || !ntdevmode )
4036 init_unistr(&devmode->devicename, ntdevmode->devicename);
4038 init_unistr(&devmode->formname, ntdevmode->formname);
4040 devmode->specversion = ntdevmode->specversion;
4041 devmode->driverversion = ntdevmode->driverversion;
4042 devmode->size = ntdevmode->size;
4043 devmode->driverextra = ntdevmode->driverextra;
4044 devmode->fields = ntdevmode->fields;
4046 devmode->orientation = ntdevmode->orientation;
4047 devmode->papersize = ntdevmode->papersize;
4048 devmode->paperlength = ntdevmode->paperlength;
4049 devmode->paperwidth = ntdevmode->paperwidth;
4050 devmode->scale = ntdevmode->scale;
4051 devmode->copies = ntdevmode->copies;
4052 devmode->defaultsource = ntdevmode->defaultsource;
4053 devmode->printquality = ntdevmode->printquality;
4054 devmode->color = ntdevmode->color;
4055 devmode->duplex = ntdevmode->duplex;
4056 devmode->yresolution = ntdevmode->yresolution;
4057 devmode->ttoption = ntdevmode->ttoption;
4058 devmode->collate = ntdevmode->collate;
4059 devmode->icmmethod = ntdevmode->icmmethod;
4060 devmode->icmintent = ntdevmode->icmintent;
4061 devmode->mediatype = ntdevmode->mediatype;
4062 devmode->dithertype = ntdevmode->dithertype;
4064 if (ntdevmode->nt_dev_private != NULL) {
4065 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4072 /****************************************************************************
4073 Create a DEVMODE struct. Returns malloced memory.
4074 ****************************************************************************/
4076 DEVICEMODE *construct_dev_mode(int snum)
4078 NT_PRINTER_INFO_LEVEL *printer = NULL;
4079 DEVICEMODE *devmode = NULL;
4081 DEBUG(7,("construct_dev_mode\n"));
4083 DEBUGADD(8,("getting printer characteristics\n"));
4085 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4088 if ( !printer->info_2->devmode ) {
4089 DEBUG(5, ("BONG! There was no device mode!\n"));
4093 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4094 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4098 ZERO_STRUCTP(devmode);
4100 DEBUGADD(8,("loading DEVICEMODE\n"));
4102 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4103 free_dev_mode( devmode );
4108 free_a_printer(&printer,2);
4113 /********************************************************************
4114 * construct_printer_info_2
4115 * fill a printer_info_2 struct
4116 ********************************************************************/
4118 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4121 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4123 print_status_struct status;
4125 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4128 count = print_queue_length(snum, &status);
4130 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4131 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4132 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4133 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4134 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4136 if (*ntprinter->info_2->comment == '\0')
4137 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4139 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4141 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4142 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4143 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4144 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4145 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4147 printer->attributes = ntprinter->info_2->attributes;
4149 printer->priority = ntprinter->info_2->priority; /* priority */
4150 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4151 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4152 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4153 printer->status = nt_printq_status(status.status); /* status */
4154 printer->cjobs = count; /* jobs */
4155 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4157 if ( !(printer->devmode = construct_dev_mode(snum)) )
4158 DEBUG(8, ("Returning NULL Devicemode!\n"));
4160 printer->secdesc = NULL;
4162 if ( ntprinter->info_2->secdesc_buf
4163 && ntprinter->info_2->secdesc_buf->len != 0 )
4165 /* don't use talloc_steal() here unless you do a deep steal of all
4166 the SEC_DESC members */
4168 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4169 ntprinter->info_2->secdesc_buf->sec );
4172 free_a_printer(&ntprinter, 2);
4177 /********************************************************************
4178 * construct_printer_info_3
4179 * fill a printer_info_3 struct
4180 ********************************************************************/
4182 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4184 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4185 PRINTER_INFO_3 *printer = NULL;
4187 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4192 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4196 ZERO_STRUCTP(printer);
4198 /* These are the components of the SD we are returning. */
4200 printer->flags = 0x4;
4202 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4203 /* don't use talloc_steal() here unless you do a deep steal of all
4204 the SEC_DESC members */
4206 printer->secdesc = dup_sec_desc( get_talloc_ctx(),
4207 ntprinter->info_2->secdesc_buf->sec );
4210 free_a_printer(&ntprinter, 2);
4212 *pp_printer = printer;
4216 /********************************************************************
4217 * construct_printer_info_4
4218 * fill a printer_info_4 struct
4219 ********************************************************************/
4221 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4223 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4225 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4228 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4229 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4230 printer->attributes = ntprinter->info_2->attributes;
4232 free_a_printer(&ntprinter, 2);
4236 /********************************************************************
4237 * construct_printer_info_5
4238 * fill a printer_info_5 struct
4239 ********************************************************************/
4241 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4243 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4245 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4248 init_unistr(&printer->printername, ntprinter->info_2->printername);
4249 init_unistr(&printer->portname, ntprinter->info_2->portname);
4250 printer->attributes = ntprinter->info_2->attributes;
4252 /* these two are not used by NT+ according to MSDN */
4254 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4255 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4257 free_a_printer(&ntprinter, 2);
4262 /********************************************************************
4263 * construct_printer_info_7
4264 * fill a printer_info_7 struct
4265 ********************************************************************/
4267 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4269 char *guid_str = NULL;
4272 if (is_printer_published(print_hnd, snum, &guid)) {
4273 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4274 strupper_m(guid_str);
4275 init_unistr(&printer->guid, guid_str);
4276 printer->action = SPOOL_DS_PUBLISH;
4278 init_unistr(&printer->guid, "");
4279 printer->action = SPOOL_DS_UNPUBLISH;
4285 /********************************************************************
4286 Spoolss_enumprinters.
4287 ********************************************************************/
4289 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4293 int n_services=lp_numservices();
4294 PRINTER_INFO_1 *tp, *printers=NULL;
4295 PRINTER_INFO_1 current_prt;
4296 WERROR result = WERR_OK;
4298 DEBUG(4,("enum_all_printers_info_1\n"));
4300 for (snum=0; snum<n_services; snum++) {
4301 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4302 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4304 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4305 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4306 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4307 SAFE_FREE(printers);
4312 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4314 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4320 /* check the required size. */
4321 for (i=0; i<*returned; i++)
4322 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4324 if (*needed > offered) {
4325 result = WERR_INSUFFICIENT_BUFFER;
4329 if (!rpcbuf_alloc_size(buffer, *needed)) {
4330 result = WERR_NOMEM;
4334 /* fill the buffer with the structures */
4335 for (i=0; i<*returned; i++)
4336 smb_io_printer_info_1("", buffer, &printers[i], 0);
4341 SAFE_FREE(printers);
4343 if ( !W_ERROR_IS_OK(result) )
4349 /********************************************************************
4350 enum_all_printers_info_1_local.
4351 *********************************************************************/
4353 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4355 DEBUG(4,("enum_all_printers_info_1_local\n"));
4357 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4360 /********************************************************************
4361 enum_all_printers_info_1_name.
4362 *********************************************************************/
4364 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4368 DEBUG(4,("enum_all_printers_info_1_name\n"));
4370 if ((name[0] == '\\') && (name[1] == '\\'))
4373 if (is_myname_or_ipaddr(s)) {
4374 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4377 return WERR_INVALID_NAME;
4380 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4381 /********************************************************************
4382 enum_all_printers_info_1_remote.
4383 *********************************************************************/
4385 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4387 PRINTER_INFO_1 *printer;
4388 fstring printername;
4391 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4392 WERROR result = WERR_OK;
4394 /* JFM: currently it's more a place holder than anything else.
4395 * In the spooler world there is a notion of server registration.
4396 * the print servers are registered on the PDC (in the same domain)
4398 * We should have a TDB here. The registration is done thru an
4399 * undocumented RPC call.
4402 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4407 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4408 slprintf(desc, sizeof(desc)-1,"%s", name);
4409 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4411 init_unistr(&printer->description, desc);
4412 init_unistr(&printer->name, printername);
4413 init_unistr(&printer->comment, comment);
4414 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4416 /* check the required size. */
4417 *needed += spoolss_size_printer_info_1(printer);
4419 if (*needed > offered) {
4420 result = WERR_INSUFFICIENT_BUFFER;
4424 if (!rpcbuf_alloc_size(buffer, *needed)) {
4425 result = WERR_NOMEM;
4429 /* fill the buffer with the structures */
4430 smb_io_printer_info_1("", buffer, printer, 0);
4436 if ( !W_ERROR_IS_OK(result) )
4444 /********************************************************************
4445 enum_all_printers_info_1_network.
4446 *********************************************************************/
4448 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4452 DEBUG(4,("enum_all_printers_info_1_network\n"));
4454 /* If we respond to a enum_printers level 1 on our name with flags
4455 set to PRINTER_ENUM_REMOTE with a list of printers then these
4456 printers incorrectly appear in the APW browse list.
4457 Specifically the printers for the server appear at the workgroup
4458 level where all the other servers in the domain are
4459 listed. Windows responds to this call with a
4460 WERR_CAN_NOT_COMPLETE so we should do the same. */
4462 if (name[0] == '\\' && name[1] == '\\')
4465 if (is_myname_or_ipaddr(s))
4466 return WERR_CAN_NOT_COMPLETE;
4468 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4471 /********************************************************************
4472 * api_spoolss_enumprinters
4474 * called from api_spoolss_enumprinters (see this to understand)
4475 ********************************************************************/
4477 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4481 int n_services=lp_numservices();
4482 PRINTER_INFO_2 *tp, *printers=NULL;
4483 PRINTER_INFO_2 current_prt;
4484 WERROR result = WERR_OK;
4486 for (snum=0; snum<n_services; snum++) {
4487 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4488 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4490 if (construct_printer_info_2(NULL, ¤t_prt, snum))
4492 if ( !(tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4493 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4494 SAFE_FREE(printers);
4499 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4502 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4509 /* check the required size. */
4510 for (i=0; i<*returned; i++)
4511 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4513 if (*needed > offered) {
4514 result = WERR_INSUFFICIENT_BUFFER;
4518 if (!rpcbuf_alloc_size(buffer, *needed)) {
4519 result = WERR_NOMEM;
4523 /* fill the buffer with the structures */
4524 for (i=0; i<*returned; i++)
4525 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4530 for (i=0; i<*returned; i++)
4531 free_devmode(printers[i].devmode);
4533 SAFE_FREE(printers);
4535 if ( !W_ERROR_IS_OK(result) )
4541 /********************************************************************
4542 * handle enumeration of printers at level 1
4543 ********************************************************************/
4545 static WERROR enumprinters_level1( uint32 flags, fstring name,
4546 RPC_BUFFER *buffer, uint32 offered,
4547 uint32 *needed, uint32 *returned)
4549 /* Not all the flags are equals */
4551 if (flags & PRINTER_ENUM_LOCAL)
4552 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4554 if (flags & PRINTER_ENUM_NAME)
4555 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4557 #if 0 /* JERRY - disabled for now */
4558 if (flags & PRINTER_ENUM_REMOTE)
4559 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4562 if (flags & PRINTER_ENUM_NETWORK)
4563 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4565 return WERR_OK; /* NT4sp5 does that */
4568 /********************************************************************
4569 * handle enumeration of printers at level 2
4570 ********************************************************************/
4572 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4573 RPC_BUFFER *buffer, uint32 offered,
4574 uint32 *needed, uint32 *returned)
4576 char *s = servername;
4578 if (flags & PRINTER_ENUM_LOCAL) {
4579 return enum_all_printers_info_2(buffer, offered, needed, returned);
4582 if (flags & PRINTER_ENUM_NAME) {
4583 if ((servername[0] == '\\') && (servername[1] == '\\'))
4585 if (is_myname_or_ipaddr(s))
4586 return enum_all_printers_info_2(buffer, offered, needed, returned);
4588 return WERR_INVALID_NAME;
4591 if (flags & PRINTER_ENUM_REMOTE)
4592 return WERR_UNKNOWN_LEVEL;
4597 /********************************************************************
4598 * handle enumeration of printers at level 5
4599 ********************************************************************/
4601 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4602 RPC_BUFFER *buffer, uint32 offered,
4603 uint32 *needed, uint32 *returned)
4605 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4609 /********************************************************************
4610 * api_spoolss_enumprinters
4612 * called from api_spoolss_enumprinters (see this to understand)
4613 ********************************************************************/
4615 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4617 uint32 flags = q_u->flags;
4618 UNISTR2 *servername = &q_u->servername;
4619 uint32 level = q_u->level;
4620 RPC_BUFFER *buffer = NULL;
4621 uint32 offered = q_u->offered;
4622 uint32 *needed = &r_u->needed;
4623 uint32 *returned = &r_u->returned;
4627 /* that's an [in out] buffer */
4629 if ( q_u->buffer ) {
4630 rpcbuf_move(q_u->buffer, &r_u->buffer);
4631 buffer = r_u->buffer;
4634 DEBUG(4,("_spoolss_enumprinters\n"));
4641 * flags==PRINTER_ENUM_NAME
4642 * if name=="" then enumerates all printers
4643 * if name!="" then enumerate the printer
4644 * flags==PRINTER_ENUM_REMOTE
4645 * name is NULL, enumerate printers
4646 * Level 2: name!="" enumerates printers, name can't be NULL
4647 * Level 3: doesn't exist
4648 * Level 4: does a local registry lookup
4649 * Level 5: same as Level 2
4652 unistr2_to_ascii(name, servername, sizeof(name)-1);
4657 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4659 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4661 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4666 return WERR_UNKNOWN_LEVEL;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4674 PRINTER_INFO_0 *printer=NULL;
4675 WERROR result = WERR_OK;
4677 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4680 construct_printer_info_0(print_hnd, printer, snum);
4682 /* check the required size. */
4683 *needed += spoolss_size_printer_info_0(printer);
4685 if (*needed > offered) {
4686 result = WERR_INSUFFICIENT_BUFFER;
4690 if (!rpcbuf_alloc_size(buffer, *needed)) {
4691 result = WERR_NOMEM;
4695 /* fill the buffer with the structures */
4696 smb_io_printer_info_0("", buffer, printer, 0);
4706 /****************************************************************************
4707 ****************************************************************************/
4709 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4711 PRINTER_INFO_1 *printer=NULL;
4712 WERROR result = WERR_OK;
4714 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4717 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4719 /* check the required size. */
4720 *needed += spoolss_size_printer_info_1(printer);
4722 if (*needed > offered) {
4723 result = WERR_INSUFFICIENT_BUFFER;
4727 if (!rpcbuf_alloc_size(buffer, *needed)) {
4728 result = WERR_NOMEM;
4732 /* fill the buffer with the structures */
4733 smb_io_printer_info_1("", buffer, printer, 0);
4742 /****************************************************************************
4743 ****************************************************************************/
4745 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4747 PRINTER_INFO_2 *printer=NULL;
4748 WERROR result = WERR_OK;
4750 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4753 construct_printer_info_2(print_hnd, printer, snum);
4755 /* check the required size. */
4756 *needed += spoolss_size_printer_info_2(printer);
4758 if (*needed > offered) {
4759 result = WERR_INSUFFICIENT_BUFFER;
4763 if (!rpcbuf_alloc_size(buffer, *needed)) {
4764 result = WERR_NOMEM;
4768 /* fill the buffer with the structures */
4769 if (!smb_io_printer_info_2("", buffer, printer, 0))
4770 result = WERR_NOMEM;
4774 free_printer_info_2(printer);
4779 /****************************************************************************
4780 ****************************************************************************/
4782 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4784 PRINTER_INFO_3 *printer=NULL;
4785 WERROR result = WERR_OK;
4787 if (!construct_printer_info_3(print_hnd, &printer, snum))
4790 /* check the required size. */
4791 *needed += spoolss_size_printer_info_3(printer);
4793 if (*needed > offered) {
4794 result = WERR_INSUFFICIENT_BUFFER;
4798 if (!rpcbuf_alloc_size(buffer, *needed)) {
4799 result = WERR_NOMEM;
4803 /* fill the buffer with the structures */
4804 smb_io_printer_info_3("", buffer, printer, 0);
4808 free_printer_info_3(printer);
4813 /****************************************************************************
4814 ****************************************************************************/
4816 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4818 PRINTER_INFO_4 *printer=NULL;
4819 WERROR result = WERR_OK;
4821 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4824 if (!construct_printer_info_4(print_hnd, printer, snum))
4827 /* check the required size. */
4828 *needed += spoolss_size_printer_info_4(printer);
4830 if (*needed > offered) {
4831 result = WERR_INSUFFICIENT_BUFFER;
4835 if (!rpcbuf_alloc_size(buffer, *needed)) {
4836 result = WERR_NOMEM;
4840 /* fill the buffer with the structures */
4841 smb_io_printer_info_4("", buffer, printer, 0);
4845 free_printer_info_4(printer);
4850 /****************************************************************************
4851 ****************************************************************************/
4853 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4855 PRINTER_INFO_5 *printer=NULL;
4856 WERROR result = WERR_OK;
4858 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4861 if (!construct_printer_info_5(print_hnd, printer, snum))
4864 /* check the required size. */
4865 *needed += spoolss_size_printer_info_5(printer);
4867 if (*needed > offered) {
4868 result = WERR_INSUFFICIENT_BUFFER;
4872 if (!rpcbuf_alloc_size(buffer, *needed)) {
4873 result = WERR_NOMEM;
4877 /* fill the buffer with the structures */
4878 smb_io_printer_info_5("", buffer, printer, 0);
4882 free_printer_info_5(printer);
4887 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4889 PRINTER_INFO_7 *printer=NULL;
4890 WERROR result = WERR_OK;
4892 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4895 if (!construct_printer_info_7(print_hnd, printer, snum))
4898 /* check the required size. */
4899 *needed += spoolss_size_printer_info_7(printer);
4901 if (*needed > offered) {
4902 result = WERR_INSUFFICIENT_BUFFER;
4906 if (!rpcbuf_alloc_size(buffer, *needed)) {
4907 result = WERR_NOMEM;
4912 /* fill the buffer with the structures */
4913 smb_io_printer_info_7("", buffer, printer, 0);
4917 free_printer_info_7(printer);
4922 /****************************************************************************
4923 ****************************************************************************/
4925 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
4927 POLICY_HND *handle = &q_u->handle;
4928 uint32 level = q_u->level;
4929 RPC_BUFFER *buffer = NULL;
4930 uint32 offered = q_u->offered;
4931 uint32 *needed = &r_u->needed;
4932 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
4936 /* that's an [in out] buffer */
4938 if ( q_u->buffer ) {
4939 rpcbuf_move(q_u->buffer, &r_u->buffer);
4940 buffer = r_u->buffer;
4945 if (!get_printer_snum(p, handle, &snum))
4950 return getprinter_level_0(Printer, snum, buffer, offered, needed);
4952 return getprinter_level_1(Printer, snum, buffer, offered, needed);
4954 return getprinter_level_2(Printer, snum, buffer, offered, needed);
4956 return getprinter_level_3(Printer, snum, buffer, offered, needed);
4958 return getprinter_level_4(Printer, snum, buffer, offered, needed);
4960 return getprinter_level_5(Printer, snum, buffer, offered, needed);
4962 return getprinter_level_7(Printer, snum, buffer, offered, needed);
4964 return WERR_UNKNOWN_LEVEL;
4967 /********************************************************************
4968 * fill a DRIVER_INFO_1 struct
4969 ********************************************************************/
4971 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
4973 init_unistr( &info->name, driver.info_3->name);
4976 /********************************************************************
4977 * construct_printer_driver_info_1
4978 ********************************************************************/
4980 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
4982 NT_PRINTER_INFO_LEVEL *printer = NULL;
4983 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4985 ZERO_STRUCT(driver);
4987 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4988 return WERR_INVALID_PRINTER_NAME;
4990 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
4991 return WERR_UNKNOWN_PRINTER_DRIVER;
4993 fill_printer_driver_info_1(info, driver, servername, architecture);
4995 free_a_printer(&printer,2);
5000 /********************************************************************
5001 * construct_printer_driver_info_2
5002 * fill a printer_info_2 struct
5003 ********************************************************************/
5005 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5009 info->version=driver.info_3->cversion;
5011 init_unistr( &info->name, driver.info_3->name );
5012 init_unistr( &info->architecture, driver.info_3->environment );
5015 if (strlen(driver.info_3->driverpath)) {
5016 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5017 init_unistr( &info->driverpath, temp );
5019 init_unistr( &info->driverpath, "" );
5021 if (strlen(driver.info_3->datafile)) {
5022 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5023 init_unistr( &info->datafile, temp );
5025 init_unistr( &info->datafile, "" );
5027 if (strlen(driver.info_3->configfile)) {
5028 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5029 init_unistr( &info->configfile, temp );
5031 init_unistr( &info->configfile, "" );
5034 /********************************************************************
5035 * construct_printer_driver_info_2
5036 * fill a printer_info_2 struct
5037 ********************************************************************/
5039 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5041 NT_PRINTER_INFO_LEVEL *printer = NULL;
5042 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5044 ZERO_STRUCT(printer);
5045 ZERO_STRUCT(driver);
5047 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5048 return WERR_INVALID_PRINTER_NAME;
5050 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5051 return WERR_UNKNOWN_PRINTER_DRIVER;
5053 fill_printer_driver_info_2(info, driver, servername);
5055 free_a_printer(&printer,2);
5060 /********************************************************************
5061 * copy a strings array and convert to UNICODE
5063 * convert an array of ascii string to a UNICODE string
5064 ********************************************************************/
5066 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5074 DEBUG(6,("init_unistr_array\n"));
5085 v = ""; /* hack to handle null lists */
5088 /* hack to allow this to be used in places other than when generating
5089 the list of dependent files */
5092 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5096 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5098 /* add one extra unit16 for the second terminating NULL */
5100 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5101 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5109 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5114 /* special case for ""; we need to add both NULL's here */
5116 (*uni_array)[j++]=0x0000;
5117 (*uni_array)[j]=0x0000;
5120 DEBUGADD(6,("last one:done\n"));
5122 /* return size of array in uint16's */
5127 /********************************************************************
5128 * construct_printer_info_3
5129 * fill a printer_info_3 struct
5130 ********************************************************************/
5132 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5138 info->version=driver.info_3->cversion;
5140 init_unistr( &info->name, driver.info_3->name );
5141 init_unistr( &info->architecture, driver.info_3->environment );
5143 if (strlen(driver.info_3->driverpath)) {
5144 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5145 init_unistr( &info->driverpath, temp );
5147 init_unistr( &info->driverpath, "" );
5149 if (strlen(driver.info_3->datafile)) {
5150 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5151 init_unistr( &info->datafile, temp );
5153 init_unistr( &info->datafile, "" );
5155 if (strlen(driver.info_3->configfile)) {
5156 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5157 init_unistr( &info->configfile, temp );
5159 init_unistr( &info->configfile, "" );
5161 if (strlen(driver.info_3->helpfile)) {
5162 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5163 init_unistr( &info->helpfile, temp );
5165 init_unistr( &info->helpfile, "" );
5167 init_unistr( &info->monitorname, driver.info_3->monitorname );
5168 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5170 info->dependentfiles=NULL;
5171 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5174 /********************************************************************
5175 * construct_printer_info_3
5176 * fill a printer_info_3 struct
5177 ********************************************************************/
5179 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5181 NT_PRINTER_INFO_LEVEL *printer = NULL;
5182 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5184 ZERO_STRUCT(driver);
5186 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5187 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5188 if (!W_ERROR_IS_OK(status))
5189 return WERR_INVALID_PRINTER_NAME;
5191 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5192 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5197 * I put this code in during testing. Helpful when commenting out the
5198 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5199 * as win2k always queries the driver using an infor level of 6.
5200 * I've left it in (but ifdef'd out) because I'll probably
5201 * use it in experimentation again in the future. --jerry 22/01/2002
5204 if (!W_ERROR_IS_OK(status)) {
5206 * Is this a W2k client ?
5209 /* Yes - try again with a WinNT driver. */
5211 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5212 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5216 if (!W_ERROR_IS_OK(status)) {
5217 free_a_printer(&printer,2);
5218 return WERR_UNKNOWN_PRINTER_DRIVER;
5226 fill_printer_driver_info_3(info, driver, servername);
5228 free_a_printer(&printer,2);
5233 /********************************************************************
5234 * construct_printer_info_6
5235 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5236 ********************************************************************/
5238 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5244 memset(&nullstr, '\0', sizeof(fstring));
5246 info->version=driver.info_3->cversion;
5248 init_unistr( &info->name, driver.info_3->name );
5249 init_unistr( &info->architecture, driver.info_3->environment );
5251 if (strlen(driver.info_3->driverpath)) {
5252 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5253 init_unistr( &info->driverpath, temp );
5255 init_unistr( &info->driverpath, "" );
5257 if (strlen(driver.info_3->datafile)) {
5258 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5259 init_unistr( &info->datafile, temp );
5261 init_unistr( &info->datafile, "" );
5263 if (strlen(driver.info_3->configfile)) {
5264 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5265 init_unistr( &info->configfile, temp );
5267 init_unistr( &info->configfile, "" );
5269 if (strlen(driver.info_3->helpfile)) {
5270 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5271 init_unistr( &info->helpfile, temp );
5273 init_unistr( &info->helpfile, "" );
5275 init_unistr( &info->monitorname, driver.info_3->monitorname );
5276 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5278 info->dependentfiles = NULL;
5279 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5281 info->previousdrivernames=NULL;
5282 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5284 info->driver_date.low=0;
5285 info->driver_date.high=0;
5288 info->driver_version_low=0;
5289 info->driver_version_high=0;
5291 init_unistr( &info->mfgname, "");
5292 init_unistr( &info->oem_url, "");
5293 init_unistr( &info->hardware_id, "");
5294 init_unistr( &info->provider, "");
5297 /********************************************************************
5298 * construct_printer_info_6
5299 * fill a printer_info_6 struct
5300 ********************************************************************/
5302 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5303 fstring servername, fstring architecture, uint32 version)
5305 NT_PRINTER_INFO_LEVEL *printer = NULL;
5306 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5309 ZERO_STRUCT(driver);
5311 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5313 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5315 if (!W_ERROR_IS_OK(status))
5316 return WERR_INVALID_PRINTER_NAME;
5318 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5320 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5322 if (!W_ERROR_IS_OK(status))
5325 * Is this a W2k client ?
5329 free_a_printer(&printer,2);
5330 return WERR_UNKNOWN_PRINTER_DRIVER;
5333 /* Yes - try again with a WinNT driver. */
5335 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5336 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5337 if (!W_ERROR_IS_OK(status)) {
5338 free_a_printer(&printer,2);
5339 return WERR_UNKNOWN_PRINTER_DRIVER;
5343 fill_printer_driver_info_6(info, driver, servername);
5345 free_a_printer(&printer,2);
5346 free_a_printer_driver(driver, 3);
5351 /****************************************************************************
5352 ****************************************************************************/
5354 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5356 SAFE_FREE(info->dependentfiles);
5359 /****************************************************************************
5360 ****************************************************************************/
5362 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5364 SAFE_FREE(info->dependentfiles);
5367 /****************************************************************************
5368 ****************************************************************************/
5370 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5372 DRIVER_INFO_1 *info=NULL;
5375 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5378 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5379 if (!W_ERROR_IS_OK(result))
5382 /* check the required size. */
5383 *needed += spoolss_size_printer_driver_info_1(info);
5385 if (*needed > offered) {
5386 result = WERR_INSUFFICIENT_BUFFER;
5390 if (!rpcbuf_alloc_size(buffer, *needed)) {
5391 result = WERR_NOMEM;
5395 /* fill the buffer with the structures */
5396 smb_io_printer_driver_info_1("", buffer, info, 0);
5405 /****************************************************************************
5406 ****************************************************************************/
5408 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5410 DRIVER_INFO_2 *info=NULL;
5413 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5416 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5417 if (!W_ERROR_IS_OK(result))
5420 /* check the required size. */
5421 *needed += spoolss_size_printer_driver_info_2(info);
5423 if (*needed > offered) {
5424 result = WERR_INSUFFICIENT_BUFFER;
5428 if (!rpcbuf_alloc_size(buffer, *needed)) {
5429 result = WERR_NOMEM;
5433 /* fill the buffer with the structures */
5434 smb_io_printer_driver_info_2("", buffer, info, 0);
5443 /****************************************************************************
5444 ****************************************************************************/
5446 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5453 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5454 if (!W_ERROR_IS_OK(result))
5457 /* check the required size. */
5458 *needed += spoolss_size_printer_driver_info_3(&info);
5460 if (*needed > offered) {
5461 result = WERR_INSUFFICIENT_BUFFER;
5465 if (!rpcbuf_alloc_size(buffer, *needed)) {
5466 result = WERR_NOMEM;
5470 /* fill the buffer with the structures */
5471 smb_io_printer_driver_info_3("", buffer, &info, 0);
5474 free_printer_driver_info_3(&info);
5479 /****************************************************************************
5480 ****************************************************************************/
5482 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5489 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5490 if (!W_ERROR_IS_OK(result))
5493 /* check the required size. */
5494 *needed += spoolss_size_printer_driver_info_6(&info);
5496 if (*needed > offered) {
5497 result = WERR_INSUFFICIENT_BUFFER;
5501 if (!rpcbuf_alloc_size(buffer, *needed)) {
5502 result = WERR_NOMEM;
5506 /* fill the buffer with the structures */
5507 smb_io_printer_driver_info_6("", buffer, &info, 0);
5510 free_printer_driver_info_6(&info);
5515 /****************************************************************************
5516 ****************************************************************************/
5518 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5520 POLICY_HND *handle = &q_u->handle;
5521 UNISTR2 *uni_arch = &q_u->architecture;
5522 uint32 level = q_u->level;
5523 uint32 clientmajorversion = q_u->clientmajorversion;
5524 RPC_BUFFER *buffer = NULL;
5525 uint32 offered = q_u->offered;
5526 uint32 *needed = &r_u->needed;
5527 uint32 *servermajorversion = &r_u->servermajorversion;
5528 uint32 *serverminorversion = &r_u->serverminorversion;
5529 Printer_entry *printer;
5532 fstring architecture;
5535 /* that's an [in out] buffer */
5537 if ( q_u->buffer ) {
5538 rpcbuf_move(q_u->buffer, &r_u->buffer);
5539 buffer = r_u->buffer;
5542 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5544 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5545 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5546 return WERR_INVALID_PRINTER_NAME;
5550 *servermajorversion = 0;
5551 *serverminorversion = 0;
5553 fstrcpy(servername, get_server_name( printer ));
5554 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5556 if (!get_printer_snum(p, handle, &snum))
5561 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5563 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5565 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5567 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5570 /* apparently this call is the equivalent of
5571 EnumPrinterDataEx() for the DsDriver key */
5576 return WERR_UNKNOWN_LEVEL;
5579 /****************************************************************************
5580 ****************************************************************************/
5582 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5584 POLICY_HND *handle = &q_u->handle;
5586 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5589 DEBUG(3,("Error in startpageprinter printer handle\n"));
5593 Printer->page_started=True;
5597 /****************************************************************************
5598 ****************************************************************************/
5600 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5602 POLICY_HND *handle = &q_u->handle;
5605 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5608 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5612 if (!get_printer_snum(p, handle, &snum))
5615 Printer->page_started=False;
5616 print_job_endpage(snum, Printer->jobid);
5621 /********************************************************************
5622 * api_spoolss_getprinter
5623 * called from the spoolss dispatcher
5625 ********************************************************************/
5627 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5629 POLICY_HND *handle = &q_u->handle;
5630 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5631 uint32 *jobid = &r_u->jobid;
5633 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5637 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5638 struct current_user user;
5641 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5645 get_current_user(&user, p);
5648 * a nice thing with NT is it doesn't listen to what you tell it.
5649 * when asked to send _only_ RAW datas, it tries to send datas
5652 * So I add checks like in NT Server ...
5655 if (info_1->p_datatype != 0) {
5656 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5657 if (strcmp(datatype, "RAW") != 0) {
5659 return WERR_INVALID_DATATYPE;
5663 /* get the share number of the printer */
5664 if (!get_printer_snum(p, handle, &snum)) {
5668 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5670 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5672 /* An error occured in print_job_start() so return an appropriate
5675 if (Printer->jobid == -1) {
5676 return map_werror_from_unix(errno);
5679 Printer->document_started=True;
5680 (*jobid) = Printer->jobid;
5685 /********************************************************************
5686 * api_spoolss_getprinter
5687 * called from the spoolss dispatcher
5689 ********************************************************************/
5691 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5693 POLICY_HND *handle = &q_u->handle;
5695 return _spoolss_enddocprinter_internal(p, handle);
5698 /****************************************************************************
5699 ****************************************************************************/
5701 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5703 POLICY_HND *handle = &q_u->handle;
5704 uint32 buffer_size = q_u->buffer_size;
5705 uint8 *buffer = q_u->buffer;
5706 uint32 *buffer_written = &q_u->buffer_size2;
5708 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5711 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5712 r_u->buffer_written = q_u->buffer_size2;
5716 if (!get_printer_snum(p, handle, &snum))
5719 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5720 (SMB_OFF_T)-1, (size_t)buffer_size);
5721 if (*buffer_written == (uint32)-1) {
5722 r_u->buffer_written = 0;
5723 if (errno == ENOSPC)
5724 return WERR_NO_SPOOL_SPACE;
5726 return WERR_ACCESS_DENIED;
5729 r_u->buffer_written = q_u->buffer_size2;
5734 /********************************************************************
5735 * api_spoolss_getprinter
5736 * called from the spoolss dispatcher
5738 ********************************************************************/
5740 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5743 struct current_user user;
5745 WERROR errcode = WERR_BADFUNC;
5746 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5748 get_current_user(&user, p);
5751 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5755 if (!get_printer_snum(p, handle, &snum))
5759 case PRINTER_CONTROL_PAUSE:
5760 if (print_queue_pause(&user, snum, &errcode)) {
5764 case PRINTER_CONTROL_RESUME:
5765 case PRINTER_CONTROL_UNPAUSE:
5766 if (print_queue_resume(&user, snum, &errcode)) {
5770 case PRINTER_CONTROL_PURGE:
5771 if (print_queue_purge(&user, snum, &errcode)) {
5776 return WERR_UNKNOWN_LEVEL;
5782 /********************************************************************
5783 * api_spoolss_abortprinter
5784 * From MSDN: "Deletes printer's spool file if printer is configured
5786 ********************************************************************/
5788 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5790 POLICY_HND *handle = &q_u->handle;
5791 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5793 struct current_user user;
5794 WERROR errcode = WERR_OK;
5797 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5801 if (!get_printer_snum(p, handle, &snum))
5804 get_current_user( &user, p );
5806 print_job_delete( &user, snum, Printer->jobid, &errcode );
5811 /********************************************************************
5812 * called by spoolss_api_setprinter
5813 * when updating a printer description
5814 ********************************************************************/
5816 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5817 const SPOOL_PRINTER_INFO_LEVEL *info,
5818 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5820 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5824 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5826 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5827 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5828 OUR_HANDLE(handle)));
5830 result = WERR_BADFID;
5834 /* Check the user has permissions to change the security
5835 descriptor. By experimentation with two NT machines, the user
5836 requires Full Access to the printer to change security
5839 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5840 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5841 result = WERR_ACCESS_DENIED;
5845 /* NT seems to like setting the security descriptor even though
5846 nothing may have actually changed. */
5848 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5850 if (DEBUGLEVEL >= 10) {
5854 the_acl = old_secdesc_ctr->sec->dacl;
5855 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5856 PRINTERNAME(snum), the_acl->num_aces));
5858 for (i = 0; i < the_acl->num_aces; i++) {
5861 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5863 DEBUG(10, ("%s 0x%08x\n", sid_str,
5864 the_acl->ace[i].info.mask));
5867 the_acl = secdesc_ctr->sec->dacl;
5870 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5871 PRINTERNAME(snum), the_acl->num_aces));
5873 for (i = 0; i < the_acl->num_aces; i++) {
5876 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5878 DEBUG(10, ("%s 0x%08x\n", sid_str,
5879 the_acl->ace[i].info.mask));
5882 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5886 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5888 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5893 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5900 /********************************************************************
5901 Canonicalize printer info from a client
5903 ATTN: It does not matter what we set the servername to hear
5904 since we do the necessary work in get_a_printer() to set it to
5905 the correct value based on what the client sent in the
5906 _spoolss_open_printer_ex().
5907 ********************************************************************/
5909 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5911 fstring printername;
5914 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5915 "portname=%s drivername=%s comment=%s location=%s\n",
5916 info->servername, info->printername, info->sharename,
5917 info->portname, info->drivername, info->comment, info->location));
5919 /* we force some elements to "correct" values */
5920 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5921 fstrcpy(info->sharename, lp_servicename(snum));
5923 /* check to see if we allow printername != sharename */
5925 if ( lp_force_printername(snum) ) {
5926 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5927 global_myname(), info->sharename );
5930 /* make sure printername is in \\server\printername format */
5932 fstrcpy( printername, info->printername );
5934 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5935 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5939 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
5940 global_myname(), p );
5943 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5944 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5951 /****************************************************************************
5952 ****************************************************************************/
5954 BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
5956 char *cmd = lp_addprinter_cmd();
5962 fstring remote_machine = "%m";
5963 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5964 BOOL is_print_op = False;
5966 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
5968 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5969 cmd, printer->info_2->printername, printer->info_2->sharename,
5970 printer->info_2->portname, printer->info_2->drivername,
5971 printer->info_2->location, printer->info_2->comment, remote_machine);
5974 is_print_op = user_has_privileges( token, &se_printop );
5976 DEBUG(10,("Running [%s]\n", command));
5978 /********* BEGIN SePrintOperatorPrivilege **********/
5983 if ( (ret = smbrun(command, &fd)) == 0 ) {
5984 /* Tell everyone we updated smb.conf. */
5985 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
5991 /********* END SePrintOperatorPrivilege **********/
5993 DEBUGADD(10,("returned [%d]\n", ret));
6001 /* reload our services immediately */
6002 reload_services( False );
6005 /* Get lines and convert them back to dos-codepage */
6006 qlines = fd_lines_load(fd, &numlines, 0);
6007 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6010 /* Set the portname to what the script says the portname should be. */
6011 /* but don't require anything to be return from the script exit a good error code */
6014 /* Set the portname to what the script says the portname should be. */
6015 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6016 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6019 file_lines_free(qlines);
6023 /********************************************************************
6024 * Called by spoolss_api_setprinter
6025 * when updating a printer description.
6026 ********************************************************************/
6028 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6029 const SPOOL_PRINTER_INFO_LEVEL *info,
6030 DEVICEMODE *devmode)
6033 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6034 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6039 DEBUG(8,("update_printer\n"));
6044 result = WERR_BADFID;
6048 if (!get_printer_snum(p, handle, &snum)) {
6049 result = WERR_BADFID;
6053 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6054 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6055 result = WERR_BADFID;
6059 DEBUGADD(8,("Converting info_2 struct\n"));
6062 * convert_printer_info converts the incoming
6063 * info from the client and overwrites the info
6064 * just read from the tdb in the pointer 'printer'.
6067 if (!convert_printer_info(info, printer, level)) {
6068 result = WERR_NOMEM;
6073 /* we have a valid devmode
6074 convert it and link it*/
6076 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6077 if (!convert_devicemode(printer->info_2->printername, devmode,
6078 &printer->info_2->devmode)) {
6079 result = WERR_NOMEM;
6084 /* Do sanity check on the requested changes for Samba */
6086 if (!check_printer_ok(printer->info_2, snum)) {
6087 result = WERR_INVALID_PARAM;
6091 /* FIXME!!! If the driver has changed we really should verify that
6092 it is installed before doing much else --jerry */
6094 /* Check calling user has permission to update printer description */
6096 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6097 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6098 result = WERR_ACCESS_DENIED;
6102 /* Call addprinter hook */
6103 /* Check changes to see if this is really needed */
6105 if ( *lp_addprinter_cmd()
6106 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6107 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6108 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6109 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6111 /* add_printer_hook() will call reload_services() */
6113 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6114 result = WERR_ACCESS_DENIED;
6120 * When a *new* driver is bound to a printer, the drivername is used to
6121 * lookup previously saved driver initialization info, which is then
6122 * bound to the printer, simulating what happens in the Windows arch.
6124 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6126 if (!set_driver_init(printer, 2))
6128 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6129 printer->info_2->drivername));
6132 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6133 printer->info_2->drivername));
6135 notify_printer_driver(snum, printer->info_2->drivername);
6139 * flag which changes actually occured. This is a small subset of
6140 * all the possible changes. We also have to update things in the
6144 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6145 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6146 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6147 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6149 notify_printer_comment(snum, printer->info_2->comment);
6152 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6153 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6154 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6155 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6157 notify_printer_sharename(snum, printer->info_2->sharename);
6160 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6163 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6166 pname = printer->info_2->printername;
6169 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6170 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6171 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6173 notify_printer_printername( snum, pname );
6176 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6177 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6178 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6179 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6181 notify_printer_port(snum, printer->info_2->portname);
6184 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6185 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6186 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6187 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6189 notify_printer_location(snum, printer->info_2->location);
6192 /* here we need to update some more DsSpooler keys */
6193 /* uNCName, serverName, shortServerName */
6195 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6196 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6197 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6198 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6199 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6201 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6202 global_myname(), printer->info_2->sharename );
6203 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6204 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6205 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6207 /* Update printer info */
6208 result = mod_a_printer(printer, 2);
6211 free_a_printer(&printer, 2);
6212 free_a_printer(&old_printer, 2);
6218 /****************************************************************************
6219 ****************************************************************************/
6220 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6221 const SPOOL_PRINTER_INFO_LEVEL *info)
6224 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6226 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6228 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6233 if (!get_printer_snum(p, handle, &snum))
6236 nt_printer_publish(Printer, snum, info7->action);
6240 return WERR_UNKNOWN_LEVEL;
6243 /****************************************************************************
6244 ****************************************************************************/
6246 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6248 POLICY_HND *handle = &q_u->handle;
6249 uint32 level = q_u->level;
6250 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6251 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6252 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6253 uint32 command = q_u->command;
6256 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6259 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6263 /* check the level */
6266 return control_printer(handle, command, p);
6268 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6269 if (!W_ERROR_IS_OK(result))
6272 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6275 return update_printer_sec(handle, level, info, p,
6278 return publish_or_unpublish_printer(p, handle, info);
6280 return WERR_UNKNOWN_LEVEL;
6284 /****************************************************************************
6285 ****************************************************************************/
6287 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6289 POLICY_HND *handle = &q_u->handle;
6290 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6293 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6297 if (Printer->notify.client_connected==True) {
6300 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6302 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6303 !get_printer_snum(p, handle, &snum) )
6306 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6309 Printer->notify.flags=0;
6310 Printer->notify.options=0;
6311 Printer->notify.localmachine[0]='\0';
6312 Printer->notify.printerlocal=0;
6313 if (Printer->notify.option)
6314 free_spool_notify_option(&Printer->notify.option);
6315 Printer->notify.client_connected=False;
6320 /****************************************************************************
6321 ****************************************************************************/
6323 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6325 /* that's an [in out] buffer */
6328 rpcbuf_move(q_u->buffer, &r_u->buffer);
6331 return WERR_INVALID_PARAM; /* this is what a NT server
6332 returns for AddJob. AddJob
6333 must fail on non-local
6337 /****************************************************************************
6338 ****************************************************************************/
6340 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6341 int position, int snum,
6342 NT_PRINTER_INFO_LEVEL *ntprinter)
6346 t=gmtime(&queue->time);
6348 job_info->jobid=queue->job;
6349 init_unistr(&job_info->printername, lp_servicename(snum));
6350 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6351 init_unistr(&job_info->username, queue->fs_user);
6352 init_unistr(&job_info->document, queue->fs_file);
6353 init_unistr(&job_info->datatype, "RAW");
6354 init_unistr(&job_info->text_status, "");
6355 job_info->status=nt_printj_status(queue->status);
6356 job_info->priority=queue->priority;
6357 job_info->position=position;
6358 job_info->totalpages=queue->page_count;
6359 job_info->pagesprinted=0;
6361 make_systemtime(&job_info->submitted, t);
6364 /****************************************************************************
6365 ****************************************************************************/
6367 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6368 int position, int snum,
6369 NT_PRINTER_INFO_LEVEL *ntprinter,
6370 DEVICEMODE *devmode)
6374 t=gmtime(&queue->time);
6376 job_info->jobid=queue->job;
6378 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6380 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6381 init_unistr(&job_info->username, queue->fs_user);
6382 init_unistr(&job_info->document, queue->fs_file);
6383 init_unistr(&job_info->notifyname, queue->fs_user);
6384 init_unistr(&job_info->datatype, "RAW");
6385 init_unistr(&job_info->printprocessor, "winprint");
6386 init_unistr(&job_info->parameters, "");
6387 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6388 init_unistr(&job_info->text_status, "");
6390 /* and here the security descriptor */
6392 job_info->status=nt_printj_status(queue->status);
6393 job_info->priority=queue->priority;
6394 job_info->position=position;
6395 job_info->starttime=0;
6396 job_info->untiltime=0;
6397 job_info->totalpages=queue->page_count;
6398 job_info->size=queue->size;
6399 make_systemtime(&(job_info->submitted), t);
6400 job_info->timeelapsed=0;
6401 job_info->pagesprinted=0;
6403 job_info->devmode = devmode;
6408 /****************************************************************************
6409 Enumjobs at level 1.
6410 ****************************************************************************/
6412 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6413 NT_PRINTER_INFO_LEVEL *ntprinter,
6414 RPC_BUFFER *buffer, uint32 offered,
6415 uint32 *needed, uint32 *returned)
6419 WERROR result = WERR_OK;
6421 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6428 for (i=0; i<*returned; i++)
6429 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6433 /* check the required size. */
6434 for (i=0; i<*returned; i++)
6435 (*needed) += spoolss_size_job_info_1(&info[i]);
6437 if (*needed > offered) {
6438 result = WERR_INSUFFICIENT_BUFFER;
6442 if (!rpcbuf_alloc_size(buffer, *needed)) {
6443 result = WERR_NOMEM;
6447 /* fill the buffer with the structures */
6448 for (i=0; i<*returned; i++)
6449 smb_io_job_info_1("", buffer, &info[i], 0);
6455 if ( !W_ERROR_IS_OK(result) )
6461 /****************************************************************************
6462 Enumjobs at level 2.
6463 ****************************************************************************/
6465 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6466 NT_PRINTER_INFO_LEVEL *ntprinter,
6467 RPC_BUFFER *buffer, uint32 offered,
6468 uint32 *needed, uint32 *returned)
6470 JOB_INFO_2 *info = NULL;
6472 WERROR result = WERR_OK;
6473 DEVICEMODE *devmode = NULL;
6475 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6480 /* this should not be a failure condition if the devmode is NULL */
6482 devmode = construct_dev_mode(snum);
6484 for (i=0; i<*returned; i++)
6485 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6487 free_a_printer(&ntprinter, 2);
6490 /* check the required size. */
6491 for (i=0; i<*returned; i++)
6492 (*needed) += spoolss_size_job_info_2(&info[i]);
6494 if (*needed > offered) {
6495 result = WERR_INSUFFICIENT_BUFFER;
6499 if (!rpcbuf_alloc_size(buffer, *needed)) {
6500 result = WERR_NOMEM;
6504 /* fill the buffer with the structures */
6505 for (i=0; i<*returned; i++)
6506 smb_io_job_info_2("", buffer, &info[i], 0);
6509 free_devmode(devmode);
6512 if ( !W_ERROR_IS_OK(result) )
6519 /****************************************************************************
6521 ****************************************************************************/
6523 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6525 POLICY_HND *handle = &q_u->handle;
6526 uint32 level = q_u->level;
6527 RPC_BUFFER *buffer = NULL;
6528 uint32 offered = q_u->offered;
6529 uint32 *needed = &r_u->needed;
6530 uint32 *returned = &r_u->returned;
6532 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6534 print_status_struct prt_status;
6535 print_queue_struct *queue=NULL;
6537 /* that's an [in out] buffer */
6539 if ( q_u->buffer ) {
6540 rpcbuf_move(q_u->buffer, &r_u->buffer);
6541 buffer = r_u->buffer;
6544 DEBUG(4,("_spoolss_enumjobs\n"));
6549 /* lookup the printer snum and tdb entry */
6551 if (!get_printer_snum(p, handle, &snum))
6554 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6555 if ( !W_ERROR_IS_OK(wret) )
6558 *returned = print_queue_status(snum, &queue, &prt_status);
6559 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6561 if (*returned == 0) {
6568 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6571 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6576 wret = WERR_UNKNOWN_LEVEL;
6579 free_a_printer( &ntprinter, 2 );
6583 /****************************************************************************
6584 ****************************************************************************/
6586 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6591 /****************************************************************************
6592 ****************************************************************************/
6594 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6596 POLICY_HND *handle = &q_u->handle;
6597 uint32 jobid = q_u->jobid;
6598 uint32 command = q_u->command;
6600 struct current_user user;
6602 WERROR errcode = WERR_BADFUNC;
6604 if (!get_printer_snum(p, handle, &snum)) {
6608 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6609 return WERR_INVALID_PRINTER_NAME;
6612 get_current_user(&user, p);
6615 case JOB_CONTROL_CANCEL:
6616 case JOB_CONTROL_DELETE:
6617 if (print_job_delete(&user, snum, jobid, &errcode)) {
6621 case JOB_CONTROL_PAUSE:
6622 if (print_job_pause(&user, snum, jobid, &errcode)) {
6626 case JOB_CONTROL_RESTART:
6627 case JOB_CONTROL_RESUME:
6628 if (print_job_resume(&user, snum, jobid, &errcode)) {
6633 return WERR_UNKNOWN_LEVEL;
6639 /****************************************************************************
6640 Enumerates all printer drivers at level 1.
6641 ****************************************************************************/
6643 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6648 fstring *list = NULL;
6649 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6650 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6651 WERROR result = WERR_OK;
6655 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6657 ndrivers=get_ntdrivers(&list, architecture, version);
6658 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6664 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6665 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6666 SAFE_FREE(driver_info_1);
6670 else driver_info_1 = tdi1;
6673 for (i=0; i<ndrivers; i++) {
6675 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6676 ZERO_STRUCT(driver);
6677 status = get_a_printer_driver(&driver, 3, list[i],
6678 architecture, version);
6679 if (!W_ERROR_IS_OK(status)) {
6683 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6684 free_a_printer_driver(driver, 3);
6687 *returned+=ndrivers;
6691 /* check the required size. */
6692 for (i=0; i<*returned; i++) {
6693 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6694 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6697 if (*needed > offered) {
6698 result = WERR_INSUFFICIENT_BUFFER;
6702 if (!rpcbuf_alloc_size(buffer, *needed)) {
6703 result = WERR_NOMEM;
6707 /* fill the buffer with the driver structures */
6708 for (i=0; i<*returned; i++) {
6709 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6710 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6714 SAFE_FREE(driver_info_1);
6716 if ( !W_ERROR_IS_OK(result) )
6722 /****************************************************************************
6723 Enumerates all printer drivers at level 2.
6724 ****************************************************************************/
6726 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6731 fstring *list = NULL;
6732 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6733 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6734 WERROR result = WERR_OK;
6738 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6740 ndrivers=get_ntdrivers(&list, architecture, version);
6741 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6747 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6748 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6749 SAFE_FREE(driver_info_2);
6753 else driver_info_2 = tdi2;
6756 for (i=0; i<ndrivers; i++) {
6759 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6760 ZERO_STRUCT(driver);
6761 status = get_a_printer_driver(&driver, 3, list[i],
6762 architecture, version);
6763 if (!W_ERROR_IS_OK(status)) {
6767 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6768 free_a_printer_driver(driver, 3);
6771 *returned+=ndrivers;
6775 /* check the required size. */
6776 for (i=0; i<*returned; i++) {
6777 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6778 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6781 if (*needed > offered) {
6782 result = WERR_INSUFFICIENT_BUFFER;
6786 if (!rpcbuf_alloc_size(buffer, *needed)) {
6787 result = WERR_NOMEM;
6791 /* fill the buffer with the form structures */
6792 for (i=0; i<*returned; i++) {
6793 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6794 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6798 SAFE_FREE(driver_info_2);
6800 if ( !W_ERROR_IS_OK(result) )
6806 /****************************************************************************
6807 Enumerates all printer drivers at level 3.
6808 ****************************************************************************/
6810 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6815 fstring *list = NULL;
6816 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6817 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6818 WERROR result = WERR_OK;
6822 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6824 ndrivers=get_ntdrivers(&list, architecture, version);
6825 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6831 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6832 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6833 SAFE_FREE(driver_info_3);
6837 else driver_info_3 = tdi3;
6840 for (i=0; i<ndrivers; i++) {
6843 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6844 ZERO_STRUCT(driver);
6845 status = get_a_printer_driver(&driver, 3, list[i],
6846 architecture, version);
6847 if (!W_ERROR_IS_OK(status)) {
6851 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6852 free_a_printer_driver(driver, 3);
6855 *returned+=ndrivers;
6859 /* check the required size. */
6860 for (i=0; i<*returned; i++) {
6861 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6862 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6865 if (*needed > offered) {
6866 result = WERR_INSUFFICIENT_BUFFER;
6870 if (!rpcbuf_alloc_size(buffer, *needed)) {
6871 result = WERR_NOMEM;
6875 /* fill the buffer with the driver structures */
6876 for (i=0; i<*returned; i++) {
6877 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6878 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6882 for (i=0; i<*returned; i++)
6883 SAFE_FREE(driver_info_3[i].dependentfiles);
6885 SAFE_FREE(driver_info_3);
6887 if ( !W_ERROR_IS_OK(result) )
6893 /****************************************************************************
6894 Enumerates all printer drivers.
6895 ****************************************************************************/
6897 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6899 uint32 level = q_u->level;
6900 RPC_BUFFER *buffer = NULL;
6901 uint32 offered = q_u->offered;
6902 uint32 *needed = &r_u->needed;
6903 uint32 *returned = &r_u->returned;
6906 fstring architecture;
6908 /* that's an [in out] buffer */
6910 if ( q_u->buffer ) {
6911 rpcbuf_move(q_u->buffer, &r_u->buffer);
6912 buffer = r_u->buffer;
6915 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6920 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
6921 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
6923 if ( !is_myname_or_ipaddr( servername ) )
6924 return WERR_UNKNOWN_PRINTER_DRIVER;
6928 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
6930 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
6932 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
6934 return WERR_UNKNOWN_LEVEL;
6938 /****************************************************************************
6939 ****************************************************************************/
6941 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
6943 form->flag=list->flag;
6944 init_unistr(&form->name, list->name);
6945 form->width=list->width;
6946 form->length=list->length;
6947 form->left=list->left;
6948 form->top=list->top;
6949 form->right=list->right;
6950 form->bottom=list->bottom;
6953 /****************************************************************************
6954 ****************************************************************************/
6956 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
6958 uint32 level = q_u->level;
6959 RPC_BUFFER *buffer = NULL;
6960 uint32 offered = q_u->offered;
6961 uint32 *needed = &r_u->needed;
6962 uint32 *numofforms = &r_u->numofforms;
6963 uint32 numbuiltinforms;
6965 nt_forms_struct *list=NULL;
6966 nt_forms_struct *builtinlist=NULL;
6971 /* that's an [in out] buffer */
6973 if ( q_u->buffer ) {
6974 rpcbuf_move(q_u->buffer, &r_u->buffer);
6975 buffer = r_u->buffer;
6978 DEBUG(4,("_spoolss_enumforms\n"));
6979 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
6980 DEBUGADD(5,("Info level [%d]\n", level));
6982 numbuiltinforms = get_builtin_ntforms(&builtinlist);
6983 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
6984 *numofforms = get_ntforms(&list);
6985 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
6986 *numofforms += numbuiltinforms;
6988 if (*numofforms == 0)
6989 return WERR_NO_MORE_ITEMS;
6993 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
6998 /* construct the list of form structures */
6999 for (i=0; i<numbuiltinforms; i++) {
7000 DEBUGADD(6,("Filling form number [%d]\n",i));
7001 fill_form_1(&forms_1[i], &builtinlist[i]);
7004 SAFE_FREE(builtinlist);
7006 for (; i<*numofforms; i++) {
7007 DEBUGADD(6,("Filling form number [%d]\n",i));
7008 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7013 /* check the required size. */
7014 for (i=0; i<numbuiltinforms; i++) {
7015 DEBUGADD(6,("adding form [%d]'s size\n",i));
7016 buffer_size += spoolss_size_form_1(&forms_1[i]);
7018 for (; i<*numofforms; i++) {
7019 DEBUGADD(6,("adding form [%d]'s size\n",i));
7020 buffer_size += spoolss_size_form_1(&forms_1[i]);
7023 *needed=buffer_size;
7025 if (*needed > offered) {
7028 return WERR_INSUFFICIENT_BUFFER;
7031 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7037 /* fill the buffer with the form structures */
7038 for (i=0; i<numbuiltinforms; i++) {
7039 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7040 smb_io_form_1("", buffer, &forms_1[i], 0);
7042 for (; i<*numofforms; i++) {
7043 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7044 smb_io_form_1("", buffer, &forms_1[i], 0);
7053 SAFE_FREE(builtinlist);
7054 return WERR_UNKNOWN_LEVEL;
7059 /****************************************************************************
7060 ****************************************************************************/
7062 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7064 uint32 level = q_u->level;
7065 UNISTR2 *uni_formname = &q_u->formname;
7066 RPC_BUFFER *buffer = NULL;
7067 uint32 offered = q_u->offered;
7068 uint32 *needed = &r_u->needed;
7070 nt_forms_struct *list=NULL;
7071 nt_forms_struct builtin_form;
7076 int numofforms=0, i=0;
7078 /* that's an [in out] buffer */
7080 if ( q_u->buffer ) {
7081 rpcbuf_move(q_u->buffer, &r_u->buffer);
7082 buffer = r_u->buffer;
7085 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7087 DEBUG(4,("_spoolss_getform\n"));
7088 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7089 DEBUGADD(5,("Info level [%d]\n", level));
7091 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7092 if (!foundBuiltin) {
7093 numofforms = get_ntforms(&list);
7094 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7096 if (numofforms == 0)
7103 fill_form_1(&form_1, &builtin_form);
7106 /* Check if the requested name is in the list of form structures */
7107 for (i=0; i<numofforms; i++) {
7109 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7111 if (strequal(form_name, list[i].name)) {
7112 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7113 fill_form_1(&form_1, &list[i]);
7119 if (i == numofforms) {
7123 /* check the required size. */
7125 *needed=spoolss_size_form_1(&form_1);
7127 if (*needed > offered)
7128 return WERR_INSUFFICIENT_BUFFER;
7130 if (!rpcbuf_alloc_size(buffer, buffer_size))
7133 /* fill the buffer with the form structures */
7134 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7135 smb_io_form_1("", buffer, &form_1, 0);
7141 return WERR_UNKNOWN_LEVEL;
7145 /****************************************************************************
7146 ****************************************************************************/
7148 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7150 init_unistr(&port->port_name, name);
7153 /****************************************************************************
7154 ****************************************************************************/
7156 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7158 init_unistr(&port->port_name, name);
7159 init_unistr(&port->monitor_name, "Local Monitor");
7160 init_unistr(&port->description, "Local Port");
7161 port->port_type=PORT_TYPE_WRITE;
7166 /****************************************************************************
7167 wrapper around the enumer ports command
7168 ****************************************************************************/
7170 WERROR enumports_hook( int *count, char ***lines )
7172 char *cmd = lp_enumports_cmd();
7180 /* if no hook then just fill in the default port */
7183 qlines = SMB_MALLOC_ARRAY( char*, 2 );
7184 qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME );
7189 /* we have a valid enumport command */
7191 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7193 DEBUG(10,("Running [%s]\n", command));
7194 ret = smbrun(command, &fd);
7195 DEBUG(10,("Returned [%d]\n", ret));
7200 return WERR_ACCESS_DENIED;
7204 qlines = fd_lines_load(fd, &numlines, 0);
7205 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7215 /****************************************************************************
7217 ****************************************************************************/
7219 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7221 PORT_INFO_1 *ports=NULL;
7223 WERROR result = WERR_OK;
7227 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7231 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7232 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7233 dos_errstr(WERR_NOMEM)));
7234 file_lines_free(qlines);
7238 for (i=0; i<numlines; i++) {
7239 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7240 fill_port_1(&ports[i], qlines[i]);
7243 file_lines_free(qlines);
7246 *returned = numlines;
7248 /* check the required size. */
7249 for (i=0; i<*returned; i++) {
7250 DEBUGADD(6,("adding port [%d]'s size\n", i));
7251 *needed += spoolss_size_port_info_1(&ports[i]);
7254 if (*needed > offered) {
7255 result = WERR_INSUFFICIENT_BUFFER;
7259 if (!rpcbuf_alloc_size(buffer, *needed)) {
7260 result = WERR_NOMEM;
7264 /* fill the buffer with the ports structures */
7265 for (i=0; i<*returned; i++) {
7266 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7267 smb_io_port_1("", buffer, &ports[i], 0);
7273 if ( !W_ERROR_IS_OK(result) )
7279 /****************************************************************************
7281 ****************************************************************************/
7283 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7285 PORT_INFO_2 *ports=NULL;
7287 WERROR result = WERR_OK;
7291 if ( !W_ERROR_IS_OK(result = enumports_hook( &numlines, &qlines )) )
7296 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7297 file_lines_free(qlines);
7301 for (i=0; i<numlines; i++) {
7302 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7303 fill_port_2(&(ports[i]), qlines[i]);
7306 file_lines_free(qlines);
7309 *returned = numlines;
7311 /* check the required size. */
7312 for (i=0; i<*returned; i++) {
7313 DEBUGADD(6,("adding port [%d]'s size\n", i));
7314 *needed += spoolss_size_port_info_2(&ports[i]);
7317 if (*needed > offered) {
7318 result = WERR_INSUFFICIENT_BUFFER;
7322 if (!rpcbuf_alloc_size(buffer, *needed)) {
7323 result = WERR_NOMEM;
7327 /* fill the buffer with the ports structures */
7328 for (i=0; i<*returned; i++) {
7329 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7330 smb_io_port_2("", buffer, &ports[i], 0);
7336 if ( !W_ERROR_IS_OK(result) )
7342 /****************************************************************************
7344 ****************************************************************************/
7346 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7348 uint32 level = q_u->level;
7349 RPC_BUFFER *buffer = NULL;
7350 uint32 offered = q_u->offered;
7351 uint32 *needed = &r_u->needed;
7352 uint32 *returned = &r_u->returned;
7354 /* that's an [in out] buffer */
7356 if ( q_u->buffer ) {
7357 rpcbuf_move(q_u->buffer, &r_u->buffer);
7358 buffer = r_u->buffer;
7361 DEBUG(4,("_spoolss_enumports\n"));
7368 return enumports_level_1(buffer, offered, needed, returned);
7370 return enumports_level_2(buffer, offered, needed, returned);
7372 return WERR_UNKNOWN_LEVEL;
7376 /****************************************************************************
7377 ****************************************************************************/
7379 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7380 const SPOOL_PRINTER_INFO_LEVEL *info,
7381 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7382 uint32 user_switch, const SPOOL_USER_CTR *user,
7385 NT_PRINTER_INFO_LEVEL *printer = NULL;
7388 WERROR err = WERR_OK;
7390 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7391 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7395 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7396 if (!convert_printer_info(info, printer, 2)) {
7397 free_a_printer(&printer, 2);
7401 /* check to see if the printer already exists */
7403 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7404 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7405 printer->info_2->sharename));
7406 free_a_printer(&printer, 2);
7407 return WERR_PRINTER_ALREADY_EXISTS;
7410 /* FIXME!!! smbd should check to see if the driver is installed before
7411 trying to add a printer like this --jerry */
7413 if (*lp_addprinter_cmd() ) {
7414 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7415 free_a_printer(&printer,2);
7416 return WERR_ACCESS_DENIED;
7419 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7420 "smb.conf parameter \"addprinter command\" is defined. This"
7421 "parameter must exist for this call to succeed\n",
7422 printer->info_2->sharename ));
7425 /* use our primary netbios name since get_a_printer() will convert
7426 it to what the client expects on a case by case basis */
7428 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7429 printer->info_2->sharename);
7432 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7433 free_a_printer(&printer,2);
7434 return WERR_ACCESS_DENIED;
7437 /* you must be a printer admin to add a new printer */
7438 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7439 free_a_printer(&printer,2);
7440 return WERR_ACCESS_DENIED;
7444 * Do sanity check on the requested changes for Samba.
7447 if (!check_printer_ok(printer->info_2, snum)) {
7448 free_a_printer(&printer,2);
7449 return WERR_INVALID_PARAM;
7453 * When a printer is created, the drivername bound to the printer is used
7454 * to lookup previously saved driver initialization info, which is then
7455 * bound to the new printer, simulating what happens in the Windows arch.
7460 set_driver_init(printer, 2);
7464 /* A valid devmode was included, convert and link it
7466 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7468 if (!convert_devicemode(printer->info_2->printername, devmode,
7469 &printer->info_2->devmode))
7473 /* write the ASCII on disk */
7474 err = mod_a_printer(printer, 2);
7475 if (!W_ERROR_IS_OK(err)) {
7476 free_a_printer(&printer,2);
7480 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7481 /* Handle open failed - remove addition. */
7482 del_a_printer(printer->info_2->sharename);
7483 free_a_printer(&printer,2);
7484 return WERR_ACCESS_DENIED;
7487 update_c_setprinter(False);
7488 free_a_printer(&printer,2);
7493 /****************************************************************************
7494 ****************************************************************************/
7496 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7498 UNISTR2 *uni_srv_name = q_u->server_name;
7499 uint32 level = q_u->level;
7500 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7501 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7502 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7503 uint32 user_switch = q_u->user_switch;
7504 SPOOL_USER_CTR *user = &q_u->user_ctr;
7505 POLICY_HND *handle = &r_u->handle;
7509 /* we don't handle yet */
7510 /* but I know what to do ... */
7511 return WERR_UNKNOWN_LEVEL;
7513 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7515 user_switch, user, handle);
7517 return WERR_UNKNOWN_LEVEL;
7521 /****************************************************************************
7522 ****************************************************************************/
7524 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7526 uint32 level = q_u->level;
7527 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7528 WERROR err = WERR_OK;
7529 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7530 struct current_user user;
7531 fstring driver_name;
7534 ZERO_STRUCT(driver);
7536 get_current_user(&user, p);
7538 if (!convert_printer_driver_info(info, &driver, level)) {
7543 DEBUG(5,("Cleaning driver's information\n"));
7544 err = clean_up_driver_struct(driver, level, &user);
7545 if (!W_ERROR_IS_OK(err))
7548 DEBUG(5,("Moving driver to final destination\n"));
7549 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &user, &err)) ) {
7553 if (add_a_printer_driver(driver, level)!=0) {
7554 err = WERR_ACCESS_DENIED;
7558 /* BEGIN_ADMIN_LOG */
7561 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7562 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7563 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.ut.uid));
7566 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7567 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7568 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.ut.uid));
7574 * I think this is where he DrvUpgradePrinter() hook would be
7575 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7576 * server. Right now, we just need to send ourselves a message
7577 * to update each printer bound to this driver. --jerry
7580 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7581 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7586 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7587 * decide if the driver init data should be deleted. The rules are:
7588 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7589 * 2) delete init data only if there is no 2k/Xp driver
7590 * 3) always delete init data
7591 * The generalized rule is always use init data from the highest order driver.
7592 * It is necessary to follow the driver install by an initialization step to
7593 * finish off this process.
7596 version = driver.info_3->cversion;
7597 else if (level == 6)
7598 version = driver.info_6->version;
7603 * 9x printer driver - never delete init data
7606 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7611 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7612 * there is no 2k/Xp driver init data for this driver name.
7616 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7618 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7620 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7622 if (!del_driver_init(driver_name))
7623 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7626 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7628 free_a_printer_driver(driver1,3);
7629 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7636 * 2k or Xp printer driver - always delete init data
7639 if (!del_driver_init(driver_name))
7640 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7644 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7650 free_a_printer_driver(driver, level);
7654 /********************************************************************
7655 * spoolss_addprinterdriverex
7656 ********************************************************************/
7658 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7660 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7661 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7664 * we only support the semantics of AddPrinterDriver()
7665 * i.e. only copy files that are newer than existing ones
7668 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7669 return WERR_ACCESS_DENIED;
7671 ZERO_STRUCT(q_u_local);
7672 ZERO_STRUCT(r_u_local);
7674 /* just pass the information off to _spoolss_addprinterdriver() */
7675 q_u_local.server_name_ptr = q_u->server_name_ptr;
7676 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7677 q_u_local.level = q_u->level;
7678 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7680 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7683 /****************************************************************************
7684 ****************************************************************************/
7686 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7688 init_unistr(&info->name, name);
7691 /****************************************************************************
7692 ****************************************************************************/
7694 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7700 const char *short_archi;
7701 DRIVER_DIRECTORY_1 *info=NULL;
7702 WERROR result = WERR_OK;
7704 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7705 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7707 /* check for beginning double '\'s and that the server
7710 pservername = servername;
7711 if ( *pservername == '\\' && strlen(servername)>2 ) {
7715 if ( !is_myname_or_ipaddr( pservername ) )
7716 return WERR_INVALID_PARAM;
7718 if (!(short_archi = get_short_archi(long_archi)))
7719 return WERR_INVALID_ENVIRONMENT;
7721 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7724 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7726 DEBUG(4,("printer driver directory: [%s]\n", path));
7728 fill_driverdir_1(info, path);
7730 *needed += spoolss_size_driverdir_info_1(info);
7732 if (*needed > offered) {
7733 result = WERR_INSUFFICIENT_BUFFER;
7737 if (!rpcbuf_alloc_size(buffer, *needed)) {
7738 result = WERR_NOMEM;
7742 smb_io_driverdir_1("", buffer, info, 0);
7750 /****************************************************************************
7751 ****************************************************************************/
7753 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7755 UNISTR2 *name = &q_u->name;
7756 UNISTR2 *uni_environment = &q_u->environment;
7757 uint32 level = q_u->level;
7758 RPC_BUFFER *buffer = NULL;
7759 uint32 offered = q_u->offered;
7760 uint32 *needed = &r_u->needed;
7762 /* that's an [in out] buffer */
7764 if ( q_u->buffer ) {
7765 rpcbuf_move(q_u->buffer, &r_u->buffer);
7766 buffer = r_u->buffer;
7769 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7775 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7777 return WERR_UNKNOWN_LEVEL;
7781 /****************************************************************************
7782 ****************************************************************************/
7784 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7786 POLICY_HND *handle = &q_u->handle;
7787 uint32 idx = q_u->index;
7788 uint32 in_value_len = q_u->valuesize;
7789 uint32 in_data_len = q_u->datasize;
7790 uint32 *out_max_value_len = &r_u->valuesize;
7791 uint16 **out_value = &r_u->value;
7792 uint32 *out_value_len = &r_u->realvaluesize;
7793 uint32 *out_type = &r_u->type;
7794 uint32 *out_max_data_len = &r_u->datasize;
7795 uint8 **data_out = &r_u->data;
7796 uint32 *out_data_len = &r_u->realdatasize;
7798 NT_PRINTER_INFO_LEVEL *printer = NULL;
7800 uint32 biggest_valuesize;
7801 uint32 biggest_datasize;
7803 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7806 REGISTRY_VALUE *val = NULL;
7807 NT_PRINTER_DATA *p_data;
7808 int i, key_index, num_values;
7813 *out_max_data_len = 0;
7817 DEBUG(5,("spoolss_enumprinterdata\n"));
7820 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7824 if (!get_printer_snum(p,handle, &snum))
7827 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7828 if (!W_ERROR_IS_OK(result))
7831 p_data = printer->info_2->data;
7832 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7837 * The NT machine wants to know the biggest size of value and data
7839 * cf: MSDN EnumPrinterData remark section
7842 if ( !in_value_len && !in_data_len && (key_index != -1) )
7844 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7846 biggest_valuesize = 0;
7847 biggest_datasize = 0;
7849 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
7851 for ( i=0; i<num_values; i++ )
7853 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
7855 name_length = strlen(val->valuename);
7856 if ( strlen(val->valuename) > biggest_valuesize )
7857 biggest_valuesize = name_length;
7859 if ( val->size > biggest_datasize )
7860 biggest_datasize = val->size;
7862 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7866 /* the value is an UNICODE string but real_value_size is the length
7867 in bytes including the trailing 0 */
7869 *out_value_len = 2 * (1+biggest_valuesize);
7870 *out_data_len = biggest_datasize;
7872 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7878 * the value len is wrong in NT sp3
7879 * that's the number of bytes not the number of unicode chars
7882 if ( key_index != -1 )
7883 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
7888 /* out_value should default to "" or else NT4 has
7889 problems unmarshalling the response */
7891 *out_max_value_len=(in_value_len/sizeof(uint16));
7893 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7895 result = WERR_NOMEM;
7899 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
7901 /* the data is counted in bytes */
7903 *out_max_data_len = in_data_len;
7904 *out_data_len = in_data_len;
7906 /* only allocate when given a non-zero data_len */
7908 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
7910 result = WERR_NOMEM;
7914 result = WERR_NO_MORE_ITEMS;
7920 * - counted in bytes in the request
7921 * - counted in UNICODE chars in the max reply
7922 * - counted in bytes in the real size
7924 * take a pause *before* coding not *during* coding
7928 *out_max_value_len=(in_value_len/sizeof(uint16));
7929 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
7931 result = WERR_NOMEM;
7935 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
7939 *out_type = regval_type( val );
7941 /* data - counted in bytes */
7943 *out_max_data_len = in_data_len;
7944 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
7946 result = WERR_NOMEM;
7949 data_len = regval_size(val);
7951 memcpy( *data_out, regval_data_p(val), data_len );
7952 *out_data_len = data_len;
7956 free_a_printer(&printer, 2);
7960 /****************************************************************************
7961 ****************************************************************************/
7963 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
7965 POLICY_HND *handle = &q_u->handle;
7966 UNISTR2 *value = &q_u->value;
7967 uint32 type = q_u->type;
7968 uint8 *data = q_u->data;
7969 uint32 real_len = q_u->real_len;
7971 NT_PRINTER_INFO_LEVEL *printer = NULL;
7973 WERROR status = WERR_OK;
7974 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
7977 DEBUG(5,("spoolss_setprinterdata\n"));
7980 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7984 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
7985 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7986 return WERR_INVALID_PARAM;
7989 if (!get_printer_snum(p,handle, &snum))
7993 * Access check : NT returns "access denied" if you make a
7994 * SetPrinterData call without the necessary privildge.
7995 * we were originally returning OK if nothing changed
7996 * which made Win2k issue **a lot** of SetPrinterData
7997 * when connecting to a printer --jerry
8000 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8002 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8003 status = WERR_ACCESS_DENIED;
8007 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8008 if (!W_ERROR_IS_OK(status))
8011 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8014 * When client side code sets a magic printer data key, detect it and save
8015 * the current printer data and the magic key's data (its the DEVMODE) for
8016 * future printer/driver initializations.
8018 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8020 /* Set devmode and printer initialization info */
8021 status = save_driver_init( printer, 2, data, real_len );
8023 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8027 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8028 type, data, real_len );
8029 if ( W_ERROR_IS_OK(status) )
8030 status = mod_a_printer(printer, 2);
8034 free_a_printer(&printer, 2);
8039 /****************************************************************************
8040 ****************************************************************************/
8042 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8044 POLICY_HND *handle = &q_u->handle;
8045 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8048 DEBUG(5,("_spoolss_resetprinter\n"));
8051 * All we do is to check to see if the handle and queue is valid.
8052 * This call really doesn't mean anything to us because we only
8053 * support RAW printing. --jerry
8057 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8061 if (!get_printer_snum(p,handle, &snum))
8065 /* blindly return success */
8070 /****************************************************************************
8071 ****************************************************************************/
8073 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8075 POLICY_HND *handle = &q_u->handle;
8076 UNISTR2 *value = &q_u->valuename;
8078 NT_PRINTER_INFO_LEVEL *printer = NULL;
8080 WERROR status = WERR_OK;
8081 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8084 DEBUG(5,("spoolss_deleteprinterdata\n"));
8087 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8091 if (!get_printer_snum(p, handle, &snum))
8094 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8095 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8096 return WERR_ACCESS_DENIED;
8099 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8100 if (!W_ERROR_IS_OK(status))
8103 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8105 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8107 if ( W_ERROR_IS_OK(status) )
8108 mod_a_printer( printer, 2 );
8110 free_a_printer(&printer, 2);
8115 /****************************************************************************
8116 ****************************************************************************/
8118 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8120 POLICY_HND *handle = &q_u->handle;
8121 FORM *form = &q_u->form;
8122 nt_forms_struct tmpForm;
8124 WERROR status = WERR_OK;
8125 NT_PRINTER_INFO_LEVEL *printer = NULL;
8128 nt_forms_struct *list=NULL;
8129 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8131 DEBUG(5,("spoolss_addform\n"));
8134 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8139 /* forms can be added on printer of on the print server handle */
8141 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8143 if (!get_printer_snum(p,handle, &snum))
8146 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8147 if (!W_ERROR_IS_OK(status))
8151 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8152 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8153 status = WERR_ACCESS_DENIED;
8157 /* can't add if builtin */
8159 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8160 status = WERR_ALREADY_EXISTS;
8164 count = get_ntforms(&list);
8166 if(!add_a_form(&list, form, &count)) {
8167 status = WERR_NOMEM;
8171 write_ntforms(&list, count);
8174 * ChangeID must always be set if this is a printer
8177 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8178 status = mod_a_printer(printer, 2);
8182 free_a_printer(&printer, 2);
8188 /****************************************************************************
8189 ****************************************************************************/
8191 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8193 POLICY_HND *handle = &q_u->handle;
8194 UNISTR2 *form_name = &q_u->name;
8195 nt_forms_struct tmpForm;
8197 nt_forms_struct *list=NULL;
8198 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8200 WERROR status = WERR_OK;
8201 NT_PRINTER_INFO_LEVEL *printer = NULL;
8203 DEBUG(5,("spoolss_deleteform\n"));
8206 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8210 /* forms can be deleted on printer of on the print server handle */
8212 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8214 if (!get_printer_snum(p,handle, &snum))
8217 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8218 if (!W_ERROR_IS_OK(status))
8222 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8223 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8224 status = WERR_ACCESS_DENIED;
8228 /* can't delete if builtin */
8230 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8231 status = WERR_INVALID_PARAM;
8235 count = get_ntforms(&list);
8237 if ( !delete_a_form(&list, form_name, &count, &status ))
8241 * ChangeID must always be set if this is a printer
8244 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8245 status = mod_a_printer(printer, 2);
8249 free_a_printer(&printer, 2);
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8260 POLICY_HND *handle = &q_u->handle;
8261 FORM *form = &q_u->form;
8262 nt_forms_struct tmpForm;
8264 WERROR status = WERR_OK;
8265 NT_PRINTER_INFO_LEVEL *printer = NULL;
8268 nt_forms_struct *list=NULL;
8269 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8271 DEBUG(5,("spoolss_setform\n"));
8274 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8278 /* forms can be modified on printer of on the print server handle */
8280 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8282 if (!get_printer_snum(p,handle, &snum))
8285 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8286 if (!W_ERROR_IS_OK(status))
8290 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8291 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8292 status = WERR_ACCESS_DENIED;
8296 /* can't set if builtin */
8297 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8298 status = WERR_INVALID_PARAM;
8302 count = get_ntforms(&list);
8303 update_a_form(&list, form, count);
8304 write_ntforms(&list, count);
8307 * ChangeID must always be set if this is a printer
8310 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8311 status = mod_a_printer(printer, 2);
8316 free_a_printer(&printer, 2);
8322 /****************************************************************************
8323 enumprintprocessors level 1.
8324 ****************************************************************************/
8326 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8328 PRINTPROCESSOR_1 *info_1=NULL;
8329 WERROR result = WERR_OK;
8331 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8336 init_unistr(&info_1->name, "winprint");
8338 *needed += spoolss_size_printprocessor_info_1(info_1);
8340 if (*needed > offered) {
8341 result = WERR_INSUFFICIENT_BUFFER;
8345 if (!rpcbuf_alloc_size(buffer, *needed)) {
8346 result = WERR_NOMEM;
8350 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8355 if ( !W_ERROR_IS_OK(result) )
8361 /****************************************************************************
8362 ****************************************************************************/
8364 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8366 uint32 level = q_u->level;
8367 RPC_BUFFER *buffer = NULL;
8368 uint32 offered = q_u->offered;
8369 uint32 *needed = &r_u->needed;
8370 uint32 *returned = &r_u->returned;
8372 /* that's an [in out] buffer */
8374 if ( q_u->buffer ) {
8375 rpcbuf_move(q_u->buffer, &r_u->buffer);
8376 buffer = r_u->buffer;
8379 DEBUG(5,("spoolss_enumprintprocessors\n"));
8382 * Enumerate the print processors ...
8384 * Just reply with "winprint", to keep NT happy
8385 * and I can use my nice printer checker.
8393 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8395 return WERR_UNKNOWN_LEVEL;
8399 /****************************************************************************
8400 enumprintprocdatatypes level 1.
8401 ****************************************************************************/
8403 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8405 PRINTPROCDATATYPE_1 *info_1=NULL;
8406 WERROR result = WERR_NOMEM;
8408 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8413 init_unistr(&info_1->name, "RAW");
8415 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8417 if (*needed > offered) {
8418 result = WERR_INSUFFICIENT_BUFFER;
8422 if (!rpcbuf_alloc_size(buffer, *needed)) {
8423 result = WERR_NOMEM;
8427 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8432 if ( !W_ERROR_IS_OK(result) )
8438 /****************************************************************************
8439 ****************************************************************************/
8441 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8443 uint32 level = q_u->level;
8444 RPC_BUFFER *buffer = NULL;
8445 uint32 offered = q_u->offered;
8446 uint32 *needed = &r_u->needed;
8447 uint32 *returned = &r_u->returned;
8449 /* that's an [in out] buffer */
8451 if ( q_u->buffer ) {
8452 rpcbuf_move(q_u->buffer, &r_u->buffer);
8453 buffer = r_u->buffer;
8456 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8463 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8465 return WERR_UNKNOWN_LEVEL;
8469 /****************************************************************************
8470 enumprintmonitors level 1.
8471 ****************************************************************************/
8473 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8475 PRINTMONITOR_1 *info_1=NULL;
8476 WERROR result = WERR_OK;
8478 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8483 init_unistr(&info_1->name, "Local Port");
8485 *needed += spoolss_size_printmonitor_info_1(info_1);
8487 if (*needed > offered) {
8488 result = WERR_INSUFFICIENT_BUFFER;
8492 if (!rpcbuf_alloc_size(buffer, *needed)) {
8493 result = WERR_NOMEM;
8497 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8502 if ( !W_ERROR_IS_OK(result) )
8508 /****************************************************************************
8509 enumprintmonitors level 2.
8510 ****************************************************************************/
8512 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8514 PRINTMONITOR_2 *info_2=NULL;
8515 WERROR result = WERR_OK;
8517 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8522 init_unistr(&info_2->name, "Local Port");
8523 init_unistr(&info_2->environment, "Windows NT X86");
8524 init_unistr(&info_2->dll_name, "localmon.dll");
8526 *needed += spoolss_size_printmonitor_info_2(info_2);
8528 if (*needed > offered) {
8529 result = WERR_INSUFFICIENT_BUFFER;
8533 if (!rpcbuf_alloc_size(buffer, *needed)) {
8534 result = WERR_NOMEM;
8538 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8543 if ( !W_ERROR_IS_OK(result) )
8549 /****************************************************************************
8550 ****************************************************************************/
8552 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8554 uint32 level = q_u->level;
8555 RPC_BUFFER *buffer = NULL;
8556 uint32 offered = q_u->offered;
8557 uint32 *needed = &r_u->needed;
8558 uint32 *returned = &r_u->returned;
8560 /* that's an [in out] buffer */
8562 if ( q_u->buffer ) {
8563 rpcbuf_move(q_u->buffer, &r_u->buffer);
8564 buffer = r_u->buffer;
8567 DEBUG(5,("spoolss_enumprintmonitors\n"));
8570 * Enumerate the print monitors ...
8572 * Just reply with "Local Port", to keep NT happy
8573 * and I can use my nice printer checker.
8581 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8583 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8585 return WERR_UNKNOWN_LEVEL;
8589 /****************************************************************************
8590 ****************************************************************************/
8592 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8593 NT_PRINTER_INFO_LEVEL *ntprinter,
8594 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8599 JOB_INFO_1 *info_1=NULL;
8600 WERROR result = WERR_OK;
8602 info_1=SMB_MALLOC_P(JOB_INFO_1);
8604 if (info_1 == NULL) {
8608 for (i=0; i<count && found==False; i++) {
8609 if ((*queue)[i].job==(int)jobid)
8615 /* NT treats not found as bad param... yet another bad choice */
8616 return WERR_INVALID_PARAM;
8619 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8621 *needed += spoolss_size_job_info_1(info_1);
8623 if (*needed > offered) {
8624 result = WERR_INSUFFICIENT_BUFFER;
8628 if (!rpcbuf_alloc_size(buffer, *needed)) {
8629 result = WERR_NOMEM;
8633 smb_io_job_info_1("", buffer, info_1, 0);
8641 /****************************************************************************
8642 ****************************************************************************/
8644 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8645 NT_PRINTER_INFO_LEVEL *ntprinter,
8646 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8653 DEVICEMODE *devmode = NULL;
8654 NT_DEVICEMODE *nt_devmode = NULL;
8656 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8659 ZERO_STRUCTP(info_2);
8661 for ( i=0; i<count && found==False; i++ )
8663 if ((*queue)[i].job == (int)jobid)
8668 /* NT treats not found as bad param... yet another bad
8670 result = WERR_INVALID_PARAM;
8675 * if the print job does not have a DEVMODE associated with it,
8676 * just use the one for the printer. A NULL devicemode is not
8677 * a failure condition
8680 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8681 devmode = construct_dev_mode(snum);
8683 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8684 ZERO_STRUCTP( devmode );
8685 convert_nt_devicemode( devmode, nt_devmode );
8689 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8691 *needed += spoolss_size_job_info_2(info_2);
8693 if (*needed > offered) {
8694 result = WERR_INSUFFICIENT_BUFFER;
8698 if (!rpcbuf_alloc_size(buffer, *needed)) {
8699 result = WERR_NOMEM;
8703 smb_io_job_info_2("", buffer, info_2, 0);
8708 /* Cleanup allocated memory */
8710 free_job_info_2(info_2); /* Also frees devmode */
8716 /****************************************************************************
8717 ****************************************************************************/
8719 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8721 POLICY_HND *handle = &q_u->handle;
8722 uint32 jobid = q_u->jobid;
8723 uint32 level = q_u->level;
8724 RPC_BUFFER *buffer = NULL;
8725 uint32 offered = q_u->offered;
8726 uint32 *needed = &r_u->needed;
8727 WERROR wstatus = WERR_OK;
8728 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8731 print_queue_struct *queue = NULL;
8732 print_status_struct prt_status;
8734 /* that's an [in out] buffer */
8736 if ( q_u->buffer ) {
8737 rpcbuf_move(q_u->buffer, &r_u->buffer);
8738 buffer = r_u->buffer;
8741 DEBUG(5,("spoolss_getjob\n"));
8745 if (!get_printer_snum(p, handle, &snum))
8748 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8749 if ( !W_ERROR_IS_OK(wstatus) )
8752 count = print_queue_status(snum, &queue, &prt_status);
8754 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8755 count, prt_status.status, prt_status.message));
8759 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8760 buffer, offered, needed);
8763 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8764 buffer, offered, needed);
8767 wstatus = WERR_UNKNOWN_LEVEL;
8772 free_a_printer( &ntprinter, 2 );
8777 /********************************************************************
8778 spoolss_getprinterdataex
8780 From MSDN documentation of GetPrinterDataEx: pass request
8781 to GetPrinterData if key is "PrinterDriverData".
8782 ********************************************************************/
8784 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8786 POLICY_HND *handle = &q_u->handle;
8787 uint32 in_size = q_u->size;
8788 uint32 *type = &r_u->type;
8789 uint32 *out_size = &r_u->size;
8790 uint8 **data = &r_u->data;
8791 uint32 *needed = &r_u->needed;
8792 fstring keyname, valuename;
8794 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8796 NT_PRINTER_INFO_LEVEL *printer = NULL;
8798 WERROR status = WERR_OK;
8800 DEBUG(4,("_spoolss_getprinterdataex\n"));
8802 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8803 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8805 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8806 keyname, valuename));
8808 /* in case of problem, return some default values */
8812 *out_size = in_size;
8815 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8816 status = WERR_BADFID;
8820 /* Is the handle to a printer or to the server? */
8822 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8823 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8824 status = WERR_INVALID_PARAM;
8828 if ( !get_printer_snum(p,handle, &snum) )
8831 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8832 if ( !W_ERROR_IS_OK(status) )
8835 /* check to see if the keyname is valid */
8836 if ( !strlen(keyname) ) {
8837 status = WERR_INVALID_PARAM;
8841 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
8842 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8843 free_a_printer( &printer, 2 );
8844 status = WERR_BADFILE;
8848 /* When given a new keyname, we should just create it */
8850 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8852 if (*needed > *out_size)
8853 status = WERR_MORE_DATA;
8856 if ( !W_ERROR_IS_OK(status) )
8858 DEBUG(5, ("error: allocating %d\n", *out_size));
8860 /* reply this param doesn't exist */
8864 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8865 status = WERR_NOMEM;
8875 free_a_printer( &printer, 2 );
8880 /********************************************************************
8881 * spoolss_setprinterdataex
8882 ********************************************************************/
8884 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8886 POLICY_HND *handle = &q_u->handle;
8887 uint32 type = q_u->type;
8888 uint8 *data = q_u->data;
8889 uint32 real_len = q_u->real_len;
8891 NT_PRINTER_INFO_LEVEL *printer = NULL;
8893 WERROR status = WERR_OK;
8894 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8899 DEBUG(4,("_spoolss_setprinterdataex\n"));
8901 /* From MSDN documentation of SetPrinterDataEx: pass request to
8902 SetPrinterData if key is "PrinterDriverData" */
8905 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8909 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8910 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8911 return WERR_INVALID_PARAM;
8914 if ( !get_printer_snum(p,handle, &snum) )
8918 * Access check : NT returns "access denied" if you make a
8919 * SetPrinterData call without the necessary privildge.
8920 * we were originally returning OK if nothing changed
8921 * which made Win2k issue **a lot** of SetPrinterData
8922 * when connecting to a printer --jerry
8925 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8927 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8928 return WERR_ACCESS_DENIED;
8931 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8932 if (!W_ERROR_IS_OK(status))
8935 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
8936 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
8938 /* check for OID in valuename */
8940 if ( (oid_string = strchr( valuename, ',' )) != NULL )
8946 /* save the registry data */
8948 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
8950 if ( W_ERROR_IS_OK(status) )
8952 /* save the OID if one was specified */
8954 fstrcat( keyname, "\\" );
8955 fstrcat( keyname, SPOOL_OID_KEY );
8958 * I'm not checking the status here on purpose. Don't know
8959 * if this is right, but I'm returning the status from the
8960 * previous set_printer_dataex() call. I have no idea if
8961 * this is right. --jerry
8964 set_printer_dataex( printer, keyname, valuename,
8965 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
8968 status = mod_a_printer(printer, 2);
8971 free_a_printer(&printer, 2);
8977 /********************************************************************
8978 * spoolss_deleteprinterdataex
8979 ********************************************************************/
8981 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
8983 POLICY_HND *handle = &q_u->handle;
8984 UNISTR2 *value = &q_u->valuename;
8985 UNISTR2 *key = &q_u->keyname;
8987 NT_PRINTER_INFO_LEVEL *printer = NULL;
8989 WERROR status = WERR_OK;
8990 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8991 pstring valuename, keyname;
8993 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8996 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9000 if (!get_printer_snum(p, handle, &snum))
9003 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9004 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9005 return WERR_ACCESS_DENIED;
9008 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9009 if (!W_ERROR_IS_OK(status))
9012 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9013 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9015 status = delete_printer_dataex( printer, keyname, valuename );
9017 if ( W_ERROR_IS_OK(status) )
9018 mod_a_printer( printer, 2 );
9020 free_a_printer(&printer, 2);
9025 /********************************************************************
9026 * spoolss_enumprinterkey
9027 ********************************************************************/
9030 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9033 fstring *keynames = NULL;
9034 uint16 *enumkeys = NULL;
9037 POLICY_HND *handle = &q_u->handle;
9038 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9039 NT_PRINTER_DATA *data;
9040 NT_PRINTER_INFO_LEVEL *printer = NULL;
9042 WERROR status = WERR_BADFILE;
9045 DEBUG(4,("_spoolss_enumprinterkey\n"));
9048 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9052 if ( !get_printer_snum(p,handle, &snum) )
9055 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9056 if (!W_ERROR_IS_OK(status))
9059 /* get the list of subkey names */
9061 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9062 data = printer->info_2->data;
9064 num_keys = get_printer_subkeys( data, key, &keynames );
9066 if ( num_keys == -1 ) {
9067 status = WERR_BADFILE;
9071 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9073 r_u->needed = printerkey_len*2;
9075 if ( q_u->size < r_u->needed ) {
9076 status = WERR_MORE_DATA;
9080 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9081 status = WERR_NOMEM;
9087 if ( q_u->size < r_u->needed )
9088 status = WERR_MORE_DATA;
9091 free_a_printer( &printer, 2 );
9092 SAFE_FREE( keynames );
9097 /********************************************************************
9098 * spoolss_deleteprinterkey
9099 ********************************************************************/
9101 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9103 POLICY_HND *handle = &q_u->handle;
9104 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9106 NT_PRINTER_INFO_LEVEL *printer = NULL;
9110 DEBUG(5,("spoolss_deleteprinterkey\n"));
9113 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9117 /* if keyname == NULL, return error */
9119 if ( !q_u->keyname.buffer )
9120 return WERR_INVALID_PARAM;
9122 if (!get_printer_snum(p, handle, &snum))
9125 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9126 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9127 return WERR_ACCESS_DENIED;
9130 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9131 if (!W_ERROR_IS_OK(status))
9134 /* delete the key and all subneys */
9136 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9138 status = delete_all_printer_data( printer->info_2, key );
9140 if ( W_ERROR_IS_OK(status) )
9141 status = mod_a_printer(printer, 2);
9143 free_a_printer( &printer, 2 );
9149 /********************************************************************
9150 * spoolss_enumprinterdataex
9151 ********************************************************************/
9153 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9155 POLICY_HND *handle = &q_u->handle;
9156 uint32 in_size = q_u->size;
9159 NT_PRINTER_INFO_LEVEL *printer = NULL;
9160 PRINTER_ENUM_VALUES *enum_values = NULL;
9161 NT_PRINTER_DATA *p_data;
9163 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9168 REGISTRY_VALUE *val;
9173 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9176 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9181 * first check for a keyname of NULL or "". Win2k seems to send
9182 * this a lot and we should send back WERR_INVALID_PARAM
9183 * no need to spend time looking up the printer in this case.
9187 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9188 if ( !strlen(key) ) {
9189 result = WERR_INVALID_PARAM;
9193 /* get the printer off of disk */
9195 if (!get_printer_snum(p,handle, &snum))
9198 ZERO_STRUCT(printer);
9199 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9200 if (!W_ERROR_IS_OK(result))
9203 /* now look for a match on the key name */
9205 p_data = printer->info_2->data;
9207 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9208 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9210 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9211 result = WERR_INVALID_PARAM;
9218 /* allocate the memory for the array of pointers -- if necessary */
9220 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9223 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9225 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9226 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9227 result = WERR_NOMEM;
9231 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9235 * loop through all params and build the array to pass
9236 * back to the client
9239 for ( i=0; i<num_entries; i++ )
9241 /* lookup the registry value */
9243 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9244 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9248 value_name = regval_name( val );
9249 init_unistr( &enum_values[i].valuename, value_name );
9250 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9251 enum_values[i].type = regval_type( val );
9253 data_len = regval_size( val );
9255 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9257 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9259 result = WERR_NOMEM;
9263 enum_values[i].data_len = data_len;
9265 /* keep track of the size of the array in bytes */
9267 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9270 /* housekeeping information in the reply */
9272 r_u->needed = needed;
9273 r_u->returned = num_entries;
9275 if (needed > in_size) {
9276 result = WERR_MORE_DATA;
9280 /* copy data into the reply */
9282 r_u->ctr.size = r_u->needed;
9283 r_u->ctr.size_of_array = r_u->returned;
9284 r_u->ctr.values = enum_values;
9290 free_a_printer(&printer, 2);
9295 /****************************************************************************
9296 ****************************************************************************/
9298 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9300 init_unistr(&info->name, name);
9303 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9304 UNISTR2 *environment,
9311 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9312 WERROR result = WERR_OK;
9314 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9316 if (!get_short_archi(long_archi))
9317 return WERR_INVALID_ENVIRONMENT;
9319 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9322 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9324 fill_printprocessordirectory_1(info, path);
9326 *needed += spoolss_size_printprocessordirectory_info_1(info);
9328 if (*needed > offered) {
9329 result = WERR_INSUFFICIENT_BUFFER;
9333 if (!rpcbuf_alloc_size(buffer, *needed)) {
9334 result = WERR_INSUFFICIENT_BUFFER;
9338 smb_io_printprocessordirectory_1("", buffer, info, 0);
9346 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9348 uint32 level = q_u->level;
9349 RPC_BUFFER *buffer = NULL;
9350 uint32 offered = q_u->offered;
9351 uint32 *needed = &r_u->needed;
9354 /* that's an [in out] buffer */
9356 if ( q_u->buffer ) {
9357 rpcbuf_move(q_u->buffer, &r_u->buffer);
9358 buffer = r_u->buffer;
9361 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9367 result = getprintprocessordirectory_level_1
9368 (&q_u->name, &q_u->environment, buffer, offered, needed);
9371 result = WERR_UNKNOWN_LEVEL;
9379 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9380 SPOOL_R_REPLYOPENPRINTER *r_u)
9382 DEBUG(5,("_spoolss_replyopenprinter\n"));
9384 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9389 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9390 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9392 DEBUG(5,("_spoolss_replycloseprinter\n"));