2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info
;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os
[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver
)
55 if (ver
< 0 || ver
> 3)
57 return drv_ver_to_os
[ver
];
61 const char *long_archi
;
62 const char *short_archi
;
66 static Printer_entry
*printers_list
;
68 typedef struct _counter_printer_0
{
69 struct _counter_printer_0
*next
;
70 struct _counter_printer_0
*prev
;
76 static counter_printer_0
*counter_list
;
78 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
79 static uint32 smb_connections
=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v
)
96 return JOB_STATUS_PAUSED
;
98 return JOB_STATUS_SPOOLING
;
100 return JOB_STATUS_PRINTING
;
102 return JOB_STATUS_ERROR
;
104 return JOB_STATUS_DELETING
;
106 return JOB_STATUS_OFFLINE
;
108 return JOB_STATUS_PAPEROUT
;
110 return JOB_STATUS_PRINTED
;
112 return JOB_STATUS_DELETED
;
114 return JOB_STATUS_BLOCKED
;
115 case LPQ_USER_INTERVENTION
:
116 return JOB_STATUS_USER_INTERVENTION
;
121 static int nt_printq_status(int v
)
125 return PRINTER_STATUS_PAUSED
;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
143 SAFE_FREE((*pp
)->ctr
.type
);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum
))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections
==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result
= rpccli_spoolss_reply_close_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, handle
);
171 if (!W_ERROR_IS_OK(result
))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result
)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections
==1) {
178 cli_shutdown( notify_cli_pipe
->cli
);
179 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2
);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr
)
198 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
200 if (Printer
->notify
.client_connected
==True
) {
203 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
205 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
206 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
207 snum
= print_queue_snum(Printer
->sharename
);
209 srv_spoolss_replycloseprinter(snum
,
210 &Printer
->notify
.client_hnd
);
214 Printer
->notify
.flags
=0;
215 Printer
->notify
.options
=0;
216 Printer
->notify
.localmachine
[0]='\0';
217 Printer
->notify
.printerlocal
=0;
218 free_spool_notify_option(&Printer
->notify
.option
);
219 Printer
->notify
.option
=NULL
;
220 Printer
->notify
.client_connected
=False
;
222 free_nt_devicemode( &Printer
->nt_devmode
);
223 free_a_printer( &Printer
->printer_info
, 2 );
225 talloc_destroy( Printer
->ctx
);
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list
, Printer
);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
239 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
244 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
251 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
253 if (!new_sp
->ctr
.type
) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
268 Printer_entry
*find_printer
= NULL
;
270 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
284 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
291 close_policy_hnd(p
, hnd
);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR
delete_printer_hook( NT_USER_TOKEN
*token
, const char *sharename
)
301 char *cmd
= lp_deleteprinter_cmd();
304 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
305 BOOL is_print_op
= False
;
307 /* can't fail if we don't try */
312 pstr_sprintf(command
, "%s \"%s\"", cmd
, sharename
);
315 is_print_op
= user_has_privileges( token
, &se_printop
);
317 DEBUG(10,("Running [%s]\n", command
));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret
));
337 return WERR_BADFID
; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False
);
342 if ( lp_servicenumber( sharename
) < 0 )
343 return WERR_ACCESS_DENIED
;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
354 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED
;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer
->sharename
) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
381 return delete_printer_hook( p
->pipe_user
.nt_user_token
, Printer
->sharename
);
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
390 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
397 switch (Printer
->printer_type
) {
398 case PRINTER_HANDLE_IS_PRINTER
:
399 DEBUG(4,("short name:%s\n", Printer
->sharename
));
400 *number
= print_queue_snum(Printer
->sharename
);
401 return (*number
!= -1);
402 case PRINTER_HANDLE_IS_PRINTSERVER
:
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
416 DEBUG(3,("Setting printer type=%s\n", handlename
));
418 if ( strlen(handlename
) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
423 /* it's a print server */
424 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
437 /****************************************************************************
438 Set printer handle name.
439 ****************************************************************************/
441 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
444 int n_services
=lp_numservices();
445 char *aprinter
, *printername
;
446 const char *servername
;
449 NT_PRINTER_INFO_LEVEL
*printer
;
452 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
454 aprinter
= handlename
;
455 if ( *handlename
== '\\' ) {
456 servername
= handlename
+ 2;
457 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
466 /* save the servername to fill in replies on this handle */
468 if ( !is_myname_or_ipaddr( servername
) )
471 fstrcpy( Printer
->servername
, servername
);
473 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
476 if ( Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTER
)
479 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
481 /* Search all sharenames first as this is easier than pulling
482 the printer_info_2 off of disk. Don't use find_service() since
483 that calls out to map_username() */
485 /* do another loop to look for printernames */
487 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
489 /* no point going on if this is not a printer */
491 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
494 fstrcpy(sname
, lp_servicename(snum
));
495 if ( strequal( aprinter
, sname
) ) {
500 /* no point looking up the printer object if
501 we aren't allowing printername != sharename */
503 if ( lp_force_printername(snum
) )
506 fstrcpy(sname
, lp_servicename(snum
));
509 result
= get_a_printer( NULL
, &printer
, 2, sname
);
510 if ( !W_ERROR_IS_OK(result
) ) {
511 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
512 sname
, dos_errstr(result
)));
516 /* printername is always returned as \\server\printername */
517 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
518 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
519 printer
->info_2
->printername
));
520 free_a_printer( &printer
, 2);
526 if ( strequal(printername
, aprinter
) ) {
531 DEBUGADD(10, ("printername: %s\n", printername
));
533 free_a_printer( &printer
, 2);
537 DEBUGADD(4,("Printer not found\n"));
541 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
543 fstrcpy(Printer
->sharename
, sname
);
548 /****************************************************************************
549 Find first available printer slot. creates a printer handle for you.
550 ****************************************************************************/
552 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
554 Printer_entry
*new_printer
;
556 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
558 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
561 ZERO_STRUCTP(new_printer
);
563 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
564 SAFE_FREE(new_printer
);
568 /* Add to the internal list. */
569 DLIST_ADD(printers_list
, new_printer
);
571 new_printer
->notify
.option
=NULL
;
573 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
574 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
575 close_printer_handle(p
, hnd
);
579 if (!set_printer_hnd_printertype(new_printer
, name
)) {
580 close_printer_handle(p
, hnd
);
584 if (!set_printer_hnd_name(new_printer
, name
)) {
585 close_printer_handle(p
, hnd
);
589 new_printer
->access_granted
= access_granted
;
591 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
596 /***************************************************************************
597 check to see if the client motify handle is monitoring the notification
598 given by (notify_type, notify_field).
599 **************************************************************************/
601 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
607 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
610 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
614 * Flags should always be zero when the change notify
615 * is registered by the client's spooler. A user Win32 app
616 * might use the flags though instead of the NOTIFY_OPTION_INFO
625 return is_monitoring_event_flags(
626 p
->notify
.flags
, notify_type
, notify_field
);
628 for (i
= 0; i
< option
->count
; i
++) {
630 /* Check match for notify_type */
632 if (option
->ctr
.type
[i
].type
!= notify_type
)
635 /* Check match for field */
637 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
638 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
644 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
645 p
->servername
, p
->sharename
, notify_type
, notify_field
));
650 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
652 static void notify_one_value(struct spoolss_notify_msg
*msg
,
653 SPOOL_NOTIFY_INFO_DATA
*data
,
656 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
657 data
->notify_data
.value
[1] = 0;
660 static void notify_string(struct spoolss_notify_msg
*msg
,
661 SPOOL_NOTIFY_INFO_DATA
*data
,
666 /* The length of the message includes the trailing \0 */
668 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
670 data
->notify_data
.data
.length
= msg
->len
* 2;
671 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
673 if (!data
->notify_data
.data
.string
) {
674 data
->notify_data
.data
.length
= 0;
678 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
681 static void notify_system_time(struct spoolss_notify_msg
*msg
,
682 SPOOL_NOTIFY_INFO_DATA
*data
,
688 if (msg
->len
!= sizeof(time_t)) {
689 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
694 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
695 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
699 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
700 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
704 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
707 data
->notify_data
.data
.length
= prs_offset(&ps
);
708 data
->notify_data
.data
.string
= TALLOC(mem_ctx
, prs_offset(&ps
));
710 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
715 struct notify2_message_table
{
717 void (*fn
)(struct spoolss_notify_msg
*msg
,
718 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
721 static struct notify2_message_table printer_notify_table
[] = {
722 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
723 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
724 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
725 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
726 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
727 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
728 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
729 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
730 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
731 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
732 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
733 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
734 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
735 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
736 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
737 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
738 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
739 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
740 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
743 static struct notify2_message_table job_notify_table
[] = {
744 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
745 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
746 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
747 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
748 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
749 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
750 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
751 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
752 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
753 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
754 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
755 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
756 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
757 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
758 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
759 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
760 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
761 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
762 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
763 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
764 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
765 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
766 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
767 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
771 /***********************************************************************
772 Allocate talloc context for container object
773 **********************************************************************/
775 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
780 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
785 /***********************************************************************
786 release all allocated memory and zero out structure
787 **********************************************************************/
789 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
795 talloc_destroy(ctr
->ctx
);
802 /***********************************************************************
803 **********************************************************************/
805 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
813 /***********************************************************************
814 **********************************************************************/
816 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
818 if ( !ctr
|| !ctr
->msg_groups
)
821 if ( idx
>= ctr
->num_groups
)
824 return &ctr
->msg_groups
[idx
];
828 /***********************************************************************
829 How many groups of change messages do we have ?
830 **********************************************************************/
832 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
837 return ctr
->num_groups
;
840 /***********************************************************************
841 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
842 **********************************************************************/
844 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
846 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
847 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
848 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
854 /* loop over all groups looking for a matching printer name */
856 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
857 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
861 /* add a new group? */
863 if ( i
== ctr
->num_groups
) {
866 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
867 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
870 ctr
->msg_groups
= groups
;
872 /* clear the new entry and set the printer name */
874 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
875 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
878 /* add the change messages; 'i' is the correct index now regardless */
880 msg_grp
= &ctr
->msg_groups
[i
];
884 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
888 msg_grp
->msgs
= msg_list
;
890 new_slot
= msg_grp
->num_msgs
-1;
891 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
893 /* need to allocate own copy of data */
896 msg_grp
->msgs
[new_slot
].notify
.data
= TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
898 return ctr
->num_groups
;
901 /***********************************************************************
902 Send a change notication message on all handles which have a call
904 **********************************************************************/
906 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
909 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
910 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
911 SPOOLSS_NOTIFY_MSG
*messages
;
912 int sending_msg_count
;
915 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
919 messages
= msg_group
->msgs
;
922 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
926 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
928 /* loop over all printers */
930 for (p
= printers_list
; p
; p
= p
->next
) {
931 SPOOL_NOTIFY_INFO_DATA
*data
;
936 /* Is there notification on this handle? */
938 if ( !p
->notify
.client_connected
)
941 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
943 /* For this printer? Print servers always receive
946 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
947 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
950 DEBUG(10,("Our printer\n"));
952 /* allocate the max entries possible */
954 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
957 /* build the array of change notifications */
959 sending_msg_count
= 0;
961 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
962 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
964 /* Are we monitoring this event? */
966 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
972 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
973 msg
->type
, msg
->field
, p
->sharename
));
976 * if the is a printer notification handle and not a job notification
977 * type, then set the id to 0. Other wise just use what was specified
980 * When registering change notification on a print server handle
981 * we always need to send back the id (snum) matching the printer
982 * for which the change took place. For change notify registered
983 * on a printer handle, this does not matter and the id should be 0.
988 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
994 /* Convert unix jobid to smb jobid */
996 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
997 id
= sysjob_to_jobid(msg
->id
);
1000 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1005 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1008 case PRINTER_NOTIFY_TYPE
:
1009 if ( printer_notify_table
[msg
->field
].fn
)
1010 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1013 case JOB_NOTIFY_TYPE
:
1014 if ( job_notify_table
[msg
->field
].fn
)
1015 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1019 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1026 if ( sending_msg_count
) {
1027 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1028 data_len
, data
, p
->notify
.change
, 0 );
1033 DEBUG(8,("send_notify2_changes: Exit...\n"));
1037 /***********************************************************************
1038 **********************************************************************/
1040 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1043 uint32 tv_sec
, tv_usec
;
1046 /* Unpack message */
1048 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1051 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1053 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1056 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1057 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1059 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1060 &msg
->len
, &msg
->notify
.data
);
1062 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1063 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1065 tv
->tv_sec
= tv_sec
;
1066 tv
->tv_usec
= tv_usec
;
1069 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1070 msg
->notify
.value
[1]));
1072 dump_data(3, msg
->notify
.data
, msg
->len
);
1077 /********************************************************************
1078 Receive a notify2 message list
1079 ********************************************************************/
1081 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1082 void *msg
, size_t len
)
1084 size_t msg_count
, i
;
1085 char *buf
= (char *)msg
;
1088 SPOOLSS_NOTIFY_MSG notify
;
1089 SPOOLSS_NOTIFY_MSG_CTR messages
;
1093 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1097 msg_count
= IVAL(buf
, 0);
1100 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1102 if (msg_count
== 0) {
1103 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1107 /* initialize the container */
1109 ZERO_STRUCT( messages
);
1110 notify_msg_ctr_init( &messages
);
1113 * build message groups for each printer identified
1114 * in a change_notify msg. Remember that a PCN message
1115 * includes the handle returned for the srv_spoolss_replyopenprinter()
1116 * call. Therefore messages are grouped according to printer handle.
1119 for ( i
=0; i
<msg_count
; i
++ ) {
1120 struct timeval msg_tv
;
1122 if (msg_ptr
+ 4 - buf
> len
) {
1123 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1127 msg_len
= IVAL(msg_ptr
,0);
1130 if (msg_ptr
+ msg_len
- buf
> len
) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1135 /* unpack messages */
1137 ZERO_STRUCT( notify
);
1138 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1141 /* add to correct list in container */
1143 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1145 /* free memory that might have been allocated by notify2_unpack_msg() */
1147 if ( notify
.len
!= 0 )
1148 SAFE_FREE( notify
.notify
.data
);
1151 /* process each group of messages */
1153 num_groups
= notify_msg_ctr_numgroups( &messages
);
1154 for ( i
=0; i
<num_groups
; i
++ )
1155 send_notify2_changes( &messages
, i
);
1160 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1162 notify_msg_ctr_destroy( &messages
);
1167 /********************************************************************
1168 Send a message to ourself about new driver being installed
1169 so we can upgrade the information for each printer bound to this
1171 ********************************************************************/
1173 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1175 int len
= strlen(drivername
);
1180 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1183 message_send_pid(pid_to_procid(sys_getpid()),
1184 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1189 /**********************************************************************
1190 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1191 over all printers, upgrading ones as necessary
1192 **********************************************************************/
1194 void do_drv_upgrade_printer(int msg_type
, struct process_id src
, void *buf
, size_t len
)
1198 int n_services
= lp_numservices();
1200 len
= MIN(len
,sizeof(drivername
)-1);
1201 strncpy(drivername
, buf
, len
);
1203 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1205 /* Iterate the printer list */
1207 for (snum
=0; snum
<n_services
; snum
++)
1209 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1212 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1214 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1215 if (!W_ERROR_IS_OK(result
))
1218 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1220 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1222 /* all we care about currently is the change_id */
1224 result
= mod_a_printer(printer
, 2);
1225 if (!W_ERROR_IS_OK(result
)) {
1226 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1227 dos_errstr(result
)));
1231 free_a_printer(&printer
, 2);
1238 /********************************************************************
1239 Update the cache for all printq's with a registered client
1241 ********************************************************************/
1243 void update_monitored_printq_cache( void )
1245 Printer_entry
*printer
= printers_list
;
1248 /* loop through all printers and update the cache where
1249 client_connected == True */
1252 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1253 && printer
->notify
.client_connected
)
1255 snum
= print_queue_snum(printer
->sharename
);
1256 print_queue_status( snum
, NULL
, NULL
);
1259 printer
= printer
->next
;
1264 /********************************************************************
1265 Send a message to ourself about new driver being installed
1266 so we can upgrade the information for each printer bound to this
1268 ********************************************************************/
1270 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1272 int len
= strlen(drivername
);
1277 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1280 message_send_pid(pid_to_procid(sys_getpid()),
1281 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1286 /**********************************************************************
1287 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1288 over all printers, resetting printer data as neessary
1289 **********************************************************************/
1291 void reset_all_printerdata(int msg_type
, struct process_id src
,
1292 void *buf
, size_t len
)
1296 int n_services
= lp_numservices();
1298 len
= MIN( len
, sizeof(drivername
)-1 );
1299 strncpy( drivername
, buf
, len
);
1301 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1303 /* Iterate the printer list */
1305 for ( snum
=0; snum
<n_services
; snum
++ )
1307 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1310 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1312 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1313 if ( !W_ERROR_IS_OK(result
) )
1317 * if the printer is bound to the driver,
1318 * then reset to the new driver initdata
1321 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1323 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1325 if ( !set_driver_init(printer
, 2) ) {
1326 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1327 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1330 result
= mod_a_printer( printer
, 2 );
1331 if ( !W_ERROR_IS_OK(result
) ) {
1332 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1333 get_dos_error_msg(result
)));
1337 free_a_printer( &printer
, 2 );
1346 /********************************************************************
1347 Copy routines used by convert_to_openprinterex()
1348 *******************************************************************/
1350 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1358 DEBUG (8,("dup_devmode\n"));
1360 /* bulk copy first */
1362 d
= TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1366 /* dup the pointer members separately */
1368 len
= unistrlen(devmode
->devicename
.buffer
);
1370 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1371 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1376 len
= unistrlen(devmode
->formname
.buffer
);
1378 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1379 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1383 d
->dev_private
= TALLOC_MEMDUP(ctx
, devmode
->dev_private
, devmode
->driverextra
);
1388 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1390 if (!new_ctr
|| !ctr
)
1393 DEBUG(8,("copy_devmode_ctr\n"));
1395 new_ctr
->size
= ctr
->size
;
1396 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1398 if(ctr
->devmode_ptr
)
1399 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1402 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1404 if (!new_def
|| !def
)
1407 DEBUG(8,("copy_printer_defaults\n"));
1409 new_def
->datatype_ptr
= def
->datatype_ptr
;
1411 if (def
->datatype_ptr
)
1412 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1414 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1416 new_def
->access_required
= def
->access_required
;
1419 /********************************************************************
1420 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1421 * SPOOL_Q_OPEN_PRINTER_EX structure
1422 ********************************************************************/
1424 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1426 if (!q_u_ex
|| !q_u
)
1429 DEBUG(8,("convert_to_openprinterex\n"));
1431 if ( q_u
->printername
) {
1432 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1433 if (q_u_ex
->printername
== NULL
)
1435 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1438 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1443 /********************************************************************
1444 * spoolss_open_printer
1446 * called from the spoolss dispatcher
1447 ********************************************************************/
1449 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1451 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1452 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1457 ZERO_STRUCT(q_u_ex
);
1458 ZERO_STRUCT(r_u_ex
);
1460 /* convert the OpenPrinter() call to OpenPrinterEx() */
1462 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1463 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1464 return r_u_ex
.status
;
1466 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1468 /* convert back to OpenPrinter() */
1470 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1475 /********************************************************************
1476 * spoolss_open_printer
1478 * If the openprinterex rpc call contains a devmode,
1479 * it's a per-user one. This per-user devmode is derivated
1480 * from the global devmode. Openprinterex() contains a per-user
1481 * devmode for when you do EMF printing and spooling.
1482 * In the EMF case, the NT workstation is only doing half the job
1483 * of rendering the page. The other half is done by running the printer
1484 * driver on the server.
1485 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1486 * The EMF file only contains what is to be printed on the page.
1487 * So in order for the server to know how to print, the NT client sends
1488 * a devicemode attached to the openprinterex call.
1489 * But this devicemode is short lived, it's only valid for the current print job.
1491 * If Samba would have supported EMF spooling, this devicemode would
1492 * have been attached to the handle, to sent it to the driver to correctly
1493 * rasterize the EMF file.
1495 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1496 * we just act as a pass-thru between windows and the printer.
1498 * In order to know that Samba supports only RAW spooling, NT has to call
1499 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1500 * and until NT sends a RAW job, we refuse it.
1502 * But to call getprinter() or startdoc(), you first need a valid handle,
1503 * and to get an handle you have to call openprintex(). Hence why you have
1504 * a devicemode in the openprinterex() call.
1507 * Differences between NT4 and NT 2000.
1510 * On NT4, you only have a global devicemode. This global devicemode can be changed
1511 * by the administrator (or by a user with enough privs). Everytime a user
1512 * wants to print, the devicemode is resetted to the default. In Word, everytime
1513 * you print, the printer's characteristics are always reset to the global devicemode.
1517 * In W2K, there is the notion of per-user devicemode. The first time you use
1518 * a printer, a per-user devicemode is build from the global devicemode.
1519 * If you change your per-user devicemode, it is saved in the registry, under the
1520 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1521 * printer preferences available.
1523 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1524 * on the General Tab of the printer properties windows.
1526 * To change the global devicemode: it's the "Printing Defaults..." button
1527 * on the Advanced Tab of the printer properties window.
1530 ********************************************************************/
1532 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1534 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1535 POLICY_HND
*handle
= &r_u
->handle
;
1539 struct current_user user
;
1540 Printer_entry
*Printer
=NULL
;
1542 if ( !q_u
->printername
)
1543 return WERR_INVALID_PRINTER_NAME
;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1550 DEBUGADD(3,("checking name: %s\n",name
));
1552 if (!open_printer_hnd(p
, handle
, name
, 0))
1553 return WERR_INVALID_PRINTER_NAME
;
1555 Printer
=find_printer_index_by_hnd(p
, handle
);
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name
));
1559 close_printer_handle(p
,handle
);
1560 return WERR_INVALID_PRINTER_NAME
;
1563 get_current_user(&user
, p
);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1586 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1588 /* Printserver handles use global struct... */
1592 /* Map standard access rights to object specific access rights */
1594 se_map_standard(&printer_default
->access_required
,
1595 &printserver_std_mapping
);
1597 /* Deny any object specific bits that don't apply to print
1598 servers (i.e printer and job specific bits) */
1600 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1602 if (printer_default
->access_required
&
1603 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1604 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1605 close_printer_handle(p
, handle
);
1606 return WERR_ACCESS_DENIED
;
1609 /* Allow admin access */
1611 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1613 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1615 if (!lp_ms_add_printer_wizard()) {
1616 close_printer_handle(p
, handle
);
1617 return WERR_ACCESS_DENIED
;
1620 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1621 and not a printer admin, then fail */
1624 && !user_has_privileges( user
.nt_user_token
, &se_printop
)
1625 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1627 close_printer_handle(p
, handle
);
1628 return WERR_ACCESS_DENIED
;
1631 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1635 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1638 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1639 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1641 /* We fall through to return WERR_OK */
1646 /* NT doesn't let us connect to a printer if the connecting user
1647 doesn't have print permission. */
1649 if (!get_printer_snum(p
, handle
, &snum
)) {
1650 close_printer_handle(p
, handle
);
1654 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1656 /* map an empty access mask to the minimum access mask */
1657 if (printer_default
->access_required
== 0x0)
1658 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1661 * If we are not serving the printer driver for this printer,
1662 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1663 * will keep NT clients happy --jerry
1666 if (lp_use_client_driver(snum
)
1667 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1669 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1672 /* check smb.conf parameters and the the sec_desc */
1674 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1675 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1676 return WERR_ACCESS_DENIED
;
1679 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p
, handle
);
1682 return WERR_ACCESS_DENIED
;
1685 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p
, handle
);
1688 return WERR_ACCESS_DENIED
;
1691 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1692 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1694 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1701 Printer
->access_granted
= printer_default
->access_required
;
1704 * If the client sent a devmode in the OpenPrinter() call, then
1705 * save it here in case we get a job submission on this handle
1708 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1709 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1711 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1712 &Printer
->nt_devmode
);
1715 #if 0 /* JERRY -- I'm doubtful this is really effective */
1716 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1717 optimization in Windows 2000 clients --jerry */
1719 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1720 && (RA_WIN2K
== get_remote_arch()) )
1722 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1723 sys_usleep( 500000 );
1730 /****************************************************************************
1731 ****************************************************************************/
1733 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1734 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1740 /* allocate memory if needed. Messy because
1741 convert_printer_info is used to update an existing
1742 printer or build a new one */
1744 if ( !printer
->info_2
) {
1745 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1746 if ( !printer
->info_2
) {
1747 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1752 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1753 printer
->info_2
->setuptime
= time(NULL
);
1761 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1762 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1768 printer
->info_3
=NULL
;
1769 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1773 printer
->info_6
=NULL
;
1774 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1784 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1785 NT_DEVICEMODE
**pp_nt_devmode
)
1787 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1790 * Ensure nt_devmode is a valid pointer
1791 * as we will be overwriting it.
1794 if (nt_devmode
== NULL
) {
1795 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1796 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1800 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1801 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1803 nt_devmode
->specversion
=devmode
->specversion
;
1804 nt_devmode
->driverversion
=devmode
->driverversion
;
1805 nt_devmode
->size
=devmode
->size
;
1806 nt_devmode
->fields
=devmode
->fields
;
1807 nt_devmode
->orientation
=devmode
->orientation
;
1808 nt_devmode
->papersize
=devmode
->papersize
;
1809 nt_devmode
->paperlength
=devmode
->paperlength
;
1810 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1811 nt_devmode
->scale
=devmode
->scale
;
1812 nt_devmode
->copies
=devmode
->copies
;
1813 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1814 nt_devmode
->printquality
=devmode
->printquality
;
1815 nt_devmode
->color
=devmode
->color
;
1816 nt_devmode
->duplex
=devmode
->duplex
;
1817 nt_devmode
->yresolution
=devmode
->yresolution
;
1818 nt_devmode
->ttoption
=devmode
->ttoption
;
1819 nt_devmode
->collate
=devmode
->collate
;
1821 nt_devmode
->logpixels
=devmode
->logpixels
;
1822 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1823 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1824 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1825 nt_devmode
->displayflags
=devmode
->displayflags
;
1826 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1827 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1828 nt_devmode
->icmintent
=devmode
->icmintent
;
1829 nt_devmode
->mediatype
=devmode
->mediatype
;
1830 nt_devmode
->dithertype
=devmode
->dithertype
;
1831 nt_devmode
->reserved1
=devmode
->reserved1
;
1832 nt_devmode
->reserved2
=devmode
->reserved2
;
1833 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1834 nt_devmode
->panningheight
=devmode
->panningheight
;
1837 * Only change private and driverextra if the incoming devmode
1838 * has a new one. JRA.
1841 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1842 SAFE_FREE(nt_devmode
->nt_dev_private
);
1843 nt_devmode
->driverextra
=devmode
->driverextra
;
1844 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1846 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1849 *pp_nt_devmode
= nt_devmode
;
1854 /********************************************************************
1855 * _spoolss_enddocprinter_internal.
1856 ********************************************************************/
1858 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1860 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1864 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1868 if (!get_printer_snum(p
, handle
, &snum
))
1871 Printer
->document_started
=False
;
1872 print_job_end(snum
, Printer
->jobid
,True
);
1873 /* error codes unhandled so far ... */
1878 /********************************************************************
1879 * api_spoolss_closeprinter
1880 ********************************************************************/
1882 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1884 POLICY_HND
*handle
= &q_u
->handle
;
1886 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1888 if (Printer
&& Printer
->document_started
)
1889 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1891 if (!close_printer_handle(p
, handle
))
1894 /* clear the returned printer handle. Observed behavior
1895 from Win2k server. Don't think this really matters.
1896 Previous code just copied the value of the closed
1899 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1904 /********************************************************************
1905 * api_spoolss_deleteprinter
1907 ********************************************************************/
1909 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1911 POLICY_HND
*handle
= &q_u
->handle
;
1912 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1915 if (Printer
&& Printer
->document_started
)
1916 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1918 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1920 result
= delete_printer_handle(p
, handle
);
1922 update_c_setprinter(False
);
1927 /*******************************************************************
1928 * static function to lookup the version id corresponding to an
1929 * long architecture string
1930 ******************************************************************/
1932 static int get_version_id (char * arch
)
1935 struct table_node archi_table
[]= {
1937 {"Windows 4.0", "WIN40", 0 },
1938 {"Windows NT x86", "W32X86", 2 },
1939 {"Windows NT R4000", "W32MIPS", 2 },
1940 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1941 {"Windows NT PowerPC", "W32PPC", 2 },
1942 {"Windows IA64", "IA64", 3 },
1943 {"Windows x64", "x64", 3 },
1947 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1949 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1950 return (archi_table
[i
].version
);
1956 /********************************************************************
1957 * _spoolss_deleteprinterdriver
1958 ********************************************************************/
1960 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1964 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1965 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1967 struct current_user user
;
1969 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1971 get_current_user(&user
, p
);
1973 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1974 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1976 /* check that we have a valid driver name first */
1978 if ((version
=get_version_id(arch
)) == -1)
1979 return WERR_INVALID_ENVIRONMENT
;
1982 ZERO_STRUCT(info_win2k
);
1984 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1986 /* try for Win2k driver if "Windows NT x86" */
1988 if ( version
== 2 ) {
1990 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1991 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1995 /* otherwise it was a failure */
1997 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2003 if (printer_driver_in_use(info
.info_3
)) {
2004 status
= WERR_PRINTER_DRIVER_IN_USE
;
2010 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2012 /* if we get to here, we now have 2 driver info structures to remove */
2013 /* remove the Win2k driver first*/
2015 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2016 free_a_printer_driver( info_win2k
, 3 );
2018 /* this should not have failed---if it did, report to client */
2019 if ( !W_ERROR_IS_OK(status_win2k
) )
2021 status
= status_win2k
;
2027 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2029 /* if at least one of the deletes succeeded return OK */
2031 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2035 free_a_printer_driver( info
, 3 );
2040 /********************************************************************
2041 * spoolss_deleteprinterdriverex
2042 ********************************************************************/
2044 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2048 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2049 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2051 uint32 flags
= q_u
->delete_flags
;
2053 struct current_user user
;
2055 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2057 get_current_user(&user
, p
);
2059 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2060 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2062 /* check that we have a valid driver name first */
2063 if ((version
=get_version_id(arch
)) == -1) {
2064 /* this is what NT returns */
2065 return WERR_INVALID_ENVIRONMENT
;
2068 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2069 version
= q_u
->version
;
2072 ZERO_STRUCT(info_win2k
);
2074 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2076 if ( !W_ERROR_IS_OK(status
) )
2079 * if the client asked for a specific version,
2080 * or this is something other than Windows NT x86,
2084 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2087 /* try for Win2k driver if "Windows NT x86" */
2090 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2091 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2096 if ( printer_driver_in_use(info
.info_3
) ) {
2097 status
= WERR_PRINTER_DRIVER_IN_USE
;
2102 * we have a couple of cases to consider.
2103 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2104 * then the delete should fail if **any** files overlap with
2106 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2107 * non-overlapping files
2108 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2109 * is set, the do not delete any files
2110 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2113 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2115 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2117 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2118 /* no idea of the correct error here */
2119 status
= WERR_ACCESS_DENIED
;
2124 /* also check for W32X86/3 if necessary; maybe we already have? */
2126 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2127 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2130 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2131 /* no idea of the correct error here */
2132 free_a_printer_driver( info_win2k
, 3 );
2133 status
= WERR_ACCESS_DENIED
;
2137 /* if we get to here, we now have 2 driver info structures to remove */
2138 /* remove the Win2k driver first*/
2140 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2141 free_a_printer_driver( info_win2k
, 3 );
2143 /* this should not have failed---if it did, report to client */
2145 if ( !W_ERROR_IS_OK(status_win2k
) )
2150 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2152 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2155 free_a_printer_driver( info
, 3 );
2161 /****************************************************************************
2162 Internal routine for retreiving printerdata
2163 ***************************************************************************/
2165 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2166 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2167 uint32
*needed
, uint32 in_size
)
2169 REGISTRY_VALUE
*val
;
2173 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2174 return WERR_BADFILE
;
2176 *type
= regval_type( val
);
2178 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2180 size
= regval_size( val
);
2182 /* copy the min(in_size, len) */
2185 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2187 /* special case for 0 length values */
2189 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2193 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2202 DEBUG(5,("get_printer_dataex: copy done\n"));
2207 /****************************************************************************
2208 Internal routine for removing printerdata
2209 ***************************************************************************/
2211 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2213 return delete_printer_data( printer
->info_2
, key
, value
);
2216 /****************************************************************************
2217 Internal routine for storing printerdata
2218 ***************************************************************************/
2220 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2221 uint32 type
, uint8
*data
, int real_len
)
2223 /* the registry objects enforce uniqueness based on value name */
2225 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2228 /********************************************************************
2229 GetPrinterData on a printer server Handle.
2230 ********************************************************************/
2232 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2236 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2238 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2240 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2246 if (!StrCaseCmp(value
, "BeepEnabled")) {
2248 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2250 SIVAL(*data
, 0, 0x00);
2255 if (!StrCaseCmp(value
, "EventLog")) {
2257 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2259 /* formally was 0x1b */
2260 SIVAL(*data
, 0, 0x0);
2265 if (!StrCaseCmp(value
, "NetPopup")) {
2267 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2269 SIVAL(*data
, 0, 0x00);
2274 if (!StrCaseCmp(value
, "MajorVersion")) {
2276 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2279 /* Windows NT 4.0 seems to not allow uploading of drivers
2280 to a server that reports 0x3 as the MajorVersion.
2281 need to investigate more how Win2k gets around this .
2284 if ( RA_WINNT
== get_remote_arch() )
2293 if (!StrCaseCmp(value
, "MinorVersion")) {
2295 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2303 * uint32 size = 0x114
2305 * uint32 minor = [0|1]
2306 * uint32 build = [2195|2600]
2307 * extra unicode string = e.g. "Service Pack 3"
2309 if (!StrCaseCmp(value
, "OSVersion")) {
2313 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2316 SIVAL(*data
, 0, *needed
); /* size */
2317 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2319 SIVAL(*data
, 12, 2195); /* build */
2321 /* leave extra string empty */
2327 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2328 const char *string
="C:\\PRINTERS";
2330 *needed
= 2*(strlen(string
)+1);
2331 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2333 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2335 /* it's done by hand ready to go on the wire */
2336 for (i
=0; i
<strlen(string
); i
++) {
2337 (*data
)[2*i
]=string
[i
];
2338 (*data
)[2*i
+1]='\0';
2343 if (!StrCaseCmp(value
, "Architecture")) {
2344 const char *string
="Windows NT x86";
2346 *needed
= 2*(strlen(string
)+1);
2347 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2349 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2350 for (i
=0; i
<strlen(string
); i
++) {
2351 (*data
)[2*i
]=string
[i
];
2352 (*data
)[2*i
+1]='\0';
2357 if (!StrCaseCmp(value
, "DsPresent")) {
2359 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2362 /* only show the publish check box if we are a
2363 memeber of a AD domain */
2365 if ( lp_security() == SEC_ADS
)
2366 SIVAL(*data
, 0, 0x01);
2368 SIVAL(*data
, 0, 0x00);
2374 if (!StrCaseCmp(value
, "DNSMachineName")) {
2377 if (!get_mydnsfullname(hostname
))
2378 return WERR_BADFILE
;
2380 *needed
= 2*(strlen(hostname
)+1);
2381 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2383 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2384 for (i
=0; i
<strlen(hostname
); i
++) {
2385 (*data
)[2*i
]=hostname
[i
];
2386 (*data
)[2*i
+1]='\0';
2392 return WERR_BADFILE
;
2395 /********************************************************************
2396 * spoolss_getprinterdata
2397 ********************************************************************/
2399 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2401 POLICY_HND
*handle
= &q_u
->handle
;
2402 UNISTR2
*valuename
= &q_u
->valuename
;
2403 uint32 in_size
= q_u
->size
;
2404 uint32
*type
= &r_u
->type
;
2405 uint32
*out_size
= &r_u
->size
;
2406 uint8
**data
= &r_u
->data
;
2407 uint32
*needed
= &r_u
->needed
;
2410 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2411 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2415 * Reminder: when it's a string, the length is in BYTES
2416 * even if UNICODE is negociated.
2421 *out_size
= in_size
;
2423 /* in case of problem, return some default values */
2428 DEBUG(4,("_spoolss_getprinterdata\n"));
2431 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2432 status
= WERR_BADFID
;
2436 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2438 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2439 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2442 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2443 status
= WERR_BADFID
;
2447 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2448 if ( !W_ERROR_IS_OK(status
) )
2451 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2453 if ( strequal(value
, "ChangeId") ) {
2455 *needed
= sizeof(uint32
);
2456 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2457 status
= WERR_NOMEM
;
2460 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2464 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2467 if (*needed
> *out_size
)
2468 status
= WERR_MORE_DATA
;
2471 if ( !W_ERROR_IS_OK(status
) )
2473 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2475 /* reply this param doesn't exist */
2478 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2480 free_a_printer( &printer
, 2 );
2489 /* cleanup & exit */
2492 free_a_printer( &printer
, 2 );
2497 /*********************************************************
2498 Connect to the client machine.
2499 **********************************************************/
2501 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2502 struct in_addr
*client_ip
, const char *remote_machine
)
2505 struct cli_state
*the_cli
;
2506 struct in_addr rm_addr
;
2508 if ( is_zero_ip(*client_ip
) ) {
2509 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2510 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2514 if ( ismyip( rm_addr
)) {
2515 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2519 rm_addr
.s_addr
= client_ip
->s_addr
;
2520 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2521 inet_ntoa(*client_ip
) ));
2524 /* setup the connection */
2526 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2527 &rm_addr
, 0, "IPC$", "IPC",
2531 0, lp_client_signing(), NULL
);
2533 if ( !NT_STATUS_IS_OK( ret
) ) {
2534 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2539 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2540 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2541 cli_shutdown(the_cli
);
2546 * Ok - we have an anonymous connection to the IPC$ share.
2547 * Now start the NT Domain stuff :-).
2550 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2551 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2552 remote_machine
, nt_errstr(ret
)));
2553 cli_shutdown(the_cli
);
2557 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2559 (*pp_pipe
)->cli
= the_cli
;
2564 /***************************************************************************
2565 Connect to the client.
2566 ****************************************************************************/
2568 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2569 uint32 localprinter
, uint32 type
,
2570 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2575 * If it's the first connection, contact the client
2576 * and connect to the IPC$ share anonymously
2578 if (smb_connections
==0) {
2579 fstring unix_printer
;
2581 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2583 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2586 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2587 /* Tell the connections db we're now interested in printer
2588 * notify messages. */
2589 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2593 * Tell the specific printing tdb we want messages for this printer
2594 * by registering our PID.
2597 if (!print_notify_register_pid(snum
))
2598 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2602 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2605 if (!W_ERROR_IS_OK(result
))
2606 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2607 dos_errstr(result
)));
2609 return (W_ERROR_IS_OK(result
));
2612 /********************************************************************
2614 * ReplyFindFirstPrinterChangeNotifyEx
2616 * before replying OK: status=0 a rpc call is made to the workstation
2617 * asking ReplyOpenPrinter
2619 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2620 * called from api_spoolss_rffpcnex
2621 ********************************************************************/
2623 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2625 POLICY_HND
*handle
= &q_u
->handle
;
2626 uint32 flags
= q_u
->flags
;
2627 uint32 options
= q_u
->options
;
2628 UNISTR2
*localmachine
= &q_u
->localmachine
;
2629 uint32 printerlocal
= q_u
->printerlocal
;
2631 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2632 struct in_addr client_ip
;
2634 /* store the notify value in the printer struct */
2636 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2639 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2643 Printer
->notify
.flags
=flags
;
2644 Printer
->notify
.options
=options
;
2645 Printer
->notify
.printerlocal
=printerlocal
;
2647 if (Printer
->notify
.option
)
2648 free_spool_notify_option(&Printer
->notify
.option
);
2650 Printer
->notify
.option
=dup_spool_notify_option(option
);
2652 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2653 sizeof(Printer
->notify
.localmachine
)-1);
2655 /* Connect to the client machine and send a ReplyOpenPrinter */
2657 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2659 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2660 !get_printer_snum(p
, handle
, &snum
) )
2663 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2665 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2666 Printer
->notify
.printerlocal
, 1,
2667 &Printer
->notify
.client_hnd
, &client_ip
))
2668 return WERR_SERVER_UNAVAILABLE
;
2670 Printer
->notify
.client_connected
=True
;
2675 /*******************************************************************
2676 * fill a notify_info_data with the servername
2677 ********************************************************************/
2679 void spoolss_notify_server_name(int snum
,
2680 SPOOL_NOTIFY_INFO_DATA
*data
,
2681 print_queue_struct
*queue
,
2682 NT_PRINTER_INFO_LEVEL
*printer
,
2683 TALLOC_CTX
*mem_ctx
)
2688 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2690 data
->notify_data
.data
.length
= len
;
2691 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2693 if (!data
->notify_data
.data
.string
) {
2694 data
->notify_data
.data
.length
= 0;
2698 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2701 /*******************************************************************
2702 * fill a notify_info_data with the printername (not including the servername).
2703 ********************************************************************/
2705 void spoolss_notify_printer_name(int snum
,
2706 SPOOL_NOTIFY_INFO_DATA
*data
,
2707 print_queue_struct
*queue
,
2708 NT_PRINTER_INFO_LEVEL
*printer
,
2709 TALLOC_CTX
*mem_ctx
)
2714 /* the notify name should not contain the \\server\ part */
2715 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2718 p
= printer
->info_2
->printername
;
2723 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2725 data
->notify_data
.data
.length
= len
;
2726 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2728 if (!data
->notify_data
.data
.string
) {
2729 data
->notify_data
.data
.length
= 0;
2733 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2736 /*******************************************************************
2737 * fill a notify_info_data with the servicename
2738 ********************************************************************/
2740 void spoolss_notify_share_name(int snum
,
2741 SPOOL_NOTIFY_INFO_DATA
*data
,
2742 print_queue_struct
*queue
,
2743 NT_PRINTER_INFO_LEVEL
*printer
,
2744 TALLOC_CTX
*mem_ctx
)
2749 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2751 data
->notify_data
.data
.length
= len
;
2752 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2754 if (!data
->notify_data
.data
.string
) {
2755 data
->notify_data
.data
.length
= 0;
2759 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2762 /*******************************************************************
2763 * fill a notify_info_data with the port name
2764 ********************************************************************/
2766 void spoolss_notify_port_name(int snum
,
2767 SPOOL_NOTIFY_INFO_DATA
*data
,
2768 print_queue_struct
*queue
,
2769 NT_PRINTER_INFO_LEVEL
*printer
,
2770 TALLOC_CTX
*mem_ctx
)
2775 /* even if it's strange, that's consistant in all the code */
2777 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2779 data
->notify_data
.data
.length
= len
;
2780 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2782 if (!data
->notify_data
.data
.string
) {
2783 data
->notify_data
.data
.length
= 0;
2787 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2790 /*******************************************************************
2791 * fill a notify_info_data with the printername
2792 * but it doesn't exist, have to see what to do
2793 ********************************************************************/
2795 void spoolss_notify_driver_name(int snum
,
2796 SPOOL_NOTIFY_INFO_DATA
*data
,
2797 print_queue_struct
*queue
,
2798 NT_PRINTER_INFO_LEVEL
*printer
,
2799 TALLOC_CTX
*mem_ctx
)
2804 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2806 data
->notify_data
.data
.length
= len
;
2807 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2809 if (!data
->notify_data
.data
.string
) {
2810 data
->notify_data
.data
.length
= 0;
2814 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2817 /*******************************************************************
2818 * fill a notify_info_data with the comment
2819 ********************************************************************/
2821 void spoolss_notify_comment(int snum
,
2822 SPOOL_NOTIFY_INFO_DATA
*data
,
2823 print_queue_struct
*queue
,
2824 NT_PRINTER_INFO_LEVEL
*printer
,
2825 TALLOC_CTX
*mem_ctx
)
2830 if (*printer
->info_2
->comment
== '\0')
2831 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2833 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2835 data
->notify_data
.data
.length
= len
;
2836 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2838 if (!data
->notify_data
.data
.string
) {
2839 data
->notify_data
.data
.length
= 0;
2843 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2846 /*******************************************************************
2847 * fill a notify_info_data with the comment
2848 * location = "Room 1, floor 2, building 3"
2849 ********************************************************************/
2851 void spoolss_notify_location(int snum
,
2852 SPOOL_NOTIFY_INFO_DATA
*data
,
2853 print_queue_struct
*queue
,
2854 NT_PRINTER_INFO_LEVEL
*printer
,
2855 TALLOC_CTX
*mem_ctx
)
2860 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2862 data
->notify_data
.data
.length
= len
;
2863 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2865 if (!data
->notify_data
.data
.string
) {
2866 data
->notify_data
.data
.length
= 0;
2870 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2873 /*******************************************************************
2874 * fill a notify_info_data with the device mode
2875 * jfm:xxxx don't to it for know but that's a real problem !!!
2876 ********************************************************************/
2878 static void spoolss_notify_devmode(int snum
,
2879 SPOOL_NOTIFY_INFO_DATA
*data
,
2880 print_queue_struct
*queue
,
2881 NT_PRINTER_INFO_LEVEL
*printer
,
2882 TALLOC_CTX
*mem_ctx
)
2886 /*******************************************************************
2887 * fill a notify_info_data with the separator file name
2888 ********************************************************************/
2890 void spoolss_notify_sepfile(int snum
,
2891 SPOOL_NOTIFY_INFO_DATA
*data
,
2892 print_queue_struct
*queue
,
2893 NT_PRINTER_INFO_LEVEL
*printer
,
2894 TALLOC_CTX
*mem_ctx
)
2899 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2901 data
->notify_data
.data
.length
= len
;
2902 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2904 if (!data
->notify_data
.data
.string
) {
2905 data
->notify_data
.data
.length
= 0;
2909 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor
2914 * jfm:xxxx return always winprint to indicate we don't do anything to it
2915 ********************************************************************/
2917 void spoolss_notify_print_processor(int snum
,
2918 SPOOL_NOTIFY_INFO_DATA
*data
,
2919 print_queue_struct
*queue
,
2920 NT_PRINTER_INFO_LEVEL
*printer
,
2921 TALLOC_CTX
*mem_ctx
)
2926 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2928 data
->notify_data
.data
.length
= len
;
2929 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2931 if (!data
->notify_data
.data
.string
) {
2932 data
->notify_data
.data
.length
= 0;
2936 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2939 /*******************************************************************
2940 * fill a notify_info_data with the print processor options
2941 * jfm:xxxx send an empty string
2942 ********************************************************************/
2944 void spoolss_notify_parameters(int snum
,
2945 SPOOL_NOTIFY_INFO_DATA
*data
,
2946 print_queue_struct
*queue
,
2947 NT_PRINTER_INFO_LEVEL
*printer
,
2948 TALLOC_CTX
*mem_ctx
)
2953 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2955 data
->notify_data
.data
.length
= len
;
2956 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2958 if (!data
->notify_data
.data
.string
) {
2959 data
->notify_data
.data
.length
= 0;
2963 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2966 /*******************************************************************
2967 * fill a notify_info_data with the data type
2968 * jfm:xxxx always send RAW as data type
2969 ********************************************************************/
2971 void spoolss_notify_datatype(int snum
,
2972 SPOOL_NOTIFY_INFO_DATA
*data
,
2973 print_queue_struct
*queue
,
2974 NT_PRINTER_INFO_LEVEL
*printer
,
2975 TALLOC_CTX
*mem_ctx
)
2980 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2982 data
->notify_data
.data
.length
= len
;
2983 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2985 if (!data
->notify_data
.data
.string
) {
2986 data
->notify_data
.data
.length
= 0;
2990 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2993 /*******************************************************************
2994 * fill a notify_info_data with the security descriptor
2995 * jfm:xxxx send an null pointer to say no security desc
2996 * have to implement security before !
2997 ********************************************************************/
2999 static void spoolss_notify_security_desc(int snum
,
3000 SPOOL_NOTIFY_INFO_DATA
*data
,
3001 print_queue_struct
*queue
,
3002 NT_PRINTER_INFO_LEVEL
*printer
,
3003 TALLOC_CTX
*mem_ctx
)
3005 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3006 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3009 /*******************************************************************
3010 * fill a notify_info_data with the attributes
3011 * jfm:xxxx a samba printer is always shared
3012 ********************************************************************/
3014 void spoolss_notify_attributes(int snum
,
3015 SPOOL_NOTIFY_INFO_DATA
*data
,
3016 print_queue_struct
*queue
,
3017 NT_PRINTER_INFO_LEVEL
*printer
,
3018 TALLOC_CTX
*mem_ctx
)
3020 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3021 data
->notify_data
.value
[1] = 0;
3024 /*******************************************************************
3025 * fill a notify_info_data with the priority
3026 ********************************************************************/
3028 static void spoolss_notify_priority(int snum
,
3029 SPOOL_NOTIFY_INFO_DATA
*data
,
3030 print_queue_struct
*queue
,
3031 NT_PRINTER_INFO_LEVEL
*printer
,
3032 TALLOC_CTX
*mem_ctx
)
3034 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3035 data
->notify_data
.value
[1] = 0;
3038 /*******************************************************************
3039 * fill a notify_info_data with the default priority
3040 ********************************************************************/
3042 static void spoolss_notify_default_priority(int snum
,
3043 SPOOL_NOTIFY_INFO_DATA
*data
,
3044 print_queue_struct
*queue
,
3045 NT_PRINTER_INFO_LEVEL
*printer
,
3046 TALLOC_CTX
*mem_ctx
)
3048 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3049 data
->notify_data
.value
[1] = 0;
3052 /*******************************************************************
3053 * fill a notify_info_data with the start time
3054 ********************************************************************/
3056 static void spoolss_notify_start_time(int snum
,
3057 SPOOL_NOTIFY_INFO_DATA
*data
,
3058 print_queue_struct
*queue
,
3059 NT_PRINTER_INFO_LEVEL
*printer
,
3060 TALLOC_CTX
*mem_ctx
)
3062 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3063 data
->notify_data
.value
[1] = 0;
3066 /*******************************************************************
3067 * fill a notify_info_data with the until time
3068 ********************************************************************/
3070 static void spoolss_notify_until_time(int snum
,
3071 SPOOL_NOTIFY_INFO_DATA
*data
,
3072 print_queue_struct
*queue
,
3073 NT_PRINTER_INFO_LEVEL
*printer
,
3074 TALLOC_CTX
*mem_ctx
)
3076 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3077 data
->notify_data
.value
[1] = 0;
3080 /*******************************************************************
3081 * fill a notify_info_data with the status
3082 ********************************************************************/
3084 static void spoolss_notify_status(int snum
,
3085 SPOOL_NOTIFY_INFO_DATA
*data
,
3086 print_queue_struct
*queue
,
3087 NT_PRINTER_INFO_LEVEL
*printer
,
3088 TALLOC_CTX
*mem_ctx
)
3090 print_status_struct status
;
3092 print_queue_length(snum
, &status
);
3093 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3094 data
->notify_data
.value
[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the number of jobs queued
3099 ********************************************************************/
3101 void spoolss_notify_cjobs(int snum
,
3102 SPOOL_NOTIFY_INFO_DATA
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3108 data
->notify_data
.value
[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the average ppm
3113 ********************************************************************/
3115 static void spoolss_notify_average_ppm(int snum
,
3116 SPOOL_NOTIFY_INFO_DATA
*data
,
3117 print_queue_struct
*queue
,
3118 NT_PRINTER_INFO_LEVEL
*printer
,
3119 TALLOC_CTX
*mem_ctx
)
3121 /* always respond 8 pages per minutes */
3122 /* a little hard ! */
3123 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3124 data
->notify_data
.value
[1] = 0;
3127 /*******************************************************************
3128 * fill a notify_info_data with username
3129 ********************************************************************/
3131 static void spoolss_notify_username(int snum
,
3132 SPOOL_NOTIFY_INFO_DATA
*data
,
3133 print_queue_struct
*queue
,
3134 NT_PRINTER_INFO_LEVEL
*printer
,
3135 TALLOC_CTX
*mem_ctx
)
3140 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3142 data
->notify_data
.data
.length
= len
;
3143 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3145 if (!data
->notify_data
.data
.string
) {
3146 data
->notify_data
.data
.length
= 0;
3150 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3153 /*******************************************************************
3154 * fill a notify_info_data with job status
3155 ********************************************************************/
3157 static void spoolss_notify_job_status(int snum
,
3158 SPOOL_NOTIFY_INFO_DATA
*data
,
3159 print_queue_struct
*queue
,
3160 NT_PRINTER_INFO_LEVEL
*printer
,
3161 TALLOC_CTX
*mem_ctx
)
3163 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3164 data
->notify_data
.value
[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with job name
3169 ********************************************************************/
3171 static void spoolss_notify_job_name(int snum
,
3172 SPOOL_NOTIFY_INFO_DATA
*data
,
3173 print_queue_struct
*queue
,
3174 NT_PRINTER_INFO_LEVEL
*printer
,
3175 TALLOC_CTX
*mem_ctx
)
3180 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3182 data
->notify_data
.data
.length
= len
;
3183 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3185 if (!data
->notify_data
.data
.string
) {
3186 data
->notify_data
.data
.length
= 0;
3190 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3193 /*******************************************************************
3194 * fill a notify_info_data with job status
3195 ********************************************************************/
3197 static void spoolss_notify_job_status_string(int snum
,
3198 SPOOL_NOTIFY_INFO_DATA
*data
,
3199 print_queue_struct
*queue
,
3200 NT_PRINTER_INFO_LEVEL
*printer
,
3201 TALLOC_CTX
*mem_ctx
)
3204 * Now we're returning job status codes we just return a "" here. JRA.
3211 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3214 switch (queue
->status
) {
3219 p
= ""; /* NT provides the paused string */
3228 #endif /* NO LONGER NEEDED. */
3230 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3232 data
->notify_data
.data
.length
= len
;
3233 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3235 if (!data
->notify_data
.data
.string
) {
3236 data
->notify_data
.data
.length
= 0;
3240 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3243 /*******************************************************************
3244 * fill a notify_info_data with job time
3245 ********************************************************************/
3247 static void spoolss_notify_job_time(int snum
,
3248 SPOOL_NOTIFY_INFO_DATA
*data
,
3249 print_queue_struct
*queue
,
3250 NT_PRINTER_INFO_LEVEL
*printer
,
3251 TALLOC_CTX
*mem_ctx
)
3253 data
->notify_data
.value
[0]=0x0;
3254 data
->notify_data
.value
[1]=0;
3257 /*******************************************************************
3258 * fill a notify_info_data with job size
3259 ********************************************************************/
3261 static void spoolss_notify_job_size(int snum
,
3262 SPOOL_NOTIFY_INFO_DATA
*data
,
3263 print_queue_struct
*queue
,
3264 NT_PRINTER_INFO_LEVEL
*printer
,
3265 TALLOC_CTX
*mem_ctx
)
3267 data
->notify_data
.value
[0]=queue
->size
;
3268 data
->notify_data
.value
[1]=0;
3271 /*******************************************************************
3272 * fill a notify_info_data with page info
3273 ********************************************************************/
3274 static void spoolss_notify_total_pages(int snum
,
3275 SPOOL_NOTIFY_INFO_DATA
*data
,
3276 print_queue_struct
*queue
,
3277 NT_PRINTER_INFO_LEVEL
*printer
,
3278 TALLOC_CTX
*mem_ctx
)
3280 data
->notify_data
.value
[0]=queue
->page_count
;
3281 data
->notify_data
.value
[1]=0;
3284 /*******************************************************************
3285 * fill a notify_info_data with pages printed info.
3286 ********************************************************************/
3287 static void spoolss_notify_pages_printed(int snum
,
3288 SPOOL_NOTIFY_INFO_DATA
*data
,
3289 print_queue_struct
*queue
,
3290 NT_PRINTER_INFO_LEVEL
*printer
,
3291 TALLOC_CTX
*mem_ctx
)
3293 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3294 data
->notify_data
.value
[1]=0;
3297 /*******************************************************************
3298 Fill a notify_info_data with job position.
3299 ********************************************************************/
3301 static void spoolss_notify_job_position(int snum
,
3302 SPOOL_NOTIFY_INFO_DATA
*data
,
3303 print_queue_struct
*queue
,
3304 NT_PRINTER_INFO_LEVEL
*printer
,
3305 TALLOC_CTX
*mem_ctx
)
3307 data
->notify_data
.value
[0]=queue
->job
;
3308 data
->notify_data
.value
[1]=0;
3311 /*******************************************************************
3312 Fill a notify_info_data with submitted time.
3313 ********************************************************************/
3315 static void spoolss_notify_submitted_time(int snum
,
3316 SPOOL_NOTIFY_INFO_DATA
*data
,
3317 print_queue_struct
*queue
,
3318 NT_PRINTER_INFO_LEVEL
*printer
,
3319 TALLOC_CTX
*mem_ctx
)
3326 t
=gmtime(&queue
->time
);
3328 len
= sizeof(SYSTEMTIME
);
3330 data
->notify_data
.data
.length
= len
;
3331 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3333 if (!data
->notify_data
.data
.string
) {
3334 data
->notify_data
.data
.length
= 0;
3338 make_systemtime(&st
, t
);
3341 * Systemtime must be linearized as a set of UINT16's.
3342 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3345 p
= (char *)data
->notify_data
.data
.string
;
3346 SSVAL(p
, 0, st
.year
);
3347 SSVAL(p
, 2, st
.month
);
3348 SSVAL(p
, 4, st
.dayofweek
);
3349 SSVAL(p
, 6, st
.day
);
3350 SSVAL(p
, 8, st
.hour
);
3351 SSVAL(p
, 10, st
.minute
);
3352 SSVAL(p
, 12, st
.second
);
3353 SSVAL(p
, 14, st
.milliseconds
);
3356 struct s_notify_info_data_table
3362 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3363 print_queue_struct
*queue
,
3364 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3367 /* A table describing the various print notification constants and
3368 whether the notification data is a pointer to a variable sized
3369 buffer, a one value uint32 or a two value uint32. */
3371 static const struct s_notify_info_data_table notify_info_data_table
[] =
3373 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3374 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3375 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3376 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3377 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3378 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3379 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3380 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3381 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3382 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3383 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3384 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3385 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3386 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3387 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3388 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3389 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3390 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3391 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3392 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3393 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3394 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3395 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3396 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3397 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3398 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3399 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3400 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3401 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3402 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3403 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3404 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3405 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3406 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3407 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3408 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3409 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3410 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3411 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3412 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3413 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3414 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3415 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3416 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3417 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3418 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3419 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3420 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3421 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3422 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3425 /*******************************************************************
3426 Return the size of info_data structure.
3427 ********************************************************************/
3429 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3433 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3435 if ( (notify_info_data_table
[i
].type
== type
)
3436 && (notify_info_data_table
[i
].field
== field
) )
3438 switch(notify_info_data_table
[i
].size
)
3440 case NOTIFY_ONE_VALUE
:
3441 case NOTIFY_TWO_VALUE
:
3446 /* The only pointer notify data I have seen on
3447 the wire is the submitted time and this has
3448 the notify size set to 4. -tpot */
3450 case NOTIFY_POINTER
:
3453 case NOTIFY_SECDESC
:
3459 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3464 /*******************************************************************
3465 Return the type of notify_info_data.
3466 ********************************************************************/
3468 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3472 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3473 if (notify_info_data_table
[i
].type
== type
&&
3474 notify_info_data_table
[i
].field
== field
)
3475 return notify_info_data_table
[i
].size
;
3481 /****************************************************************************
3482 ****************************************************************************/
3484 static int search_notify(uint16 type
, uint16 field
, int *value
)
3488 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3489 if (notify_info_data_table
[i
].type
== type
&&
3490 notify_info_data_table
[i
].field
== field
&&
3491 notify_info_data_table
[i
].fn
!= NULL
) {
3500 /****************************************************************************
3501 ****************************************************************************/
3503 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3505 info_data
->type
= type
;
3506 info_data
->field
= field
;
3507 info_data
->reserved
= 0;
3509 info_data
->size
= size_of_notify_info_data(type
, field
);
3510 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3517 /*******************************************************************
3519 * fill a notify_info struct with info asked
3521 ********************************************************************/
3523 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3524 snum
, SPOOL_NOTIFY_OPTION_TYPE
3525 *option_type
, uint32 id
,
3526 TALLOC_CTX
*mem_ctx
)
3532 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3533 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3534 print_queue_struct
*queue
=NULL
;
3536 type
=option_type
->type
;
3538 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3539 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3540 option_type
->count
, lp_servicename(snum
)));
3542 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3545 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3546 field
= option_type
->fields
[field_num
];
3548 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3550 if (!search_notify(type
, field
, &j
) )
3553 if((tid
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3554 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3559 current_data
= &info
->data
[info
->count
];
3561 construct_info_data(current_data
, type
, field
, id
);
3563 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3564 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3566 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3572 free_a_printer(&printer
, 2);
3576 /*******************************************************************
3578 * fill a notify_info struct with info asked
3580 ********************************************************************/
3582 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3583 SPOOL_NOTIFY_INFO
*info
,
3584 NT_PRINTER_INFO_LEVEL
*printer
,
3585 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3586 *option_type
, uint32 id
,
3587 TALLOC_CTX
*mem_ctx
)
3593 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3595 DEBUG(4,("construct_notify_jobs_info\n"));
3597 type
= option_type
->type
;
3599 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3600 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3601 option_type
->count
));
3603 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3604 field
= option_type
->fields
[field_num
];
3606 if (!search_notify(type
, field
, &j
) )
3609 if((tid
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3610 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3613 else info
->data
= tid
;
3615 current_data
=&(info
->data
[info
->count
]);
3617 construct_info_data(current_data
, type
, field
, id
);
3618 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3627 * JFM: The enumeration is not that simple, it's even non obvious.
3629 * let's take an example: I want to monitor the PRINTER SERVER for
3630 * the printer's name and the number of jobs currently queued.
3631 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3632 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3634 * I have 3 printers on the back of my server.
3636 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3639 * 1 printer 1 name 1
3640 * 2 printer 1 cjob 1
3641 * 3 printer 2 name 2
3642 * 4 printer 2 cjob 2
3643 * 5 printer 3 name 3
3644 * 6 printer 3 name 3
3646 * that's the print server case, the printer case is even worse.
3649 /*******************************************************************
3651 * enumerate all printers on the printserver
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3657 SPOOL_NOTIFY_INFO
*info
,
3658 TALLOC_CTX
*mem_ctx
)
3661 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3662 int n_services
=lp_numservices();
3664 SPOOL_NOTIFY_OPTION
*option
;
3665 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3667 DEBUG(4,("printserver_notify_info\n"));
3672 option
=Printer
->notify
.option
;
3677 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3678 sending a ffpcn() request first */
3683 for (i
=0; i
<option
->count
; i
++) {
3684 option_type
=&(option
->ctr
.type
[i
]);
3686 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3689 for (snum
=0; snum
<n_services
; snum
++)
3691 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3692 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3698 * Debugging information, don't delete.
3701 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3703 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3705 for (i
=0; i
<info
->count
; i
++) {
3706 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3708 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3715 /*******************************************************************
3717 * fill a notify_info struct with info asked
3719 ********************************************************************/
3721 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3722 TALLOC_CTX
*mem_ctx
)
3725 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3728 SPOOL_NOTIFY_OPTION
*option
;
3729 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3731 print_queue_struct
*queue
=NULL
;
3732 print_status_struct status
;
3734 DEBUG(4,("printer_notify_info\n"));
3739 option
=Printer
->notify
.option
;
3745 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3746 sending a ffpcn() request first */
3751 get_printer_snum(p
, hnd
, &snum
);
3753 for (i
=0; i
<option
->count
; i
++) {
3754 option_type
=&option
->ctr
.type
[i
];
3756 switch ( option_type
->type
) {
3757 case PRINTER_NOTIFY_TYPE
:
3758 if(construct_notify_printer_info(Printer
, info
, snum
,
3764 case JOB_NOTIFY_TYPE
: {
3765 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3767 count
= print_queue_status(snum
, &queue
, &status
);
3769 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3772 for (j
=0; j
<count
; j
++) {
3773 construct_notify_jobs_info(&queue
[j
], info
,
3780 free_a_printer(&printer
, 2);
3790 * Debugging information, don't delete.
3793 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3794 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3795 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3797 for (i=0; i<info->count; i++) {
3798 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3799 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3800 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3806 /********************************************************************
3808 ********************************************************************/
3810 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3812 POLICY_HND
*handle
= &q_u
->handle
;
3813 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3815 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3816 WERROR result
= WERR_BADFID
;
3818 /* we always have a NOTIFY_INFO struct */
3822 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3823 OUR_HANDLE(handle
)));
3827 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3830 * We are now using the change value, and
3831 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3832 * I don't have a global notification system, I'm sending back all the
3833 * informations even when _NOTHING_ has changed.
3836 /* We need to keep track of the change value to send back in
3837 RRPCN replies otherwise our updates are ignored. */
3839 Printer
->notify
.fnpcn
= True
;
3841 if (Printer
->notify
.client_connected
) {
3842 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3843 Printer
->notify
.change
= q_u
->change
;
3846 /* just ignore the SPOOL_NOTIFY_OPTION */
3848 switch (Printer
->printer_type
) {
3849 case PRINTER_HANDLE_IS_PRINTSERVER
:
3850 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3853 case PRINTER_HANDLE_IS_PRINTER
:
3854 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3858 Printer
->notify
.fnpcn
= False
;
3864 /********************************************************************
3865 * construct_printer_info_0
3866 * fill a printer_info_0 struct
3867 ********************************************************************/
3869 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3873 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3874 counter_printer_0
*session_counter
;
3875 uint32 global_counter
;
3878 print_status_struct status
;
3880 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3883 count
= print_queue_length(snum
, &status
);
3885 /* check if we already have a counter for this printer */
3886 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3887 if (session_counter
->snum
== snum
)
3891 /* it's the first time, add it to the list */
3892 if (session_counter
==NULL
) {
3893 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3894 free_a_printer(&ntprinter
, 2);
3897 ZERO_STRUCTP(session_counter
);
3898 session_counter
->snum
=snum
;
3899 session_counter
->counter
=0;
3900 DLIST_ADD(counter_list
, session_counter
);
3904 session_counter
->counter
++;
3907 * the global_counter should be stored in a TDB as it's common to all the clients
3908 * and should be zeroed on samba startup
3910 global_counter
=session_counter
->counter
;
3912 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3914 init_unistr(&printer
->printername
, chaine
);
3916 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3917 init_unistr(&printer
->servername
, chaine
);
3919 printer
->cjobs
= count
;
3920 printer
->total_jobs
= 0;
3921 printer
->total_bytes
= 0;
3923 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3924 t
=gmtime(&setuptime
);
3926 printer
->year
= t
->tm_year
+1900;
3927 printer
->month
= t
->tm_mon
+1;
3928 printer
->dayofweek
= t
->tm_wday
;
3929 printer
->day
= t
->tm_mday
;
3930 printer
->hour
= t
->tm_hour
;
3931 printer
->minute
= t
->tm_min
;
3932 printer
->second
= t
->tm_sec
;
3933 printer
->milliseconds
= 0;
3935 printer
->global_counter
= global_counter
;
3936 printer
->total_pages
= 0;
3938 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3939 printer
->major_version
= 0x0005; /* NT 5 */
3940 printer
->build_version
= 0x0893; /* build 2195 */
3942 printer
->unknown7
= 0x1;
3943 printer
->unknown8
= 0x0;
3944 printer
->unknown9
= 0x0;
3945 printer
->session_counter
= session_counter
->counter
;
3946 printer
->unknown11
= 0x0;
3947 printer
->printer_errors
= 0x0; /* number of print failure */
3948 printer
->unknown13
= 0x0;
3949 printer
->unknown14
= 0x1;
3950 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3951 printer
->unknown16
= 0x0;
3952 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3953 printer
->unknown18
= 0x0;
3954 printer
->status
= nt_printq_status(status
.status
);
3955 printer
->unknown20
= 0x0;
3956 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3957 printer
->unknown22
= 0x0;
3958 printer
->unknown23
= 0x6; /* 6 ???*/
3959 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3960 printer
->unknown25
= 0;
3961 printer
->unknown26
= 0;
3962 printer
->unknown27
= 0;
3963 printer
->unknown28
= 0;
3964 printer
->unknown29
= 0;
3966 free_a_printer(&ntprinter
,2);
3970 /********************************************************************
3971 * construct_printer_info_1
3972 * fill a printer_info_1 struct
3973 ********************************************************************/
3974 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3978 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3980 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3983 printer
->flags
=flags
;
3985 if (*ntprinter
->info_2
->comment
== '\0') {
3986 init_unistr(&printer
->comment
, lp_comment(snum
));
3987 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3988 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3991 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3992 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3993 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3996 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3998 init_unistr(&printer
->description
, chaine
);
3999 init_unistr(&printer
->name
, chaine2
);
4001 free_a_printer(&ntprinter
,2);
4006 /****************************************************************************
4007 Free a DEVMODE struct.
4008 ****************************************************************************/
4010 static void free_dev_mode(DEVICEMODE
*dev
)
4015 SAFE_FREE(dev
->dev_private
);
4020 /****************************************************************************
4021 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4022 should be valid upon entry
4023 ****************************************************************************/
4025 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4027 if ( !devmode
|| !ntdevmode
)
4030 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4032 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4034 devmode
->specversion
= ntdevmode
->specversion
;
4035 devmode
->driverversion
= ntdevmode
->driverversion
;
4036 devmode
->size
= ntdevmode
->size
;
4037 devmode
->driverextra
= ntdevmode
->driverextra
;
4038 devmode
->fields
= ntdevmode
->fields
;
4040 devmode
->orientation
= ntdevmode
->orientation
;
4041 devmode
->papersize
= ntdevmode
->papersize
;
4042 devmode
->paperlength
= ntdevmode
->paperlength
;
4043 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4044 devmode
->scale
= ntdevmode
->scale
;
4045 devmode
->copies
= ntdevmode
->copies
;
4046 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4047 devmode
->printquality
= ntdevmode
->printquality
;
4048 devmode
->color
= ntdevmode
->color
;
4049 devmode
->duplex
= ntdevmode
->duplex
;
4050 devmode
->yresolution
= ntdevmode
->yresolution
;
4051 devmode
->ttoption
= ntdevmode
->ttoption
;
4052 devmode
->collate
= ntdevmode
->collate
;
4053 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4054 devmode
->icmintent
= ntdevmode
->icmintent
;
4055 devmode
->mediatype
= ntdevmode
->mediatype
;
4056 devmode
->dithertype
= ntdevmode
->dithertype
;
4058 if (ntdevmode
->nt_dev_private
!= NULL
) {
4059 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4066 /****************************************************************************
4067 Create a DEVMODE struct. Returns malloced memory.
4068 ****************************************************************************/
4070 DEVICEMODE
*construct_dev_mode(int snum
)
4072 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4073 DEVICEMODE
*devmode
= NULL
;
4075 DEBUG(7,("construct_dev_mode\n"));
4077 DEBUGADD(8,("getting printer characteristics\n"));
4079 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4082 if ( !printer
->info_2
->devmode
) {
4083 DEBUG(5, ("BONG! There was no device mode!\n"));
4087 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4088 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4092 ZERO_STRUCTP(devmode
);
4094 DEBUGADD(8,("loading DEVICEMODE\n"));
4096 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4097 free_dev_mode( devmode
);
4102 free_a_printer(&printer
,2);
4107 /********************************************************************
4108 * construct_printer_info_2
4109 * fill a printer_info_2 struct
4110 ********************************************************************/
4112 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4115 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4117 print_status_struct status
;
4119 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4122 count
= print_queue_length(snum
, &status
);
4124 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4125 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4126 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4127 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4128 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4130 if (*ntprinter
->info_2
->comment
== '\0')
4131 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4133 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4135 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4136 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4137 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4138 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4139 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4141 printer
->attributes
= ntprinter
->info_2
->attributes
;
4143 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4144 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4145 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4146 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4147 printer
->status
= nt_printq_status(status
.status
); /* status */
4148 printer
->cjobs
= count
; /* jobs */
4149 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4151 if ( !(printer
->devmode
= construct_dev_mode(snum
)) )
4152 DEBUG(8, ("Returning NULL Devicemode!\n"));
4154 printer
->secdesc
= NULL
;
4156 if ( ntprinter
->info_2
->secdesc_buf
4157 && ntprinter
->info_2
->secdesc_buf
->len
!= 0 )
4159 /* don't use talloc_steal() here unless you do a deep steal of all
4160 the SEC_DESC members */
4162 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4163 ntprinter
->info_2
->secdesc_buf
->sec
);
4166 free_a_printer(&ntprinter
, 2);
4171 /********************************************************************
4172 * construct_printer_info_3
4173 * fill a printer_info_3 struct
4174 ********************************************************************/
4176 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4178 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4179 PRINTER_INFO_3
*printer
= NULL
;
4181 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4185 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4186 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4190 ZERO_STRUCTP(printer
);
4192 /* These are the components of the SD we are returning. */
4194 printer
->flags
= 0x4;
4196 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4197 /* don't use talloc_steal() here unless you do a deep steal of all
4198 the SEC_DESC members */
4200 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4201 ntprinter
->info_2
->secdesc_buf
->sec
);
4204 free_a_printer(&ntprinter
, 2);
4206 *pp_printer
= printer
;
4210 /********************************************************************
4211 * construct_printer_info_4
4212 * fill a printer_info_4 struct
4213 ********************************************************************/
4215 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4217 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4219 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4222 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4223 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4224 printer
->attributes
= ntprinter
->info_2
->attributes
;
4226 free_a_printer(&ntprinter
, 2);
4230 /********************************************************************
4231 * construct_printer_info_5
4232 * fill a printer_info_5 struct
4233 ********************************************************************/
4235 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4237 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4239 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4242 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4243 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4244 printer
->attributes
= ntprinter
->info_2
->attributes
;
4246 /* these two are not used by NT+ according to MSDN */
4248 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4249 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4251 free_a_printer(&ntprinter
, 2);
4256 /********************************************************************
4257 * construct_printer_info_7
4258 * fill a printer_info_7 struct
4259 ********************************************************************/
4261 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4263 char *guid_str
= NULL
;
4266 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4267 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4268 strupper_m(guid_str
);
4269 init_unistr(&printer
->guid
, guid_str
);
4270 printer
->action
= SPOOL_DS_PUBLISH
;
4272 init_unistr(&printer
->guid
, "");
4273 printer
->action
= SPOOL_DS_UNPUBLISH
;
4279 /********************************************************************
4280 Spoolss_enumprinters.
4281 ********************************************************************/
4283 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4287 int n_services
=lp_numservices();
4288 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4289 PRINTER_INFO_1 current_prt
;
4290 WERROR result
= WERR_OK
;
4292 DEBUG(4,("enum_all_printers_info_1\n"));
4294 for (snum
=0; snum
<n_services
; snum
++) {
4295 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4296 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4298 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4299 if((tp
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4300 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4301 SAFE_FREE(printers
);
4306 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4308 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4314 /* check the required size. */
4315 for (i
=0; i
<*returned
; i
++)
4316 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4318 if (*needed
> offered
) {
4319 result
= WERR_INSUFFICIENT_BUFFER
;
4323 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4324 result
= WERR_NOMEM
;
4328 /* fill the buffer with the structures */
4329 for (i
=0; i
<*returned
; i
++)
4330 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4335 SAFE_FREE(printers
);
4337 if ( !W_ERROR_IS_OK(result
) )
4343 /********************************************************************
4344 enum_all_printers_info_1_local.
4345 *********************************************************************/
4347 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4349 DEBUG(4,("enum_all_printers_info_1_local\n"));
4351 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4354 /********************************************************************
4355 enum_all_printers_info_1_name.
4356 *********************************************************************/
4358 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4362 DEBUG(4,("enum_all_printers_info_1_name\n"));
4364 if ((name
[0] == '\\') && (name
[1] == '\\'))
4367 if (is_myname_or_ipaddr(s
)) {
4368 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4371 return WERR_INVALID_NAME
;
4374 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4375 /********************************************************************
4376 enum_all_printers_info_1_remote.
4377 *********************************************************************/
4379 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4381 PRINTER_INFO_1
*printer
;
4382 fstring printername
;
4385 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4386 WERROR result
= WERR_OK
;
4388 /* JFM: currently it's more a place holder than anything else.
4389 * In the spooler world there is a notion of server registration.
4390 * the print servers are registered on the PDC (in the same domain)
4392 * We should have a TDB here. The registration is done thru an
4393 * undocumented RPC call.
4396 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4401 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4402 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4403 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4405 init_unistr(&printer
->description
, desc
);
4406 init_unistr(&printer
->name
, printername
);
4407 init_unistr(&printer
->comment
, comment
);
4408 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4410 /* check the required size. */
4411 *needed
+= spoolss_size_printer_info_1(printer
);
4413 if (*needed
> offered
) {
4414 result
= WERR_INSUFFICIENT_BUFFER
;
4418 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4419 result
= WERR_NOMEM
;
4423 /* fill the buffer with the structures */
4424 smb_io_printer_info_1("", buffer
, printer
, 0);
4430 if ( !W_ERROR_IS_OK(result
) )
4438 /********************************************************************
4439 enum_all_printers_info_1_network.
4440 *********************************************************************/
4442 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4446 DEBUG(4,("enum_all_printers_info_1_network\n"));
4448 /* If we respond to a enum_printers level 1 on our name with flags
4449 set to PRINTER_ENUM_REMOTE with a list of printers then these
4450 printers incorrectly appear in the APW browse list.
4451 Specifically the printers for the server appear at the workgroup
4452 level where all the other servers in the domain are
4453 listed. Windows responds to this call with a
4454 WERR_CAN_NOT_COMPLETE so we should do the same. */
4456 if (name
[0] == '\\' && name
[1] == '\\')
4459 if (is_myname_or_ipaddr(s
))
4460 return WERR_CAN_NOT_COMPLETE
;
4462 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4465 /********************************************************************
4466 * api_spoolss_enumprinters
4468 * called from api_spoolss_enumprinters (see this to understand)
4469 ********************************************************************/
4471 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4475 int n_services
=lp_numservices();
4476 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4477 PRINTER_INFO_2 current_prt
;
4478 WERROR result
= WERR_OK
;
4480 for (snum
=0; snum
<n_services
; snum
++) {
4481 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4482 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4484 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
))
4486 if ( !(tp
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4487 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4488 SAFE_FREE(printers
);
4493 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4496 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4503 /* check the required size. */
4504 for (i
=0; i
<*returned
; i
++)
4505 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4507 if (*needed
> offered
) {
4508 result
= WERR_INSUFFICIENT_BUFFER
;
4512 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4513 result
= WERR_NOMEM
;
4517 /* fill the buffer with the structures */
4518 for (i
=0; i
<*returned
; i
++)
4519 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4524 for (i
=0; i
<*returned
; i
++)
4525 free_devmode(printers
[i
].devmode
);
4527 SAFE_FREE(printers
);
4529 if ( !W_ERROR_IS_OK(result
) )
4535 /********************************************************************
4536 * handle enumeration of printers at level 1
4537 ********************************************************************/
4539 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4540 RPC_BUFFER
*buffer
, uint32 offered
,
4541 uint32
*needed
, uint32
*returned
)
4543 /* Not all the flags are equals */
4545 if (flags
& PRINTER_ENUM_LOCAL
)
4546 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4548 if (flags
& PRINTER_ENUM_NAME
)
4549 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4551 #if 0 /* JERRY - disabled for now */
4552 if (flags
& PRINTER_ENUM_REMOTE
)
4553 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4556 if (flags
& PRINTER_ENUM_NETWORK
)
4557 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4559 return WERR_OK
; /* NT4sp5 does that */
4562 /********************************************************************
4563 * handle enumeration of printers at level 2
4564 ********************************************************************/
4566 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4567 RPC_BUFFER
*buffer
, uint32 offered
,
4568 uint32
*needed
, uint32
*returned
)
4570 char *s
= servername
;
4572 if (flags
& PRINTER_ENUM_LOCAL
) {
4573 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4576 if (flags
& PRINTER_ENUM_NAME
) {
4577 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4579 if (is_myname_or_ipaddr(s
))
4580 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4582 return WERR_INVALID_NAME
;
4585 if (flags
& PRINTER_ENUM_REMOTE
)
4586 return WERR_UNKNOWN_LEVEL
;
4591 /********************************************************************
4592 * handle enumeration of printers at level 5
4593 ********************************************************************/
4595 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4596 RPC_BUFFER
*buffer
, uint32 offered
,
4597 uint32
*needed
, uint32
*returned
)
4599 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4603 /********************************************************************
4604 * api_spoolss_enumprinters
4606 * called from api_spoolss_enumprinters (see this to understand)
4607 ********************************************************************/
4609 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4611 uint32 flags
= q_u
->flags
;
4612 UNISTR2
*servername
= &q_u
->servername
;
4613 uint32 level
= q_u
->level
;
4614 RPC_BUFFER
*buffer
= NULL
;
4615 uint32 offered
= q_u
->offered
;
4616 uint32
*needed
= &r_u
->needed
;
4617 uint32
*returned
= &r_u
->returned
;
4621 /* that's an [in out] buffer */
4623 if ( q_u
->buffer
) {
4624 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4625 buffer
= r_u
->buffer
;
4628 DEBUG(4,("_spoolss_enumprinters\n"));
4635 * flags==PRINTER_ENUM_NAME
4636 * if name=="" then enumerates all printers
4637 * if name!="" then enumerate the printer
4638 * flags==PRINTER_ENUM_REMOTE
4639 * name is NULL, enumerate printers
4640 * Level 2: name!="" enumerates printers, name can't be NULL
4641 * Level 3: doesn't exist
4642 * Level 4: does a local registry lookup
4643 * Level 5: same as Level 2
4646 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4651 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4653 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4655 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4660 return WERR_UNKNOWN_LEVEL
;
4663 /****************************************************************************
4664 ****************************************************************************/
4666 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4668 PRINTER_INFO_0
*printer
=NULL
;
4669 WERROR result
= WERR_OK
;
4671 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4674 construct_printer_info_0(print_hnd
, printer
, snum
);
4676 /* check the required size. */
4677 *needed
+= spoolss_size_printer_info_0(printer
);
4679 if (*needed
> offered
) {
4680 result
= WERR_INSUFFICIENT_BUFFER
;
4684 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4685 result
= WERR_NOMEM
;
4689 /* fill the buffer with the structures */
4690 smb_io_printer_info_0("", buffer
, printer
, 0);
4700 /****************************************************************************
4701 ****************************************************************************/
4703 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4705 PRINTER_INFO_1
*printer
=NULL
;
4706 WERROR result
= WERR_OK
;
4708 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4711 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4713 /* check the required size. */
4714 *needed
+= spoolss_size_printer_info_1(printer
);
4716 if (*needed
> offered
) {
4717 result
= WERR_INSUFFICIENT_BUFFER
;
4721 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4722 result
= WERR_NOMEM
;
4726 /* fill the buffer with the structures */
4727 smb_io_printer_info_1("", buffer
, printer
, 0);
4736 /****************************************************************************
4737 ****************************************************************************/
4739 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4741 PRINTER_INFO_2
*printer
=NULL
;
4742 WERROR result
= WERR_OK
;
4744 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4747 construct_printer_info_2(print_hnd
, printer
, snum
);
4749 /* check the required size. */
4750 *needed
+= spoolss_size_printer_info_2(printer
);
4752 if (*needed
> offered
) {
4753 result
= WERR_INSUFFICIENT_BUFFER
;
4757 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4758 result
= WERR_NOMEM
;
4762 /* fill the buffer with the structures */
4763 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4764 result
= WERR_NOMEM
;
4768 free_printer_info_2(printer
);
4773 /****************************************************************************
4774 ****************************************************************************/
4776 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4778 PRINTER_INFO_3
*printer
=NULL
;
4779 WERROR result
= WERR_OK
;
4781 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4784 /* check the required size. */
4785 *needed
+= spoolss_size_printer_info_3(printer
);
4787 if (*needed
> offered
) {
4788 result
= WERR_INSUFFICIENT_BUFFER
;
4792 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4793 result
= WERR_NOMEM
;
4797 /* fill the buffer with the structures */
4798 smb_io_printer_info_3("", buffer
, printer
, 0);
4802 free_printer_info_3(printer
);
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4812 PRINTER_INFO_4
*printer
=NULL
;
4813 WERROR result
= WERR_OK
;
4815 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4818 if (!construct_printer_info_4(print_hnd
, printer
, snum
))
4821 /* check the required size. */
4822 *needed
+= spoolss_size_printer_info_4(printer
);
4824 if (*needed
> offered
) {
4825 result
= WERR_INSUFFICIENT_BUFFER
;
4829 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4830 result
= WERR_NOMEM
;
4834 /* fill the buffer with the structures */
4835 smb_io_printer_info_4("", buffer
, printer
, 0);
4839 free_printer_info_4(printer
);
4844 /****************************************************************************
4845 ****************************************************************************/
4847 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4849 PRINTER_INFO_5
*printer
=NULL
;
4850 WERROR result
= WERR_OK
;
4852 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4855 if (!construct_printer_info_5(print_hnd
, printer
, snum
))
4858 /* check the required size. */
4859 *needed
+= spoolss_size_printer_info_5(printer
);
4861 if (*needed
> offered
) {
4862 result
= WERR_INSUFFICIENT_BUFFER
;
4866 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4867 result
= WERR_NOMEM
;
4871 /* fill the buffer with the structures */
4872 smb_io_printer_info_5("", buffer
, printer
, 0);
4876 free_printer_info_5(printer
);
4881 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4883 PRINTER_INFO_7
*printer
=NULL
;
4884 WERROR result
= WERR_OK
;
4886 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4889 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4892 /* check the required size. */
4893 *needed
+= spoolss_size_printer_info_7(printer
);
4895 if (*needed
> offered
) {
4896 result
= WERR_INSUFFICIENT_BUFFER
;
4900 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4901 result
= WERR_NOMEM
;
4906 /* fill the buffer with the structures */
4907 smb_io_printer_info_7("", buffer
, printer
, 0);
4911 free_printer_info_7(printer
);
4916 /****************************************************************************
4917 ****************************************************************************/
4919 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4921 POLICY_HND
*handle
= &q_u
->handle
;
4922 uint32 level
= q_u
->level
;
4923 RPC_BUFFER
*buffer
= NULL
;
4924 uint32 offered
= q_u
->offered
;
4925 uint32
*needed
= &r_u
->needed
;
4926 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4930 /* that's an [in out] buffer */
4932 if ( q_u
->buffer
) {
4933 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4934 buffer
= r_u
->buffer
;
4939 if (!get_printer_snum(p
, handle
, &snum
))
4944 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
4946 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
4948 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
4950 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
4952 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
4954 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
4956 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
4958 return WERR_UNKNOWN_LEVEL
;
4961 /********************************************************************
4962 * fill a DRIVER_INFO_1 struct
4963 ********************************************************************/
4965 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4967 init_unistr( &info
->name
, driver
.info_3
->name
);
4970 /********************************************************************
4971 * construct_printer_driver_info_1
4972 ********************************************************************/
4974 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4976 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4977 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4979 ZERO_STRUCT(driver
);
4981 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4982 return WERR_INVALID_PRINTER_NAME
;
4984 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4985 return WERR_UNKNOWN_PRINTER_DRIVER
;
4987 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4989 free_a_printer(&printer
,2);
4994 /********************************************************************
4995 * construct_printer_driver_info_2
4996 * fill a printer_info_2 struct
4997 ********************************************************************/
4999 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5003 info
->version
=driver
.info_3
->cversion
;
5005 init_unistr( &info
->name
, driver
.info_3
->name
);
5006 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5009 if (strlen(driver
.info_3
->driverpath
)) {
5010 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5011 init_unistr( &info
->driverpath
, temp
);
5013 init_unistr( &info
->driverpath
, "" );
5015 if (strlen(driver
.info_3
->datafile
)) {
5016 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5017 init_unistr( &info
->datafile
, temp
);
5019 init_unistr( &info
->datafile
, "" );
5021 if (strlen(driver
.info_3
->configfile
)) {
5022 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5023 init_unistr( &info
->configfile
, temp
);
5025 init_unistr( &info
->configfile
, "" );
5028 /********************************************************************
5029 * construct_printer_driver_info_2
5030 * fill a printer_info_2 struct
5031 ********************************************************************/
5033 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5035 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5036 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5038 ZERO_STRUCT(printer
);
5039 ZERO_STRUCT(driver
);
5041 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5042 return WERR_INVALID_PRINTER_NAME
;
5044 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5045 return WERR_UNKNOWN_PRINTER_DRIVER
;
5047 fill_printer_driver_info_2(info
, driver
, servername
);
5049 free_a_printer(&printer
,2);
5054 /********************************************************************
5055 * copy a strings array and convert to UNICODE
5057 * convert an array of ascii string to a UNICODE string
5058 ********************************************************************/
5060 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5068 DEBUG(6,("init_unistr_array\n"));
5079 v
= ""; /* hack to handle null lists */
5082 /* hack to allow this to be used in places other than when generating
5083 the list of dependent files */
5086 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5090 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5092 /* add one extra unit16 for the second terminating NULL */
5094 if ( (tuary
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5095 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5103 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5108 /* special case for ""; we need to add both NULL's here */
5110 (*uni_array
)[j
++]=0x0000;
5111 (*uni_array
)[j
]=0x0000;
5114 DEBUGADD(6,("last one:done\n"));
5116 /* return size of array in uint16's */
5121 /********************************************************************
5122 * construct_printer_info_3
5123 * fill a printer_info_3 struct
5124 ********************************************************************/
5126 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5132 info
->version
=driver
.info_3
->cversion
;
5134 init_unistr( &info
->name
, driver
.info_3
->name
);
5135 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5137 if (strlen(driver
.info_3
->driverpath
)) {
5138 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5139 init_unistr( &info
->driverpath
, temp
);
5141 init_unistr( &info
->driverpath
, "" );
5143 if (strlen(driver
.info_3
->datafile
)) {
5144 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5145 init_unistr( &info
->datafile
, temp
);
5147 init_unistr( &info
->datafile
, "" );
5149 if (strlen(driver
.info_3
->configfile
)) {
5150 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5151 init_unistr( &info
->configfile
, temp
);
5153 init_unistr( &info
->configfile
, "" );
5155 if (strlen(driver
.info_3
->helpfile
)) {
5156 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5157 init_unistr( &info
->helpfile
, temp
);
5159 init_unistr( &info
->helpfile
, "" );
5161 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5162 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5164 info
->dependentfiles
=NULL
;
5165 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5168 /********************************************************************
5169 * construct_printer_info_3
5170 * fill a printer_info_3 struct
5171 ********************************************************************/
5173 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5175 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5176 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5178 ZERO_STRUCT(driver
);
5180 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5181 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5182 if (!W_ERROR_IS_OK(status
))
5183 return WERR_INVALID_PRINTER_NAME
;
5185 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5186 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5191 * I put this code in during testing. Helpful when commenting out the
5192 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5193 * as win2k always queries the driver using an infor level of 6.
5194 * I've left it in (but ifdef'd out) because I'll probably
5195 * use it in experimentation again in the future. --jerry 22/01/2002
5198 if (!W_ERROR_IS_OK(status
)) {
5200 * Is this a W2k client ?
5203 /* Yes - try again with a WinNT driver. */
5205 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5206 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5210 if (!W_ERROR_IS_OK(status
)) {
5211 free_a_printer(&printer
,2);
5212 return WERR_UNKNOWN_PRINTER_DRIVER
;
5220 fill_printer_driver_info_3(info
, driver
, servername
);
5222 free_a_printer(&printer
,2);
5227 /********************************************************************
5228 * construct_printer_info_6
5229 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5230 ********************************************************************/
5232 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5238 memset(&nullstr
, '\0', sizeof(fstring
));
5240 info
->version
=driver
.info_3
->cversion
;
5242 init_unistr( &info
->name
, driver
.info_3
->name
);
5243 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5245 if (strlen(driver
.info_3
->driverpath
)) {
5246 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5247 init_unistr( &info
->driverpath
, temp
);
5249 init_unistr( &info
->driverpath
, "" );
5251 if (strlen(driver
.info_3
->datafile
)) {
5252 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5253 init_unistr( &info
->datafile
, temp
);
5255 init_unistr( &info
->datafile
, "" );
5257 if (strlen(driver
.info_3
->configfile
)) {
5258 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5259 init_unistr( &info
->configfile
, temp
);
5261 init_unistr( &info
->configfile
, "" );
5263 if (strlen(driver
.info_3
->helpfile
)) {
5264 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5265 init_unistr( &info
->helpfile
, temp
);
5267 init_unistr( &info
->helpfile
, "" );
5269 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5270 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5272 info
->dependentfiles
= NULL
;
5273 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5275 info
->previousdrivernames
=NULL
;
5276 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5278 info
->driver_date
.low
=0;
5279 info
->driver_date
.high
=0;
5282 info
->driver_version_low
=0;
5283 info
->driver_version_high
=0;
5285 init_unistr( &info
->mfgname
, "");
5286 init_unistr( &info
->oem_url
, "");
5287 init_unistr( &info
->hardware_id
, "");
5288 init_unistr( &info
->provider
, "");
5291 /********************************************************************
5292 * construct_printer_info_6
5293 * fill a printer_info_6 struct
5294 ********************************************************************/
5296 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5297 fstring servername
, fstring architecture
, uint32 version
)
5299 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5300 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5303 ZERO_STRUCT(driver
);
5305 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5307 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5309 if (!W_ERROR_IS_OK(status
))
5310 return WERR_INVALID_PRINTER_NAME
;
5312 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5314 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5316 if (!W_ERROR_IS_OK(status
))
5319 * Is this a W2k client ?
5323 free_a_printer(&printer
,2);
5324 return WERR_UNKNOWN_PRINTER_DRIVER
;
5327 /* Yes - try again with a WinNT driver. */
5329 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5331 if (!W_ERROR_IS_OK(status
)) {
5332 free_a_printer(&printer
,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER
;
5337 fill_printer_driver_info_6(info
, driver
, servername
);
5339 free_a_printer(&printer
,2);
5340 free_a_printer_driver(driver
, 3);
5345 /****************************************************************************
5346 ****************************************************************************/
5348 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5350 SAFE_FREE(info
->dependentfiles
);
5353 /****************************************************************************
5354 ****************************************************************************/
5356 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5358 SAFE_FREE(info
->dependentfiles
);
5361 /****************************************************************************
5362 ****************************************************************************/
5364 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5366 DRIVER_INFO_1
*info
=NULL
;
5369 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5372 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5373 if (!W_ERROR_IS_OK(result
))
5376 /* check the required size. */
5377 *needed
+= spoolss_size_printer_driver_info_1(info
);
5379 if (*needed
> offered
) {
5380 result
= WERR_INSUFFICIENT_BUFFER
;
5384 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5385 result
= WERR_NOMEM
;
5389 /* fill the buffer with the structures */
5390 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5399 /****************************************************************************
5400 ****************************************************************************/
5402 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5404 DRIVER_INFO_2
*info
=NULL
;
5407 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5410 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5411 if (!W_ERROR_IS_OK(result
))
5414 /* check the required size. */
5415 *needed
+= spoolss_size_printer_driver_info_2(info
);
5417 if (*needed
> offered
) {
5418 result
= WERR_INSUFFICIENT_BUFFER
;
5422 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5423 result
= WERR_NOMEM
;
5427 /* fill the buffer with the structures */
5428 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5437 /****************************************************************************
5438 ****************************************************************************/
5440 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5447 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5448 if (!W_ERROR_IS_OK(result
))
5451 /* check the required size. */
5452 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5454 if (*needed
> offered
) {
5455 result
= WERR_INSUFFICIENT_BUFFER
;
5459 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5460 result
= WERR_NOMEM
;
5464 /* fill the buffer with the structures */
5465 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5468 free_printer_driver_info_3(&info
);
5473 /****************************************************************************
5474 ****************************************************************************/
5476 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5483 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5484 if (!W_ERROR_IS_OK(result
))
5487 /* check the required size. */
5488 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5490 if (*needed
> offered
) {
5491 result
= WERR_INSUFFICIENT_BUFFER
;
5495 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5496 result
= WERR_NOMEM
;
5500 /* fill the buffer with the structures */
5501 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5504 free_printer_driver_info_6(&info
);
5509 /****************************************************************************
5510 ****************************************************************************/
5512 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5514 POLICY_HND
*handle
= &q_u
->handle
;
5515 UNISTR2
*uni_arch
= &q_u
->architecture
;
5516 uint32 level
= q_u
->level
;
5517 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5518 RPC_BUFFER
*buffer
= NULL
;
5519 uint32 offered
= q_u
->offered
;
5520 uint32
*needed
= &r_u
->needed
;
5521 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5522 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5523 Printer_entry
*printer
;
5526 fstring architecture
;
5529 /* that's an [in out] buffer */
5531 if ( q_u
->buffer
) {
5532 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5533 buffer
= r_u
->buffer
;
5536 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5538 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5539 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5540 return WERR_INVALID_PRINTER_NAME
;
5544 *servermajorversion
= 0;
5545 *serverminorversion
= 0;
5547 fstrcpy(servername
, get_server_name( printer
));
5548 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5550 if (!get_printer_snum(p
, handle
, &snum
))
5555 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5557 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5559 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5561 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5564 /* apparently this call is the equivalent of
5565 EnumPrinterDataEx() for the DsDriver key */
5570 return WERR_UNKNOWN_LEVEL
;
5573 /****************************************************************************
5574 ****************************************************************************/
5576 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5578 POLICY_HND
*handle
= &q_u
->handle
;
5580 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5583 DEBUG(3,("Error in startpageprinter printer handle\n"));
5587 Printer
->page_started
=True
;
5591 /****************************************************************************
5592 ****************************************************************************/
5594 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5596 POLICY_HND
*handle
= &q_u
->handle
;
5599 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5602 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5606 if (!get_printer_snum(p
, handle
, &snum
))
5609 Printer
->page_started
=False
;
5610 print_job_endpage(snum
, Printer
->jobid
);
5615 /********************************************************************
5616 * api_spoolss_getprinter
5617 * called from the spoolss dispatcher
5619 ********************************************************************/
5621 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5623 POLICY_HND
*handle
= &q_u
->handle
;
5624 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5625 uint32
*jobid
= &r_u
->jobid
;
5627 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5631 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5632 struct current_user user
;
5635 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5639 get_current_user(&user
, p
);
5642 * a nice thing with NT is it doesn't listen to what you tell it.
5643 * when asked to send _only_ RAW datas, it tries to send datas
5646 * So I add checks like in NT Server ...
5649 if (info_1
->p_datatype
!= 0) {
5650 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5651 if (strcmp(datatype
, "RAW") != 0) {
5653 return WERR_INVALID_DATATYPE
;
5657 /* get the share number of the printer */
5658 if (!get_printer_snum(p
, handle
, &snum
)) {
5662 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5664 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5666 /* An error occured in print_job_start() so return an appropriate
5669 if (Printer
->jobid
== -1) {
5670 return map_werror_from_unix(errno
);
5673 Printer
->document_started
=True
;
5674 (*jobid
) = Printer
->jobid
;
5679 /********************************************************************
5680 * api_spoolss_getprinter
5681 * called from the spoolss dispatcher
5683 ********************************************************************/
5685 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5687 POLICY_HND
*handle
= &q_u
->handle
;
5689 return _spoolss_enddocprinter_internal(p
, handle
);
5692 /****************************************************************************
5693 ****************************************************************************/
5695 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5697 POLICY_HND
*handle
= &q_u
->handle
;
5698 uint32 buffer_size
= q_u
->buffer_size
;
5699 uint8
*buffer
= q_u
->buffer
;
5700 uint32
*buffer_written
= &q_u
->buffer_size2
;
5702 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5705 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5706 r_u
->buffer_written
= q_u
->buffer_size2
;
5710 if (!get_printer_snum(p
, handle
, &snum
))
5713 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5714 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5715 if (*buffer_written
== (uint32
)-1) {
5716 r_u
->buffer_written
= 0;
5717 if (errno
== ENOSPC
)
5718 return WERR_NO_SPOOL_SPACE
;
5720 return WERR_ACCESS_DENIED
;
5723 r_u
->buffer_written
= q_u
->buffer_size2
;
5728 /********************************************************************
5729 * api_spoolss_getprinter
5730 * called from the spoolss dispatcher
5732 ********************************************************************/
5734 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5737 struct current_user user
;
5739 WERROR errcode
= WERR_BADFUNC
;
5740 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5742 get_current_user(&user
, p
);
5745 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5749 if (!get_printer_snum(p
, handle
, &snum
))
5753 case PRINTER_CONTROL_PAUSE
:
5754 if (print_queue_pause(&user
, snum
, &errcode
)) {
5758 case PRINTER_CONTROL_RESUME
:
5759 case PRINTER_CONTROL_UNPAUSE
:
5760 if (print_queue_resume(&user
, snum
, &errcode
)) {
5764 case PRINTER_CONTROL_PURGE
:
5765 if (print_queue_purge(&user
, snum
, &errcode
)) {
5770 return WERR_UNKNOWN_LEVEL
;
5776 /********************************************************************
5777 * api_spoolss_abortprinter
5778 * From MSDN: "Deletes printer's spool file if printer is configured
5780 ********************************************************************/
5782 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5784 POLICY_HND
*handle
= &q_u
->handle
;
5785 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5787 struct current_user user
;
5788 WERROR errcode
= WERR_OK
;
5791 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5795 if (!get_printer_snum(p
, handle
, &snum
))
5798 get_current_user( &user
, p
);
5800 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5805 /********************************************************************
5806 * called by spoolss_api_setprinter
5807 * when updating a printer description
5808 ********************************************************************/
5810 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5811 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5812 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5814 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5818 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5820 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5821 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(handle
)));
5824 result
= WERR_BADFID
;
5828 /* Check the user has permissions to change the security
5829 descriptor. By experimentation with two NT machines, the user
5830 requires Full Access to the printer to change security
5833 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5834 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5835 result
= WERR_ACCESS_DENIED
;
5839 /* NT seems to like setting the security descriptor even though
5840 nothing may have actually changed. */
5842 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5844 if (DEBUGLEVEL
>= 10) {
5848 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5849 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5850 PRINTERNAME(snum
), the_acl
->num_aces
));
5852 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5855 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5857 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5858 the_acl
->ace
[i
].info
.mask
));
5861 the_acl
= secdesc_ctr
->sec
->dacl
;
5864 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5865 PRINTERNAME(snum
), the_acl
->num_aces
));
5867 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5870 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5872 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5873 the_acl
->ace
[i
].info
.mask
));
5876 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5880 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5882 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5887 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5894 /********************************************************************
5895 Canonicalize printer info from a client
5897 ATTN: It does not matter what we set the servername to hear
5898 since we do the necessary work in get_a_printer() to set it to
5899 the correct value based on what the client sent in the
5900 _spoolss_open_printer_ex().
5901 ********************************************************************/
5903 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5905 fstring printername
;
5908 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5909 "portname=%s drivername=%s comment=%s location=%s\n",
5910 info
->servername
, info
->printername
, info
->sharename
,
5911 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5913 /* we force some elements to "correct" values */
5914 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5915 fstrcpy(info
->sharename
, lp_servicename(snum
));
5917 /* check to see if we allow printername != sharename */
5919 if ( lp_force_printername(snum
) ) {
5920 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5921 global_myname(), info
->sharename
);
5924 /* make sure printername is in \\server\printername format */
5926 fstrcpy( printername
, info
->printername
);
5928 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5929 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5933 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5934 global_myname(), p
);
5937 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5938 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5945 /****************************************************************************
5946 ****************************************************************************/
5948 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5950 char *cmd
= lp_addprinter_cmd();
5956 fstring remote_machine
= "%m";
5957 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5958 BOOL is_print_op
= False
;
5960 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5962 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5963 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5964 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5965 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5968 is_print_op
= user_has_privileges( token
, &se_printop
);
5970 DEBUG(10,("Running [%s]\n", command
));
5972 /********* BEGIN SePrintOperatorPrivilege **********/
5977 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5978 /* Tell everyone we updated smb.conf. */
5979 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
5985 /********* END SePrintOperatorPrivilege **********/
5987 DEBUGADD(10,("returned [%d]\n", ret
));
5995 /* reload our services immediately */
5996 reload_services( False
);
5999 /* Get lines and convert them back to dos-codepage */
6000 qlines
= fd_lines_load(fd
, &numlines
);
6001 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6004 /* Set the portname to what the script says the portname should be. */
6005 /* but don't require anything to be return from the script exit a good error code */
6008 /* Set the portname to what the script says the portname should be. */
6009 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6010 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6013 file_lines_free(qlines
);
6017 /********************************************************************
6018 * Called by spoolss_api_setprinter
6019 * when updating a printer description.
6020 ********************************************************************/
6022 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6023 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6024 DEVICEMODE
*devmode
)
6027 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6028 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6033 DEBUG(8,("update_printer\n"));
6038 result
= WERR_BADFID
;
6042 if (!get_printer_snum(p
, handle
, &snum
)) {
6043 result
= WERR_BADFID
;
6047 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6048 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6049 result
= WERR_BADFID
;
6053 DEBUGADD(8,("Converting info_2 struct\n"));
6056 * convert_printer_info converts the incoming
6057 * info from the client and overwrites the info
6058 * just read from the tdb in the pointer 'printer'.
6061 if (!convert_printer_info(info
, printer
, level
)) {
6062 result
= WERR_NOMEM
;
6067 /* we have a valid devmode
6068 convert it and link it*/
6070 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6071 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6072 &printer
->info_2
->devmode
)) {
6073 result
= WERR_NOMEM
;
6078 /* Do sanity check on the requested changes for Samba */
6080 if (!check_printer_ok(printer
->info_2
, snum
)) {
6081 result
= WERR_INVALID_PARAM
;
6085 /* FIXME!!! If the driver has changed we really should verify that
6086 it is installed before doing much else --jerry */
6088 /* Check calling user has permission to update printer description */
6090 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6091 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6092 result
= WERR_ACCESS_DENIED
;
6096 /* Call addprinter hook */
6097 /* Check changes to see if this is really needed */
6099 if ( *lp_addprinter_cmd()
6100 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6101 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6102 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6103 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6105 /* add_printer_hook() will call reload_services() */
6107 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6108 result
= WERR_ACCESS_DENIED
;
6114 * When a *new* driver is bound to a printer, the drivername is used to
6115 * lookup previously saved driver initialization info, which is then
6116 * bound to the printer, simulating what happens in the Windows arch.
6118 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6120 if (!set_driver_init(printer
, 2))
6122 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6123 printer
->info_2
->drivername
));
6126 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6127 printer
->info_2
->drivername
));
6129 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6133 * flag which changes actually occured. This is a small subset of
6134 * all the possible changes. We also have to update things in the
6138 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6139 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6140 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6141 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6143 notify_printer_comment(snum
, printer
->info_2
->comment
);
6146 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6147 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6148 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6149 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6151 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6154 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6157 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6160 pname
= printer
->info_2
->printername
;
6163 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6164 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6165 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6167 notify_printer_printername( snum
, pname
);
6170 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6171 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6172 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6173 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6175 notify_printer_port(snum
, printer
->info_2
->portname
);
6178 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6179 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6180 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6181 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6183 notify_printer_location(snum
, printer
->info_2
->location
);
6186 /* here we need to update some more DsSpooler keys */
6187 /* uNCName, serverName, shortServerName */
6189 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6190 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6191 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6192 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6193 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6195 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6196 global_myname(), printer
->info_2
->sharename
);
6197 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6198 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6199 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6201 /* Update printer info */
6202 result
= mod_a_printer(printer
, 2);
6205 free_a_printer(&printer
, 2);
6206 free_a_printer(&old_printer
, 2);
6212 /****************************************************************************
6213 ****************************************************************************/
6214 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6215 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6218 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6220 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6222 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6227 if (!get_printer_snum(p
, handle
, &snum
))
6230 nt_printer_publish(Printer
, snum
, info7
->action
);
6234 return WERR_UNKNOWN_LEVEL
;
6237 /****************************************************************************
6238 ****************************************************************************/
6240 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6242 POLICY_HND
*handle
= &q_u
->handle
;
6243 uint32 level
= q_u
->level
;
6244 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6245 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6246 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6247 uint32 command
= q_u
->command
;
6250 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6253 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6257 /* check the level */
6260 return control_printer(handle
, command
, p
);
6262 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6263 if (!W_ERROR_IS_OK(result
))
6266 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6269 return update_printer_sec(handle
, level
, info
, p
,
6272 return publish_or_unpublish_printer(p
, handle
, info
);
6274 return WERR_UNKNOWN_LEVEL
;
6278 /****************************************************************************
6279 ****************************************************************************/
6281 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6283 POLICY_HND
*handle
= &q_u
->handle
;
6284 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6287 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6291 if (Printer
->notify
.client_connected
==True
) {
6294 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6296 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6297 !get_printer_snum(p
, handle
, &snum
) )
6300 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6303 Printer
->notify
.flags
=0;
6304 Printer
->notify
.options
=0;
6305 Printer
->notify
.localmachine
[0]='\0';
6306 Printer
->notify
.printerlocal
=0;
6307 if (Printer
->notify
.option
)
6308 free_spool_notify_option(&Printer
->notify
.option
);
6309 Printer
->notify
.client_connected
=False
;
6314 /****************************************************************************
6315 ****************************************************************************/
6317 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6319 /* that's an [in out] buffer */
6322 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6325 return WERR_INVALID_PARAM
; /* this is what a NT server
6326 returns for AddJob. AddJob
6327 must fail on non-local
6331 /****************************************************************************
6332 ****************************************************************************/
6334 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6335 int position
, int snum
,
6336 NT_PRINTER_INFO_LEVEL
*ntprinter
)
6340 t
=gmtime(&queue
->time
);
6342 job_info
->jobid
=queue
->job
;
6343 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6344 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6345 init_unistr(&job_info
->username
, queue
->fs_user
);
6346 init_unistr(&job_info
->document
, queue
->fs_file
);
6347 init_unistr(&job_info
->datatype
, "RAW");
6348 init_unistr(&job_info
->text_status
, "");
6349 job_info
->status
=nt_printj_status(queue
->status
);
6350 job_info
->priority
=queue
->priority
;
6351 job_info
->position
=position
;
6352 job_info
->totalpages
=queue
->page_count
;
6353 job_info
->pagesprinted
=0;
6355 make_systemtime(&job_info
->submitted
, t
);
6358 /****************************************************************************
6359 ****************************************************************************/
6361 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6362 int position
, int snum
,
6363 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6364 DEVICEMODE
*devmode
)
6368 t
=gmtime(&queue
->time
);
6370 job_info
->jobid
=queue
->job
;
6372 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6374 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6375 init_unistr(&job_info
->username
, queue
->fs_user
);
6376 init_unistr(&job_info
->document
, queue
->fs_file
);
6377 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6378 init_unistr(&job_info
->datatype
, "RAW");
6379 init_unistr(&job_info
->printprocessor
, "winprint");
6380 init_unistr(&job_info
->parameters
, "");
6381 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6382 init_unistr(&job_info
->text_status
, "");
6384 /* and here the security descriptor */
6386 job_info
->status
=nt_printj_status(queue
->status
);
6387 job_info
->priority
=queue
->priority
;
6388 job_info
->position
=position
;
6389 job_info
->starttime
=0;
6390 job_info
->untiltime
=0;
6391 job_info
->totalpages
=queue
->page_count
;
6392 job_info
->size
=queue
->size
;
6393 make_systemtime(&(job_info
->submitted
), t
);
6394 job_info
->timeelapsed
=0;
6395 job_info
->pagesprinted
=0;
6397 job_info
->devmode
= devmode
;
6402 /****************************************************************************
6403 Enumjobs at level 1.
6404 ****************************************************************************/
6406 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6407 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6408 RPC_BUFFER
*buffer
, uint32 offered
,
6409 uint32
*needed
, uint32
*returned
)
6413 WERROR result
= WERR_OK
;
6415 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6422 for (i
=0; i
<*returned
; i
++)
6423 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6427 /* check the required size. */
6428 for (i
=0; i
<*returned
; i
++)
6429 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6431 if (*needed
> offered
) {
6432 result
= WERR_INSUFFICIENT_BUFFER
;
6436 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6437 result
= WERR_NOMEM
;
6441 /* fill the buffer with the structures */
6442 for (i
=0; i
<*returned
; i
++)
6443 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6449 if ( !W_ERROR_IS_OK(result
) )
6455 /****************************************************************************
6456 Enumjobs at level 2.
6457 ****************************************************************************/
6459 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6460 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6461 RPC_BUFFER
*buffer
, uint32 offered
,
6462 uint32
*needed
, uint32
*returned
)
6464 JOB_INFO_2
*info
= NULL
;
6466 WERROR result
= WERR_OK
;
6467 DEVICEMODE
*devmode
= NULL
;
6469 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6474 /* this should not be a failure condition if the devmode is NULL */
6476 devmode
= construct_dev_mode(snum
);
6478 for (i
=0; i
<*returned
; i
++)
6479 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6481 free_a_printer(&ntprinter
, 2);
6484 /* check the required size. */
6485 for (i
=0; i
<*returned
; i
++)
6486 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6488 if (*needed
> offered
) {
6489 result
= WERR_INSUFFICIENT_BUFFER
;
6493 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6494 result
= WERR_NOMEM
;
6498 /* fill the buffer with the structures */
6499 for (i
=0; i
<*returned
; i
++)
6500 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6503 free_devmode(devmode
);
6506 if ( !W_ERROR_IS_OK(result
) )
6513 /****************************************************************************
6515 ****************************************************************************/
6517 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6519 POLICY_HND
*handle
= &q_u
->handle
;
6520 uint32 level
= q_u
->level
;
6521 RPC_BUFFER
*buffer
= NULL
;
6522 uint32 offered
= q_u
->offered
;
6523 uint32
*needed
= &r_u
->needed
;
6524 uint32
*returned
= &r_u
->returned
;
6526 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6528 print_status_struct prt_status
;
6529 print_queue_struct
*queue
=NULL
;
6531 /* that's an [in out] buffer */
6533 if ( q_u
->buffer
) {
6534 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6535 buffer
= r_u
->buffer
;
6538 DEBUG(4,("_spoolss_enumjobs\n"));
6543 /* lookup the printer snum and tdb entry */
6545 if (!get_printer_snum(p
, handle
, &snum
))
6548 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6549 if ( !W_ERROR_IS_OK(wret
) )
6552 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6553 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6555 if (*returned
== 0) {
6562 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6565 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6570 wret
= WERR_UNKNOWN_LEVEL
;
6573 free_a_printer( &ntprinter
, 2 );
6577 /****************************************************************************
6578 ****************************************************************************/
6580 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6585 /****************************************************************************
6586 ****************************************************************************/
6588 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6590 POLICY_HND
*handle
= &q_u
->handle
;
6591 uint32 jobid
= q_u
->jobid
;
6592 uint32 command
= q_u
->command
;
6594 struct current_user user
;
6596 WERROR errcode
= WERR_BADFUNC
;
6598 if (!get_printer_snum(p
, handle
, &snum
)) {
6602 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6603 return WERR_INVALID_PRINTER_NAME
;
6606 get_current_user(&user
, p
);
6609 case JOB_CONTROL_CANCEL
:
6610 case JOB_CONTROL_DELETE
:
6611 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6615 case JOB_CONTROL_PAUSE
:
6616 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6620 case JOB_CONTROL_RESTART
:
6621 case JOB_CONTROL_RESUME
:
6622 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6627 return WERR_UNKNOWN_LEVEL
;
6633 /****************************************************************************
6634 Enumerates all printer drivers at level 1.
6635 ****************************************************************************/
6637 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6642 fstring
*list
= NULL
;
6643 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6644 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6645 WERROR result
= WERR_OK
;
6649 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6651 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6652 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6658 if((tdi1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6659 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6660 SAFE_FREE(driver_info_1
);
6664 else driver_info_1
= tdi1
;
6667 for (i
=0; i
<ndrivers
; i
++) {
6669 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6670 ZERO_STRUCT(driver
);
6671 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6672 architecture
, version
);
6673 if (!W_ERROR_IS_OK(status
)) {
6677 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6678 free_a_printer_driver(driver
, 3);
6681 *returned
+=ndrivers
;
6685 /* check the required size. */
6686 for (i
=0; i
<*returned
; i
++) {
6687 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6688 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6691 if (*needed
> offered
) {
6692 result
= WERR_INSUFFICIENT_BUFFER
;
6696 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6697 result
= WERR_NOMEM
;
6701 /* fill the buffer with the driver structures */
6702 for (i
=0; i
<*returned
; i
++) {
6703 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6704 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6708 SAFE_FREE(driver_info_1
);
6710 if ( !W_ERROR_IS_OK(result
) )
6716 /****************************************************************************
6717 Enumerates all printer drivers at level 2.
6718 ****************************************************************************/
6720 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6725 fstring
*list
= NULL
;
6726 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6727 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6728 WERROR result
= WERR_OK
;
6732 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6734 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6735 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6741 if((tdi2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6742 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6743 SAFE_FREE(driver_info_2
);
6747 else driver_info_2
= tdi2
;
6750 for (i
=0; i
<ndrivers
; i
++) {
6753 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6754 ZERO_STRUCT(driver
);
6755 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6756 architecture
, version
);
6757 if (!W_ERROR_IS_OK(status
)) {
6761 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6762 free_a_printer_driver(driver
, 3);
6765 *returned
+=ndrivers
;
6769 /* check the required size. */
6770 for (i
=0; i
<*returned
; i
++) {
6771 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6772 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6775 if (*needed
> offered
) {
6776 result
= WERR_INSUFFICIENT_BUFFER
;
6780 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6781 result
= WERR_NOMEM
;
6785 /* fill the buffer with the form structures */
6786 for (i
=0; i
<*returned
; i
++) {
6787 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6788 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6792 SAFE_FREE(driver_info_2
);
6794 if ( !W_ERROR_IS_OK(result
) )
6800 /****************************************************************************
6801 Enumerates all printer drivers at level 3.
6802 ****************************************************************************/
6804 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6809 fstring
*list
= NULL
;
6810 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6811 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6812 WERROR result
= WERR_OK
;
6816 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6818 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6819 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6825 if((tdi3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6826 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6827 SAFE_FREE(driver_info_3
);
6831 else driver_info_3
= tdi3
;
6834 for (i
=0; i
<ndrivers
; i
++) {
6837 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6838 ZERO_STRUCT(driver
);
6839 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6840 architecture
, version
);
6841 if (!W_ERROR_IS_OK(status
)) {
6845 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6846 free_a_printer_driver(driver
, 3);
6849 *returned
+=ndrivers
;
6853 /* check the required size. */
6854 for (i
=0; i
<*returned
; i
++) {
6855 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6856 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6859 if (*needed
> offered
) {
6860 result
= WERR_INSUFFICIENT_BUFFER
;
6864 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6865 result
= WERR_NOMEM
;
6869 /* fill the buffer with the driver structures */
6870 for (i
=0; i
<*returned
; i
++) {
6871 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6872 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6876 for (i
=0; i
<*returned
; i
++)
6877 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6879 SAFE_FREE(driver_info_3
);
6881 if ( !W_ERROR_IS_OK(result
) )
6887 /****************************************************************************
6888 Enumerates all printer drivers.
6889 ****************************************************************************/
6891 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6893 uint32 level
= q_u
->level
;
6894 RPC_BUFFER
*buffer
= NULL
;
6895 uint32 offered
= q_u
->offered
;
6896 uint32
*needed
= &r_u
->needed
;
6897 uint32
*returned
= &r_u
->returned
;
6900 fstring architecture
;
6902 /* that's an [in out] buffer */
6904 if ( q_u
->buffer
) {
6905 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6906 buffer
= r_u
->buffer
;
6909 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6914 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
6915 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
6917 if ( !is_myname_or_ipaddr( servername
) )
6918 return WERR_UNKNOWN_PRINTER_DRIVER
;
6922 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6924 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6926 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6928 return WERR_UNKNOWN_LEVEL
;
6932 /****************************************************************************
6933 ****************************************************************************/
6935 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6937 form
->flag
=list
->flag
;
6938 init_unistr(&form
->name
, list
->name
);
6939 form
->width
=list
->width
;
6940 form
->length
=list
->length
;
6941 form
->left
=list
->left
;
6942 form
->top
=list
->top
;
6943 form
->right
=list
->right
;
6944 form
->bottom
=list
->bottom
;
6947 /****************************************************************************
6948 ****************************************************************************/
6950 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6952 uint32 level
= q_u
->level
;
6953 RPC_BUFFER
*buffer
= NULL
;
6954 uint32 offered
= q_u
->offered
;
6955 uint32
*needed
= &r_u
->needed
;
6956 uint32
*numofforms
= &r_u
->numofforms
;
6957 uint32 numbuiltinforms
;
6959 nt_forms_struct
*list
=NULL
;
6960 nt_forms_struct
*builtinlist
=NULL
;
6965 /* that's an [in out] buffer */
6967 if ( q_u
->buffer
) {
6968 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6969 buffer
= r_u
->buffer
;
6972 DEBUG(4,("_spoolss_enumforms\n"));
6973 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6974 DEBUGADD(5,("Info level [%d]\n", level
));
6976 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6977 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6978 *numofforms
= get_ntforms(&list
);
6979 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6980 *numofforms
+= numbuiltinforms
;
6982 if (*numofforms
== 0)
6983 return WERR_NO_MORE_ITEMS
;
6987 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
6992 /* construct the list of form structures */
6993 for (i
=0; i
<numbuiltinforms
; i
++) {
6994 DEBUGADD(6,("Filling form number [%d]\n",i
));
6995 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6998 SAFE_FREE(builtinlist
);
7000 for (; i
<*numofforms
; i
++) {
7001 DEBUGADD(6,("Filling form number [%d]\n",i
));
7002 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7007 /* check the required size. */
7008 for (i
=0; i
<numbuiltinforms
; i
++) {
7009 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7010 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7012 for (; i
<*numofforms
; i
++) {
7013 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7014 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7017 *needed
=buffer_size
;
7019 if (*needed
> offered
) {
7022 return WERR_INSUFFICIENT_BUFFER
;
7025 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7031 /* fill the buffer with the form structures */
7032 for (i
=0; i
<numbuiltinforms
; i
++) {
7033 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7034 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7036 for (; i
<*numofforms
; i
++) {
7037 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7038 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7047 SAFE_FREE(builtinlist
);
7048 return WERR_UNKNOWN_LEVEL
;
7053 /****************************************************************************
7054 ****************************************************************************/
7056 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7058 uint32 level
= q_u
->level
;
7059 UNISTR2
*uni_formname
= &q_u
->formname
;
7060 RPC_BUFFER
*buffer
= NULL
;
7061 uint32 offered
= q_u
->offered
;
7062 uint32
*needed
= &r_u
->needed
;
7064 nt_forms_struct
*list
=NULL
;
7065 nt_forms_struct builtin_form
;
7070 int numofforms
=0, i
=0;
7072 /* that's an [in out] buffer */
7074 if ( q_u
->buffer
) {
7075 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7076 buffer
= r_u
->buffer
;
7079 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7081 DEBUG(4,("_spoolss_getform\n"));
7082 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7083 DEBUGADD(5,("Info level [%d]\n", level
));
7085 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7086 if (!foundBuiltin
) {
7087 numofforms
= get_ntforms(&list
);
7088 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7090 if (numofforms
== 0)
7097 fill_form_1(&form_1
, &builtin_form
);
7100 /* Check if the requested name is in the list of form structures */
7101 for (i
=0; i
<numofforms
; i
++) {
7103 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7105 if (strequal(form_name
, list
[i
].name
)) {
7106 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7107 fill_form_1(&form_1
, &list
[i
]);
7113 if (i
== numofforms
) {
7117 /* check the required size. */
7119 *needed
=spoolss_size_form_1(&form_1
);
7121 if (*needed
> offered
)
7122 return WERR_INSUFFICIENT_BUFFER
;
7124 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7127 /* fill the buffer with the form structures */
7128 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7129 smb_io_form_1("", buffer
, &form_1
, 0);
7135 return WERR_UNKNOWN_LEVEL
;
7139 /****************************************************************************
7140 ****************************************************************************/
7142 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7144 init_unistr(&port
->port_name
, name
);
7147 /****************************************************************************
7148 ****************************************************************************/
7150 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7152 init_unistr(&port
->port_name
, name
);
7153 init_unistr(&port
->monitor_name
, "Local Monitor");
7154 init_unistr(&port
->description
, "Local Port");
7155 port
->port_type
=PORT_TYPE_WRITE
;
7160 /****************************************************************************
7161 wrapper around the enumer ports command
7162 ****************************************************************************/
7164 WERROR
enumports_hook( int *count
, char ***lines
)
7166 char *cmd
= lp_enumports_cmd();
7174 /* if no hook then just fill in the default port */
7177 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7178 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7183 /* we have a valid enumport command */
7185 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7187 DEBUG(10,("Running [%s]\n", command
));
7188 ret
= smbrun(command
, &fd
);
7189 DEBUG(10,("Returned [%d]\n", ret
));
7194 return WERR_ACCESS_DENIED
;
7198 qlines
= fd_lines_load(fd
, &numlines
);
7199 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7209 /****************************************************************************
7211 ****************************************************************************/
7213 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7215 PORT_INFO_1
*ports
=NULL
;
7217 WERROR result
= WERR_OK
;
7221 if ( !W_ERROR_IS_OK(result
= enumports_hook( &numlines
, &qlines
)) )
7225 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7226 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7227 dos_errstr(WERR_NOMEM
)));
7228 file_lines_free(qlines
);
7232 for (i
=0; i
<numlines
; i
++) {
7233 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7234 fill_port_1(&ports
[i
], qlines
[i
]);
7237 file_lines_free(qlines
);
7240 *returned
= numlines
;
7242 /* check the required size. */
7243 for (i
=0; i
<*returned
; i
++) {
7244 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7245 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7248 if (*needed
> offered
) {
7249 result
= WERR_INSUFFICIENT_BUFFER
;
7253 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7254 result
= WERR_NOMEM
;
7258 /* fill the buffer with the ports structures */
7259 for (i
=0; i
<*returned
; i
++) {
7260 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7261 smb_io_port_1("", buffer
, &ports
[i
], 0);
7267 if ( !W_ERROR_IS_OK(result
) )
7273 /****************************************************************************
7275 ****************************************************************************/
7277 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7279 PORT_INFO_2
*ports
=NULL
;
7281 WERROR result
= WERR_OK
;
7285 if ( !W_ERROR_IS_OK(result
= enumports_hook( &numlines
, &qlines
)) )
7290 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7291 file_lines_free(qlines
);
7295 for (i
=0; i
<numlines
; i
++) {
7296 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7297 fill_port_2(&(ports
[i
]), qlines
[i
]);
7300 file_lines_free(qlines
);
7303 *returned
= numlines
;
7305 /* check the required size. */
7306 for (i
=0; i
<*returned
; i
++) {
7307 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7308 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7311 if (*needed
> offered
) {
7312 result
= WERR_INSUFFICIENT_BUFFER
;
7316 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7317 result
= WERR_NOMEM
;
7321 /* fill the buffer with the ports structures */
7322 for (i
=0; i
<*returned
; i
++) {
7323 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7324 smb_io_port_2("", buffer
, &ports
[i
], 0);
7330 if ( !W_ERROR_IS_OK(result
) )
7336 /****************************************************************************
7338 ****************************************************************************/
7340 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7342 uint32 level
= q_u
->level
;
7343 RPC_BUFFER
*buffer
= NULL
;
7344 uint32 offered
= q_u
->offered
;
7345 uint32
*needed
= &r_u
->needed
;
7346 uint32
*returned
= &r_u
->returned
;
7348 /* that's an [in out] buffer */
7350 if ( q_u
->buffer
) {
7351 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7352 buffer
= r_u
->buffer
;
7355 DEBUG(4,("_spoolss_enumports\n"));
7362 return enumports_level_1(buffer
, offered
, needed
, returned
);
7364 return enumports_level_2(buffer
, offered
, needed
, returned
);
7366 return WERR_UNKNOWN_LEVEL
;
7370 /****************************************************************************
7371 ****************************************************************************/
7373 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7374 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7375 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7376 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7379 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7382 WERROR err
= WERR_OK
;
7384 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7385 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7389 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7390 if (!convert_printer_info(info
, printer
, 2)) {
7391 free_a_printer(&printer
, 2);
7395 /* check to see if the printer already exists */
7397 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7398 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7399 printer
->info_2
->sharename
));
7400 free_a_printer(&printer
, 2);
7401 return WERR_PRINTER_ALREADY_EXISTS
;
7404 /* FIXME!!! smbd should check to see if the driver is installed before
7405 trying to add a printer like this --jerry */
7407 if (*lp_addprinter_cmd() ) {
7408 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7409 free_a_printer(&printer
,2);
7410 return WERR_ACCESS_DENIED
;
7413 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7414 "smb.conf parameter \"addprinter command\" is defined. This"
7415 "parameter must exist for this call to succeed\n",
7416 printer
->info_2
->sharename
));
7419 /* use our primary netbios name since get_a_printer() will convert
7420 it to what the client expects on a case by case basis */
7422 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7423 printer
->info_2
->sharename
);
7426 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7427 free_a_printer(&printer
,2);
7428 return WERR_ACCESS_DENIED
;
7431 /* you must be a printer admin to add a new printer */
7432 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7433 free_a_printer(&printer
,2);
7434 return WERR_ACCESS_DENIED
;
7438 * Do sanity check on the requested changes for Samba.
7441 if (!check_printer_ok(printer
->info_2
, snum
)) {
7442 free_a_printer(&printer
,2);
7443 return WERR_INVALID_PARAM
;
7447 * When a printer is created, the drivername bound to the printer is used
7448 * to lookup previously saved driver initialization info, which is then
7449 * bound to the new printer, simulating what happens in the Windows arch.
7454 set_driver_init(printer
, 2);
7458 /* A valid devmode was included, convert and link it
7460 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7462 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7463 &printer
->info_2
->devmode
))
7467 /* write the ASCII on disk */
7468 err
= mod_a_printer(printer
, 2);
7469 if (!W_ERROR_IS_OK(err
)) {
7470 free_a_printer(&printer
,2);
7474 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7475 /* Handle open failed - remove addition. */
7476 del_a_printer(printer
->info_2
->sharename
);
7477 free_a_printer(&printer
,2);
7478 return WERR_ACCESS_DENIED
;
7481 update_c_setprinter(False
);
7482 free_a_printer(&printer
,2);
7487 /****************************************************************************
7488 ****************************************************************************/
7490 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7492 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7493 uint32 level
= q_u
->level
;
7494 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7495 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7496 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7497 uint32 user_switch
= q_u
->user_switch
;
7498 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7499 POLICY_HND
*handle
= &r_u
->handle
;
7503 /* we don't handle yet */
7504 /* but I know what to do ... */
7505 return WERR_UNKNOWN_LEVEL
;
7507 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7509 user_switch
, user
, handle
);
7511 return WERR_UNKNOWN_LEVEL
;
7515 /****************************************************************************
7516 ****************************************************************************/
7518 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7520 uint32 level
= q_u
->level
;
7521 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7522 WERROR err
= WERR_OK
;
7523 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7524 struct current_user user
;
7525 fstring driver_name
;
7528 ZERO_STRUCT(driver
);
7530 get_current_user(&user
, p
);
7532 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7537 DEBUG(5,("Cleaning driver's information\n"));
7538 err
= clean_up_driver_struct(driver
, level
, &user
);
7539 if (!W_ERROR_IS_OK(err
))
7542 DEBUG(5,("Moving driver to final destination\n"));
7543 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &user
, &err
)) ) {
7547 if (add_a_printer_driver(driver
, level
)!=0) {
7548 err
= WERR_ACCESS_DENIED
;
7552 /* BEGIN_ADMIN_LOG */
7555 fstrcpy(driver_name
, driver
.info_3
->name
? driver
.info_3
->name
: "");
7556 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7557 driver_name
, get_drv_ver_to_os(driver
.info_3
->cversion
),uidtoname(user
.uid
));
7560 fstrcpy(driver_name
, driver
.info_6
->name
? driver
.info_6
->name
: "");
7561 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7562 driver_name
, get_drv_ver_to_os(driver
.info_6
->version
),uidtoname(user
.uid
));
7568 * I think this is where he DrvUpgradePrinter() hook would be
7569 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7570 * server. Right now, we just need to send ourselves a message
7571 * to update each printer bound to this driver. --jerry
7574 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7575 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7580 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7581 * decide if the driver init data should be deleted. The rules are:
7582 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7583 * 2) delete init data only if there is no 2k/Xp driver
7584 * 3) always delete init data
7585 * The generalized rule is always use init data from the highest order driver.
7586 * It is necessary to follow the driver install by an initialization step to
7587 * finish off this process.
7590 version
= driver
.info_3
->cversion
;
7591 else if (level
== 6)
7592 version
= driver
.info_6
->version
;
7597 * 9x printer driver - never delete init data
7600 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7605 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7606 * there is no 2k/Xp driver init data for this driver name.
7610 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7612 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7614 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7616 if (!del_driver_init(driver_name
))
7617 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7620 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7622 free_a_printer_driver(driver1
,3);
7623 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7630 * 2k or Xp printer driver - always delete init data
7633 if (!del_driver_init(driver_name
))
7634 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7638 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7644 free_a_printer_driver(driver
, level
);
7648 /********************************************************************
7649 * spoolss_addprinterdriverex
7650 ********************************************************************/
7652 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7654 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7655 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7658 * we only support the semantics of AddPrinterDriver()
7659 * i.e. only copy files that are newer than existing ones
7662 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7663 return WERR_ACCESS_DENIED
;
7665 ZERO_STRUCT(q_u_local
);
7666 ZERO_STRUCT(r_u_local
);
7668 /* just pass the information off to _spoolss_addprinterdriver() */
7669 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7670 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7671 q_u_local
.level
= q_u
->level
;
7672 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7674 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7677 /****************************************************************************
7678 ****************************************************************************/
7680 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7682 init_unistr(&info
->name
, name
);
7685 /****************************************************************************
7686 ****************************************************************************/
7688 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7694 const char *short_archi
;
7695 DRIVER_DIRECTORY_1
*info
=NULL
;
7696 WERROR result
= WERR_OK
;
7698 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7699 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7701 /* check for beginning double '\'s and that the server
7704 pservername
= servername
;
7705 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7709 if ( !is_myname_or_ipaddr( pservername
) )
7710 return WERR_INVALID_PARAM
;
7712 if (!(short_archi
= get_short_archi(long_archi
)))
7713 return WERR_INVALID_ENVIRONMENT
;
7715 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7718 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7720 DEBUG(4,("printer driver directory: [%s]\n", path
));
7722 fill_driverdir_1(info
, path
);
7724 *needed
+= spoolss_size_driverdir_info_1(info
);
7726 if (*needed
> offered
) {
7727 result
= WERR_INSUFFICIENT_BUFFER
;
7731 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7732 result
= WERR_NOMEM
;
7736 smb_io_driverdir_1("", buffer
, info
, 0);
7744 /****************************************************************************
7745 ****************************************************************************/
7747 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7749 UNISTR2
*name
= &q_u
->name
;
7750 UNISTR2
*uni_environment
= &q_u
->environment
;
7751 uint32 level
= q_u
->level
;
7752 RPC_BUFFER
*buffer
= NULL
;
7753 uint32 offered
= q_u
->offered
;
7754 uint32
*needed
= &r_u
->needed
;
7756 /* that's an [in out] buffer */
7758 if ( q_u
->buffer
) {
7759 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7760 buffer
= r_u
->buffer
;
7763 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7769 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7771 return WERR_UNKNOWN_LEVEL
;
7775 /****************************************************************************
7776 ****************************************************************************/
7778 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7780 POLICY_HND
*handle
= &q_u
->handle
;
7781 uint32 idx
= q_u
->index
;
7782 uint32 in_value_len
= q_u
->valuesize
;
7783 uint32 in_data_len
= q_u
->datasize
;
7784 uint32
*out_max_value_len
= &r_u
->valuesize
;
7785 uint16
**out_value
= &r_u
->value
;
7786 uint32
*out_value_len
= &r_u
->realvaluesize
;
7787 uint32
*out_type
= &r_u
->type
;
7788 uint32
*out_max_data_len
= &r_u
->datasize
;
7789 uint8
**data_out
= &r_u
->data
;
7790 uint32
*out_data_len
= &r_u
->realdatasize
;
7792 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7794 uint32 biggest_valuesize
;
7795 uint32 biggest_datasize
;
7797 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7800 REGISTRY_VALUE
*val
= NULL
;
7801 NT_PRINTER_DATA
*p_data
;
7802 int i
, key_index
, num_values
;
7807 *out_max_data_len
= 0;
7811 DEBUG(5,("spoolss_enumprinterdata\n"));
7814 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7818 if (!get_printer_snum(p
,handle
, &snum
))
7821 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7822 if (!W_ERROR_IS_OK(result
))
7825 p_data
= printer
->info_2
->data
;
7826 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7831 * The NT machine wants to know the biggest size of value and data
7833 * cf: MSDN EnumPrinterData remark section
7836 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7838 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7840 biggest_valuesize
= 0;
7841 biggest_datasize
= 0;
7843 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
7845 for ( i
=0; i
<num_values
; i
++ )
7847 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
7849 name_length
= strlen(val
->valuename
);
7850 if ( strlen(val
->valuename
) > biggest_valuesize
)
7851 biggest_valuesize
= name_length
;
7853 if ( val
->size
> biggest_datasize
)
7854 biggest_datasize
= val
->size
;
7856 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7860 /* the value is an UNICODE string but real_value_size is the length
7861 in bytes including the trailing 0 */
7863 *out_value_len
= 2 * (1+biggest_valuesize
);
7864 *out_data_len
= biggest_datasize
;
7866 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7872 * the value len is wrong in NT sp3
7873 * that's the number of bytes not the number of unicode chars
7876 if ( key_index
!= -1 )
7877 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
7882 /* out_value should default to "" or else NT4 has
7883 problems unmarshalling the response */
7885 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7887 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7889 result
= WERR_NOMEM
;
7893 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7895 /* the data is counted in bytes */
7897 *out_max_data_len
= in_data_len
;
7898 *out_data_len
= in_data_len
;
7900 /* only allocate when given a non-zero data_len */
7902 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7904 result
= WERR_NOMEM
;
7908 result
= WERR_NO_MORE_ITEMS
;
7914 * - counted in bytes in the request
7915 * - counted in UNICODE chars in the max reply
7916 * - counted in bytes in the real size
7918 * take a pause *before* coding not *during* coding
7922 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7923 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7925 result
= WERR_NOMEM
;
7929 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7933 *out_type
= regval_type( val
);
7935 /* data - counted in bytes */
7937 *out_max_data_len
= in_data_len
;
7938 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7940 result
= WERR_NOMEM
;
7943 data_len
= regval_size(val
);
7945 memcpy( *data_out
, regval_data_p(val
), data_len
);
7946 *out_data_len
= data_len
;
7950 free_a_printer(&printer
, 2);
7954 /****************************************************************************
7955 ****************************************************************************/
7957 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7959 POLICY_HND
*handle
= &q_u
->handle
;
7960 UNISTR2
*value
= &q_u
->value
;
7961 uint32 type
= q_u
->type
;
7962 uint8
*data
= q_u
->data
;
7963 uint32 real_len
= q_u
->real_len
;
7965 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7967 WERROR status
= WERR_OK
;
7968 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7971 DEBUG(5,("spoolss_setprinterdata\n"));
7974 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7978 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
7979 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7980 return WERR_INVALID_PARAM
;
7983 if (!get_printer_snum(p
,handle
, &snum
))
7987 * Access check : NT returns "access denied" if you make a
7988 * SetPrinterData call without the necessary privildge.
7989 * we were originally returning OK if nothing changed
7990 * which made Win2k issue **a lot** of SetPrinterData
7991 * when connecting to a printer --jerry
7994 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7996 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7997 status
= WERR_ACCESS_DENIED
;
8001 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8002 if (!W_ERROR_IS_OK(status
))
8005 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8008 * When client side code sets a magic printer data key, detect it and save
8009 * the current printer data and the magic key's data (its the DEVMODE) for
8010 * future printer/driver initializations.
8012 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8014 /* Set devmode and printer initialization info */
8015 status
= save_driver_init( printer
, 2, data
, real_len
);
8017 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8021 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8022 type
, data
, real_len
);
8023 if ( W_ERROR_IS_OK(status
) )
8024 status
= mod_a_printer(printer
, 2);
8028 free_a_printer(&printer
, 2);
8033 /****************************************************************************
8034 ****************************************************************************/
8036 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8038 POLICY_HND
*handle
= &q_u
->handle
;
8039 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8042 DEBUG(5,("_spoolss_resetprinter\n"));
8045 * All we do is to check to see if the handle and queue is valid.
8046 * This call really doesn't mean anything to us because we only
8047 * support RAW printing. --jerry
8051 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8055 if (!get_printer_snum(p
,handle
, &snum
))
8059 /* blindly return success */
8064 /****************************************************************************
8065 ****************************************************************************/
8067 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8069 POLICY_HND
*handle
= &q_u
->handle
;
8070 UNISTR2
*value
= &q_u
->valuename
;
8072 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8074 WERROR status
= WERR_OK
;
8075 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8078 DEBUG(5,("spoolss_deleteprinterdata\n"));
8081 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8085 if (!get_printer_snum(p
, handle
, &snum
))
8088 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8089 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8090 return WERR_ACCESS_DENIED
;
8093 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8094 if (!W_ERROR_IS_OK(status
))
8097 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8099 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8101 if ( W_ERROR_IS_OK(status
) )
8102 mod_a_printer( printer
, 2 );
8104 free_a_printer(&printer
, 2);
8109 /****************************************************************************
8110 ****************************************************************************/
8112 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8114 POLICY_HND
*handle
= &q_u
->handle
;
8115 FORM
*form
= &q_u
->form
;
8116 nt_forms_struct tmpForm
;
8118 WERROR status
= WERR_OK
;
8119 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8122 nt_forms_struct
*list
=NULL
;
8123 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8125 DEBUG(5,("spoolss_addform\n"));
8128 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8133 /* forms can be added on printer of on the print server handle */
8135 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8137 if (!get_printer_snum(p
,handle
, &snum
))
8140 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8141 if (!W_ERROR_IS_OK(status
))
8145 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8146 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8147 status
= WERR_ACCESS_DENIED
;
8151 /* can't add if builtin */
8153 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8154 status
= WERR_ALREADY_EXISTS
;
8158 count
= get_ntforms(&list
);
8160 if(!add_a_form(&list
, form
, &count
)) {
8161 status
= WERR_NOMEM
;
8165 write_ntforms(&list
, count
);
8168 * ChangeID must always be set if this is a printer
8171 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8172 status
= mod_a_printer(printer
, 2);
8176 free_a_printer(&printer
, 2);
8182 /****************************************************************************
8183 ****************************************************************************/
8185 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8187 POLICY_HND
*handle
= &q_u
->handle
;
8188 UNISTR2
*form_name
= &q_u
->name
;
8189 nt_forms_struct tmpForm
;
8191 nt_forms_struct
*list
=NULL
;
8192 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8194 WERROR status
= WERR_OK
;
8195 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8197 DEBUG(5,("spoolss_deleteform\n"));
8200 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8204 /* forms can be deleted on printer of on the print server handle */
8206 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8208 if (!get_printer_snum(p
,handle
, &snum
))
8211 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8212 if (!W_ERROR_IS_OK(status
))
8216 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8217 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8218 status
= WERR_ACCESS_DENIED
;
8222 /* can't delete if builtin */
8224 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8225 status
= WERR_INVALID_PARAM
;
8229 count
= get_ntforms(&list
);
8231 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8235 * ChangeID must always be set if this is a printer
8238 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8239 status
= mod_a_printer(printer
, 2);
8243 free_a_printer(&printer
, 2);
8249 /****************************************************************************
8250 ****************************************************************************/
8252 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8254 POLICY_HND
*handle
= &q_u
->handle
;
8255 FORM
*form
= &q_u
->form
;
8256 nt_forms_struct tmpForm
;
8258 WERROR status
= WERR_OK
;
8259 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8262 nt_forms_struct
*list
=NULL
;
8263 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8265 DEBUG(5,("spoolss_setform\n"));
8268 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8272 /* forms can be modified on printer of on the print server handle */
8274 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8276 if (!get_printer_snum(p
,handle
, &snum
))
8279 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8280 if (!W_ERROR_IS_OK(status
))
8284 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8285 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8286 status
= WERR_ACCESS_DENIED
;
8290 /* can't set if builtin */
8291 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8292 status
= WERR_INVALID_PARAM
;
8296 count
= get_ntforms(&list
);
8297 update_a_form(&list
, form
, count
);
8298 write_ntforms(&list
, count
);
8301 * ChangeID must always be set if this is a printer
8304 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8305 status
= mod_a_printer(printer
, 2);
8310 free_a_printer(&printer
, 2);
8316 /****************************************************************************
8317 enumprintprocessors level 1.
8318 ****************************************************************************/
8320 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8322 PRINTPROCESSOR_1
*info_1
=NULL
;
8323 WERROR result
= WERR_OK
;
8325 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8330 init_unistr(&info_1
->name
, "winprint");
8332 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8334 if (*needed
> offered
) {
8335 result
= WERR_INSUFFICIENT_BUFFER
;
8339 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8340 result
= WERR_NOMEM
;
8344 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8349 if ( !W_ERROR_IS_OK(result
) )
8355 /****************************************************************************
8356 ****************************************************************************/
8358 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8360 uint32 level
= q_u
->level
;
8361 RPC_BUFFER
*buffer
= NULL
;
8362 uint32 offered
= q_u
->offered
;
8363 uint32
*needed
= &r_u
->needed
;
8364 uint32
*returned
= &r_u
->returned
;
8366 /* that's an [in out] buffer */
8368 if ( q_u
->buffer
) {
8369 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8370 buffer
= r_u
->buffer
;
8373 DEBUG(5,("spoolss_enumprintprocessors\n"));
8376 * Enumerate the print processors ...
8378 * Just reply with "winprint", to keep NT happy
8379 * and I can use my nice printer checker.
8387 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8389 return WERR_UNKNOWN_LEVEL
;
8393 /****************************************************************************
8394 enumprintprocdatatypes level 1.
8395 ****************************************************************************/
8397 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8399 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8400 WERROR result
= WERR_NOMEM
;
8402 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8407 init_unistr(&info_1
->name
, "RAW");
8409 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8411 if (*needed
> offered
) {
8412 result
= WERR_INSUFFICIENT_BUFFER
;
8416 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8417 result
= WERR_NOMEM
;
8421 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8426 if ( !W_ERROR_IS_OK(result
) )
8432 /****************************************************************************
8433 ****************************************************************************/
8435 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8437 uint32 level
= q_u
->level
;
8438 RPC_BUFFER
*buffer
= NULL
;
8439 uint32 offered
= q_u
->offered
;
8440 uint32
*needed
= &r_u
->needed
;
8441 uint32
*returned
= &r_u
->returned
;
8443 /* that's an [in out] buffer */
8445 if ( q_u
->buffer
) {
8446 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8447 buffer
= r_u
->buffer
;
8450 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8457 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8459 return WERR_UNKNOWN_LEVEL
;
8463 /****************************************************************************
8464 enumprintmonitors level 1.
8465 ****************************************************************************/
8467 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8469 PRINTMONITOR_1
*info_1
=NULL
;
8470 WERROR result
= WERR_OK
;
8472 if((info_1
= SMB_MALLOC_P(PRINTMONITOR_1
)) == NULL
)
8477 init_unistr(&info_1
->name
, "Local Port");
8479 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8481 if (*needed
> offered
) {
8482 result
= WERR_INSUFFICIENT_BUFFER
;
8486 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8487 result
= WERR_NOMEM
;
8491 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8496 if ( !W_ERROR_IS_OK(result
) )
8502 /****************************************************************************
8503 enumprintmonitors level 2.
8504 ****************************************************************************/
8506 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8508 PRINTMONITOR_2
*info_2
=NULL
;
8509 WERROR result
= WERR_OK
;
8511 if((info_2
= SMB_MALLOC_P(PRINTMONITOR_2
)) == NULL
)
8516 init_unistr(&info_2
->name
, "Local Port");
8517 init_unistr(&info_2
->environment
, "Windows NT X86");
8518 init_unistr(&info_2
->dll_name
, "localmon.dll");
8520 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8522 if (*needed
> offered
) {
8523 result
= WERR_INSUFFICIENT_BUFFER
;
8527 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8528 result
= WERR_NOMEM
;
8532 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8537 if ( !W_ERROR_IS_OK(result
) )
8543 /****************************************************************************
8544 ****************************************************************************/
8546 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8548 uint32 level
= q_u
->level
;
8549 RPC_BUFFER
*buffer
= NULL
;
8550 uint32 offered
= q_u
->offered
;
8551 uint32
*needed
= &r_u
->needed
;
8552 uint32
*returned
= &r_u
->returned
;
8554 /* that's an [in out] buffer */
8556 if ( q_u
->buffer
) {
8557 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8558 buffer
= r_u
->buffer
;
8561 DEBUG(5,("spoolss_enumprintmonitors\n"));
8564 * Enumerate the print monitors ...
8566 * Just reply with "Local Port", to keep NT happy
8567 * and I can use my nice printer checker.
8575 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8577 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8579 return WERR_UNKNOWN_LEVEL
;
8583 /****************************************************************************
8584 ****************************************************************************/
8586 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8587 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8588 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8593 JOB_INFO_1
*info_1
=NULL
;
8594 WERROR result
= WERR_OK
;
8596 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8598 if (info_1
== NULL
) {
8602 for (i
=0; i
<count
&& found
==False
; i
++) {
8603 if ((*queue
)[i
].job
==(int)jobid
)
8609 /* NT treats not found as bad param... yet another bad choice */
8610 return WERR_INVALID_PARAM
;
8613 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8615 *needed
+= spoolss_size_job_info_1(info_1
);
8617 if (*needed
> offered
) {
8618 result
= WERR_INSUFFICIENT_BUFFER
;
8622 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8623 result
= WERR_NOMEM
;
8627 smb_io_job_info_1("", buffer
, info_1
, 0);
8635 /****************************************************************************
8636 ****************************************************************************/
8638 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8639 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8640 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8647 DEVICEMODE
*devmode
= NULL
;
8648 NT_DEVICEMODE
*nt_devmode
= NULL
;
8650 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8653 ZERO_STRUCTP(info_2
);
8655 for ( i
=0; i
<count
&& found
==False
; i
++ )
8657 if ((*queue
)[i
].job
== (int)jobid
)
8662 /* NT treats not found as bad param... yet another bad
8664 result
= WERR_INVALID_PARAM
;
8669 * if the print job does not have a DEVMODE associated with it,
8670 * just use the one for the printer. A NULL devicemode is not
8671 * a failure condition
8674 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8675 devmode
= construct_dev_mode(snum
);
8677 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8678 ZERO_STRUCTP( devmode
);
8679 convert_nt_devicemode( devmode
, nt_devmode
);
8683 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8685 *needed
+= spoolss_size_job_info_2(info_2
);
8687 if (*needed
> offered
) {
8688 result
= WERR_INSUFFICIENT_BUFFER
;
8692 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8693 result
= WERR_NOMEM
;
8697 smb_io_job_info_2("", buffer
, info_2
, 0);
8702 /* Cleanup allocated memory */
8704 free_job_info_2(info_2
); /* Also frees devmode */
8710 /****************************************************************************
8711 ****************************************************************************/
8713 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8715 POLICY_HND
*handle
= &q_u
->handle
;
8716 uint32 jobid
= q_u
->jobid
;
8717 uint32 level
= q_u
->level
;
8718 RPC_BUFFER
*buffer
= NULL
;
8719 uint32 offered
= q_u
->offered
;
8720 uint32
*needed
= &r_u
->needed
;
8721 WERROR wstatus
= WERR_OK
;
8722 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8725 print_queue_struct
*queue
= NULL
;
8726 print_status_struct prt_status
;
8728 /* that's an [in out] buffer */
8730 if ( q_u
->buffer
) {
8731 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8732 buffer
= r_u
->buffer
;
8735 DEBUG(5,("spoolss_getjob\n"));
8739 if (!get_printer_snum(p
, handle
, &snum
))
8742 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8743 if ( !W_ERROR_IS_OK(wstatus
) )
8746 count
= print_queue_status(snum
, &queue
, &prt_status
);
8748 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8749 count
, prt_status
.status
, prt_status
.message
));
8753 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8754 buffer
, offered
, needed
);
8757 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8758 buffer
, offered
, needed
);
8761 wstatus
= WERR_UNKNOWN_LEVEL
;
8766 free_a_printer( &ntprinter
, 2 );
8771 /********************************************************************
8772 spoolss_getprinterdataex
8774 From MSDN documentation of GetPrinterDataEx: pass request
8775 to GetPrinterData if key is "PrinterDriverData".
8776 ********************************************************************/
8778 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8780 POLICY_HND
*handle
= &q_u
->handle
;
8781 uint32 in_size
= q_u
->size
;
8782 uint32
*type
= &r_u
->type
;
8783 uint32
*out_size
= &r_u
->size
;
8784 uint8
**data
= &r_u
->data
;
8785 uint32
*needed
= &r_u
->needed
;
8786 fstring keyname
, valuename
;
8788 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8790 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8792 WERROR status
= WERR_OK
;
8794 DEBUG(4,("_spoolss_getprinterdataex\n"));
8796 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8797 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8799 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8800 keyname
, valuename
));
8802 /* in case of problem, return some default values */
8806 *out_size
= in_size
;
8809 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8810 status
= WERR_BADFID
;
8814 /* Is the handle to a printer or to the server? */
8816 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8817 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8818 status
= WERR_INVALID_PARAM
;
8822 if ( !get_printer_snum(p
,handle
, &snum
) )
8825 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8826 if ( !W_ERROR_IS_OK(status
) )
8829 /* check to see if the keyname is valid */
8830 if ( !strlen(keyname
) ) {
8831 status
= WERR_INVALID_PARAM
;
8835 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
8836 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8837 free_a_printer( &printer
, 2 );
8838 status
= WERR_BADFILE
;
8842 /* When given a new keyname, we should just create it */
8844 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8846 if (*needed
> *out_size
)
8847 status
= WERR_MORE_DATA
;
8850 if ( !W_ERROR_IS_OK(status
) )
8852 DEBUG(5, ("error: allocating %d\n", *out_size
));
8854 /* reply this param doesn't exist */
8858 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8859 status
= WERR_NOMEM
;
8869 free_a_printer( &printer
, 2 );
8874 /********************************************************************
8875 * spoolss_setprinterdataex
8876 ********************************************************************/
8878 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8880 POLICY_HND
*handle
= &q_u
->handle
;
8881 uint32 type
= q_u
->type
;
8882 uint8
*data
= q_u
->data
;
8883 uint32 real_len
= q_u
->real_len
;
8885 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8887 WERROR status
= WERR_OK
;
8888 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8893 DEBUG(4,("_spoolss_setprinterdataex\n"));
8895 /* From MSDN documentation of SetPrinterDataEx: pass request to
8896 SetPrinterData if key is "PrinterDriverData" */
8899 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8903 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8904 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8905 return WERR_INVALID_PARAM
;
8908 if ( !get_printer_snum(p
,handle
, &snum
) )
8912 * Access check : NT returns "access denied" if you make a
8913 * SetPrinterData call without the necessary privildge.
8914 * we were originally returning OK if nothing changed
8915 * which made Win2k issue **a lot** of SetPrinterData
8916 * when connecting to a printer --jerry
8919 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8921 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8922 return WERR_ACCESS_DENIED
;
8925 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8926 if (!W_ERROR_IS_OK(status
))
8929 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8930 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8932 /* check for OID in valuename */
8934 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8940 /* save the registry data */
8942 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8944 if ( W_ERROR_IS_OK(status
) )
8946 /* save the OID if one was specified */
8948 fstrcat( keyname
, "\\" );
8949 fstrcat( keyname
, SPOOL_OID_KEY
);
8952 * I'm not checking the status here on purpose. Don't know
8953 * if this is right, but I'm returning the status from the
8954 * previous set_printer_dataex() call. I have no idea if
8955 * this is right. --jerry
8958 set_printer_dataex( printer
, keyname
, valuename
,
8959 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8962 status
= mod_a_printer(printer
, 2);
8965 free_a_printer(&printer
, 2);
8971 /********************************************************************
8972 * spoolss_deleteprinterdataex
8973 ********************************************************************/
8975 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8977 POLICY_HND
*handle
= &q_u
->handle
;
8978 UNISTR2
*value
= &q_u
->valuename
;
8979 UNISTR2
*key
= &q_u
->keyname
;
8981 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8983 WERROR status
= WERR_OK
;
8984 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8985 pstring valuename
, keyname
;
8987 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8990 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8994 if (!get_printer_snum(p
, handle
, &snum
))
8997 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8998 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8999 return WERR_ACCESS_DENIED
;
9002 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9003 if (!W_ERROR_IS_OK(status
))
9006 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9007 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9009 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9011 if ( W_ERROR_IS_OK(status
) )
9012 mod_a_printer( printer
, 2 );
9014 free_a_printer(&printer
, 2);
9019 /********************************************************************
9020 * spoolss_enumprinterkey
9021 ********************************************************************/
9024 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9027 fstring
*keynames
= NULL
;
9028 uint16
*enumkeys
= NULL
;
9031 POLICY_HND
*handle
= &q_u
->handle
;
9032 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9033 NT_PRINTER_DATA
*data
;
9034 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9036 WERROR status
= WERR_BADFILE
;
9039 DEBUG(4,("_spoolss_enumprinterkey\n"));
9042 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9046 if ( !get_printer_snum(p
,handle
, &snum
) )
9049 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9050 if (!W_ERROR_IS_OK(status
))
9053 /* get the list of subkey names */
9055 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9056 data
= printer
->info_2
->data
;
9058 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9060 if ( num_keys
== -1 ) {
9061 status
= WERR_BADFILE
;
9065 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9067 r_u
->needed
= printerkey_len
*2;
9069 if ( q_u
->size
< r_u
->needed
) {
9070 status
= WERR_MORE_DATA
;
9074 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9075 status
= WERR_NOMEM
;
9081 if ( q_u
->size
< r_u
->needed
)
9082 status
= WERR_MORE_DATA
;
9085 free_a_printer( &printer
, 2 );
9086 SAFE_FREE( keynames
);
9091 /********************************************************************
9092 * spoolss_deleteprinterkey
9093 ********************************************************************/
9095 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9097 POLICY_HND
*handle
= &q_u
->handle
;
9098 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9100 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9104 DEBUG(5,("spoolss_deleteprinterkey\n"));
9107 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9111 /* if keyname == NULL, return error */
9113 if ( !q_u
->keyname
.buffer
)
9114 return WERR_INVALID_PARAM
;
9116 if (!get_printer_snum(p
, handle
, &snum
))
9119 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9120 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9121 return WERR_ACCESS_DENIED
;
9124 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9125 if (!W_ERROR_IS_OK(status
))
9128 /* delete the key and all subneys */
9130 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9132 status
= delete_all_printer_data( printer
->info_2
, key
);
9134 if ( W_ERROR_IS_OK(status
) )
9135 status
= mod_a_printer(printer
, 2);
9137 free_a_printer( &printer
, 2 );
9143 /********************************************************************
9144 * spoolss_enumprinterdataex
9145 ********************************************************************/
9147 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9149 POLICY_HND
*handle
= &q_u
->handle
;
9150 uint32 in_size
= q_u
->size
;
9153 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9154 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9155 NT_PRINTER_DATA
*p_data
;
9157 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9162 REGISTRY_VALUE
*val
;
9167 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9170 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9175 * first check for a keyname of NULL or "". Win2k seems to send
9176 * this a lot and we should send back WERR_INVALID_PARAM
9177 * no need to spend time looking up the printer in this case.
9181 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9182 if ( !strlen(key
) ) {
9183 result
= WERR_INVALID_PARAM
;
9187 /* get the printer off of disk */
9189 if (!get_printer_snum(p
,handle
, &snum
))
9192 ZERO_STRUCT(printer
);
9193 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9194 if (!W_ERROR_IS_OK(result
))
9197 /* now look for a match on the key name */
9199 p_data
= printer
->info_2
->data
;
9201 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9202 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9204 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9205 result
= WERR_INVALID_PARAM
;
9212 /* allocate the memory for the array of pointers -- if necessary */
9214 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9217 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9219 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9220 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9221 result
= WERR_NOMEM
;
9225 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9229 * loop through all params and build the array to pass
9230 * back to the client
9233 for ( i
=0; i
<num_entries
; i
++ )
9235 /* lookup the registry value */
9237 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9238 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9242 value_name
= regval_name( val
);
9243 init_unistr( &enum_values
[i
].valuename
, value_name
);
9244 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9245 enum_values
[i
].type
= regval_type( val
);
9247 data_len
= regval_size( val
);
9249 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9251 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9253 result
= WERR_NOMEM
;
9257 enum_values
[i
].data_len
= data_len
;
9259 /* keep track of the size of the array in bytes */
9261 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9264 /* housekeeping information in the reply */
9266 r_u
->needed
= needed
;
9267 r_u
->returned
= num_entries
;
9269 if (needed
> in_size
) {
9270 result
= WERR_MORE_DATA
;
9274 /* copy data into the reply */
9276 r_u
->ctr
.size
= r_u
->needed
;
9277 r_u
->ctr
.size_of_array
= r_u
->returned
;
9278 r_u
->ctr
.values
= enum_values
;
9284 free_a_printer(&printer
, 2);
9289 /****************************************************************************
9290 ****************************************************************************/
9292 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9294 init_unistr(&info
->name
, name
);
9297 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9298 UNISTR2
*environment
,
9305 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9306 WERROR result
= WERR_OK
;
9308 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9310 if (!get_short_archi(long_archi
))
9311 return WERR_INVALID_ENVIRONMENT
;
9313 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9316 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9318 fill_printprocessordirectory_1(info
, path
);
9320 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9322 if (*needed
> offered
) {
9323 result
= WERR_INSUFFICIENT_BUFFER
;
9327 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9328 result
= WERR_INSUFFICIENT_BUFFER
;
9332 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9340 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9342 uint32 level
= q_u
->level
;
9343 RPC_BUFFER
*buffer
= NULL
;
9344 uint32 offered
= q_u
->offered
;
9345 uint32
*needed
= &r_u
->needed
;
9348 /* that's an [in out] buffer */
9350 if ( q_u
->buffer
) {
9351 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9352 buffer
= r_u
->buffer
;
9355 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9361 result
= getprintprocessordirectory_level_1
9362 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9365 result
= WERR_UNKNOWN_LEVEL
;
9373 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9374 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9376 DEBUG(5,("_spoolss_replyopenprinter\n"));
9378 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9383 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9384 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9386 DEBUG(5,("_spoolss_replycloseprinter\n"));