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. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver)
53 if (ver < 0 || ver > 3)
55 return drv_ver_to_os[ver];
59 const char *long_archi;
60 const char *short_archi;
64 static Printer_entry *printers_list;
66 typedef struct _counter_printer_0 {
67 struct _counter_printer_0 *next;
68 struct _counter_printer_0 *prev;
74 static counter_printer_0 *counter_list;
76 static struct cli_state notify_cli; /* print notify back-channel */
77 static uint32 smb_connections=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping, printserver_std_mapping;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v)
94 return JOB_STATUS_PAUSED;
96 return JOB_STATUS_SPOOLING;
98 return JOB_STATUS_PRINTING;
100 return JOB_STATUS_ERROR;
102 return JOB_STATUS_DELETING;
104 return JOB_STATUS_OFFLINE;
106 return JOB_STATUS_PAPEROUT;
108 return JOB_STATUS_PRINTED;
110 return JOB_STATUS_DELETED;
112 return JOB_STATUS_BLOCKED;
113 case LPQ_USER_INTERVENTION:
114 return JOB_STATUS_USER_INTERVENTION;
119 static int nt_printq_status(int v)
123 return PRINTER_STATUS_PAUSED;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
141 SAFE_FREE((*pp)->ctr.type);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
169 if (!W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
175 cli_nt_session_close(¬ify_cli);
176 cli_ulogoff(¬ify_cli);
177 cli_shutdown(¬ify_cli);
178 message_deregister(MSG_PRINTER_NOTIFY2);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr)
195 Printer_entry *Printer = (Printer_entry *)ptr;
197 if (Printer->notify.client_connected==True) {
200 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
204 snum = print_queue_snum(Printer->sharename);
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 free_spool_notify_option(&Printer->notify.option);
216 Printer->notify.option=NULL;
217 Printer->notify.client_connected=False;
219 free_nt_devicemode( &Printer->nt_devmode );
220 free_a_printer( &Printer->printer_info, 2 );
222 talloc_destroy( Printer->ctx );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list, Printer);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
236 SPOOL_NOTIFY_OPTION *new_sp = NULL;
241 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
248 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
250 if (!new_sp->ctr.type) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
265 Printer_entry *find_printer = NULL;
267 if(!find_policy_by_hnd(p,hnd,(void **)&find_printer)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2,
280 const char *servername, const char *printername )
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
285 servername, printername));
287 for ( p=printers_list; p; p=p->next )
289 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
291 && strequal( p->sharename, printername )
292 && strequal( p->servername, servername ) )
294 DEBUG(10,("Found printer\n"));
295 *info2 = dup_printer_2( ctx, p->printer_info->info_2 );
301 return WERR_INVALID_PRINTER_NAME;
304 /****************************************************************************
305 destroy any cached printer_info_2 structures on open handles
306 ****************************************************************************/
308 void invalidate_printer_hnd_cache( char *printername )
312 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername));
314 for ( p=printers_list; p; p=p->next )
316 if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER
318 && StrCaseCmp(p->sharename, printername)==0)
320 DEBUG(10,("invalidating printer_info cache for handl:\n"));
321 free_a_printer( &p->printer_info, 2 );
322 p->printer_info = NULL;
328 /****************************************************************************
329 Close printer index by handle.
330 ****************************************************************************/
332 static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
334 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
337 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
341 close_policy_hnd(p, hnd);
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
372 /* Check calling user has permission to delete printer. Note that
373 since we set the snum parameter to -1 only administrators can
374 delete the printer. This stops people with the Full Control
375 permission from deleting the printer. */
377 if (!print_access_check(NULL, -1, PRINTER_ACCESS_ADMINISTER)) {
378 DEBUG(3, ("printer delete denied by security descriptor\n"));
379 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 if (del_a_printer( Printer->sharename ) != 0) {
387 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
391 /* the delete printer script shoudl be run as root if the user has perms */
393 if (*lp_deleteprinter_cmd()) {
395 char *cmd = lp_deleteprinter_cmd();
398 SE_PRIV se_printop = SE_PRINT_OPERATOR;
401 pstr_sprintf(command, "%s \"%s\"", cmd, Printer->sharename);
403 is_print_op = user_has_privileges( p->pipe_user.nt_user_token, &se_printop );
405 DEBUG(10,("Running [%s]\n", command));
407 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
412 if ( (ret = smbrun(command, NULL)) == 0 ) {
413 /* Tell everyone we updated smb.conf. */
414 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
420 /********** END SePrintOperatorPrivlege BLOCK **********/
422 DEBUGADD(10,("returned [%d]\n", ret));
425 return WERR_BADFID; /* What to return here? */
427 /* go ahead and re-read the services immediately */
428 reload_services( False );
430 if ( lp_servicenumber( Printer->sharename ) < 0 )
431 return WERR_ACCESS_DENIED;
437 /****************************************************************************
438 Return the snum of a printer corresponding to an handle.
439 ****************************************************************************/
441 static BOOL get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number)
443 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
446 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
450 switch (Printer->printer_type) {
451 case PRINTER_HANDLE_IS_PRINTER:
452 DEBUG(4,("short name:%s\n", Printer->sharename));
453 *number = print_queue_snum(Printer->sharename);
454 return (*number != -1);
455 case PRINTER_HANDLE_IS_PRINTSERVER:
462 /****************************************************************************
463 Set printer handle type.
464 Check if it's \\server or \\server\printer
465 ****************************************************************************/
467 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
469 DEBUG(3,("Setting printer type=%s\n", handlename));
471 if ( strlen(handlename) < 3 ) {
472 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
476 /* it's a print server */
477 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
478 DEBUGADD(4,("Printer is a print server\n"));
479 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
483 DEBUGADD(4,("Printer is a printer\n"));
484 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
490 /****************************************************************************
491 Set printer handle name.
492 ****************************************************************************/
494 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
497 int n_services=lp_numservices();
498 char *aprinter, *printername;
499 const char *servername;
502 NT_PRINTER_INFO_LEVEL *printer;
505 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
507 aprinter = handlename;
508 if ( *handlename == '\\' ) {
509 servername = handlename + 2;
510 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
519 /* save the servername to fill in replies on this handle */
521 if ( !is_myname_or_ipaddr( servername ) )
524 fstrcpy( Printer->servername, servername );
526 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
529 if ( Printer->printer_type != PRINTER_HANDLE_IS_PRINTER )
532 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
534 /* Search all sharenames first as this is easier than pulling
535 the printer_info_2 off of disk */
537 snum = find_service(aprinter);
539 if ( lp_snum_ok(snum) && lp_print_ok(snum) ) {
541 fstrcpy( sname, aprinter );
544 /* do another loop to look for printernames */
546 for (snum=0; !found && snum<n_services; snum++) {
548 /* no point in checking if this is not a printer or
549 we aren't allowing printername != sharename */
551 if ( !(lp_snum_ok(snum)
553 && !lp_force_printername(snum)) )
558 fstrcpy(sname, lp_servicename(snum));
561 result = get_a_printer( NULL, &printer, 2, sname );
562 if ( !W_ERROR_IS_OK(result) ) {
563 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
564 sname, dos_errstr(result)));
568 /* printername is always returned as \\server\printername */
569 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
570 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
571 printer->info_2->printername));
572 free_a_printer( &printer, 2);
578 if ( strequal(printername, aprinter) ) {
582 DEBUGADD(10, ("printername: %s\n", printername));
584 free_a_printer( &printer, 2);
588 DEBUGADD(4,("Printer not found\n"));
592 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
594 fstrcpy(Printer->sharename, sname);
599 /****************************************************************************
600 Find first available printer slot. creates a printer handle for you.
601 ****************************************************************************/
603 static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
605 Printer_entry *new_printer;
607 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
609 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
612 ZERO_STRUCTP(new_printer);
614 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
615 SAFE_FREE(new_printer);
619 /* Add to the internal list. */
620 DLIST_ADD(printers_list, new_printer);
622 new_printer->notify.option=NULL;
624 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
625 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
626 close_printer_handle(p, hnd);
630 if (!set_printer_hnd_printertype(new_printer, name)) {
631 close_printer_handle(p, hnd);
635 if (!set_printer_hnd_name(new_printer, name)) {
636 close_printer_handle(p, hnd);
640 new_printer->access_granted = access_granted;
642 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
647 /***************************************************************************
648 check to see if the client motify handle is monitoring the notification
649 given by (notify_type, notify_field).
650 **************************************************************************/
652 static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
658 static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
661 SPOOL_NOTIFY_OPTION *option = p->notify.option;
665 * Flags should always be zero when the change notify
666 * is registered by the client's spooler. A user Win32 app
667 * might use the flags though instead of the NOTIFY_OPTION_INFO
676 return is_monitoring_event_flags(
677 p->notify.flags, notify_type, notify_field);
679 for (i = 0; i < option->count; i++) {
681 /* Check match for notify_type */
683 if (option->ctr.type[i].type != notify_type)
686 /* Check match for field */
688 for (j = 0; j < option->ctr.type[i].count; j++) {
689 if (option->ctr.type[i].fields[j] == notify_field) {
695 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
696 p->servername, p->sharename, notify_type, notify_field));
701 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
703 static void notify_one_value(struct spoolss_notify_msg *msg,
704 SPOOL_NOTIFY_INFO_DATA *data,
707 data->notify_data.value[0] = msg->notify.value[0];
708 data->notify_data.value[1] = 0;
711 static void notify_string(struct spoolss_notify_msg *msg,
712 SPOOL_NOTIFY_INFO_DATA *data,
717 /* The length of the message includes the trailing \0 */
719 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
721 data->notify_data.data.length = msg->len * 2;
722 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
724 if (!data->notify_data.data.string) {
725 data->notify_data.data.length = 0;
729 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
732 static void notify_system_time(struct spoolss_notify_msg *msg,
733 SPOOL_NOTIFY_INFO_DATA *data,
739 if (msg->len != sizeof(time_t)) {
740 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
745 if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
746 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
750 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
751 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
755 if (!spoolss_io_system_time("", &ps, 0, &systime))
758 data->notify_data.data.length = prs_offset(&ps);
759 data->notify_data.data.string = TALLOC(mem_ctx, prs_offset(&ps));
761 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
766 struct notify2_message_table {
768 void (*fn)(struct spoolss_notify_msg *msg,
769 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
772 static struct notify2_message_table printer_notify_table[] = {
773 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
774 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
775 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
776 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
777 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
778 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
779 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
780 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
781 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
782 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
783 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
784 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
785 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
786 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
787 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
788 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
789 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
790 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
791 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
794 static struct notify2_message_table job_notify_table[] = {
795 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
796 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
797 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
798 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
799 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
800 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
801 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
802 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
803 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
804 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
805 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
806 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
807 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
808 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
809 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
810 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
811 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
812 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
813 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
814 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
815 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
816 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
817 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
818 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
822 /***********************************************************************
823 Allocate talloc context for container object
824 **********************************************************************/
826 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
836 /***********************************************************************
837 release all allocated memory and zero out structure
838 **********************************************************************/
840 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
846 talloc_destroy(ctr->ctx);
853 /***********************************************************************
854 **********************************************************************/
856 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
864 /***********************************************************************
865 **********************************************************************/
867 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
869 if ( !ctr || !ctr->msg_groups )
872 if ( idx >= ctr->num_groups )
875 return &ctr->msg_groups[idx];
879 /***********************************************************************
880 How many groups of change messages do we have ?
881 **********************************************************************/
883 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
888 return ctr->num_groups;
891 /***********************************************************************
892 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
893 **********************************************************************/
895 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
897 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
898 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
899 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
905 /* loop over all groups looking for a matching printer name */
907 for ( i=0; i<ctr->num_groups; i++ ) {
908 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
912 /* add a new group? */
914 if ( i == ctr->num_groups ) {
917 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
918 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
921 ctr->msg_groups = groups;
923 /* clear the new entry and set the printer name */
925 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
926 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
929 /* add the change messages; 'i' is the correct index now regardless */
931 msg_grp = &ctr->msg_groups[i];
935 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
936 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
939 msg_grp->msgs = msg_list;
941 new_slot = msg_grp->num_msgs-1;
942 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
944 /* need to allocate own copy of data */
947 msg_grp->msgs[new_slot].notify.data = TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
949 return ctr->num_groups;
952 /***********************************************************************
953 Send a change notication message on all handles which have a call
955 **********************************************************************/
957 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
960 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
961 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
962 SPOOLSS_NOTIFY_MSG *messages;
963 int sending_msg_count;
966 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
970 messages = msg_group->msgs;
973 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
977 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
979 /* loop over all printers */
981 for (p = printers_list; p; p = p->next) {
982 SPOOL_NOTIFY_INFO_DATA *data;
987 /* Is there notification on this handle? */
989 if ( !p->notify.client_connected )
992 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
994 /* For this printer? Print servers always receive
997 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
998 ( !strequal(msg_group->printername, p->sharename) ) )
1001 DEBUG(10,("Our printer\n"));
1003 /* allocate the max entries possible */
1005 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
1008 /* build the array of change notifications */
1010 sending_msg_count = 0;
1012 for ( i=0; i<msg_group->num_msgs; i++ ) {
1013 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1015 /* Are we monitoring this event? */
1017 if (!is_monitoring_event(p, msg->type, msg->field))
1020 sending_msg_count++;
1023 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1024 msg->type, msg->field, p->sharename));
1027 * if the is a printer notification handle and not a job notification
1028 * type, then set the id to 0. Other wise just use what was specified
1031 * When registering change notification on a print server handle
1032 * we always need to send back the id (snum) matching the printer
1033 * for which the change took place. For change notify registered
1034 * on a printer handle, this does not matter and the id should be 0.
1039 if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1045 /* Convert unix jobid to smb jobid */
1047 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1048 id = sysjob_to_jobid(msg->id);
1051 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1056 construct_info_data( &data[data_len], msg->type, msg->field, id );
1059 case PRINTER_NOTIFY_TYPE:
1060 if ( printer_notify_table[msg->field].fn )
1061 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1064 case JOB_NOTIFY_TYPE:
1065 if ( job_notify_table[msg->field].fn )
1066 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1070 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1077 if ( sending_msg_count ) {
1078 cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
1079 data_len, data, p->notify.change, 0 );
1084 DEBUG(8,("send_notify2_changes: Exit...\n"));
1088 /***********************************************************************
1089 **********************************************************************/
1091 static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1094 uint32 tv_sec, tv_usec;
1097 /* Unpack message */
1099 offset += tdb_unpack((char *)buf + offset, len - offset, "f",
1102 offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd",
1104 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1107 tdb_unpack((char *)buf + offset, len - offset, "dd",
1108 &msg->notify.value[0], &msg->notify.value[1]);
1110 tdb_unpack((char *)buf + offset, len - offset, "B",
1111 &msg->len, &msg->notify.data);
1113 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1114 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1116 tv->tv_sec = tv_sec;
1117 tv->tv_usec = tv_usec;
1120 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1121 msg->notify.value[1]));
1123 dump_data(3, msg->notify.data, msg->len);
1128 /********************************************************************
1129 Receive a notify2 message list
1130 ********************************************************************/
1132 static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
1134 size_t msg_count, i;
1135 char *buf = (char *)msg;
1138 SPOOLSS_NOTIFY_MSG notify;
1139 SPOOLSS_NOTIFY_MSG_CTR messages;
1143 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1147 msg_count = IVAL(buf, 0);
1150 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1152 if (msg_count == 0) {
1153 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1157 /* initialize the container */
1159 ZERO_STRUCT( messages );
1160 notify_msg_ctr_init( &messages );
1163 * build message groups for each printer identified
1164 * in a change_notify msg. Remember that a PCN message
1165 * includes the handle returned for the srv_spoolss_replyopenprinter()
1166 * call. Therefore messages are grouped according to printer handle.
1169 for ( i=0; i<msg_count; i++ ) {
1170 struct timeval msg_tv;
1172 if (msg_ptr + 4 - buf > len) {
1173 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1177 msg_len = IVAL(msg_ptr,0);
1180 if (msg_ptr + msg_len - buf > len) {
1181 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1185 /* unpack messages */
1187 ZERO_STRUCT( notify );
1188 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1191 /* add to correct list in container */
1193 notify_msg_ctr_addmsg( &messages, ¬ify );
1195 /* free memory that might have been allocated by notify2_unpack_msg() */
1197 if ( notify.len != 0 )
1198 SAFE_FREE( notify.notify.data );
1201 /* process each group of messages */
1203 num_groups = notify_msg_ctr_numgroups( &messages );
1204 for ( i=0; i<num_groups; i++ )
1205 send_notify2_changes( &messages, i );
1210 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1212 notify_msg_ctr_destroy( &messages );
1217 /********************************************************************
1218 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1219 one smbd, all of processes must clear their printer cache immediately.
1220 ********************************************************************/
1222 void receive_printer_mod_msg(int msg_type, pid_t src, void *buf, size_t len)
1224 fstring printername;
1226 fstrcpy( printername, buf );
1228 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername ));
1230 invalidate_printer_hnd_cache( printername );
1233 /********************************************************************
1234 Send a message to ourself about new driver being installed
1235 so we can upgrade the information for each printer bound to this
1237 ********************************************************************/
1239 static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
1241 int len = strlen(drivername);
1246 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1249 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
1254 /**********************************************************************
1255 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1256 over all printers, upgrading ones as necessary
1257 **********************************************************************/
1259 void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
1263 int n_services = lp_numservices();
1265 len = MIN(len,sizeof(drivername)-1);
1266 strncpy(drivername, buf, len);
1268 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1270 /* Iterate the printer list */
1272 for (snum=0; snum<n_services; snum++)
1274 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1277 NT_PRINTER_INFO_LEVEL *printer = NULL;
1279 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1280 if (!W_ERROR_IS_OK(result))
1283 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1285 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1287 /* all we care about currently is the change_id */
1289 result = mod_a_printer(printer, 2);
1290 if (!W_ERROR_IS_OK(result)) {
1291 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1292 dos_errstr(result)));
1296 free_a_printer(&printer, 2);
1303 /********************************************************************
1304 Update the cache for all printq's with a registered client
1306 ********************************************************************/
1308 void update_monitored_printq_cache( void )
1310 Printer_entry *printer = printers_list;
1313 /* loop through all printers and update the cache where
1314 client_connected == True */
1317 if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER)
1318 && printer->notify.client_connected )
1320 snum = print_queue_snum(printer->sharename);
1321 print_queue_status( snum, NULL, NULL );
1324 printer = printer->next;
1329 /********************************************************************
1330 Send a message to ourself about new driver being installed
1331 so we can upgrade the information for each printer bound to this
1333 ********************************************************************/
1335 static BOOL srv_spoolss_reset_printerdata(char* drivername)
1337 int len = strlen(drivername);
1342 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1345 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
1350 /**********************************************************************
1351 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1352 over all printers, resetting printer data as neessary
1353 **********************************************************************/
1355 void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
1359 int n_services = lp_numservices();
1361 len = MIN( len, sizeof(drivername)-1 );
1362 strncpy( drivername, buf, len );
1364 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1366 /* Iterate the printer list */
1368 for ( snum=0; snum<n_services; snum++ )
1370 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1373 NT_PRINTER_INFO_LEVEL *printer = NULL;
1375 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1376 if ( !W_ERROR_IS_OK(result) )
1380 * if the printer is bound to the driver,
1381 * then reset to the new driver initdata
1384 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1386 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1388 if ( !set_driver_init(printer, 2) ) {
1389 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1390 printer->info_2->printername, printer->info_2->drivername));
1393 result = mod_a_printer( printer, 2 );
1394 if ( !W_ERROR_IS_OK(result) ) {
1395 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1396 get_dos_error_msg(result)));
1400 free_a_printer( &printer, 2 );
1409 /********************************************************************
1410 Copy routines used by convert_to_openprinterex()
1411 *******************************************************************/
1413 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1421 DEBUG (8,("dup_devmode\n"));
1423 /* bulk copy first */
1425 d = TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1429 /* dup the pointer members separately */
1431 len = unistrlen(devmode->devicename.buffer);
1433 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1434 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1439 len = unistrlen(devmode->formname.buffer);
1441 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1442 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1446 d->private = TALLOC_MEMDUP(ctx, devmode->private, devmode->driverextra);
1451 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1453 if (!new_ctr || !ctr)
1456 DEBUG(8,("copy_devmode_ctr\n"));
1458 new_ctr->size = ctr->size;
1459 new_ctr->devmode_ptr = ctr->devmode_ptr;
1461 if(ctr->devmode_ptr)
1462 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1465 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1467 if (!new_def || !def)
1470 DEBUG(8,("copy_printer_defaults\n"));
1472 new_def->datatype_ptr = def->datatype_ptr;
1474 if (def->datatype_ptr)
1475 copy_unistr2(&new_def->datatype, &def->datatype);
1477 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1479 new_def->access_required = def->access_required;
1482 /********************************************************************
1483 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1484 * SPOOL_Q_OPEN_PRINTER_EX structure
1485 ********************************************************************/
1487 static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1489 if (!q_u_ex || !q_u)
1492 DEBUG(8,("convert_to_openprinterex\n"));
1494 q_u_ex->printername_ptr = q_u->printername_ptr;
1496 if (q_u->printername_ptr)
1497 copy_unistr2(&q_u_ex->printername, &q_u->printername);
1499 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1502 /********************************************************************
1503 * spoolss_open_printer
1505 * called from the spoolss dispatcher
1506 ********************************************************************/
1508 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1510 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1511 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1516 ZERO_STRUCT(q_u_ex);
1517 ZERO_STRUCT(r_u_ex);
1519 /* convert the OpenPrinter() call to OpenPrinterEx() */
1521 convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1523 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1525 /* convert back to OpenPrinter() */
1527 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1532 /********************************************************************
1533 * spoolss_open_printer
1535 * If the openprinterex rpc call contains a devmode,
1536 * it's a per-user one. This per-user devmode is derivated
1537 * from the global devmode. Openprinterex() contains a per-user
1538 * devmode for when you do EMF printing and spooling.
1539 * In the EMF case, the NT workstation is only doing half the job
1540 * of rendering the page. The other half is done by running the printer
1541 * driver on the server.
1542 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1543 * The EMF file only contains what is to be printed on the page.
1544 * So in order for the server to know how to print, the NT client sends
1545 * a devicemode attached to the openprinterex call.
1546 * But this devicemode is short lived, it's only valid for the current print job.
1548 * If Samba would have supported EMF spooling, this devicemode would
1549 * have been attached to the handle, to sent it to the driver to correctly
1550 * rasterize the EMF file.
1552 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1553 * we just act as a pass-thru between windows and the printer.
1555 * In order to know that Samba supports only RAW spooling, NT has to call
1556 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1557 * and until NT sends a RAW job, we refuse it.
1559 * But to call getprinter() or startdoc(), you first need a valid handle,
1560 * and to get an handle you have to call openprintex(). Hence why you have
1561 * a devicemode in the openprinterex() call.
1564 * Differences between NT4 and NT 2000.
1567 * On NT4, you only have a global devicemode. This global devicemode can be changed
1568 * by the administrator (or by a user with enough privs). Everytime a user
1569 * wants to print, the devicemode is resetted to the default. In Word, everytime
1570 * you print, the printer's characteristics are always reset to the global devicemode.
1574 * In W2K, there is the notion of per-user devicemode. The first time you use
1575 * a printer, a per-user devicemode is build from the global devicemode.
1576 * If you change your per-user devicemode, it is saved in the registry, under the
1577 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1578 * printer preferences available.
1580 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1581 * on the General Tab of the printer properties windows.
1583 * To change the global devicemode: it's the "Printing Defaults..." button
1584 * on the Advanced Tab of the printer properties window.
1587 ********************************************************************/
1589 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1591 UNISTR2 *printername = NULL;
1592 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1593 POLICY_HND *handle = &r_u->handle;
1597 struct current_user user;
1598 Printer_entry *Printer=NULL;
1600 if (q_u->printername_ptr != 0)
1601 printername = &q_u->printername;
1603 if (printername == NULL)
1604 return WERR_INVALID_PRINTER_NAME;
1606 /* some sanity check because you can open a printer or a print server */
1607 /* aka: \\server\printer or \\server */
1608 unistr2_to_ascii(name, printername, sizeof(name)-1);
1610 DEBUGADD(3,("checking name: %s\n",name));
1612 if (!open_printer_hnd(p, handle, name, 0))
1613 return WERR_INVALID_PRINTER_NAME;
1615 Printer=find_printer_index_by_hnd(p, handle);
1617 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1618 "handle we created for printer %s\n", name ));
1619 close_printer_handle(p,handle);
1620 return WERR_INVALID_PRINTER_NAME;
1623 get_current_user(&user, p);
1626 * First case: the user is opening the print server:
1628 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1629 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1631 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1632 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1633 * or if the user is listed in the smb.conf printer admin parameter.
1635 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1636 * client view printer folder, but does not show the MSAPW.
1638 * Note: this test needs code to check access rights here too. Jeremy
1639 * could you look at this?
1641 * Second case: the user is opening a printer:
1642 * NT doesn't let us connect to a printer if the connecting user
1643 * doesn't have print permission.
1646 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
1648 /* Printserver handles use global struct... */
1652 /* Map standard access rights to object specific access rights */
1654 se_map_standard(&printer_default->access_required,
1655 &printserver_std_mapping);
1657 /* Deny any object specific bits that don't apply to print
1658 servers (i.e printer and job specific bits) */
1660 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1662 if (printer_default->access_required &
1663 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1664 DEBUG(3, ("access DENIED for non-printserver bits"));
1665 close_printer_handle(p, handle);
1666 return WERR_ACCESS_DENIED;
1669 /* Allow admin access */
1671 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1673 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1675 if (!lp_ms_add_printer_wizard()) {
1676 close_printer_handle(p, handle);
1677 return WERR_ACCESS_DENIED;
1680 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1681 and not a printer admin, then fail */
1684 && !user_has_privileges( user.nt_user_token, &se_printop )
1685 && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum), user.groups, user.ngroups) )
1687 close_printer_handle(p, handle);
1688 return WERR_ACCESS_DENIED;
1691 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1695 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1698 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1699 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1701 /* We fall through to return WERR_OK */
1706 /* NT doesn't let us connect to a printer if the connecting user
1707 doesn't have print permission. */
1709 if (!get_printer_snum(p, handle, &snum)) {
1710 close_printer_handle(p, handle);
1714 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1716 /* map an empty access mask to the minimum access mask */
1717 if (printer_default->access_required == 0x0)
1718 printer_default->access_required = PRINTER_ACCESS_USE;
1721 * If we are not serving the printer driver for this printer,
1722 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1723 * will keep NT clients happy --jerry
1726 if (lp_use_client_driver(snum)
1727 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1729 printer_default->access_required = PRINTER_ACCESS_USE;
1732 /* check smb.conf parameters and the the sec_desc */
1734 if (!user_ok(uidtoname(user.uid), snum, user.groups, user.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
1735 DEBUG(3, ("access DENIED for printer open\n"));
1736 close_printer_handle(p, handle);
1737 return WERR_ACCESS_DENIED;
1740 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1741 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1742 close_printer_handle(p, handle);
1743 return WERR_ACCESS_DENIED;
1746 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1747 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1749 printer_default->access_required = PRINTER_ACCESS_USE;
1751 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1752 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1756 Printer->access_granted = printer_default->access_required;
1759 * If the client sent a devmode in the OpenPrinter() call, then
1760 * save it here in case we get a job submission on this handle
1763 if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
1764 && q_u->printer_default.devmode_cont.devmode_ptr )
1766 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1767 &Printer->nt_devmode );
1770 #if 0 /* JERRY -- I'm doubtful this is really effective */
1771 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1772 optimization in Windows 2000 clients --jerry */
1774 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1775 && (RA_WIN2K == get_remote_arch()) )
1777 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1778 sys_usleep( 500000 );
1785 /****************************************************************************
1786 ****************************************************************************/
1788 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1789 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1795 ret = uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
1804 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1805 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1811 printer->info_3=NULL;
1812 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1816 printer->info_6=NULL;
1817 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1827 BOOL convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1828 NT_DEVICEMODE **pp_nt_devmode)
1830 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1833 * Ensure nt_devmode is a valid pointer
1834 * as we will be overwriting it.
1837 if (nt_devmode == NULL) {
1838 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1839 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1843 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1844 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1846 nt_devmode->specversion=devmode->specversion;
1847 nt_devmode->driverversion=devmode->driverversion;
1848 nt_devmode->size=devmode->size;
1849 nt_devmode->fields=devmode->fields;
1850 nt_devmode->orientation=devmode->orientation;
1851 nt_devmode->papersize=devmode->papersize;
1852 nt_devmode->paperlength=devmode->paperlength;
1853 nt_devmode->paperwidth=devmode->paperwidth;
1854 nt_devmode->scale=devmode->scale;
1855 nt_devmode->copies=devmode->copies;
1856 nt_devmode->defaultsource=devmode->defaultsource;
1857 nt_devmode->printquality=devmode->printquality;
1858 nt_devmode->color=devmode->color;
1859 nt_devmode->duplex=devmode->duplex;
1860 nt_devmode->yresolution=devmode->yresolution;
1861 nt_devmode->ttoption=devmode->ttoption;
1862 nt_devmode->collate=devmode->collate;
1864 nt_devmode->logpixels=devmode->logpixels;
1865 nt_devmode->bitsperpel=devmode->bitsperpel;
1866 nt_devmode->pelswidth=devmode->pelswidth;
1867 nt_devmode->pelsheight=devmode->pelsheight;
1868 nt_devmode->displayflags=devmode->displayflags;
1869 nt_devmode->displayfrequency=devmode->displayfrequency;
1870 nt_devmode->icmmethod=devmode->icmmethod;
1871 nt_devmode->icmintent=devmode->icmintent;
1872 nt_devmode->mediatype=devmode->mediatype;
1873 nt_devmode->dithertype=devmode->dithertype;
1874 nt_devmode->reserved1=devmode->reserved1;
1875 nt_devmode->reserved2=devmode->reserved2;
1876 nt_devmode->panningwidth=devmode->panningwidth;
1877 nt_devmode->panningheight=devmode->panningheight;
1880 * Only change private and driverextra if the incoming devmode
1881 * has a new one. JRA.
1884 if ((devmode->driverextra != 0) && (devmode->private != NULL)) {
1885 SAFE_FREE(nt_devmode->private);
1886 nt_devmode->driverextra=devmode->driverextra;
1887 if((nt_devmode->private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1889 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
1892 *pp_nt_devmode = nt_devmode;
1897 /********************************************************************
1898 * _spoolss_enddocprinter_internal.
1899 ********************************************************************/
1901 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1903 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1907 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1911 if (!get_printer_snum(p, handle, &snum))
1914 Printer->document_started=False;
1915 print_job_end(snum, Printer->jobid,True);
1916 /* error codes unhandled so far ... */
1921 /********************************************************************
1922 * api_spoolss_closeprinter
1923 ********************************************************************/
1925 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1927 POLICY_HND *handle = &q_u->handle;
1929 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1931 if (Printer && Printer->document_started)
1932 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1934 if (!close_printer_handle(p, handle))
1937 /* clear the returned printer handle. Observed behavior
1938 from Win2k server. Don't think this really matters.
1939 Previous code just copied the value of the closed
1942 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1947 /********************************************************************
1948 * api_spoolss_deleteprinter
1950 ********************************************************************/
1952 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1954 POLICY_HND *handle = &q_u->handle;
1955 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1958 if (Printer && Printer->document_started)
1959 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1961 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1963 result = delete_printer_handle(p, handle);
1965 update_c_setprinter(False);
1970 /*******************************************************************
1971 * static function to lookup the version id corresponding to an
1972 * long architecture string
1973 ******************************************************************/
1975 static int get_version_id (char * arch)
1978 struct table_node archi_table[]= {
1980 {"Windows 4.0", "WIN40", 0 },
1981 {"Windows NT x86", "W32X86", 2 },
1982 {"Windows NT R4000", "W32MIPS", 2 },
1983 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1984 {"Windows NT PowerPC", "W32PPC", 2 },
1985 {"Windows IA64", "IA64", 3 },
1986 {"Windows x64", "x64", 3 },
1990 for (i=0; archi_table[i].long_archi != NULL; i++)
1992 if (strcmp(arch, archi_table[i].long_archi) == 0)
1993 return (archi_table[i].version);
1999 /********************************************************************
2000 * _spoolss_deleteprinterdriver
2001 ********************************************************************/
2003 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
2007 NT_PRINTER_DRIVER_INFO_LEVEL info;
2008 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2010 struct current_user user;
2012 WERROR status_win2k = WERR_ACCESS_DENIED;
2014 get_current_user(&user, p);
2016 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2017 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2019 /* check that we have a valid driver name first */
2021 if ((version=get_version_id(arch)) == -1)
2022 return WERR_INVALID_ENVIRONMENT;
2025 ZERO_STRUCT(info_win2k);
2027 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2029 /* try for Win2k driver if "Windows NT x86" */
2031 if ( version == 2 ) {
2033 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2034 status = WERR_UNKNOWN_PRINTER_DRIVER;
2038 /* otherwise it was a failure */
2040 status = WERR_UNKNOWN_PRINTER_DRIVER;
2046 if (printer_driver_in_use(info.info_3)) {
2047 status = WERR_PRINTER_DRIVER_IN_USE;
2053 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2055 /* if we get to here, we now have 2 driver info structures to remove */
2056 /* remove the Win2k driver first*/
2058 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
2059 free_a_printer_driver( info_win2k, 3 );
2061 /* this should not have failed---if it did, report to client */
2062 if ( !W_ERROR_IS_OK(status_win2k) )
2067 status = delete_printer_driver(info.info_3, &user, version, False);
2069 /* if at least one of the deletes succeeded return OK */
2071 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2075 free_a_printer_driver( info, 3 );
2080 /********************************************************************
2081 * spoolss_deleteprinterdriverex
2082 ********************************************************************/
2084 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2088 NT_PRINTER_DRIVER_INFO_LEVEL info;
2089 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2091 uint32 flags = q_u->delete_flags;
2093 struct current_user user;
2095 WERROR status_win2k = WERR_ACCESS_DENIED;
2097 get_current_user(&user, p);
2099 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
2100 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
2102 /* check that we have a valid driver name first */
2103 if ((version=get_version_id(arch)) == -1) {
2104 /* this is what NT returns */
2105 return WERR_INVALID_ENVIRONMENT;
2108 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2109 version = q_u->version;
2112 ZERO_STRUCT(info_win2k);
2114 status = get_a_printer_driver(&info, 3, driver, arch, version);
2116 if ( !W_ERROR_IS_OK(status) )
2119 * if the client asked for a specific version,
2120 * or this is something other than Windows NT x86,
2124 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2127 /* try for Win2k driver if "Windows NT x86" */
2130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2131 status = WERR_UNKNOWN_PRINTER_DRIVER;
2136 if ( printer_driver_in_use(info.info_3) ) {
2137 status = WERR_PRINTER_DRIVER_IN_USE;
2142 * we have a couple of cases to consider.
2143 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2144 * then the delete should fail if **any** files overlap with
2146 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2147 * non-overlapping files
2148 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2149 * is set, the do not delete any files
2150 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2155 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2157 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2158 /* no idea of the correct error here */
2159 status = WERR_ACCESS_DENIED;
2164 /* also check for W32X86/3 if necessary; maybe we already have? */
2166 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2170 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 free_a_printer_driver( info_win2k, 3 );
2173 status = WERR_ACCESS_DENIED;
2177 /* if we get to here, we now have 2 driver info structures to remove */
2178 /* remove the Win2k driver first*/
2180 status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
2181 free_a_printer_driver( info_win2k, 3 );
2183 /* this should not have failed---if it did, report to client */
2185 if ( !W_ERROR_IS_OK(status_win2k) )
2190 status = delete_printer_driver(info.info_3, &user, version, delete_files);
2192 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2195 free_a_printer_driver( info, 3 );
2201 /****************************************************************************
2202 Internal routine for retreiving printerdata
2203 ***************************************************************************/
2205 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2206 const char *key, const char *value, uint32 *type, uint8 **data,
2207 uint32 *needed, uint32 in_size )
2209 REGISTRY_VALUE *val;
2212 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2213 return WERR_BADFILE;
2215 *type = regval_type( val );
2217 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2219 size = regval_size( val );
2221 /* copy the min(in_size, len) */
2224 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2226 /* special case for 0 length values */
2228 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2232 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2241 DEBUG(5,("get_printer_dataex: copy done\n"));
2246 /****************************************************************************
2247 Internal routine for removing printerdata
2248 ***************************************************************************/
2250 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2252 return delete_printer_data( printer->info_2, key, value );
2255 /****************************************************************************
2256 Internal routine for storing printerdata
2257 ***************************************************************************/
2259 static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2260 uint32 type, uint8 *data, int real_len )
2262 delete_printer_data( printer->info_2, key, value );
2264 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2267 /********************************************************************
2268 GetPrinterData on a printer server Handle.
2269 ********************************************************************/
2271 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2275 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2277 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2279 if((*data = (uint8 *)TALLOC_ZERO(ctx, 4*sizeof(uint8) )) == NULL)
2285 if (!StrCaseCmp(value, "BeepEnabled")) {
2287 if((*data = (uint8 *)TALLOC(ctx, 4*sizeof(uint8) )) == NULL)
2289 SIVAL(*data, 0, 0x00);
2294 if (!StrCaseCmp(value, "EventLog")) {
2296 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2298 /* formally was 0x1b */
2299 SIVAL(*data, 0, 0x0);
2304 if (!StrCaseCmp(value, "NetPopup")) {
2306 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2308 SIVAL(*data, 0, 0x00);
2313 if (!StrCaseCmp(value, "MajorVersion")) {
2315 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2318 /* Windows NT 4.0 seems to not allow uploading of drivers
2319 to a server that reports 0x3 as the MajorVersion.
2320 need to investigate more how Win2k gets around this .
2323 if ( RA_WINNT == get_remote_arch() )
2332 if (!StrCaseCmp(value, "MinorVersion")) {
2334 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2342 * uint32 size = 0x114
2344 * uint32 minor = [0|1]
2345 * uint32 build = [2195|2600]
2346 * extra unicode string = e.g. "Service Pack 3"
2348 if (!StrCaseCmp(value, "OSVersion")) {
2352 if((*data = (uint8 *)TALLOC(ctx, *needed)) == NULL)
2354 ZERO_STRUCTP( *data );
2356 SIVAL(*data, 0, *needed); /* size */
2357 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2359 SIVAL(*data, 12, 2195); /* build */
2361 /* leave extra string empty */
2367 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2368 const char *string="C:\\PRINTERS";
2370 *needed = 2*(strlen(string)+1);
2371 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2373 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2375 /* it's done by hand ready to go on the wire */
2376 for (i=0; i<strlen(string); i++) {
2377 (*data)[2*i]=string[i];
2378 (*data)[2*i+1]='\0';
2383 if (!StrCaseCmp(value, "Architecture")) {
2384 const char *string="Windows NT x86";
2386 *needed = 2*(strlen(string)+1);
2387 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2389 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2397 if (!StrCaseCmp(value, "DsPresent")) {
2399 if((*data = (uint8 *)TALLOC(ctx, 4 )) == NULL)
2402 /* only show the publish check box if we are a
2403 memeber of a AD domain */
2405 if ( lp_security() == SEC_ADS )
2406 SIVAL(*data, 0, 0x01);
2408 SIVAL(*data, 0, 0x00);
2414 if (!StrCaseCmp(value, "DNSMachineName")) {
2417 if (!get_mydnsfullname(hostname))
2418 return WERR_BADFILE;
2420 *needed = 2*(strlen(hostname)+1);
2421 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2423 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2424 for (i=0; i<strlen(hostname); i++) {
2425 (*data)[2*i]=hostname[i];
2426 (*data)[2*i+1]='\0';
2432 return WERR_BADFILE;
2435 /********************************************************************
2436 * spoolss_getprinterdata
2437 ********************************************************************/
2439 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2441 POLICY_HND *handle = &q_u->handle;
2442 UNISTR2 *valuename = &q_u->valuename;
2443 uint32 in_size = q_u->size;
2444 uint32 *type = &r_u->type;
2445 uint32 *out_size = &r_u->size;
2446 uint8 **data = &r_u->data;
2447 uint32 *needed = &r_u->needed;
2450 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2451 NT_PRINTER_INFO_LEVEL *printer = NULL;
2455 * Reminder: when it's a string, the length is in BYTES
2456 * even if UNICODE is negociated.
2461 *out_size = in_size;
2463 /* in case of problem, return some default values */
2468 DEBUG(4,("_spoolss_getprinterdata\n"));
2471 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2472 status = WERR_BADFID;
2476 unistr2_to_ascii(value, valuename, sizeof(value)-1);
2478 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
2479 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2482 if ( !get_printer_snum(p,handle, &snum) ) {
2483 status = WERR_BADFID;
2487 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2488 if ( !W_ERROR_IS_OK(status) )
2491 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2493 if ( strequal(value, "ChangeId") ) {
2495 *needed = sizeof(uint32);
2496 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2497 status = WERR_NOMEM;
2500 SIVAL( *data, 0, printer->info_2->changeid );
2504 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2507 if (*needed > *out_size)
2508 status = WERR_MORE_DATA;
2511 if ( !W_ERROR_IS_OK(status) )
2513 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2515 /* reply this param doesn't exist */
2518 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2520 free_a_printer( &printer, 2 );
2529 /* cleanup & exit */
2532 free_a_printer( &printer, 2 );
2537 /*********************************************************
2538 Connect to the client machine.
2539 **********************************************************/
2541 static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
2542 struct in_addr *client_ip, const char *remote_machine)
2544 ZERO_STRUCTP(the_cli);
2546 if(cli_initialise(the_cli) == NULL) {
2547 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2551 if ( is_zero_ip(*client_ip) ) {
2552 if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
2553 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2554 cli_shutdown(the_cli);
2558 if (ismyip(the_cli->dest_ip)) {
2559 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2560 cli_shutdown(the_cli);
2565 the_cli->dest_ip.s_addr = client_ip->s_addr;
2566 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2567 inet_ntoa(*client_ip) ));
2570 if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
2571 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2572 cli_shutdown(the_cli);
2576 if (!attempt_netbios_session_request(the_cli, global_myname(), remote_machine, &the_cli->dest_ip)) {
2577 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2579 cli_shutdown(the_cli);
2583 the_cli->protocol = PROTOCOL_NT1;
2584 cli_setup_signing_state(the_cli, lp_client_signing());
2586 if (!cli_negprot(the_cli)) {
2587 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2588 cli_shutdown(the_cli);
2592 if (the_cli->protocol != PROTOCOL_NT1) {
2593 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2594 cli_shutdown(the_cli);
2599 * Do an anonymous session setup.
2602 if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
2603 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2604 cli_shutdown(the_cli);
2608 if (!(the_cli->sec_mode & 1)) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
2610 cli_shutdown(the_cli);
2614 if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
2615 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
2616 cli_shutdown(the_cli);
2621 * Ok - we have an anonymous connection to the IPC$ share.
2622 * Now start the NT Domain stuff :-).
2625 if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
2626 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
2627 cli_nt_session_close(the_cli);
2628 cli_ulogoff(the_cli);
2629 cli_shutdown(the_cli);
2636 /***************************************************************************
2637 Connect to the client.
2638 ****************************************************************************/
2640 static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
2641 uint32 localprinter, uint32 type,
2642 POLICY_HND *handle, struct in_addr *client_ip)
2647 * If it's the first connection, contact the client
2648 * and connect to the IPC$ share anonymously
2650 if (smb_connections==0) {
2651 fstring unix_printer;
2653 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2655 ZERO_STRUCT(notify_cli);
2657 if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer))
2660 message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
2661 /* Tell the connections db we're now interested in printer
2662 * notify messages. */
2663 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2667 * Tell the specific printing tdb we want messages for this printer
2668 * by registering our PID.
2671 if (!print_notify_register_pid(snum))
2672 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2676 result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
2679 if (!W_ERROR_IS_OK(result))
2680 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2681 dos_errstr(result)));
2683 return (W_ERROR_IS_OK(result));
2686 /********************************************************************
2688 * ReplyFindFirstPrinterChangeNotifyEx
2690 * before replying OK: status=0 a rpc call is made to the workstation
2691 * asking ReplyOpenPrinter
2693 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2694 * called from api_spoolss_rffpcnex
2695 ********************************************************************/
2697 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2699 POLICY_HND *handle = &q_u->handle;
2700 uint32 flags = q_u->flags;
2701 uint32 options = q_u->options;
2702 UNISTR2 *localmachine = &q_u->localmachine;
2703 uint32 printerlocal = q_u->printerlocal;
2705 SPOOL_NOTIFY_OPTION *option = q_u->option;
2706 struct in_addr client_ip;
2708 /* store the notify value in the printer struct */
2710 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2713 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2717 Printer->notify.flags=flags;
2718 Printer->notify.options=options;
2719 Printer->notify.printerlocal=printerlocal;
2721 if (Printer->notify.option)
2722 free_spool_notify_option(&Printer->notify.option);
2724 Printer->notify.option=dup_spool_notify_option(option);
2726 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2727 sizeof(Printer->notify.localmachine)-1);
2729 /* Connect to the client machine and send a ReplyOpenPrinter */
2731 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
2733 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
2734 !get_printer_snum(p, handle, &snum) )
2737 client_ip.s_addr = inet_addr(p->conn->client_address);
2739 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2740 Printer->notify.printerlocal, 1,
2741 &Printer->notify.client_hnd, &client_ip))
2742 return WERR_SERVER_UNAVAILABLE;
2744 Printer->notify.client_connected=True;
2749 /*******************************************************************
2750 * fill a notify_info_data with the servername
2751 ********************************************************************/
2753 void spoolss_notify_server_name(int snum,
2754 SPOOL_NOTIFY_INFO_DATA *data,
2755 print_queue_struct *queue,
2756 NT_PRINTER_INFO_LEVEL *printer,
2757 TALLOC_CTX *mem_ctx)
2762 len = rpcstr_push(temp, printer->info_2->servername, sizeof(temp)-2, STR_TERMINATE);
2764 data->notify_data.data.length = len;
2765 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2767 if (!data->notify_data.data.string) {
2768 data->notify_data.data.length = 0;
2772 memcpy(data->notify_data.data.string, temp, len);
2775 /*******************************************************************
2776 * fill a notify_info_data with the printername (not including the servername).
2777 ********************************************************************/
2779 void spoolss_notify_printer_name(int snum,
2780 SPOOL_NOTIFY_INFO_DATA *data,
2781 print_queue_struct *queue,
2782 NT_PRINTER_INFO_LEVEL *printer,
2783 TALLOC_CTX *mem_ctx)
2788 /* the notify name should not contain the \\server\ part */
2789 char *p = strrchr(printer->info_2->printername, '\\');
2792 p = printer->info_2->printername;
2797 len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
2799 data->notify_data.data.length = len;
2800 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2802 if (!data->notify_data.data.string) {
2803 data->notify_data.data.length = 0;
2807 memcpy(data->notify_data.data.string, temp, len);
2810 /*******************************************************************
2811 * fill a notify_info_data with the servicename
2812 ********************************************************************/
2814 void spoolss_notify_share_name(int snum,
2815 SPOOL_NOTIFY_INFO_DATA *data,
2816 print_queue_struct *queue,
2817 NT_PRINTER_INFO_LEVEL *printer,
2818 TALLOC_CTX *mem_ctx)
2823 len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
2825 data->notify_data.data.length = len;
2826 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2828 if (!data->notify_data.data.string) {
2829 data->notify_data.data.length = 0;
2833 memcpy(data->notify_data.data.string, temp, len);
2836 /*******************************************************************
2837 * fill a notify_info_data with the port name
2838 ********************************************************************/
2840 void spoolss_notify_port_name(int snum,
2841 SPOOL_NOTIFY_INFO_DATA *data,
2842 print_queue_struct *queue,
2843 NT_PRINTER_INFO_LEVEL *printer,
2844 TALLOC_CTX *mem_ctx)
2849 /* even if it's strange, that's consistant in all the code */
2851 len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
2853 data->notify_data.data.length = len;
2854 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2856 if (!data->notify_data.data.string) {
2857 data->notify_data.data.length = 0;
2861 memcpy(data->notify_data.data.string, temp, len);
2864 /*******************************************************************
2865 * fill a notify_info_data with the printername
2866 * but it doesn't exist, have to see what to do
2867 ********************************************************************/
2869 void spoolss_notify_driver_name(int snum,
2870 SPOOL_NOTIFY_INFO_DATA *data,
2871 print_queue_struct *queue,
2872 NT_PRINTER_INFO_LEVEL *printer,
2873 TALLOC_CTX *mem_ctx)
2878 len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
2880 data->notify_data.data.length = len;
2881 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2883 if (!data->notify_data.data.string) {
2884 data->notify_data.data.length = 0;
2888 memcpy(data->notify_data.data.string, temp, len);
2891 /*******************************************************************
2892 * fill a notify_info_data with the comment
2893 ********************************************************************/
2895 void spoolss_notify_comment(int snum,
2896 SPOOL_NOTIFY_INFO_DATA *data,
2897 print_queue_struct *queue,
2898 NT_PRINTER_INFO_LEVEL *printer,
2899 TALLOC_CTX *mem_ctx)
2904 if (*printer->info_2->comment == '\0')
2905 len = rpcstr_push(temp, lp_comment(snum), sizeof(temp)-2, STR_TERMINATE);
2907 len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
2909 data->notify_data.data.length = len;
2910 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2912 if (!data->notify_data.data.string) {
2913 data->notify_data.data.length = 0;
2917 memcpy(data->notify_data.data.string, temp, len);
2920 /*******************************************************************
2921 * fill a notify_info_data with the comment
2922 * location = "Room 1, floor 2, building 3"
2923 ********************************************************************/
2925 void spoolss_notify_location(int snum,
2926 SPOOL_NOTIFY_INFO_DATA *data,
2927 print_queue_struct *queue,
2928 NT_PRINTER_INFO_LEVEL *printer,
2929 TALLOC_CTX *mem_ctx)
2934 len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
2936 data->notify_data.data.length = len;
2937 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2939 if (!data->notify_data.data.string) {
2940 data->notify_data.data.length = 0;
2944 memcpy(data->notify_data.data.string, temp, len);
2947 /*******************************************************************
2948 * fill a notify_info_data with the device mode
2949 * jfm:xxxx don't to it for know but that's a real problem !!!
2950 ********************************************************************/
2952 static void spoolss_notify_devmode(int snum,
2953 SPOOL_NOTIFY_INFO_DATA *data,
2954 print_queue_struct *queue,
2955 NT_PRINTER_INFO_LEVEL *printer,
2956 TALLOC_CTX *mem_ctx)
2960 /*******************************************************************
2961 * fill a notify_info_data with the separator file name
2962 ********************************************************************/
2964 void spoolss_notify_sepfile(int snum,
2965 SPOOL_NOTIFY_INFO_DATA *data,
2966 print_queue_struct *queue,
2967 NT_PRINTER_INFO_LEVEL *printer,
2968 TALLOC_CTX *mem_ctx)
2973 len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
2975 data->notify_data.data.length = len;
2976 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
2978 if (!data->notify_data.data.string) {
2979 data->notify_data.data.length = 0;
2983 memcpy(data->notify_data.data.string, temp, len);
2986 /*******************************************************************
2987 * fill a notify_info_data with the print processor
2988 * jfm:xxxx return always winprint to indicate we don't do anything to it
2989 ********************************************************************/
2991 void spoolss_notify_print_processor(int snum,
2992 SPOOL_NOTIFY_INFO_DATA *data,
2993 print_queue_struct *queue,
2994 NT_PRINTER_INFO_LEVEL *printer,
2995 TALLOC_CTX *mem_ctx)
3000 len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
3002 data->notify_data.data.length = len;
3003 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3005 if (!data->notify_data.data.string) {
3006 data->notify_data.data.length = 0;
3010 memcpy(data->notify_data.data.string, temp, len);
3013 /*******************************************************************
3014 * fill a notify_info_data with the print processor options
3015 * jfm:xxxx send an empty string
3016 ********************************************************************/
3018 void spoolss_notify_parameters(int snum,
3019 SPOOL_NOTIFY_INFO_DATA *data,
3020 print_queue_struct *queue,
3021 NT_PRINTER_INFO_LEVEL *printer,
3022 TALLOC_CTX *mem_ctx)
3027 len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
3029 data->notify_data.data.length = len;
3030 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3032 if (!data->notify_data.data.string) {
3033 data->notify_data.data.length = 0;
3037 memcpy(data->notify_data.data.string, temp, len);
3040 /*******************************************************************
3041 * fill a notify_info_data with the data type
3042 * jfm:xxxx always send RAW as data type
3043 ********************************************************************/
3045 void spoolss_notify_datatype(int snum,
3046 SPOOL_NOTIFY_INFO_DATA *data,
3047 print_queue_struct *queue,
3048 NT_PRINTER_INFO_LEVEL *printer,
3049 TALLOC_CTX *mem_ctx)
3054 len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
3056 data->notify_data.data.length = len;
3057 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3059 if (!data->notify_data.data.string) {
3060 data->notify_data.data.length = 0;
3064 memcpy(data->notify_data.data.string, temp, len);
3067 /*******************************************************************
3068 * fill a notify_info_data with the security descriptor
3069 * jfm:xxxx send an null pointer to say no security desc
3070 * have to implement security before !
3071 ********************************************************************/
3073 static void spoolss_notify_security_desc(int snum,
3074 SPOOL_NOTIFY_INFO_DATA *data,
3075 print_queue_struct *queue,
3076 NT_PRINTER_INFO_LEVEL *printer,
3077 TALLOC_CTX *mem_ctx)
3079 data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
3080 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
3083 /*******************************************************************
3084 * fill a notify_info_data with the attributes
3085 * jfm:xxxx a samba printer is always shared
3086 ********************************************************************/
3088 void spoolss_notify_attributes(int snum,
3089 SPOOL_NOTIFY_INFO_DATA *data,
3090 print_queue_struct *queue,
3091 NT_PRINTER_INFO_LEVEL *printer,
3092 TALLOC_CTX *mem_ctx)
3094 data->notify_data.value[0] = printer->info_2->attributes;
3095 data->notify_data.value[1] = 0;
3098 /*******************************************************************
3099 * fill a notify_info_data with the priority
3100 ********************************************************************/
3102 static void spoolss_notify_priority(int snum,
3103 SPOOL_NOTIFY_INFO_DATA *data,
3104 print_queue_struct *queue,
3105 NT_PRINTER_INFO_LEVEL *printer,
3106 TALLOC_CTX *mem_ctx)
3108 data->notify_data.value[0] = printer->info_2->priority;
3109 data->notify_data.value[1] = 0;
3112 /*******************************************************************
3113 * fill a notify_info_data with the default priority
3114 ********************************************************************/
3116 static void spoolss_notify_default_priority(int snum,
3117 SPOOL_NOTIFY_INFO_DATA *data,
3118 print_queue_struct *queue,
3119 NT_PRINTER_INFO_LEVEL *printer,
3120 TALLOC_CTX *mem_ctx)
3122 data->notify_data.value[0] = printer->info_2->default_priority;
3123 data->notify_data.value[1] = 0;
3126 /*******************************************************************
3127 * fill a notify_info_data with the start time
3128 ********************************************************************/
3130 static void spoolss_notify_start_time(int snum,
3131 SPOOL_NOTIFY_INFO_DATA *data,
3132 print_queue_struct *queue,
3133 NT_PRINTER_INFO_LEVEL *printer,
3134 TALLOC_CTX *mem_ctx)
3136 data->notify_data.value[0] = printer->info_2->starttime;
3137 data->notify_data.value[1] = 0;
3140 /*******************************************************************
3141 * fill a notify_info_data with the until time
3142 ********************************************************************/
3144 static void spoolss_notify_until_time(int snum,
3145 SPOOL_NOTIFY_INFO_DATA *data,
3146 print_queue_struct *queue,
3147 NT_PRINTER_INFO_LEVEL *printer,
3148 TALLOC_CTX *mem_ctx)
3150 data->notify_data.value[0] = printer->info_2->untiltime;
3151 data->notify_data.value[1] = 0;
3154 /*******************************************************************
3155 * fill a notify_info_data with the status
3156 ********************************************************************/
3158 static void spoolss_notify_status(int snum,
3159 SPOOL_NOTIFY_INFO_DATA *data,
3160 print_queue_struct *queue,
3161 NT_PRINTER_INFO_LEVEL *printer,
3162 TALLOC_CTX *mem_ctx)
3164 print_status_struct status;
3166 print_queue_length(snum, &status);
3167 data->notify_data.value[0]=(uint32) status.status;
3168 data->notify_data.value[1] = 0;
3171 /*******************************************************************
3172 * fill a notify_info_data with the number of jobs queued
3173 ********************************************************************/
3175 void spoolss_notify_cjobs(int snum,
3176 SPOOL_NOTIFY_INFO_DATA *data,
3177 print_queue_struct *queue,
3178 NT_PRINTER_INFO_LEVEL *printer,
3179 TALLOC_CTX *mem_ctx)
3181 data->notify_data.value[0] = print_queue_length(snum, NULL);
3182 data->notify_data.value[1] = 0;
3185 /*******************************************************************
3186 * fill a notify_info_data with the average ppm
3187 ********************************************************************/
3189 static void spoolss_notify_average_ppm(int snum,
3190 SPOOL_NOTIFY_INFO_DATA *data,
3191 print_queue_struct *queue,
3192 NT_PRINTER_INFO_LEVEL *printer,
3193 TALLOC_CTX *mem_ctx)
3195 /* always respond 8 pages per minutes */
3196 /* a little hard ! */
3197 data->notify_data.value[0] = printer->info_2->averageppm;
3198 data->notify_data.value[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with username
3203 ********************************************************************/
3205 static void spoolss_notify_username(int snum,
3206 SPOOL_NOTIFY_INFO_DATA *data,
3207 print_queue_struct *queue,
3208 NT_PRINTER_INFO_LEVEL *printer,
3209 TALLOC_CTX *mem_ctx)
3214 len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
3216 data->notify_data.data.length = len;
3217 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3219 if (!data->notify_data.data.string) {
3220 data->notify_data.data.length = 0;
3224 memcpy(data->notify_data.data.string, temp, len);
3227 /*******************************************************************
3228 * fill a notify_info_data with job status
3229 ********************************************************************/
3231 static void spoolss_notify_job_status(int snum,
3232 SPOOL_NOTIFY_INFO_DATA *data,
3233 print_queue_struct *queue,
3234 NT_PRINTER_INFO_LEVEL *printer,
3235 TALLOC_CTX *mem_ctx)
3237 data->notify_data.value[0]=nt_printj_status(queue->status);
3238 data->notify_data.value[1] = 0;
3241 /*******************************************************************
3242 * fill a notify_info_data with job name
3243 ********************************************************************/
3245 static void spoolss_notify_job_name(int snum,
3246 SPOOL_NOTIFY_INFO_DATA *data,
3247 print_queue_struct *queue,
3248 NT_PRINTER_INFO_LEVEL *printer,
3249 TALLOC_CTX *mem_ctx)
3254 len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
3256 data->notify_data.data.length = len;
3257 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3259 if (!data->notify_data.data.string) {
3260 data->notify_data.data.length = 0;
3264 memcpy(data->notify_data.data.string, temp, len);
3267 /*******************************************************************
3268 * fill a notify_info_data with job status
3269 ********************************************************************/
3271 static void spoolss_notify_job_status_string(int snum,
3272 SPOOL_NOTIFY_INFO_DATA *data,
3273 print_queue_struct *queue,
3274 NT_PRINTER_INFO_LEVEL *printer,
3275 TALLOC_CTX *mem_ctx)
3278 * Now we're returning job status codes we just return a "" here. JRA.
3285 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3288 switch (queue->status) {
3293 p = ""; /* NT provides the paused string */
3302 #endif /* NO LONGER NEEDED. */
3304 len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
3306 data->notify_data.data.length = len;
3307 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3309 if (!data->notify_data.data.string) {
3310 data->notify_data.data.length = 0;
3314 memcpy(data->notify_data.data.string, temp, len);
3317 /*******************************************************************
3318 * fill a notify_info_data with job time
3319 ********************************************************************/
3321 static void spoolss_notify_job_time(int snum,
3322 SPOOL_NOTIFY_INFO_DATA *data,
3323 print_queue_struct *queue,
3324 NT_PRINTER_INFO_LEVEL *printer,
3325 TALLOC_CTX *mem_ctx)
3327 data->notify_data.value[0]=0x0;
3328 data->notify_data.value[1]=0;
3331 /*******************************************************************
3332 * fill a notify_info_data with job size
3333 ********************************************************************/
3335 static void spoolss_notify_job_size(int snum,
3336 SPOOL_NOTIFY_INFO_DATA *data,
3337 print_queue_struct *queue,
3338 NT_PRINTER_INFO_LEVEL *printer,
3339 TALLOC_CTX *mem_ctx)
3341 data->notify_data.value[0]=queue->size;
3342 data->notify_data.value[1]=0;
3345 /*******************************************************************
3346 * fill a notify_info_data with page info
3347 ********************************************************************/
3348 static void spoolss_notify_total_pages(int snum,
3349 SPOOL_NOTIFY_INFO_DATA *data,
3350 print_queue_struct *queue,
3351 NT_PRINTER_INFO_LEVEL *printer,
3352 TALLOC_CTX *mem_ctx)
3354 data->notify_data.value[0]=queue->page_count;
3355 data->notify_data.value[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with pages printed info.
3360 ********************************************************************/
3361 static void spoolss_notify_pages_printed(int snum,
3362 SPOOL_NOTIFY_INFO_DATA *data,
3363 print_queue_struct *queue,
3364 NT_PRINTER_INFO_LEVEL *printer,
3365 TALLOC_CTX *mem_ctx)
3367 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3368 data->notify_data.value[1]=0;
3371 /*******************************************************************
3372 Fill a notify_info_data with job position.
3373 ********************************************************************/
3375 static void spoolss_notify_job_position(int snum,
3376 SPOOL_NOTIFY_INFO_DATA *data,
3377 print_queue_struct *queue,
3378 NT_PRINTER_INFO_LEVEL *printer,
3379 TALLOC_CTX *mem_ctx)
3381 data->notify_data.value[0]=queue->job;
3382 data->notify_data.value[1]=0;
3385 /*******************************************************************
3386 Fill a notify_info_data with submitted time.
3387 ********************************************************************/
3389 static void spoolss_notify_submitted_time(int snum,
3390 SPOOL_NOTIFY_INFO_DATA *data,
3391 print_queue_struct *queue,
3392 NT_PRINTER_INFO_LEVEL *printer,
3393 TALLOC_CTX *mem_ctx)
3400 t=gmtime(&queue->time);
3402 len = sizeof(SYSTEMTIME);
3404 data->notify_data.data.length = len;
3405 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3407 if (!data->notify_data.data.string) {
3408 data->notify_data.data.length = 0;
3412 make_systemtime(&st, t);
3415 * Systemtime must be linearized as a set of UINT16's.
3416 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3419 p = (char *)data->notify_data.data.string;
3420 SSVAL(p, 0, st.year);
3421 SSVAL(p, 2, st.month);
3422 SSVAL(p, 4, st.dayofweek);
3423 SSVAL(p, 6, st.day);
3424 SSVAL(p, 8, st.hour);
3425 SSVAL(p, 10, st.minute);
3426 SSVAL(p, 12, st.second);
3427 SSVAL(p, 14, st.milliseconds);
3430 struct s_notify_info_data_table
3436 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3437 print_queue_struct *queue,
3438 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3441 /* A table describing the various print notification constants and
3442 whether the notification data is a pointer to a variable sized
3443 buffer, a one value uint32 or a two value uint32. */
3445 static const struct s_notify_info_data_table notify_info_data_table[] =
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3468 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3469 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3470 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3471 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3472 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3491 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3492 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3493 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3494 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3495 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3496 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3499 /*******************************************************************
3500 Return the size of info_data structure.
3501 ********************************************************************/
3503 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3507 for (i = 0; i < sizeof(notify_info_data_table); i++)
3509 if ( (notify_info_data_table[i].type == type)
3510 && (notify_info_data_table[i].field == field) )
3512 switch(notify_info_data_table[i].size)
3514 case NOTIFY_ONE_VALUE:
3515 case NOTIFY_TWO_VALUE:
3520 /* The only pointer notify data I have seen on
3521 the wire is the submitted time and this has
3522 the notify size set to 4. -tpot */
3524 case NOTIFY_POINTER:
3527 case NOTIFY_SECDESC:
3533 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3538 /*******************************************************************
3539 Return the type of notify_info_data.
3540 ********************************************************************/
3542 static int type_of_notify_info_data(uint16 type, uint16 field)
3546 for (i = 0; i < sizeof(notify_info_data_table); i++) {
3547 if (notify_info_data_table[i].type == type &&
3548 notify_info_data_table[i].field == field)
3549 return notify_info_data_table[i].size;
3555 /****************************************************************************
3556 ****************************************************************************/
3558 static int search_notify(uint16 type, uint16 field, int *value)
3562 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3563 if (notify_info_data_table[i].type == type &&
3564 notify_info_data_table[i].field == field &&
3565 notify_info_data_table[i].fn != NULL) {
3574 /****************************************************************************
3575 ****************************************************************************/
3577 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3579 info_data->type = type;
3580 info_data->field = field;
3581 info_data->reserved = 0;
3583 info_data->size = size_of_notify_info_data(type, field);
3584 info_data->enc_type = type_of_notify_info_data(type, field);
3591 /*******************************************************************
3593 * fill a notify_info struct with info asked
3595 ********************************************************************/
3597 static BOOL construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3598 snum, SPOOL_NOTIFY_OPTION_TYPE
3599 *option_type, uint32 id,
3600 TALLOC_CTX *mem_ctx)
3606 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3607 NT_PRINTER_INFO_LEVEL *printer = NULL;
3608 print_queue_struct *queue=NULL;
3610 type=option_type->type;
3612 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3613 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3614 option_type->count, lp_servicename(snum)));
3616 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3619 for(field_num=0; field_num<option_type->count; field_num++) {
3620 field = option_type->fields[field_num];
3622 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3624 if (!search_notify(type, field, &j) )
3627 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3628 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3633 current_data = &info->data[info->count];
3635 construct_info_data(current_data, type, field, id);
3637 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3638 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3640 notify_info_data_table[j].fn(snum, current_data, queue,
3646 free_a_printer(&printer, 2);
3650 /*******************************************************************
3652 * fill a notify_info struct with info asked
3654 ********************************************************************/
3656 static BOOL construct_notify_jobs_info(print_queue_struct *queue,
3657 SPOOL_NOTIFY_INFO *info,
3658 NT_PRINTER_INFO_LEVEL *printer,
3659 int snum, SPOOL_NOTIFY_OPTION_TYPE
3660 *option_type, uint32 id,
3661 TALLOC_CTX *mem_ctx)
3667 SPOOL_NOTIFY_INFO_DATA *current_data, *tid;
3669 DEBUG(4,("construct_notify_jobs_info\n"));
3671 type = option_type->type;
3673 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3674 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3675 option_type->count));
3677 for(field_num=0; field_num<option_type->count; field_num++) {
3678 field = option_type->fields[field_num];
3680 if (!search_notify(type, field, &j) )
3683 if((tid=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3684 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3687 else info->data = tid;
3689 current_data=&(info->data[info->count]);
3691 construct_info_data(current_data, type, field, id);
3692 notify_info_data_table[j].fn(snum, current_data, queue,
3701 * JFM: The enumeration is not that simple, it's even non obvious.
3703 * let's take an example: I want to monitor the PRINTER SERVER for
3704 * the printer's name and the number of jobs currently queued.
3705 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3706 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3708 * I have 3 printers on the back of my server.
3710 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3713 * 1 printer 1 name 1
3714 * 2 printer 1 cjob 1
3715 * 3 printer 2 name 2
3716 * 4 printer 2 cjob 2
3717 * 5 printer 3 name 3
3718 * 6 printer 3 name 3
3720 * that's the print server case, the printer case is even worse.
3723 /*******************************************************************
3725 * enumerate all printers on the printserver
3726 * fill a notify_info struct with info asked
3728 ********************************************************************/
3730 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3731 SPOOL_NOTIFY_INFO *info,
3732 TALLOC_CTX *mem_ctx)
3735 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3736 int n_services=lp_numservices();
3738 SPOOL_NOTIFY_OPTION *option;
3739 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3741 DEBUG(4,("printserver_notify_info\n"));
3746 option=Printer->notify.option;
3751 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3752 sending a ffpcn() request first */
3757 for (i=0; i<option->count; i++) {
3758 option_type=&(option->ctr.type[i]);
3760 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3763 for (snum=0; snum<n_services; snum++)
3765 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3766 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3772 * Debugging information, don't delete.
3775 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3776 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3777 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3779 for (i=0; i<info->count; i++) {
3780 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3781 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3782 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3789 /*******************************************************************
3791 * fill a notify_info struct with info asked
3793 ********************************************************************/
3795 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3796 TALLOC_CTX *mem_ctx)
3799 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3802 SPOOL_NOTIFY_OPTION *option;
3803 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3805 print_queue_struct *queue=NULL;
3806 print_status_struct status;
3808 DEBUG(4,("printer_notify_info\n"));
3813 option=Printer->notify.option;
3819 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3820 sending a ffpcn() request first */
3825 get_printer_snum(p, hnd, &snum);
3827 for (i=0; i<option->count; i++) {
3828 option_type=&option->ctr.type[i];
3830 switch ( option_type->type ) {
3831 case PRINTER_NOTIFY_TYPE:
3832 if(construct_notify_printer_info(Printer, info, snum,
3838 case JOB_NOTIFY_TYPE: {
3839 NT_PRINTER_INFO_LEVEL *printer = NULL;
3841 count = print_queue_status(snum, &queue, &status);
3843 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3846 for (j=0; j<count; j++) {
3847 construct_notify_jobs_info(&queue[j], info,
3854 free_a_printer(&printer, 2);
3864 * Debugging information, don't delete.
3867 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3868 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3869 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3871 for (i=0; i<info->count; i++) {
3872 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3873 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3874 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3880 /********************************************************************
3882 ********************************************************************/
3884 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3886 POLICY_HND *handle = &q_u->handle;
3887 SPOOL_NOTIFY_INFO *info = &r_u->info;
3889 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3890 WERROR result = WERR_BADFID;
3892 /* we always have a NOTIFY_INFO struct */
3896 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3897 OUR_HANDLE(handle)));
3901 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3904 * We are now using the change value, and
3905 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3906 * I don't have a global notification system, I'm sending back all the
3907 * informations even when _NOTHING_ has changed.
3910 /* We need to keep track of the change value to send back in
3911 RRPCN replies otherwise our updates are ignored. */
3913 Printer->notify.fnpcn = True;
3915 if (Printer->notify.client_connected) {
3916 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3917 Printer->notify.change = q_u->change;
3920 /* just ignore the SPOOL_NOTIFY_OPTION */
3922 switch (Printer->printer_type) {
3923 case PRINTER_HANDLE_IS_PRINTSERVER:
3924 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3927 case PRINTER_HANDLE_IS_PRINTER:
3928 result = printer_notify_info(p, handle, info, p->mem_ctx);
3932 Printer->notify.fnpcn = False;
3938 /********************************************************************
3939 * construct_printer_info_0
3940 * fill a printer_info_0 struct
3941 ********************************************************************/
3943 static BOOL construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3947 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3948 counter_printer_0 *session_counter;
3949 uint32 global_counter;
3952 print_status_struct status;
3954 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3957 count = print_queue_length(snum, &status);
3959 /* check if we already have a counter for this printer */
3960 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3961 if (session_counter->snum == snum)
3965 /* it's the first time, add it to the list */
3966 if (session_counter==NULL) {
3967 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3968 free_a_printer(&ntprinter, 2);
3971 ZERO_STRUCTP(session_counter);
3972 session_counter->snum=snum;
3973 session_counter->counter=0;
3974 DLIST_ADD(counter_list, session_counter);
3978 session_counter->counter++;
3981 * the global_counter should be stored in a TDB as it's common to all the clients
3982 * and should be zeroed on samba startup
3984 global_counter=session_counter->counter;
3986 pstrcpy(chaine,ntprinter->info_2->printername);
3988 init_unistr(&printer->printername, chaine);
3990 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", get_server_name(print_hnd));
3991 init_unistr(&printer->servername, chaine);
3993 printer->cjobs = count;
3994 printer->total_jobs = 0;
3995 printer->total_bytes = 0;
3997 setuptime = (time_t)ntprinter->info_2->setuptime;
3998 t=gmtime(&setuptime);
4000 printer->year = t->tm_year+1900;
4001 printer->month = t->tm_mon+1;
4002 printer->dayofweek = t->tm_wday;
4003 printer->day = t->tm_mday;
4004 printer->hour = t->tm_hour;
4005 printer->minute = t->tm_min;
4006 printer->second = t->tm_sec;
4007 printer->milliseconds = 0;
4009 printer->global_counter = global_counter;
4010 printer->total_pages = 0;
4012 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4013 printer->major_version = 0x0005; /* NT 5 */
4014 printer->build_version = 0x0893; /* build 2195 */
4016 printer->unknown7 = 0x1;
4017 printer->unknown8 = 0x0;
4018 printer->unknown9 = 0x0;
4019 printer->session_counter = session_counter->counter;
4020 printer->unknown11 = 0x0;
4021 printer->printer_errors = 0x0; /* number of print failure */
4022 printer->unknown13 = 0x0;
4023 printer->unknown14 = 0x1;
4024 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4025 printer->unknown16 = 0x0;
4026 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4027 printer->unknown18 = 0x0;
4028 printer->status = nt_printq_status(status.status);
4029 printer->unknown20 = 0x0;
4030 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4031 printer->unknown22 = 0x0;
4032 printer->unknown23 = 0x6; /* 6 ???*/
4033 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4034 printer->unknown25 = 0;
4035 printer->unknown26 = 0;
4036 printer->unknown27 = 0;
4037 printer->unknown28 = 0;
4038 printer->unknown29 = 0;
4040 free_a_printer(&ntprinter,2);
4044 /********************************************************************
4045 * construct_printer_info_1
4046 * fill a printer_info_1 struct
4047 ********************************************************************/
4048 static BOOL construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4052 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4054 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4057 printer->flags=flags;
4059 if (*ntprinter->info_2->comment == '\0') {
4060 init_unistr(&printer->comment, lp_comment(snum));
4061 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4062 ntprinter->info_2->drivername, lp_comment(snum));
4065 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4066 slprintf(chaine,sizeof(chaine)-1,"%s,%s,%s", ntprinter->info_2->printername,
4067 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4070 slprintf(chaine2,sizeof(chaine)-1,"%s", ntprinter->info_2->printername);
4072 init_unistr(&printer->description, chaine);
4073 init_unistr(&printer->name, chaine2);
4075 free_a_printer(&ntprinter,2);
4080 /****************************************************************************
4081 Free a DEVMODE struct.
4082 ****************************************************************************/
4084 static void free_dev_mode(DEVICEMODE *dev)
4089 SAFE_FREE(dev->private);
4094 /****************************************************************************
4095 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4096 should be valid upon entry
4097 ****************************************************************************/
4099 static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4101 if ( !devmode || !ntdevmode )
4104 init_unistr(&devmode->devicename, ntdevmode->devicename);
4106 init_unistr(&devmode->formname, ntdevmode->formname);
4108 devmode->specversion = ntdevmode->specversion;
4109 devmode->driverversion = ntdevmode->driverversion;
4110 devmode->size = ntdevmode->size;
4111 devmode->driverextra = ntdevmode->driverextra;
4112 devmode->fields = ntdevmode->fields;
4114 devmode->orientation = ntdevmode->orientation;
4115 devmode->papersize = ntdevmode->papersize;
4116 devmode->paperlength = ntdevmode->paperlength;
4117 devmode->paperwidth = ntdevmode->paperwidth;
4118 devmode->scale = ntdevmode->scale;
4119 devmode->copies = ntdevmode->copies;
4120 devmode->defaultsource = ntdevmode->defaultsource;
4121 devmode->printquality = ntdevmode->printquality;
4122 devmode->color = ntdevmode->color;
4123 devmode->duplex = ntdevmode->duplex;
4124 devmode->yresolution = ntdevmode->yresolution;
4125 devmode->ttoption = ntdevmode->ttoption;
4126 devmode->collate = ntdevmode->collate;
4127 devmode->icmmethod = ntdevmode->icmmethod;
4128 devmode->icmintent = ntdevmode->icmintent;
4129 devmode->mediatype = ntdevmode->mediatype;
4130 devmode->dithertype = ntdevmode->dithertype;
4132 if (ntdevmode->private != NULL) {
4133 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
4140 /****************************************************************************
4141 Create a DEVMODE struct. Returns malloced memory.
4142 ****************************************************************************/
4144 DEVICEMODE *construct_dev_mode(int snum)
4146 NT_PRINTER_INFO_LEVEL *printer = NULL;
4147 DEVICEMODE *devmode = NULL;
4149 DEBUG(7,("construct_dev_mode\n"));
4151 DEBUGADD(8,("getting printer characteristics\n"));
4153 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
4156 if ( !printer->info_2->devmode ) {
4157 DEBUG(5, ("BONG! There was no device mode!\n"));
4161 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4162 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4166 ZERO_STRUCTP(devmode);
4168 DEBUGADD(8,("loading DEVICEMODE\n"));
4170 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4171 free_dev_mode( devmode );
4176 free_a_printer(&printer,2);
4181 /********************************************************************
4182 * construct_printer_info_2
4183 * fill a printer_info_2 struct
4184 ********************************************************************/
4186 static BOOL construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4189 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4191 print_status_struct status;
4193 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4196 count = print_queue_length(snum, &status);
4198 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4199 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4200 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4201 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4202 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4204 if (*ntprinter->info_2->comment == '\0')
4205 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4207 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4209 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4210 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4211 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4212 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4213 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4215 printer->attributes = ntprinter->info_2->attributes;
4217 printer->priority = ntprinter->info_2->priority; /* priority */
4218 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4219 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4220 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4221 printer->status = nt_printq_status(status.status); /* status */
4222 printer->cjobs = count; /* jobs */
4223 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4225 if((printer->devmode = construct_dev_mode(snum)) == NULL) {
4226 DEBUG(8, ("Returning NULL Devicemode!\n"));
4229 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4230 /* steal the printer info sec_desc structure. [badly done]. */
4231 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4232 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
4233 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
4234 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
4237 printer->secdesc = NULL;
4240 free_a_printer(&ntprinter, 2);
4244 /********************************************************************
4245 * construct_printer_info_3
4246 * fill a printer_info_3 struct
4247 ********************************************************************/
4249 static BOOL construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4251 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4252 PRINTER_INFO_3 *printer = NULL;
4254 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4258 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4259 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4263 ZERO_STRUCTP(printer);
4265 printer->flags = 4; /* These are the components of the SD we are returning. */
4266 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
4267 /* steal the printer info sec_desc structure. [badly done]. */
4268 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
4272 * Set the flags for the components we are returning.
4275 if (printer->secdesc->owner_sid)
4276 printer->flags |= OWNER_SECURITY_INFORMATION;
4278 if (printer->secdesc->grp_sid)
4279 printer->flags |= GROUP_SECURITY_INFORMATION;
4281 if (printer->secdesc->dacl)
4282 printer->flags |= DACL_SECURITY_INFORMATION;
4284 if (printer->secdesc->sacl)
4285 printer->flags |= SACL_SECURITY_INFORMATION;
4288 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
4289 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
4290 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
4293 free_a_printer(&ntprinter, 2);
4295 *pp_printer = printer;
4299 /********************************************************************
4300 * construct_printer_info_4
4301 * fill a printer_info_4 struct
4302 ********************************************************************/
4304 static BOOL construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4306 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4308 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4311 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4312 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4313 printer->attributes = ntprinter->info_2->attributes;
4315 free_a_printer(&ntprinter, 2);
4319 /********************************************************************
4320 * construct_printer_info_5
4321 * fill a printer_info_5 struct
4322 ********************************************************************/
4324 static BOOL construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4326 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4328 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4331 init_unistr(&printer->printername, ntprinter->info_2->printername);
4332 init_unistr(&printer->portname, ntprinter->info_2->portname);
4333 printer->attributes = ntprinter->info_2->attributes;
4335 /* these two are not used by NT+ according to MSDN */
4337 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4338 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4340 free_a_printer(&ntprinter, 2);
4345 /********************************************************************
4346 * construct_printer_info_7
4347 * fill a printer_info_7 struct
4348 ********************************************************************/
4350 static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4352 char *guid_str = NULL;
4355 if (is_printer_published(print_hnd, snum, &guid)) {
4356 asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid));
4357 strupper_m(guid_str);
4358 init_unistr(&printer->guid, guid_str);
4359 printer->action = SPOOL_DS_PUBLISH;
4361 init_unistr(&printer->guid, "");
4362 printer->action = SPOOL_DS_UNPUBLISH;
4368 /********************************************************************
4369 Spoolss_enumprinters.
4370 ********************************************************************/
4372 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4376 int n_services=lp_numservices();
4377 PRINTER_INFO_1 *tp, *printers=NULL;
4378 PRINTER_INFO_1 current_prt;
4379 WERROR result = WERR_OK;
4381 DEBUG(4,("enum_all_printers_info_1\n"));
4383 for (snum=0; snum<n_services; snum++) {
4384 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4385 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4387 if (construct_printer_info_1(NULL, flags, ¤t_prt, snum)) {
4388 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4389 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4390 SAFE_FREE(printers);
4395 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4397 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_1));
4403 /* check the required size. */
4404 for (i=0; i<*returned; i++)
4405 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4407 if (*needed > offered) {
4408 result = WERR_INSUFFICIENT_BUFFER;
4412 if (!rpcbuf_alloc_size(buffer, *needed)) {
4413 result = WERR_NOMEM;
4417 /* fill the buffer with the structures */
4418 for (i=0; i<*returned; i++)
4419 smb_io_printer_info_1("", buffer, &printers[i], 0);
4424 SAFE_FREE(printers);
4426 if ( !W_ERROR_IS_OK(result) )
4432 /********************************************************************
4433 enum_all_printers_info_1_local.
4434 *********************************************************************/
4436 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4438 DEBUG(4,("enum_all_printers_info_1_local\n"));
4440 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4443 /********************************************************************
4444 enum_all_printers_info_1_name.
4445 *********************************************************************/
4447 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4451 DEBUG(4,("enum_all_printers_info_1_name\n"));
4453 if ((name[0] == '\\') && (name[1] == '\\'))
4456 if (is_myname_or_ipaddr(s)) {
4457 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4460 return WERR_INVALID_NAME;
4463 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4464 /********************************************************************
4465 enum_all_printers_info_1_remote.
4466 *********************************************************************/
4468 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4470 PRINTER_INFO_1 *printer;
4471 fstring printername;
4474 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4475 WERROR result = WERR_OK;
4477 /* JFM: currently it's more a place holder than anything else.
4478 * In the spooler world there is a notion of server registration.
4479 * the print servers are registered on the PDC (in the same domain)
4481 * We should have a TDB here. The registration is done thru an
4482 * undocumented RPC call.
4485 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4490 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4491 slprintf(desc, sizeof(desc)-1,"%s", name);
4492 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4494 init_unistr(&printer->description, desc);
4495 init_unistr(&printer->name, printername);
4496 init_unistr(&printer->comment, comment);
4497 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4499 /* check the required size. */
4500 *needed += spoolss_size_printer_info_1(printer);
4502 if (*needed > offered) {
4503 result = WERR_INSUFFICIENT_BUFFER;
4507 if (!rpcbuf_alloc_size(buffer, *needed)) {
4508 result = WERR_NOMEM;
4512 /* fill the buffer with the structures */
4513 smb_io_printer_info_1("", buffer, printer, 0);
4519 if ( !W_ERROR_IS_OK(result) )
4527 /********************************************************************
4528 enum_all_printers_info_1_network.
4529 *********************************************************************/
4531 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4535 DEBUG(4,("enum_all_printers_info_1_network\n"));
4537 /* If we respond to a enum_printers level 1 on our name with flags
4538 set to PRINTER_ENUM_REMOTE with a list of printers then these
4539 printers incorrectly appear in the APW browse list.
4540 Specifically the printers for the server appear at the workgroup
4541 level where all the other servers in the domain are
4542 listed. Windows responds to this call with a
4543 WERR_CAN_NOT_COMPLETE so we should do the same. */
4545 if (name[0] == '\\' && name[1] == '\\')
4548 if (is_myname_or_ipaddr(s))
4549 return WERR_CAN_NOT_COMPLETE;
4551 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4554 /********************************************************************
4555 * api_spoolss_enumprinters
4557 * called from api_spoolss_enumprinters (see this to understand)
4558 ********************************************************************/
4560 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4564 int n_services=lp_numservices();
4565 PRINTER_INFO_2 *tp, *printers=NULL;
4566 PRINTER_INFO_2 current_prt;
4567 WERROR result = WERR_OK;
4569 for (snum=0; snum<n_services; snum++) {
4570 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4571 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4573 if (construct_printer_info_2(NULL, ¤t_prt, snum)) {
4574 if((tp=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) == NULL) {
4575 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4576 SAFE_FREE(printers);
4581 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
4582 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
4588 /* check the required size. */
4589 for (i=0; i<*returned; i++)
4590 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4592 if (*needed > offered) {
4593 result = WERR_INSUFFICIENT_BUFFER;
4597 if (!rpcbuf_alloc_size(buffer, *needed)) {
4598 result = WERR_NOMEM;
4602 /* fill the buffer with the structures */
4603 for (i=0; i<*returned; i++)
4604 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4608 for (i=0; i<*returned; i++) {
4609 free_devmode(printers[i].devmode);
4611 SAFE_FREE(printers);
4613 if ( !W_ERROR_IS_OK(result) )
4619 /********************************************************************
4620 * handle enumeration of printers at level 1
4621 ********************************************************************/
4623 static WERROR enumprinters_level1( uint32 flags, fstring name,
4624 RPC_BUFFER *buffer, uint32 offered,
4625 uint32 *needed, uint32 *returned)
4627 /* Not all the flags are equals */
4629 if (flags & PRINTER_ENUM_LOCAL)
4630 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4632 if (flags & PRINTER_ENUM_NAME)
4633 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4635 #if 0 /* JERRY - disabled for now */
4636 if (flags & PRINTER_ENUM_REMOTE)
4637 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4640 if (flags & PRINTER_ENUM_NETWORK)
4641 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4643 return WERR_OK; /* NT4sp5 does that */
4646 /********************************************************************
4647 * handle enumeration of printers at level 2
4648 ********************************************************************/
4650 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4651 RPC_BUFFER *buffer, uint32 offered,
4652 uint32 *needed, uint32 *returned)
4654 char *s = servername;
4656 if (flags & PRINTER_ENUM_LOCAL) {
4657 return enum_all_printers_info_2(buffer, offered, needed, returned);
4660 if (flags & PRINTER_ENUM_NAME) {
4661 if ((servername[0] == '\\') && (servername[1] == '\\'))
4663 if (is_myname_or_ipaddr(s))
4664 return enum_all_printers_info_2(buffer, offered, needed, returned);
4666 return WERR_INVALID_NAME;
4669 if (flags & PRINTER_ENUM_REMOTE)
4670 return WERR_UNKNOWN_LEVEL;
4675 /********************************************************************
4676 * handle enumeration of printers at level 5
4677 ********************************************************************/
4679 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4680 RPC_BUFFER *buffer, uint32 offered,
4681 uint32 *needed, uint32 *returned)
4683 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4687 /********************************************************************
4688 * api_spoolss_enumprinters
4690 * called from api_spoolss_enumprinters (see this to understand)
4691 ********************************************************************/
4693 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4695 uint32 flags = q_u->flags;
4696 UNISTR2 *servername = &q_u->servername;
4697 uint32 level = q_u->level;
4698 RPC_BUFFER *buffer = NULL;
4699 uint32 offered = q_u->offered;
4700 uint32 *needed = &r_u->needed;
4701 uint32 *returned = &r_u->returned;
4705 /* that's an [in out] buffer */
4707 if ( q_u->buffer ) {
4708 rpcbuf_move(q_u->buffer, &r_u->buffer);
4709 buffer = r_u->buffer;
4712 DEBUG(4,("_spoolss_enumprinters\n"));
4719 * flags==PRINTER_ENUM_NAME
4720 * if name=="" then enumerates all printers
4721 * if name!="" then enumerate the printer
4722 * flags==PRINTER_ENUM_REMOTE
4723 * name is NULL, enumerate printers
4724 * Level 2: name!="" enumerates printers, name can't be NULL
4725 * Level 3: doesn't exist
4726 * Level 4: does a local registry lookup
4727 * Level 5: same as Level 2
4730 unistr2_to_ascii(name, servername, sizeof(name)-1);
4735 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4737 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4739 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4744 return WERR_UNKNOWN_LEVEL;
4747 /****************************************************************************
4748 ****************************************************************************/
4750 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4752 PRINTER_INFO_0 *printer=NULL;
4753 WERROR result = WERR_OK;
4755 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4758 construct_printer_info_0(print_hnd, printer, snum);
4760 /* check the required size. */
4761 *needed += spoolss_size_printer_info_0(printer);
4763 if (*needed > offered) {
4764 result = WERR_INSUFFICIENT_BUFFER;
4768 if (!rpcbuf_alloc_size(buffer, *needed)) {
4769 result = WERR_NOMEM;
4773 /* fill the buffer with the structures */
4774 smb_io_printer_info_0("", buffer, printer, 0);
4784 /****************************************************************************
4785 ****************************************************************************/
4787 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4789 PRINTER_INFO_1 *printer=NULL;
4790 WERROR result = WERR_OK;
4792 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4795 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4797 /* check the required size. */
4798 *needed += spoolss_size_printer_info_1(printer);
4800 if (*needed > offered) {
4801 result = WERR_INSUFFICIENT_BUFFER;
4805 if (!rpcbuf_alloc_size(buffer, *needed)) {
4806 result = WERR_NOMEM;
4810 /* fill the buffer with the structures */
4811 smb_io_printer_info_1("", buffer, printer, 0);
4820 /****************************************************************************
4821 ****************************************************************************/
4823 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4825 PRINTER_INFO_2 *printer=NULL;
4826 WERROR result = WERR_OK;
4828 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4831 construct_printer_info_2(print_hnd, printer, snum);
4833 /* check the required size. */
4834 *needed += spoolss_size_printer_info_2(printer);
4836 if (*needed > offered) {
4837 result = WERR_INSUFFICIENT_BUFFER;
4841 if (!rpcbuf_alloc_size(buffer, *needed)) {
4842 result = WERR_NOMEM;
4846 /* fill the buffer with the structures */
4847 if (!smb_io_printer_info_2("", buffer, printer, 0))
4848 result = WERR_NOMEM;
4852 free_printer_info_2(printer);
4857 /****************************************************************************
4858 ****************************************************************************/
4860 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4862 PRINTER_INFO_3 *printer=NULL;
4863 WERROR result = WERR_OK;
4865 if (!construct_printer_info_3(print_hnd, &printer, snum))
4868 /* check the required size. */
4869 *needed += spoolss_size_printer_info_3(printer);
4871 if (*needed > offered) {
4872 result = WERR_INSUFFICIENT_BUFFER;
4876 if (!rpcbuf_alloc_size(buffer, *needed)) {
4877 result = WERR_NOMEM;
4881 /* fill the buffer with the structures */
4882 smb_io_printer_info_3("", buffer, printer, 0);
4886 free_printer_info_3(printer);
4891 /****************************************************************************
4892 ****************************************************************************/
4894 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4896 PRINTER_INFO_4 *printer=NULL;
4897 WERROR result = WERR_OK;
4899 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4902 if (!construct_printer_info_4(print_hnd, printer, snum))
4905 /* check the required size. */
4906 *needed += spoolss_size_printer_info_4(printer);
4908 if (*needed > offered) {
4909 result = WERR_INSUFFICIENT_BUFFER;
4913 if (!rpcbuf_alloc_size(buffer, *needed)) {
4914 result = WERR_NOMEM;
4918 /* fill the buffer with the structures */
4919 smb_io_printer_info_4("", buffer, printer, 0);
4923 free_printer_info_4(printer);
4928 /****************************************************************************
4929 ****************************************************************************/
4931 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4933 PRINTER_INFO_5 *printer=NULL;
4934 WERROR result = WERR_OK;
4936 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4939 if (!construct_printer_info_5(print_hnd, printer, snum))
4942 /* check the required size. */
4943 *needed += spoolss_size_printer_info_5(printer);
4945 if (*needed > offered) {
4946 result = WERR_INSUFFICIENT_BUFFER;
4950 if (!rpcbuf_alloc_size(buffer, *needed)) {
4951 result = WERR_NOMEM;
4955 /* fill the buffer with the structures */
4956 smb_io_printer_info_5("", buffer, printer, 0);
4960 free_printer_info_5(printer);
4965 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4967 PRINTER_INFO_7 *printer=NULL;
4968 WERROR result = WERR_OK;
4970 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
4973 if (!construct_printer_info_7(print_hnd, printer, snum))
4976 /* check the required size. */
4977 *needed += spoolss_size_printer_info_7(printer);
4979 if (*needed > offered) {
4980 result = WERR_INSUFFICIENT_BUFFER;
4984 if (!rpcbuf_alloc_size(buffer, *needed)) {
4985 result = WERR_NOMEM;
4990 /* fill the buffer with the structures */
4991 smb_io_printer_info_7("", buffer, printer, 0);
4995 free_printer_info_7(printer);
5000 /****************************************************************************
5001 ****************************************************************************/
5003 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5005 POLICY_HND *handle = &q_u->handle;
5006 uint32 level = q_u->level;
5007 RPC_BUFFER *buffer = NULL;
5008 uint32 offered = q_u->offered;
5009 uint32 *needed = &r_u->needed;
5010 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5014 /* that's an [in out] buffer */
5016 if ( q_u->buffer ) {
5017 rpcbuf_move(q_u->buffer, &r_u->buffer);
5018 buffer = r_u->buffer;
5023 if (!get_printer_snum(p, handle, &snum))
5028 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5030 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5032 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5034 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5036 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5038 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5040 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5042 return WERR_UNKNOWN_LEVEL;
5045 /********************************************************************
5046 * fill a DRIVER_INFO_1 struct
5047 ********************************************************************/
5049 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5051 init_unistr( &info->name, driver.info_3->name);
5054 /********************************************************************
5055 * construct_printer_driver_info_1
5056 ********************************************************************/
5058 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5060 NT_PRINTER_INFO_LEVEL *printer = NULL;
5061 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5063 ZERO_STRUCT(driver);
5065 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5066 return WERR_INVALID_PRINTER_NAME;
5068 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5069 return WERR_UNKNOWN_PRINTER_DRIVER;
5071 fill_printer_driver_info_1(info, driver, servername, architecture);
5073 free_a_printer(&printer,2);
5078 /********************************************************************
5079 * construct_printer_driver_info_2
5080 * fill a printer_info_2 struct
5081 ********************************************************************/
5083 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5087 info->version=driver.info_3->cversion;
5089 init_unistr( &info->name, driver.info_3->name );
5090 init_unistr( &info->architecture, driver.info_3->environment );
5093 if (strlen(driver.info_3->driverpath)) {
5094 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5095 init_unistr( &info->driverpath, temp );
5097 init_unistr( &info->driverpath, "" );
5099 if (strlen(driver.info_3->datafile)) {
5100 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5101 init_unistr( &info->datafile, temp );
5103 init_unistr( &info->datafile, "" );
5105 if (strlen(driver.info_3->configfile)) {
5106 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5107 init_unistr( &info->configfile, temp );
5109 init_unistr( &info->configfile, "" );
5112 /********************************************************************
5113 * construct_printer_driver_info_2
5114 * fill a printer_info_2 struct
5115 ********************************************************************/
5117 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5119 NT_PRINTER_INFO_LEVEL *printer = NULL;
5120 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5122 ZERO_STRUCT(printer);
5123 ZERO_STRUCT(driver);
5125 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5126 return WERR_INVALID_PRINTER_NAME;
5128 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version)))
5129 return WERR_UNKNOWN_PRINTER_DRIVER;
5131 fill_printer_driver_info_2(info, driver, servername);
5133 free_a_printer(&printer,2);
5138 /********************************************************************
5139 * copy a strings array and convert to UNICODE
5141 * convert an array of ascii string to a UNICODE string
5142 ********************************************************************/
5144 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5152 DEBUG(6,("init_unistr_array\n"));
5163 v = ""; /* hack to handle null lists */
5166 /* hack to allow this to be used in places other than when generating
5167 the list of dependent files */
5170 slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
5174 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5176 /* add one extra unit16 for the second terminating NULL */
5178 if ( (tuary=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5179 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5187 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5192 /* special case for ""; we need to add both NULL's here */
5194 (*uni_array)[j++]=0x0000;
5195 (*uni_array)[j]=0x0000;
5198 DEBUGADD(6,("last one:done\n"));
5200 /* return size of array in uint16's */
5205 /********************************************************************
5206 * construct_printer_info_3
5207 * fill a printer_info_3 struct
5208 ********************************************************************/
5210 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5216 info->version=driver.info_3->cversion;
5218 init_unistr( &info->name, driver.info_3->name );
5219 init_unistr( &info->architecture, driver.info_3->environment );
5221 if (strlen(driver.info_3->driverpath)) {
5222 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5223 init_unistr( &info->driverpath, temp );
5225 init_unistr( &info->driverpath, "" );
5227 if (strlen(driver.info_3->datafile)) {
5228 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5229 init_unistr( &info->datafile, temp );
5231 init_unistr( &info->datafile, "" );
5233 if (strlen(driver.info_3->configfile)) {
5234 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5235 init_unistr( &info->configfile, temp );
5237 init_unistr( &info->configfile, "" );
5239 if (strlen(driver.info_3->helpfile)) {
5240 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5241 init_unistr( &info->helpfile, temp );
5243 init_unistr( &info->helpfile, "" );
5245 init_unistr( &info->monitorname, driver.info_3->monitorname );
5246 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5248 info->dependentfiles=NULL;
5249 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5252 /********************************************************************
5253 * construct_printer_info_3
5254 * fill a printer_info_3 struct
5255 ********************************************************************/
5257 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5259 NT_PRINTER_INFO_LEVEL *printer = NULL;
5260 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5262 ZERO_STRUCT(driver);
5264 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5265 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5266 if (!W_ERROR_IS_OK(status))
5267 return WERR_INVALID_PRINTER_NAME;
5269 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5270 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5275 * I put this code in during testing. Helpful when commenting out the
5276 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5277 * as win2k always queries the driver using an infor level of 6.
5278 * I've left it in (but ifdef'd out) because I'll probably
5279 * use it in experimentation again in the future. --jerry 22/01/2002
5282 if (!W_ERROR_IS_OK(status)) {
5284 * Is this a W2k client ?
5287 /* Yes - try again with a WinNT driver. */
5289 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5290 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5294 if (!W_ERROR_IS_OK(status)) {
5295 free_a_printer(&printer,2);
5296 return WERR_UNKNOWN_PRINTER_DRIVER;
5304 fill_printer_driver_info_3(info, driver, servername);
5306 free_a_printer(&printer,2);
5311 /********************************************************************
5312 * construct_printer_info_6
5313 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5314 ********************************************************************/
5316 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5322 memset(&nullstr, '\0', sizeof(fstring));
5324 info->version=driver.info_3->cversion;
5326 init_unistr( &info->name, driver.info_3->name );
5327 init_unistr( &info->architecture, driver.info_3->environment );
5329 if (strlen(driver.info_3->driverpath)) {
5330 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
5331 init_unistr( &info->driverpath, temp );
5333 init_unistr( &info->driverpath, "" );
5335 if (strlen(driver.info_3->datafile)) {
5336 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
5337 init_unistr( &info->datafile, temp );
5339 init_unistr( &info->datafile, "" );
5341 if (strlen(driver.info_3->configfile)) {
5342 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
5343 init_unistr( &info->configfile, temp );
5345 init_unistr( &info->configfile, "" );
5347 if (strlen(driver.info_3->helpfile)) {
5348 slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
5349 init_unistr( &info->helpfile, temp );
5351 init_unistr( &info->helpfile, "" );
5353 init_unistr( &info->monitorname, driver.info_3->monitorname );
5354 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5356 info->dependentfiles = NULL;
5357 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5359 info->previousdrivernames=NULL;
5360 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5362 info->driver_date.low=0;
5363 info->driver_date.high=0;
5366 info->driver_version_low=0;
5367 info->driver_version_high=0;
5369 init_unistr( &info->mfgname, "");
5370 init_unistr( &info->oem_url, "");
5371 init_unistr( &info->hardware_id, "");
5372 init_unistr( &info->provider, "");
5375 /********************************************************************
5376 * construct_printer_info_6
5377 * fill a printer_info_6 struct
5378 ********************************************************************/
5380 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5381 fstring servername, fstring architecture, uint32 version)
5383 NT_PRINTER_INFO_LEVEL *printer = NULL;
5384 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5387 ZERO_STRUCT(driver);
5389 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5391 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5393 if (!W_ERROR_IS_OK(status))
5394 return WERR_INVALID_PRINTER_NAME;
5396 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5398 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5400 if (!W_ERROR_IS_OK(status))
5403 * Is this a W2k client ?
5407 free_a_printer(&printer,2);
5408 return WERR_UNKNOWN_PRINTER_DRIVER;
5411 /* Yes - try again with a WinNT driver. */
5413 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5414 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5415 if (!W_ERROR_IS_OK(status)) {
5416 free_a_printer(&printer,2);
5417 return WERR_UNKNOWN_PRINTER_DRIVER;
5421 fill_printer_driver_info_6(info, driver, servername);
5423 free_a_printer(&printer,2);
5424 free_a_printer_driver(driver, 3);
5429 /****************************************************************************
5430 ****************************************************************************/
5432 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5434 SAFE_FREE(info->dependentfiles);
5437 /****************************************************************************
5438 ****************************************************************************/
5440 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5442 SAFE_FREE(info->dependentfiles);
5445 /****************************************************************************
5446 ****************************************************************************/
5448 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5450 DRIVER_INFO_1 *info=NULL;
5453 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5456 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5457 if (!W_ERROR_IS_OK(result))
5460 /* check the required size. */
5461 *needed += spoolss_size_printer_driver_info_1(info);
5463 if (*needed > offered) {
5464 result = WERR_INSUFFICIENT_BUFFER;
5468 if (!rpcbuf_alloc_size(buffer, *needed)) {
5469 result = WERR_NOMEM;
5473 /* fill the buffer with the structures */
5474 smb_io_printer_driver_info_1("", buffer, info, 0);
5483 /****************************************************************************
5484 ****************************************************************************/
5486 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5488 DRIVER_INFO_2 *info=NULL;
5491 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5494 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5495 if (!W_ERROR_IS_OK(result))
5498 /* check the required size. */
5499 *needed += spoolss_size_printer_driver_info_2(info);
5501 if (*needed > offered) {
5502 result = WERR_INSUFFICIENT_BUFFER;
5506 if (!rpcbuf_alloc_size(buffer, *needed)) {
5507 result = WERR_NOMEM;
5511 /* fill the buffer with the structures */
5512 smb_io_printer_driver_info_2("", buffer, info, 0);
5521 /****************************************************************************
5522 ****************************************************************************/
5524 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5531 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5532 if (!W_ERROR_IS_OK(result))
5535 /* check the required size. */
5536 *needed += spoolss_size_printer_driver_info_3(&info);
5538 if (*needed > offered) {
5539 result = WERR_INSUFFICIENT_BUFFER;
5543 if (!rpcbuf_alloc_size(buffer, *needed)) {
5544 result = WERR_NOMEM;
5548 /* fill the buffer with the structures */
5549 smb_io_printer_driver_info_3("", buffer, &info, 0);
5552 free_printer_driver_info_3(&info);
5557 /****************************************************************************
5558 ****************************************************************************/
5560 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5567 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5568 if (!W_ERROR_IS_OK(result))
5571 /* check the required size. */
5572 *needed += spoolss_size_printer_driver_info_6(&info);
5574 if (*needed > offered) {
5575 result = WERR_INSUFFICIENT_BUFFER;
5579 if (!rpcbuf_alloc_size(buffer, *needed)) {
5580 result = WERR_NOMEM;
5584 /* fill the buffer with the structures */
5585 smb_io_printer_driver_info_6("", buffer, &info, 0);
5588 free_printer_driver_info_6(&info);
5593 /****************************************************************************
5594 ****************************************************************************/
5596 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5598 POLICY_HND *handle = &q_u->handle;
5599 UNISTR2 *uni_arch = &q_u->architecture;
5600 uint32 level = q_u->level;
5601 uint32 clientmajorversion = q_u->clientmajorversion;
5602 RPC_BUFFER *buffer = NULL;
5603 uint32 offered = q_u->offered;
5604 uint32 *needed = &r_u->needed;
5605 uint32 *servermajorversion = &r_u->servermajorversion;
5606 uint32 *serverminorversion = &r_u->serverminorversion;
5607 Printer_entry *printer;
5610 fstring architecture;
5613 /* that's an [in out] buffer */
5615 if ( q_u->buffer ) {
5616 rpcbuf_move(q_u->buffer, &r_u->buffer);
5617 buffer = r_u->buffer;
5620 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5622 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5623 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5624 return WERR_INVALID_PRINTER_NAME;
5628 *servermajorversion = 0;
5629 *serverminorversion = 0;
5631 fstrcpy(servername, get_server_name( printer ));
5632 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
5634 if (!get_printer_snum(p, handle, &snum))
5639 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5641 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5643 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5645 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5648 /* apparently this call is the equivalent of
5649 EnumPrinterDataEx() for the DsDriver key */
5654 return WERR_UNKNOWN_LEVEL;
5657 /****************************************************************************
5658 ****************************************************************************/
5660 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5662 POLICY_HND *handle = &q_u->handle;
5664 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5667 DEBUG(3,("Error in startpageprinter printer handle\n"));
5671 Printer->page_started=True;
5675 /****************************************************************************
5676 ****************************************************************************/
5678 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5680 POLICY_HND *handle = &q_u->handle;
5683 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5686 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5690 if (!get_printer_snum(p, handle, &snum))
5693 Printer->page_started=False;
5694 print_job_endpage(snum, Printer->jobid);
5699 /********************************************************************
5700 * api_spoolss_getprinter
5701 * called from the spoolss dispatcher
5703 ********************************************************************/
5705 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5707 POLICY_HND *handle = &q_u->handle;
5708 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5709 uint32 *jobid = &r_u->jobid;
5711 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5715 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5716 struct current_user user;
5719 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5723 get_current_user(&user, p);
5726 * a nice thing with NT is it doesn't listen to what you tell it.
5727 * when asked to send _only_ RAW datas, it tries to send datas
5730 * So I add checks like in NT Server ...
5733 if (info_1->p_datatype != 0) {
5734 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5735 if (strcmp(datatype, "RAW") != 0) {
5737 return WERR_INVALID_DATATYPE;
5741 /* get the share number of the printer */
5742 if (!get_printer_snum(p, handle, &snum)) {
5746 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
5748 Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
5750 /* An error occured in print_job_start() so return an appropriate
5753 if (Printer->jobid == -1) {
5754 return map_werror_from_unix(errno);
5757 Printer->document_started=True;
5758 (*jobid) = Printer->jobid;
5763 /********************************************************************
5764 * api_spoolss_getprinter
5765 * called from the spoolss dispatcher
5767 ********************************************************************/
5769 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5771 POLICY_HND *handle = &q_u->handle;
5773 return _spoolss_enddocprinter_internal(p, handle);
5776 /****************************************************************************
5777 ****************************************************************************/
5779 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5781 POLICY_HND *handle = &q_u->handle;
5782 uint32 buffer_size = q_u->buffer_size;
5783 uint8 *buffer = q_u->buffer;
5784 uint32 *buffer_written = &q_u->buffer_size2;
5786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5789 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5790 r_u->buffer_written = q_u->buffer_size2;
5794 if (!get_printer_snum(p, handle, &snum))
5797 (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
5798 if (*buffer_written == -1) {
5799 r_u->buffer_written = 0;
5800 if (errno == ENOSPC)
5801 return WERR_NO_SPOOL_SPACE;
5803 return WERR_ACCESS_DENIED;
5806 r_u->buffer_written = q_u->buffer_size2;
5811 /********************************************************************
5812 * api_spoolss_getprinter
5813 * called from the spoolss dispatcher
5815 ********************************************************************/
5817 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5820 struct current_user user;
5822 WERROR errcode = WERR_BADFUNC;
5823 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5825 get_current_user(&user, p);
5828 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5832 if (!get_printer_snum(p, handle, &snum))
5836 case PRINTER_CONTROL_PAUSE:
5837 if (print_queue_pause(&user, snum, &errcode)) {
5841 case PRINTER_CONTROL_RESUME:
5842 case PRINTER_CONTROL_UNPAUSE:
5843 if (print_queue_resume(&user, snum, &errcode)) {
5847 case PRINTER_CONTROL_PURGE:
5848 if (print_queue_purge(&user, snum, &errcode)) {
5853 return WERR_UNKNOWN_LEVEL;
5859 /********************************************************************
5860 * api_spoolss_abortprinter
5861 * From MSDN: "Deletes printer's spool file if printer is configured
5863 ********************************************************************/
5865 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5867 POLICY_HND *handle = &q_u->handle;
5868 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5870 struct current_user user;
5871 WERROR errcode = WERR_OK;
5874 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5878 if (!get_printer_snum(p, handle, &snum))
5881 get_current_user( &user, p );
5883 print_job_delete( &user, snum, Printer->jobid, &errcode );
5888 /********************************************************************
5889 * called by spoolss_api_setprinter
5890 * when updating a printer description
5891 ********************************************************************/
5893 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
5894 const SPOOL_PRINTER_INFO_LEVEL *info,
5895 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
5897 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
5901 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5903 if (!Printer || !get_printer_snum(p, handle, &snum)) {
5904 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5905 OUR_HANDLE(handle)));
5907 result = WERR_BADFID;
5911 /* Check the user has permissions to change the security
5912 descriptor. By experimentation with two NT machines, the user
5913 requires Full Access to the printer to change security
5916 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5917 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5918 result = WERR_ACCESS_DENIED;
5922 /* NT seems to like setting the security descriptor even though
5923 nothing may have actually changed. */
5925 nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr);
5927 if (DEBUGLEVEL >= 10) {
5931 the_acl = old_secdesc_ctr->sec->dacl;
5932 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5933 PRINTERNAME(snum), the_acl->num_aces));
5935 for (i = 0; i < the_acl->num_aces; i++) {
5938 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5940 DEBUG(10, ("%s 0x%08x\n", sid_str,
5941 the_acl->ace[i].info.mask));
5944 the_acl = secdesc_ctr->sec->dacl;
5947 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5948 PRINTERNAME(snum), the_acl->num_aces));
5950 for (i = 0; i < the_acl->num_aces; i++) {
5953 sid_to_string(sid_str, &the_acl->ace[i].trustee);
5955 DEBUG(10, ("%s 0x%08x\n", sid_str,
5956 the_acl->ace[i].info.mask));
5959 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5963 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
5965 if (sec_desc_equal(new_secdesc_ctr->sec, old_secdesc_ctr->sec)) {
5970 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
5977 /********************************************************************
5978 Canonicalize printer info from a client
5980 ATTN: It does not matter what we set the servername to hear
5981 since we do the necessary work in get_a_printer() to set it to
5982 the correct value based on what the client sent in the
5983 _spoolss_open_printer_ex().
5984 ********************************************************************/
5986 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
5988 fstring printername;
5991 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5992 "portname=%s drivername=%s comment=%s location=%s\n",
5993 info->servername, info->printername, info->sharename,
5994 info->portname, info->drivername, info->comment, info->location));
5996 /* we force some elements to "correct" values */
5997 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
5998 fstrcpy(info->sharename, lp_servicename(snum));
6000 /* check to see if we allow printername != sharename */
6002 if ( lp_force_printername(snum) ) {
6003 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6004 global_myname(), info->sharename );
6007 /* make sure printername is in \\server\printername format */
6009 fstrcpy( printername, info->printername );
6011 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6012 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6016 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6017 global_myname(), p );
6020 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6021 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6028 /****************************************************************************
6029 ****************************************************************************/
6031 static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6033 extern userdom_struct current_user_info;
6034 char *cmd = lp_addprinter_cmd();
6040 fstring remote_machine = "%m";
6041 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6044 standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
6046 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6047 cmd, printer->info_2->printername, printer->info_2->sharename,
6048 printer->info_2->portname, printer->info_2->drivername,
6049 printer->info_2->location, printer->info_2->comment, remote_machine);
6051 is_print_op = user_has_privileges( token, &se_printop );
6053 DEBUG(10,("Running [%s]\n", command));
6055 /********* BEGIN SePrintOperatorPrivilege **********/
6060 if ( (ret = smbrun(command, &fd)) == 0 ) {
6061 /* Tell everyone we updated smb.conf. */
6062 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
6068 /********* END SePrintOperatorPrivilege **********/
6070 DEBUGADD(10,("returned [%d]\n", ret));
6078 /* reload our services immediately */
6079 reload_services( False );
6082 /* Get lines and convert them back to dos-codepage */
6083 qlines = fd_lines_load(fd, &numlines);
6084 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6087 /* Set the portname to what the script says the portname should be. */
6088 /* but don't require anything to be return from the script exit a good error code */
6091 /* Set the portname to what the script says the portname should be. */
6092 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6093 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6096 file_lines_free(qlines);
6100 /********************************************************************
6101 * Called by spoolss_api_setprinter
6102 * when updating a printer description.
6103 ********************************************************************/
6105 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6106 const SPOOL_PRINTER_INFO_LEVEL *info,
6107 DEVICEMODE *devmode)
6110 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6111 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6116 DEBUG(8,("update_printer\n"));
6121 result = WERR_BADFID;
6125 if (!get_printer_snum(p, handle, &snum)) {
6126 result = WERR_BADFID;
6130 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6131 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6132 result = WERR_BADFID;
6136 DEBUGADD(8,("Converting info_2 struct\n"));
6139 * convert_printer_info converts the incoming
6140 * info from the client and overwrites the info
6141 * just read from the tdb in the pointer 'printer'.
6144 if (!convert_printer_info(info, printer, level)) {
6145 result = WERR_NOMEM;
6150 /* we have a valid devmode
6151 convert it and link it*/
6153 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6154 if (!convert_devicemode(printer->info_2->printername, devmode,
6155 &printer->info_2->devmode)) {
6156 result = WERR_NOMEM;
6161 /* Do sanity check on the requested changes for Samba */
6163 if (!check_printer_ok(printer->info_2, snum)) {
6164 result = WERR_INVALID_PARAM;
6168 /* FIXME!!! If the driver has changed we really should verify that
6169 it is installed before doing much else --jerry */
6171 /* Check calling user has permission to update printer description */
6173 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6174 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6175 result = WERR_ACCESS_DENIED;
6179 /* Call addprinter hook */
6180 /* Check changes to see if this is really needed */
6182 if ( *lp_addprinter_cmd()
6183 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6184 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6185 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6186 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6188 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
6189 result = WERR_ACCESS_DENIED;
6194 * make sure we actually reload the services after
6195 * this as smb.conf could have a new section in it
6196 * .... shouldn't .... but could
6198 reload_services(False);
6202 * When a *new* driver is bound to a printer, the drivername is used to
6203 * lookup previously saved driver initialization info, which is then
6204 * bound to the printer, simulating what happens in the Windows arch.
6206 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6208 if (!set_driver_init(printer, 2))
6210 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6211 printer->info_2->drivername));
6214 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6215 printer->info_2->drivername));
6217 notify_printer_driver(snum, printer->info_2->drivername);
6221 * flag which changes actually occured. This is a small subset of
6222 * all the possible changes. We also have to update things in the
6226 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6227 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6228 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6229 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6231 notify_printer_comment(snum, printer->info_2->comment);
6234 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6235 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6236 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6237 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6239 notify_printer_sharename(snum, printer->info_2->sharename);
6242 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6245 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6248 pname = printer->info_2->printername;
6251 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6252 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6253 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6255 notify_printer_printername( snum, pname );
6258 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6259 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6260 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6261 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6263 notify_printer_port(snum, printer->info_2->portname);
6266 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6267 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6268 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6269 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6271 notify_printer_location(snum, printer->info_2->location);
6274 /* here we need to update some more DsSpooler keys */
6275 /* uNCName, serverName, shortServerName */
6277 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6278 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6279 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6280 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6281 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6283 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6284 global_myname(), printer->info_2->sharename );
6285 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6286 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6287 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6289 /* Update printer info */
6290 result = mod_a_printer(printer, 2);
6293 free_a_printer(&printer, 2);
6294 free_a_printer(&old_printer, 2);
6300 /****************************************************************************
6301 ****************************************************************************/
6302 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6303 const SPOOL_PRINTER_INFO_LEVEL *info)
6306 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6308 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6310 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6315 if (!get_printer_snum(p, handle, &snum))
6318 nt_printer_publish(Printer, snum, info7->action);
6322 return WERR_UNKNOWN_LEVEL;
6325 /****************************************************************************
6326 ****************************************************************************/
6328 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6330 POLICY_HND *handle = &q_u->handle;
6331 uint32 level = q_u->level;
6332 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6333 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6334 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6335 uint32 command = q_u->command;
6338 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6341 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6345 /* check the level */
6348 return control_printer(handle, command, p);
6350 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6351 if (!W_ERROR_IS_OK(result))
6354 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6357 return update_printer_sec(handle, level, info, p,
6360 return publish_or_unpublish_printer(p, handle, info);
6362 return WERR_UNKNOWN_LEVEL;
6366 /****************************************************************************
6367 ****************************************************************************/
6369 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6371 POLICY_HND *handle = &q_u->handle;
6372 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6375 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6379 if (Printer->notify.client_connected==True) {
6382 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
6384 else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
6385 !get_printer_snum(p, handle, &snum) )
6388 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6391 Printer->notify.flags=0;
6392 Printer->notify.options=0;
6393 Printer->notify.localmachine[0]='\0';
6394 Printer->notify.printerlocal=0;
6395 if (Printer->notify.option)
6396 free_spool_notify_option(&Printer->notify.option);
6397 Printer->notify.client_connected=False;
6402 /****************************************************************************
6403 ****************************************************************************/
6405 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6407 /* that's an [in out] buffer */
6410 rpcbuf_move(q_u->buffer, &r_u->buffer);
6413 return WERR_INVALID_PARAM; /* this is what a NT server
6414 returns for AddJob. AddJob
6415 must fail on non-local
6419 /****************************************************************************
6420 ****************************************************************************/
6422 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
6423 int position, int snum,
6424 NT_PRINTER_INFO_LEVEL *ntprinter)
6428 t=gmtime(&queue->time);
6430 job_info->jobid=queue->job;
6431 init_unistr(&job_info->printername, lp_servicename(snum));
6432 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6433 init_unistr(&job_info->username, queue->fs_user);
6434 init_unistr(&job_info->document, queue->fs_file);
6435 init_unistr(&job_info->datatype, "RAW");
6436 init_unistr(&job_info->text_status, "");
6437 job_info->status=nt_printj_status(queue->status);
6438 job_info->priority=queue->priority;
6439 job_info->position=position;
6440 job_info->totalpages=queue->page_count;
6441 job_info->pagesprinted=0;
6443 make_systemtime(&job_info->submitted, t);
6446 /****************************************************************************
6447 ****************************************************************************/
6449 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
6450 int position, int snum,
6451 NT_PRINTER_INFO_LEVEL *ntprinter,
6452 DEVICEMODE *devmode)
6456 t=gmtime(&queue->time);
6458 job_info->jobid=queue->job;
6460 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6462 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6463 init_unistr(&job_info->username, queue->fs_user);
6464 init_unistr(&job_info->document, queue->fs_file);
6465 init_unistr(&job_info->notifyname, queue->fs_user);
6466 init_unistr(&job_info->datatype, "RAW");
6467 init_unistr(&job_info->printprocessor, "winprint");
6468 init_unistr(&job_info->parameters, "");
6469 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6470 init_unistr(&job_info->text_status, "");
6472 /* and here the security descriptor */
6474 job_info->status=nt_printj_status(queue->status);
6475 job_info->priority=queue->priority;
6476 job_info->position=position;
6477 job_info->starttime=0;
6478 job_info->untiltime=0;
6479 job_info->totalpages=queue->page_count;
6480 job_info->size=queue->size;
6481 make_systemtime(&(job_info->submitted), t);
6482 job_info->timeelapsed=0;
6483 job_info->pagesprinted=0;
6485 job_info->devmode = devmode;
6490 /****************************************************************************
6491 Enumjobs at level 1.
6492 ****************************************************************************/
6494 static WERROR enumjobs_level1(print_queue_struct *queue, int snum,
6495 NT_PRINTER_INFO_LEVEL *ntprinter,
6496 RPC_BUFFER *buffer, uint32 offered,
6497 uint32 *needed, uint32 *returned)
6501 WERROR result = WERR_OK;
6503 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6510 for (i=0; i<*returned; i++)
6511 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6515 /* check the required size. */
6516 for (i=0; i<*returned; i++)
6517 (*needed) += spoolss_size_job_info_1(&info[i]);
6519 if (*needed > offered) {
6520 result = WERR_INSUFFICIENT_BUFFER;
6524 if (!rpcbuf_alloc_size(buffer, *needed)) {
6525 result = WERR_NOMEM;
6529 /* fill the buffer with the structures */
6530 for (i=0; i<*returned; i++)
6531 smb_io_job_info_1("", buffer, &info[i], 0);
6537 if ( !W_ERROR_IS_OK(result) )
6543 /****************************************************************************
6544 Enumjobs at level 2.
6545 ****************************************************************************/
6547 static WERROR enumjobs_level2(print_queue_struct *queue, int snum,
6548 NT_PRINTER_INFO_LEVEL *ntprinter,
6549 RPC_BUFFER *buffer, uint32 offered,
6550 uint32 *needed, uint32 *returned)
6552 JOB_INFO_2 *info = NULL;
6554 WERROR result = WERR_OK;
6555 DEVICEMODE *devmode = NULL;
6557 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6562 /* this should not be a failure condition if the devmode is NULL */
6564 devmode = construct_dev_mode(snum);
6566 for (i=0; i<*returned; i++)
6567 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6569 free_a_printer(&ntprinter, 2);
6572 /* check the required size. */
6573 for (i=0; i<*returned; i++)
6574 (*needed) += spoolss_size_job_info_2(&info[i]);
6576 if (*needed > offered) {
6577 result = WERR_INSUFFICIENT_BUFFER;
6581 if (!rpcbuf_alloc_size(buffer, *needed)) {
6582 result = WERR_NOMEM;
6586 /* fill the buffer with the structures */
6587 for (i=0; i<*returned; i++)
6588 smb_io_job_info_2("", buffer, &info[i], 0);
6591 free_devmode(devmode);
6594 if ( !W_ERROR_IS_OK(result) )
6601 /****************************************************************************
6603 ****************************************************************************/
6605 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6607 POLICY_HND *handle = &q_u->handle;
6608 uint32 level = q_u->level;
6609 RPC_BUFFER *buffer = NULL;
6610 uint32 offered = q_u->offered;
6611 uint32 *needed = &r_u->needed;
6612 uint32 *returned = &r_u->returned;
6614 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6616 print_status_struct prt_status;
6617 print_queue_struct *queue=NULL;
6619 /* that's an [in out] buffer */
6621 if ( q_u->buffer ) {
6622 rpcbuf_move(q_u->buffer, &r_u->buffer);
6623 buffer = r_u->buffer;
6626 DEBUG(4,("_spoolss_enumjobs\n"));
6631 /* lookup the printer snum and tdb entry */
6633 if (!get_printer_snum(p, handle, &snum))
6636 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6637 if ( !W_ERROR_IS_OK(wret) )
6640 *returned = print_queue_status(snum, &queue, &prt_status);
6641 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6643 if (*returned == 0) {
6650 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6653 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6658 wret = WERR_UNKNOWN_LEVEL;
6661 free_a_printer( &ntprinter, 2 );
6665 /****************************************************************************
6666 ****************************************************************************/
6668 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6673 /****************************************************************************
6674 ****************************************************************************/
6676 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6678 POLICY_HND *handle = &q_u->handle;
6679 uint32 jobid = q_u->jobid;
6680 uint32 command = q_u->command;
6682 struct current_user user;
6684 WERROR errcode = WERR_BADFUNC;
6686 if (!get_printer_snum(p, handle, &snum)) {
6690 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6691 return WERR_INVALID_PRINTER_NAME;
6694 get_current_user(&user, p);
6697 case JOB_CONTROL_CANCEL:
6698 case JOB_CONTROL_DELETE:
6699 if (print_job_delete(&user, snum, jobid, &errcode)) {
6703 case JOB_CONTROL_PAUSE:
6704 if (print_job_pause(&user, snum, jobid, &errcode)) {
6708 case JOB_CONTROL_RESTART:
6709 case JOB_CONTROL_RESUME:
6710 if (print_job_resume(&user, snum, jobid, &errcode)) {
6715 return WERR_UNKNOWN_LEVEL;
6721 /****************************************************************************
6722 Enumerates all printer drivers at level 1.
6723 ****************************************************************************/
6725 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6730 fstring *list = NULL;
6731 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6732 DRIVER_INFO_1 *tdi1, *driver_info_1=NULL;
6733 WERROR result = WERR_OK;
6737 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6739 ndrivers=get_ntdrivers(&list, architecture, version);
6740 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6746 if((tdi1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6747 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6748 SAFE_FREE(driver_info_1);
6752 else driver_info_1 = tdi1;
6755 for (i=0; i<ndrivers; i++) {
6757 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6758 ZERO_STRUCT(driver);
6759 status = get_a_printer_driver(&driver, 3, list[i],
6760 architecture, version);
6761 if (!W_ERROR_IS_OK(status)) {
6765 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6766 free_a_printer_driver(driver, 3);
6769 *returned+=ndrivers;
6773 /* check the required size. */
6774 for (i=0; i<*returned; i++) {
6775 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6776 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6779 if (*needed > offered) {
6780 result = WERR_INSUFFICIENT_BUFFER;
6784 if (!rpcbuf_alloc_size(buffer, *needed)) {
6785 result = WERR_NOMEM;
6789 /* fill the buffer with the driver structures */
6790 for (i=0; i<*returned; i++) {
6791 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6792 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6796 SAFE_FREE(driver_info_1);
6798 if ( !W_ERROR_IS_OK(result) )
6804 /****************************************************************************
6805 Enumerates all printer drivers at level 2.
6806 ****************************************************************************/
6808 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6813 fstring *list = NULL;
6814 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6815 DRIVER_INFO_2 *tdi2, *driver_info_2=NULL;
6816 WERROR result = WERR_OK;
6820 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6822 ndrivers=get_ntdrivers(&list, architecture, version);
6823 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6829 if((tdi2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
6830 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6831 SAFE_FREE(driver_info_2);
6835 else driver_info_2 = tdi2;
6838 for (i=0; i<ndrivers; i++) {
6841 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6842 ZERO_STRUCT(driver);
6843 status = get_a_printer_driver(&driver, 3, list[i],
6844 architecture, version);
6845 if (!W_ERROR_IS_OK(status)) {
6849 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
6850 free_a_printer_driver(driver, 3);
6853 *returned+=ndrivers;
6857 /* check the required size. */
6858 for (i=0; i<*returned; i++) {
6859 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6860 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
6863 if (*needed > offered) {
6864 result = WERR_INSUFFICIENT_BUFFER;
6868 if (!rpcbuf_alloc_size(buffer, *needed)) {
6869 result = WERR_NOMEM;
6873 /* fill the buffer with the form structures */
6874 for (i=0; i<*returned; i++) {
6875 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6876 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
6880 SAFE_FREE(driver_info_2);
6882 if ( !W_ERROR_IS_OK(result) )
6888 /****************************************************************************
6889 Enumerates all printer drivers at level 3.
6890 ****************************************************************************/
6892 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6897 fstring *list = NULL;
6898 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6899 DRIVER_INFO_3 *tdi3, *driver_info_3=NULL;
6900 WERROR result = WERR_OK;
6904 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6906 ndrivers=get_ntdrivers(&list, architecture, version);
6907 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6913 if((tdi3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
6914 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6915 SAFE_FREE(driver_info_3);
6919 else driver_info_3 = tdi3;
6922 for (i=0; i<ndrivers; i++) {
6925 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6926 ZERO_STRUCT(driver);
6927 status = get_a_printer_driver(&driver, 3, list[i],
6928 architecture, version);
6929 if (!W_ERROR_IS_OK(status)) {
6933 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
6934 free_a_printer_driver(driver, 3);
6937 *returned+=ndrivers;
6941 /* check the required size. */
6942 for (i=0; i<*returned; i++) {
6943 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6944 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
6947 if (*needed > offered) {
6948 result = WERR_INSUFFICIENT_BUFFER;
6952 if (!rpcbuf_alloc_size(buffer, *needed)) {
6953 result = WERR_NOMEM;
6957 /* fill the buffer with the driver structures */
6958 for (i=0; i<*returned; i++) {
6959 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6960 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
6964 for (i=0; i<*returned; i++)
6965 SAFE_FREE(driver_info_3[i].dependentfiles);
6967 SAFE_FREE(driver_info_3);
6969 if ( !W_ERROR_IS_OK(result) )
6975 /****************************************************************************
6976 Enumerates all printer drivers.
6977 ****************************************************************************/
6979 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
6981 uint32 level = q_u->level;
6982 RPC_BUFFER *buffer = NULL;
6983 uint32 offered = q_u->offered;
6984 uint32 *needed = &r_u->needed;
6985 uint32 *returned = &r_u->returned;
6988 fstring architecture;
6990 /* that's an [in out] buffer */
6992 if ( q_u->buffer ) {
6993 rpcbuf_move(q_u->buffer, &r_u->buffer);
6994 buffer = r_u->buffer;
6997 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7002 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1);
7003 unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1);
7005 if ( !is_myname_or_ipaddr( servername ) )
7006 return WERR_UNKNOWN_PRINTER_DRIVER;
7010 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7012 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7014 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7016 return WERR_UNKNOWN_LEVEL;
7020 /****************************************************************************
7021 ****************************************************************************/
7023 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7025 form->flag=list->flag;
7026 init_unistr(&form->name, list->name);
7027 form->width=list->width;
7028 form->length=list->length;
7029 form->left=list->left;
7030 form->top=list->top;
7031 form->right=list->right;
7032 form->bottom=list->bottom;
7035 /****************************************************************************
7036 ****************************************************************************/
7038 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7040 uint32 level = q_u->level;
7041 RPC_BUFFER *buffer = NULL;
7042 uint32 offered = q_u->offered;
7043 uint32 *needed = &r_u->needed;
7044 uint32 *numofforms = &r_u->numofforms;
7045 uint32 numbuiltinforms;
7047 nt_forms_struct *list=NULL;
7048 nt_forms_struct *builtinlist=NULL;
7053 /* that's an [in out] buffer */
7055 if ( q_u->buffer ) {
7056 rpcbuf_move(q_u->buffer, &r_u->buffer);
7057 buffer = r_u->buffer;
7060 DEBUG(4,("_spoolss_enumforms\n"));
7061 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7062 DEBUGADD(5,("Info level [%d]\n", level));
7064 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7065 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7066 *numofforms = get_ntforms(&list);
7067 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7068 *numofforms += numbuiltinforms;
7070 if (*numofforms == 0)
7071 return WERR_NO_MORE_ITEMS;
7075 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7080 /* construct the list of form structures */
7081 for (i=0; i<numbuiltinforms; i++) {
7082 DEBUGADD(6,("Filling form number [%d]\n",i));
7083 fill_form_1(&forms_1[i], &builtinlist[i]);
7086 SAFE_FREE(builtinlist);
7088 for (; i<*numofforms; i++) {
7089 DEBUGADD(6,("Filling form number [%d]\n",i));
7090 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7095 /* check the required size. */
7096 for (i=0; i<numbuiltinforms; i++) {
7097 DEBUGADD(6,("adding form [%d]'s size\n",i));
7098 buffer_size += spoolss_size_form_1(&forms_1[i]);
7100 for (; i<*numofforms; i++) {
7101 DEBUGADD(6,("adding form [%d]'s size\n",i));
7102 buffer_size += spoolss_size_form_1(&forms_1[i]);
7105 *needed=buffer_size;
7107 if (*needed > offered) {
7110 return WERR_INSUFFICIENT_BUFFER;
7113 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7119 /* fill the buffer with the form structures */
7120 for (i=0; i<numbuiltinforms; i++) {
7121 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7122 smb_io_form_1("", buffer, &forms_1[i], 0);
7124 for (; i<*numofforms; i++) {
7125 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7126 smb_io_form_1("", buffer, &forms_1[i], 0);
7135 SAFE_FREE(builtinlist);
7136 return WERR_UNKNOWN_LEVEL;
7141 /****************************************************************************
7142 ****************************************************************************/
7144 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7146 uint32 level = q_u->level;
7147 UNISTR2 *uni_formname = &q_u->formname;
7148 RPC_BUFFER *buffer = NULL;
7149 uint32 offered = q_u->offered;
7150 uint32 *needed = &r_u->needed;
7152 nt_forms_struct *list=NULL;
7153 nt_forms_struct builtin_form;
7158 int numofforms=0, i=0;
7160 /* that's an [in out] buffer */
7162 if ( q_u->buffer ) {
7163 rpcbuf_move(q_u->buffer, &r_u->buffer);
7164 buffer = r_u->buffer;
7167 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1);
7169 DEBUG(4,("_spoolss_getform\n"));
7170 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7171 DEBUGADD(5,("Info level [%d]\n", level));
7173 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7174 if (!foundBuiltin) {
7175 numofforms = get_ntforms(&list);
7176 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7178 if (numofforms == 0)
7185 fill_form_1(&form_1, &builtin_form);
7188 /* Check if the requested name is in the list of form structures */
7189 for (i=0; i<numofforms; i++) {
7191 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7193 if (strequal(form_name, list[i].name)) {
7194 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7195 fill_form_1(&form_1, &list[i]);
7201 if (i == numofforms) {
7205 /* check the required size. */
7207 *needed=spoolss_size_form_1(&form_1);
7209 if (*needed > offered)
7210 return WERR_INSUFFICIENT_BUFFER;
7212 if (!rpcbuf_alloc_size(buffer, buffer_size))
7215 /* fill the buffer with the form structures */
7216 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7217 smb_io_form_1("", buffer, &form_1, 0);
7223 return WERR_UNKNOWN_LEVEL;
7227 /****************************************************************************
7228 ****************************************************************************/
7230 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7232 init_unistr(&port->port_name, name);
7235 /****************************************************************************
7236 ****************************************************************************/
7238 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7240 init_unistr(&port->port_name, name);
7241 init_unistr(&port->monitor_name, "Local Monitor");
7242 init_unistr(&port->description, "Local Port");
7243 port->port_type=PORT_TYPE_WRITE;
7247 /****************************************************************************
7249 ****************************************************************************/
7251 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7253 PORT_INFO_1 *ports=NULL;
7255 WERROR result = WERR_OK;
7257 if (*lp_enumports_cmd()) {
7258 char *cmd = lp_enumports_cmd();
7265 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 1);
7267 DEBUG(10,("Running [%s]\n", command));
7268 ret = smbrun(command, &fd);
7269 DEBUG(10,("Returned [%d]\n", ret));
7273 /* Is this the best error to return here? */
7274 return WERR_ACCESS_DENIED;
7278 qlines = fd_lines_load(fd, &numlines);
7279 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7283 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7284 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7285 dos_errstr(WERR_NOMEM)));
7286 file_lines_free(qlines);
7290 for (i=0; i<numlines; i++) {
7291 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7292 fill_port_1(&ports[i], qlines[i]);
7295 file_lines_free(qlines);
7298 *returned = numlines;
7301 *returned = 1; /* Sole Samba port returned. */
7303 if((ports=SMB_MALLOC_P(PORT_INFO_1)) == NULL)
7306 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7308 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
7311 /* check the required size. */
7312 for (i=0; i<*returned; i++) {
7313 DEBUGADD(6,("adding port [%d]'s size\n", i));
7314 *needed += spoolss_size_port_info_1(&ports[i]);
7317 if (*needed > offered) {
7318 result = WERR_INSUFFICIENT_BUFFER;
7322 if (!rpcbuf_alloc_size(buffer, *needed)) {
7323 result = WERR_NOMEM;
7327 /* fill the buffer with the ports structures */
7328 for (i=0; i<*returned; i++) {
7329 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7330 smb_io_port_1("", buffer, &ports[i], 0);
7336 if ( !W_ERROR_IS_OK(result) )
7342 /****************************************************************************
7344 ****************************************************************************/
7346 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7348 PORT_INFO_2 *ports=NULL;
7350 WERROR result = WERR_OK;
7352 if (*lp_enumports_cmd()) {
7353 char *cmd = lp_enumports_cmd();
7362 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
7363 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
7365 path = lp_lockdir();
7367 slprintf(tmp_file, sizeof(tmp_file)-1, "%s/smbcmd.%u.", path, (unsigned int)sys_getpid());
7368 slprintf(command, sizeof(command)-1, "%s \"%d\"", cmd, 2);
7371 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
7372 ret = smbrun(command, &fd);
7373 DEBUGADD(10,("returned [%d]\n", ret));
7377 /* Is this the best error to return here? */
7378 return WERR_ACCESS_DENIED;
7382 qlines = fd_lines_load(fd, &numlines);
7383 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7387 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7388 file_lines_free(qlines);
7392 for (i=0; i<numlines; i++) {
7393 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7394 fill_port_2(&(ports[i]), qlines[i]);
7397 file_lines_free(qlines);
7400 *returned = numlines;
7406 if((ports=SMB_MALLOC_P(PORT_INFO_2)) == NULL)
7409 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
7411 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
7414 /* check the required size. */
7415 for (i=0; i<*returned; i++) {
7416 DEBUGADD(6,("adding port [%d]'s size\n", i));
7417 *needed += spoolss_size_port_info_2(&ports[i]);
7420 if (*needed > offered) {
7421 result = WERR_INSUFFICIENT_BUFFER;
7425 if (!rpcbuf_alloc_size(buffer, *needed)) {
7426 result = WERR_NOMEM;
7430 /* fill the buffer with the ports structures */
7431 for (i=0; i<*returned; i++) {
7432 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7433 smb_io_port_2("", buffer, &ports[i], 0);
7439 if ( !W_ERROR_IS_OK(result) )
7445 /****************************************************************************
7447 ****************************************************************************/
7449 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7451 uint32 level = q_u->level;
7452 RPC_BUFFER *buffer = NULL;
7453 uint32 offered = q_u->offered;
7454 uint32 *needed = &r_u->needed;
7455 uint32 *returned = &r_u->returned;
7457 /* that's an [in out] buffer */
7459 if ( q_u->buffer ) {
7460 rpcbuf_move(q_u->buffer, &r_u->buffer);
7461 buffer = r_u->buffer;
7464 DEBUG(4,("_spoolss_enumports\n"));
7471 return enumports_level_1(buffer, offered, needed, returned);
7473 return enumports_level_2(buffer, offered, needed, returned);
7475 return WERR_UNKNOWN_LEVEL;
7479 /****************************************************************************
7480 ****************************************************************************/
7482 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7483 const SPOOL_PRINTER_INFO_LEVEL *info,
7484 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7485 uint32 user_switch, const SPOOL_USER_CTR *user,
7488 NT_PRINTER_INFO_LEVEL *printer = NULL;
7491 WERROR err = WERR_OK;
7493 if ((printer = SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL)) == NULL) {
7494 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7498 ZERO_STRUCTP(printer);
7500 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7501 if (!convert_printer_info(info, printer, 2)) {
7502 free_a_printer(&printer, 2);
7506 /* check to see if the printer already exists */
7508 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7509 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7510 printer->info_2->sharename));
7511 free_a_printer(&printer, 2);
7512 return WERR_PRINTER_ALREADY_EXISTS;
7515 /* FIXME!!! smbd should check to see if the driver is installed before
7516 trying to add a printer like this --jerry */
7518 if (*lp_addprinter_cmd() ) {
7519 if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
7520 free_a_printer(&printer,2);
7521 return WERR_ACCESS_DENIED;
7525 /* use our primary netbios name since get_a_printer() will convert
7526 it to what the client expects on a case by case basis */
7528 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7529 printer->info_2->sharename);
7532 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7533 free_a_printer(&printer,2);
7534 return WERR_ACCESS_DENIED;
7537 /* you must be a printer admin to add a new printer */
7538 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7539 free_a_printer(&printer,2);
7540 return WERR_ACCESS_DENIED;
7544 * Do sanity check on the requested changes for Samba.
7547 if (!check_printer_ok(printer->info_2, snum)) {
7548 free_a_printer(&printer,2);
7549 return WERR_INVALID_PARAM;
7553 * When a printer is created, the drivername bound to the printer is used
7554 * to lookup previously saved driver initialization info, which is then
7555 * bound to the new printer, simulating what happens in the Windows arch.
7560 set_driver_init(printer, 2);
7564 /* A valid devmode was included, convert and link it
7566 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7568 if (!convert_devicemode(printer->info_2->printername, devmode,
7569 &printer->info_2->devmode))
7573 /* write the ASCII on disk */
7574 err = mod_a_printer(printer, 2);
7575 if (!W_ERROR_IS_OK(err)) {
7576 free_a_printer(&printer,2);
7580 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7581 /* Handle open failed - remove addition. */
7582 del_a_printer(printer->info_2->sharename);
7583 free_a_printer(&printer,2);
7584 return WERR_ACCESS_DENIED;
7587 update_c_setprinter(False);
7588 free_a_printer(&printer,2);
7593 /****************************************************************************
7594 ****************************************************************************/
7596 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7598 UNISTR2 *uni_srv_name = &q_u->server_name;
7599 uint32 level = q_u->level;
7600 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7601 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7602 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7603 uint32 user_switch = q_u->user_switch;
7604 SPOOL_USER_CTR *user = &q_u->user_ctr;
7605 POLICY_HND *handle = &r_u->handle;
7609 /* we don't handle yet */
7610 /* but I know what to do ... */
7611 return WERR_UNKNOWN_LEVEL;
7613 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7615 user_switch, user, handle);
7617 return WERR_UNKNOWN_LEVEL;
7621 /****************************************************************************
7622 ****************************************************************************/
7624 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7626 uint32 level = q_u->level;
7627 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7628 WERROR err = WERR_OK;
7629 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7630 struct current_user user;
7631 fstring driver_name;
7634 ZERO_STRUCT(driver);
7636 get_current_user(&user, p);
7638 if (!convert_printer_driver_info(info, &driver, level)) {
7643 DEBUG(5,("Cleaning driver's information\n"));
7644 err = clean_up_driver_struct(driver, level, &user);
7645 if (!W_ERROR_IS_OK(err))
7648 DEBUG(5,("Moving driver to final destination\n"));
7649 if(!move_driver_to_download_area(driver, level, &user, &err)) {
7650 if (W_ERROR_IS_OK(err))
7651 err = WERR_ACCESS_DENIED;
7655 if (add_a_printer_driver(driver, level)!=0) {
7656 err = WERR_ACCESS_DENIED;
7660 /* BEGIN_ADMIN_LOG */
7663 fstrcpy(driver_name, driver.info_3->name ? driver.info_3->name : "");
7664 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7665 driver_name, get_drv_ver_to_os(driver.info_3->cversion),uidtoname(user.uid));
7668 fstrcpy(driver_name, driver.info_6->name ? driver.info_6->name : "");
7669 sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7670 driver_name, get_drv_ver_to_os(driver.info_6->version),uidtoname(user.uid));
7676 * I think this is where he DrvUpgradePrinter() hook would be
7677 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7678 * server. Right now, we just need to send ourselves a message
7679 * to update each printer bound to this driver. --jerry
7682 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7683 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7688 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7689 * decide if the driver init data should be deleted. The rules are:
7690 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7691 * 2) delete init data only if there is no 2k/Xp driver
7692 * 3) always delete init data
7693 * The generalized rule is always use init data from the highest order driver.
7694 * It is necessary to follow the driver install by an initialization step to
7695 * finish off this process.
7698 version = driver.info_3->cversion;
7699 else if (level == 6)
7700 version = driver.info_6->version;
7705 * 9x printer driver - never delete init data
7708 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7713 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7714 * there is no 2k/Xp driver init data for this driver name.
7718 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7720 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7722 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7724 if (!del_driver_init(driver_name))
7725 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7728 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7730 free_a_printer_driver(driver1,3);
7731 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7738 * 2k or Xp printer driver - always delete init data
7741 if (!del_driver_init(driver_name))
7742 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7746 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7752 free_a_printer_driver(driver, level);
7756 /********************************************************************
7757 * spoolss_addprinterdriverex
7758 ********************************************************************/
7760 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7762 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7763 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7766 * we only support the semantics of AddPrinterDriver()
7767 * i.e. only copy files that are newer than existing ones
7770 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7771 return WERR_ACCESS_DENIED;
7773 ZERO_STRUCT(q_u_local);
7774 ZERO_STRUCT(r_u_local);
7776 /* just pass the information off to _spoolss_addprinterdriver() */
7777 q_u_local.server_name_ptr = q_u->server_name_ptr;
7778 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7779 q_u_local.level = q_u->level;
7780 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7782 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7790 init_unistr(&info->name, name);
7793 /****************************************************************************
7794 ****************************************************************************/
7796 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7802 const char *short_archi;
7803 DRIVER_DIRECTORY_1 *info=NULL;
7804 WERROR result = WERR_OK;
7806 unistr2_to_ascii(servername, name, sizeof(servername)-1);
7807 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
7809 /* check for beginning double '\'s and that the server
7812 pservername = servername;
7813 if ( *pservername == '\\' && strlen(servername)>2 ) {
7817 if ( !is_myname_or_ipaddr( pservername ) )
7818 return WERR_INVALID_PARAM;
7820 if (!(short_archi = get_short_archi(long_archi)))
7821 return WERR_INVALID_ENVIRONMENT;
7823 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
7826 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", pservername, short_archi);
7828 DEBUG(4,("printer driver directory: [%s]\n", path));
7830 fill_driverdir_1(info, path);
7832 *needed += spoolss_size_driverdir_info_1(info);
7834 if (*needed > offered) {
7835 result = WERR_INSUFFICIENT_BUFFER;
7839 if (!rpcbuf_alloc_size(buffer, *needed)) {
7840 result = WERR_NOMEM;
7844 smb_io_driverdir_1("", buffer, info, 0);
7852 /****************************************************************************
7853 ****************************************************************************/
7855 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
7857 UNISTR2 *name = &q_u->name;
7858 UNISTR2 *uni_environment = &q_u->environment;
7859 uint32 level = q_u->level;
7860 RPC_BUFFER *buffer = NULL;
7861 uint32 offered = q_u->offered;
7862 uint32 *needed = &r_u->needed;
7864 /* that's an [in out] buffer */
7866 if ( q_u->buffer ) {
7867 rpcbuf_move(q_u->buffer, &r_u->buffer);
7868 buffer = r_u->buffer;
7871 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7877 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
7879 return WERR_UNKNOWN_LEVEL;
7883 /****************************************************************************
7884 ****************************************************************************/
7886 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
7888 POLICY_HND *handle = &q_u->handle;
7889 uint32 idx = q_u->index;
7890 uint32 in_value_len = q_u->valuesize;
7891 uint32 in_data_len = q_u->datasize;
7892 uint32 *out_max_value_len = &r_u->valuesize;
7893 uint16 **out_value = &r_u->value;
7894 uint32 *out_value_len = &r_u->realvaluesize;
7895 uint32 *out_type = &r_u->type;
7896 uint32 *out_max_data_len = &r_u->datasize;
7897 uint8 **data_out = &r_u->data;
7898 uint32 *out_data_len = &r_u->realdatasize;
7900 NT_PRINTER_INFO_LEVEL *printer = NULL;
7902 uint32 biggest_valuesize;
7903 uint32 biggest_datasize;
7905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
7908 REGISTRY_VALUE *val = NULL;
7909 NT_PRINTER_DATA *p_data;
7910 int i, key_index, num_values;
7913 ZERO_STRUCT( printer );
7917 *out_max_data_len = 0;
7921 DEBUG(5,("spoolss_enumprinterdata\n"));
7924 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
7928 if (!get_printer_snum(p,handle, &snum))
7931 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
7932 if (!W_ERROR_IS_OK(result))
7935 p_data = &printer->info_2->data;
7936 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
7941 * The NT machine wants to know the biggest size of value and data
7943 * cf: MSDN EnumPrinterData remark section
7946 if ( !in_value_len && !in_data_len && (key_index != -1) )
7948 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7950 biggest_valuesize = 0;
7951 biggest_datasize = 0;
7953 num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
7955 for ( i=0; i<num_values; i++ )
7957 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
7959 name_length = strlen(val->valuename);
7960 if ( strlen(val->valuename) > biggest_valuesize )
7961 biggest_valuesize = name_length;
7963 if ( val->size > biggest_datasize )
7964 biggest_datasize = val->size;
7966 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7970 /* the value is an UNICODE string but real_value_size is the length
7971 in bytes including the trailing 0 */
7973 *out_value_len = 2 * (1+biggest_valuesize);
7974 *out_data_len = biggest_datasize;
7976 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
7982 * the value len is wrong in NT sp3
7983 * that's the number of bytes not the number of unicode chars
7986 if ( key_index != -1 )
7987 val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
7992 /* out_value should default to "" or else NT4 has
7993 problems unmarshalling the response */
7995 *out_max_value_len=(in_value_len/sizeof(uint16));
7997 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
7999 result = WERR_NOMEM;
8003 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8005 /* the data is counted in bytes */
8007 *out_max_data_len = in_data_len;
8008 *out_data_len = in_data_len;
8010 /* only allocate when given a non-zero data_len */
8012 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8014 result = WERR_NOMEM;
8018 result = WERR_NO_MORE_ITEMS;
8024 * - counted in bytes in the request
8025 * - counted in UNICODE chars in the max reply
8026 * - counted in bytes in the real size
8028 * take a pause *before* coding not *during* coding
8032 *out_max_value_len=(in_value_len/sizeof(uint16));
8033 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8035 result = WERR_NOMEM;
8039 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
8043 *out_type = regval_type( val );
8045 /* data - counted in bytes */
8047 *out_max_data_len = in_data_len;
8048 if ( (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8050 result = WERR_NOMEM;
8053 data_len = (size_t)regval_size(val);
8054 memcpy( *data_out, regval_data_p(val), data_len );
8055 *out_data_len = data_len;
8059 free_a_printer(&printer, 2);
8063 /****************************************************************************
8064 ****************************************************************************/
8066 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8068 POLICY_HND *handle = &q_u->handle;
8069 UNISTR2 *value = &q_u->value;
8070 uint32 type = q_u->type;
8071 uint8 *data = q_u->data;
8072 uint32 real_len = q_u->real_len;
8074 NT_PRINTER_INFO_LEVEL *printer = NULL;
8076 WERROR status = WERR_OK;
8077 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8080 DEBUG(5,("spoolss_setprinterdata\n"));
8083 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8087 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
8088 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8089 return WERR_INVALID_PARAM;
8092 if (!get_printer_snum(p,handle, &snum))
8096 * Access check : NT returns "access denied" if you make a
8097 * SetPrinterData call without the necessary privildge.
8098 * we were originally returning OK if nothing changed
8099 * which made Win2k issue **a lot** of SetPrinterData
8100 * when connecting to a printer --jerry
8103 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8105 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8106 status = WERR_ACCESS_DENIED;
8110 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8111 if (!W_ERROR_IS_OK(status))
8114 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8117 * When client side code sets a magic printer data key, detect it and save
8118 * the current printer data and the magic key's data (its the DEVMODE) for
8119 * future printer/driver initializations.
8121 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8123 /* Set devmode and printer initialization info */
8124 status = save_driver_init( printer, 2, data, real_len );
8126 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8130 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8131 type, data, real_len );
8132 if ( W_ERROR_IS_OK(status) )
8133 status = mod_a_printer(printer, 2);
8137 free_a_printer(&printer, 2);
8142 /****************************************************************************
8143 ****************************************************************************/
8145 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8147 POLICY_HND *handle = &q_u->handle;
8148 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8151 DEBUG(5,("_spoolss_resetprinter\n"));
8154 * All we do is to check to see if the handle and queue is valid.
8155 * This call really doesn't mean anything to us because we only
8156 * support RAW printing. --jerry
8160 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8164 if (!get_printer_snum(p,handle, &snum))
8168 /* blindly return success */
8173 /****************************************************************************
8174 ****************************************************************************/
8176 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8178 POLICY_HND *handle = &q_u->handle;
8179 UNISTR2 *value = &q_u->valuename;
8181 NT_PRINTER_INFO_LEVEL *printer = NULL;
8183 WERROR status = WERR_OK;
8184 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8187 DEBUG(5,("spoolss_deleteprinterdata\n"));
8190 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8194 if (!get_printer_snum(p, handle, &snum))
8197 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8198 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8199 return WERR_ACCESS_DENIED;
8202 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8203 if (!W_ERROR_IS_OK(status))
8206 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
8208 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8210 if ( W_ERROR_IS_OK(status) )
8211 mod_a_printer( printer, 2 );
8213 free_a_printer(&printer, 2);
8218 /****************************************************************************
8219 ****************************************************************************/
8221 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8223 POLICY_HND *handle = &q_u->handle;
8224 FORM *form = &q_u->form;
8225 nt_forms_struct tmpForm;
8227 WERROR status = WERR_OK;
8228 NT_PRINTER_INFO_LEVEL *printer = NULL;
8231 nt_forms_struct *list=NULL;
8232 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8234 DEBUG(5,("spoolss_addform\n"));
8237 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8242 /* forms can be added on printer of on the print server handle */
8244 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8246 if (!get_printer_snum(p,handle, &snum))
8249 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8250 if (!W_ERROR_IS_OK(status))
8254 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8255 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8256 status = WERR_ACCESS_DENIED;
8260 /* can't add if builtin */
8262 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8263 status = WERR_ALREADY_EXISTS;
8267 count = get_ntforms(&list);
8269 if(!add_a_form(&list, form, &count)) {
8270 status = WERR_NOMEM;
8274 write_ntforms(&list, count);
8277 * ChangeID must always be set if this is a printer
8280 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8281 status = mod_a_printer(printer, 2);
8285 free_a_printer(&printer, 2);
8291 /****************************************************************************
8292 ****************************************************************************/
8294 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8296 POLICY_HND *handle = &q_u->handle;
8297 UNISTR2 *form_name = &q_u->name;
8298 nt_forms_struct tmpForm;
8300 nt_forms_struct *list=NULL;
8301 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8303 WERROR status = WERR_OK;
8304 NT_PRINTER_INFO_LEVEL *printer = NULL;
8306 DEBUG(5,("spoolss_deleteform\n"));
8309 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8313 /* forms can be deleted on printer of on the print server handle */
8315 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8317 if (!get_printer_snum(p,handle, &snum))
8320 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8321 if (!W_ERROR_IS_OK(status))
8325 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8326 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8327 status = WERR_ACCESS_DENIED;
8331 /* can't delete if builtin */
8333 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8334 status = WERR_INVALID_PARAM;
8338 count = get_ntforms(&list);
8340 if ( !delete_a_form(&list, form_name, &count, &status ))
8344 * ChangeID must always be set if this is a printer
8347 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8348 status = mod_a_printer(printer, 2);
8352 free_a_printer(&printer, 2);
8358 /****************************************************************************
8359 ****************************************************************************/
8361 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8363 POLICY_HND *handle = &q_u->handle;
8364 FORM *form = &q_u->form;
8365 nt_forms_struct tmpForm;
8367 WERROR status = WERR_OK;
8368 NT_PRINTER_INFO_LEVEL *printer = NULL;
8371 nt_forms_struct *list=NULL;
8372 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8374 DEBUG(5,("spoolss_setform\n"));
8377 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8381 /* forms can be modified on printer of on the print server handle */
8383 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8385 if (!get_printer_snum(p,handle, &snum))
8388 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8389 if (!W_ERROR_IS_OK(status))
8393 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8394 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8395 status = WERR_ACCESS_DENIED;
8399 /* can't set if builtin */
8400 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8401 status = WERR_INVALID_PARAM;
8405 count = get_ntforms(&list);
8406 update_a_form(&list, form, count);
8407 write_ntforms(&list, count);
8410 * ChangeID must always be set if this is a printer
8413 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
8414 status = mod_a_printer(printer, 2);
8419 free_a_printer(&printer, 2);
8425 /****************************************************************************
8426 enumprintprocessors level 1.
8427 ****************************************************************************/
8429 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8431 PRINTPROCESSOR_1 *info_1=NULL;
8432 WERROR result = WERR_OK;
8434 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8439 init_unistr(&info_1->name, "winprint");
8441 *needed += spoolss_size_printprocessor_info_1(info_1);
8443 if (*needed > offered) {
8444 result = WERR_INSUFFICIENT_BUFFER;
8448 if (!rpcbuf_alloc_size(buffer, *needed)) {
8449 result = WERR_NOMEM;
8453 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8458 if ( !W_ERROR_IS_OK(result) )
8464 /****************************************************************************
8465 ****************************************************************************/
8467 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8469 uint32 level = q_u->level;
8470 RPC_BUFFER *buffer = NULL;
8471 uint32 offered = q_u->offered;
8472 uint32 *needed = &r_u->needed;
8473 uint32 *returned = &r_u->returned;
8475 /* that's an [in out] buffer */
8477 if ( q_u->buffer ) {
8478 rpcbuf_move(q_u->buffer, &r_u->buffer);
8479 buffer = r_u->buffer;
8482 DEBUG(5,("spoolss_enumprintprocessors\n"));
8485 * Enumerate the print processors ...
8487 * Just reply with "winprint", to keep NT happy
8488 * and I can use my nice printer checker.
8496 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8498 return WERR_UNKNOWN_LEVEL;
8502 /****************************************************************************
8503 enumprintprocdatatypes level 1.
8504 ****************************************************************************/
8506 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8508 PRINTPROCDATATYPE_1 *info_1=NULL;
8509 WERROR result = WERR_NOMEM;
8511 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8516 init_unistr(&info_1->name, "RAW");
8518 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8520 if (*needed > offered) {
8521 result = WERR_INSUFFICIENT_BUFFER;
8525 if (!rpcbuf_alloc_size(buffer, *needed)) {
8526 result = WERR_NOMEM;
8530 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8535 if ( !W_ERROR_IS_OK(result) )
8541 /****************************************************************************
8542 ****************************************************************************/
8544 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8546 uint32 level = q_u->level;
8547 RPC_BUFFER *buffer = NULL;
8548 uint32 offered = q_u->offered;
8549 uint32 *needed = &r_u->needed;
8550 uint32 *returned = &r_u->returned;
8552 /* that's an [in out] buffer */
8554 if ( q_u->buffer ) {
8555 rpcbuf_move(q_u->buffer, &r_u->buffer);
8556 buffer = r_u->buffer;
8559 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8566 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8568 return WERR_UNKNOWN_LEVEL;
8572 /****************************************************************************
8573 enumprintmonitors level 1.
8574 ****************************************************************************/
8576 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8578 PRINTMONITOR_1 *info_1=NULL;
8579 WERROR result = WERR_OK;
8581 if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL)
8586 init_unistr(&info_1->name, "Local Port");
8588 *needed += spoolss_size_printmonitor_info_1(info_1);
8590 if (*needed > offered) {
8591 result = WERR_INSUFFICIENT_BUFFER;
8595 if (!rpcbuf_alloc_size(buffer, *needed)) {
8596 result = WERR_NOMEM;
8600 smb_io_printmonitor_info_1("", buffer, info_1, 0);
8605 if ( !W_ERROR_IS_OK(result) )
8611 /****************************************************************************
8612 enumprintmonitors level 2.
8613 ****************************************************************************/
8615 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8617 PRINTMONITOR_2 *info_2=NULL;
8618 WERROR result = WERR_OK;
8620 if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL)
8625 init_unistr(&info_2->name, "Local Port");
8626 init_unistr(&info_2->environment, "Windows NT X86");
8627 init_unistr(&info_2->dll_name, "localmon.dll");
8629 *needed += spoolss_size_printmonitor_info_2(info_2);
8631 if (*needed > offered) {
8632 result = WERR_INSUFFICIENT_BUFFER;
8636 if (!rpcbuf_alloc_size(buffer, *needed)) {
8637 result = WERR_NOMEM;
8641 smb_io_printmonitor_info_2("", buffer, info_2, 0);
8646 if ( !W_ERROR_IS_OK(result) )
8652 /****************************************************************************
8653 ****************************************************************************/
8655 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8657 uint32 level = q_u->level;
8658 RPC_BUFFER *buffer = NULL;
8659 uint32 offered = q_u->offered;
8660 uint32 *needed = &r_u->needed;
8661 uint32 *returned = &r_u->returned;
8663 /* that's an [in out] buffer */
8665 if ( q_u->buffer ) {
8666 rpcbuf_move(q_u->buffer, &r_u->buffer);
8667 buffer = r_u->buffer;
8670 DEBUG(5,("spoolss_enumprintmonitors\n"));
8673 * Enumerate the print monitors ...
8675 * Just reply with "Local Port", to keep NT happy
8676 * and I can use my nice printer checker.
8684 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8686 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8688 return WERR_UNKNOWN_LEVEL;
8692 /****************************************************************************
8693 ****************************************************************************/
8695 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8696 NT_PRINTER_INFO_LEVEL *ntprinter,
8697 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8702 JOB_INFO_1 *info_1=NULL;
8703 WERROR result = WERR_OK;
8705 info_1=SMB_MALLOC_P(JOB_INFO_1);
8707 if (info_1 == NULL) {
8711 for (i=0; i<count && found==False; i++) {
8712 if ((*queue)[i].job==(int)jobid)
8718 /* NT treats not found as bad param... yet another bad choice */
8719 return WERR_INVALID_PARAM;
8722 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8724 *needed += spoolss_size_job_info_1(info_1);
8726 if (*needed > offered) {
8727 result = WERR_INSUFFICIENT_BUFFER;
8731 if (!rpcbuf_alloc_size(buffer, *needed)) {
8732 result = WERR_NOMEM;
8736 smb_io_job_info_1("", buffer, info_1, 0);
8744 /****************************************************************************
8745 ****************************************************************************/
8747 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8748 NT_PRINTER_INFO_LEVEL *ntprinter,
8749 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8756 DEVICEMODE *devmode = NULL;
8757 NT_DEVICEMODE *nt_devmode = NULL;
8759 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8762 ZERO_STRUCTP(info_2);
8764 for ( i=0; i<count && found==False; i++ )
8766 if ((*queue)[i].job == (int)jobid)
8771 /* NT treats not found as bad param... yet another bad
8773 result = WERR_INVALID_PARAM;
8778 * if the print job does not have a DEVMODE associated with it,
8779 * just use the one for the printer. A NULL devicemode is not
8780 * a failure condition
8783 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
8784 devmode = construct_dev_mode(snum);
8786 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
8787 ZERO_STRUCTP( devmode );
8788 convert_nt_devicemode( devmode, nt_devmode );
8792 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
8794 *needed += spoolss_size_job_info_2(info_2);
8796 if (*needed > offered) {
8797 result = WERR_INSUFFICIENT_BUFFER;
8801 if (!rpcbuf_alloc_size(buffer, *needed)) {
8802 result = WERR_NOMEM;
8806 smb_io_job_info_2("", buffer, info_2, 0);
8811 /* Cleanup allocated memory */
8813 free_job_info_2(info_2); /* Also frees devmode */
8819 /****************************************************************************
8820 ****************************************************************************/
8822 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
8824 POLICY_HND *handle = &q_u->handle;
8825 uint32 jobid = q_u->jobid;
8826 uint32 level = q_u->level;
8827 RPC_BUFFER *buffer = NULL;
8828 uint32 offered = q_u->offered;
8829 uint32 *needed = &r_u->needed;
8830 WERROR wstatus = WERR_OK;
8831 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
8834 print_queue_struct *queue = NULL;
8835 print_status_struct prt_status;
8837 /* that's an [in out] buffer */
8839 if ( q_u->buffer ) {
8840 rpcbuf_move(q_u->buffer, &r_u->buffer);
8841 buffer = r_u->buffer;
8844 DEBUG(5,("spoolss_getjob\n"));
8848 if (!get_printer_snum(p, handle, &snum))
8851 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
8852 if ( !W_ERROR_IS_OK(wstatus) )
8855 count = print_queue_status(snum, &queue, &prt_status);
8857 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8858 count, prt_status.status, prt_status.message));
8862 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
8863 buffer, offered, needed);
8866 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
8867 buffer, offered, needed);
8870 wstatus = WERR_UNKNOWN_LEVEL;
8875 free_a_printer( &ntprinter, 2 );
8880 /********************************************************************
8881 spoolss_getprinterdataex
8883 From MSDN documentation of GetPrinterDataEx: pass request
8884 to GetPrinterData if key is "PrinterDriverData".
8885 ********************************************************************/
8887 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
8889 POLICY_HND *handle = &q_u->handle;
8890 uint32 in_size = q_u->size;
8891 uint32 *type = &r_u->type;
8892 uint32 *out_size = &r_u->size;
8893 uint8 **data = &r_u->data;
8894 uint32 *needed = &r_u->needed;
8895 fstring keyname, valuename;
8897 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8899 NT_PRINTER_INFO_LEVEL *printer = NULL;
8901 WERROR status = WERR_OK;
8903 DEBUG(4,("_spoolss_getprinterdataex\n"));
8905 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
8906 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
8908 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8909 keyname, valuename));
8911 /* in case of problem, return some default values */
8915 *out_size = in_size;
8918 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8919 status = WERR_BADFID;
8923 /* Is the handle to a printer or to the server? */
8925 if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
8926 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8927 status = WERR_INVALID_PARAM;
8931 if ( !get_printer_snum(p,handle, &snum) )
8934 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
8935 if ( !W_ERROR_IS_OK(status) )
8938 /* check to see if the keyname is valid */
8939 if ( !strlen(keyname) ) {
8940 status = WERR_INVALID_PARAM;
8944 if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
8945 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
8946 free_a_printer( &printer, 2 );
8947 status = WERR_BADFILE;
8951 /* When given a new keyname, we should just create it */
8953 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
8955 if (*needed > *out_size)
8956 status = WERR_MORE_DATA;
8959 if ( !W_ERROR_IS_OK(status) )
8961 DEBUG(5, ("error: allocating %d\n", *out_size));
8963 /* reply this param doesn't exist */
8967 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
8968 status = WERR_NOMEM;
8978 free_a_printer( &printer, 2 );
8983 /********************************************************************
8984 * spoolss_setprinterdataex
8985 ********************************************************************/
8987 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
8989 POLICY_HND *handle = &q_u->handle;
8990 uint32 type = q_u->type;
8991 uint8 *data = q_u->data;
8992 uint32 real_len = q_u->real_len;
8994 NT_PRINTER_INFO_LEVEL *printer = NULL;
8996 WERROR status = WERR_OK;
8997 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9002 DEBUG(4,("_spoolss_setprinterdataex\n"));
9004 /* From MSDN documentation of SetPrinterDataEx: pass request to
9005 SetPrinterData if key is "PrinterDriverData" */
9008 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9012 if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) {
9013 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9014 return WERR_INVALID_PARAM;
9017 if ( !get_printer_snum(p,handle, &snum) )
9021 * Access check : NT returns "access denied" if you make a
9022 * SetPrinterData call without the necessary privildge.
9023 * we were originally returning OK if nothing changed
9024 * which made Win2k issue **a lot** of SetPrinterData
9025 * when connecting to a printer --jerry
9028 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9030 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9031 return WERR_ACCESS_DENIED;
9034 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9035 if (!W_ERROR_IS_OK(status))
9038 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
9039 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
9041 /* check for OID in valuename */
9043 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9049 /* save the registry data */
9051 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9053 if ( W_ERROR_IS_OK(status) )
9055 /* save the OID if one was specified */
9057 fstrcat( keyname, "\\" );
9058 fstrcat( keyname, SPOOL_OID_KEY );
9061 * I'm not checking the status here on purpose. Don't know
9062 * if this is right, but I'm returning the status from the
9063 * previous set_printer_dataex() call. I have no idea if
9064 * this is right. --jerry
9067 set_printer_dataex( printer, keyname, valuename,
9068 REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
9071 status = mod_a_printer(printer, 2);
9074 free_a_printer(&printer, 2);
9080 /********************************************************************
9081 * spoolss_deleteprinterdataex
9082 ********************************************************************/
9084 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9086 POLICY_HND *handle = &q_u->handle;
9087 UNISTR2 *value = &q_u->valuename;
9088 UNISTR2 *key = &q_u->keyname;
9090 NT_PRINTER_INFO_LEVEL *printer = NULL;
9092 WERROR status = WERR_OK;
9093 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9094 pstring valuename, keyname;
9096 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9099 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9103 if (!get_printer_snum(p, handle, &snum))
9106 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9107 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9108 return WERR_ACCESS_DENIED;
9111 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9112 if (!W_ERROR_IS_OK(status))
9115 unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
9116 unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
9118 status = delete_printer_dataex( printer, keyname, valuename );
9120 if ( W_ERROR_IS_OK(status) )
9121 mod_a_printer( printer, 2 );
9123 free_a_printer(&printer, 2);
9128 /********************************************************************
9129 * spoolss_enumprinterkey
9130 ********************************************************************/
9133 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9136 fstring *keynames = NULL;
9137 uint16 *enumkeys = NULL;
9140 POLICY_HND *handle = &q_u->handle;
9141 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9142 NT_PRINTER_DATA *data;
9143 NT_PRINTER_INFO_LEVEL *printer = NULL;
9145 WERROR status = WERR_BADFILE;
9148 DEBUG(4,("_spoolss_enumprinterkey\n"));
9151 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9155 if ( !get_printer_snum(p,handle, &snum) )
9158 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9159 if (!W_ERROR_IS_OK(status))
9162 /* get the list of subkey names */
9164 unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
9165 data = &printer->info_2->data;
9167 num_keys = get_printer_subkeys( data, key, &keynames );
9169 if ( num_keys == -1 ) {
9170 status = WERR_BADFILE;
9174 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9176 r_u->needed = printerkey_len*2;
9178 if ( q_u->size < r_u->needed ) {
9179 status = WERR_MORE_DATA;
9183 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9184 status = WERR_NOMEM;
9190 if ( q_u->size < r_u->needed )
9191 status = WERR_MORE_DATA;
9194 free_a_printer( &printer, 2 );
9195 SAFE_FREE( keynames );
9200 /********************************************************************
9201 * spoolss_deleteprinterkey
9202 ********************************************************************/
9204 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9206 POLICY_HND *handle = &q_u->handle;
9207 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9209 NT_PRINTER_INFO_LEVEL *printer = NULL;
9213 DEBUG(5,("spoolss_deleteprinterkey\n"));
9216 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9220 /* if keyname == NULL, return error */
9222 if ( !q_u->keyname.buffer )
9223 return WERR_INVALID_PARAM;
9225 if (!get_printer_snum(p, handle, &snum))
9228 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9229 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9230 return WERR_ACCESS_DENIED;
9233 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9234 if (!W_ERROR_IS_OK(status))
9237 /* delete the key and all subneys */
9239 unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
9241 status = delete_all_printer_data( printer->info_2, key );
9243 if ( W_ERROR_IS_OK(status) )
9244 status = mod_a_printer(printer, 2);
9246 free_a_printer( &printer, 2 );
9252 /********************************************************************
9253 * spoolss_enumprinterdataex
9254 ********************************************************************/
9256 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9258 POLICY_HND *handle = &q_u->handle;
9259 uint32 in_size = q_u->size;
9262 NT_PRINTER_INFO_LEVEL *printer = NULL;
9263 PRINTER_ENUM_VALUES *enum_values = NULL;
9264 NT_PRINTER_DATA *p_data;
9266 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9271 REGISTRY_VALUE *val;
9276 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9279 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9284 * first check for a keyname of NULL or "". Win2k seems to send
9285 * this a lot and we should send back WERR_INVALID_PARAM
9286 * no need to spend time looking up the printer in this case.
9290 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9291 if ( !strlen(key) ) {
9292 result = WERR_INVALID_PARAM;
9296 /* get the printer off of disk */
9298 if (!get_printer_snum(p,handle, &snum))
9301 ZERO_STRUCT(printer);
9302 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9303 if (!W_ERROR_IS_OK(result))
9306 /* now look for a match on the key name */
9308 p_data = &printer->info_2->data;
9310 unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
9311 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9313 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9314 result = WERR_INVALID_PARAM;
9321 /* allocate the memory for the array of pointers -- if necessary */
9323 num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
9326 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9328 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9329 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9330 result = WERR_NOMEM;
9334 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9338 * loop through all params and build the array to pass
9339 * back to the client
9342 for ( i=0; i<num_entries; i++ )
9344 /* lookup the registry value */
9346 val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
9347 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9351 value_name = regval_name( val );
9352 init_unistr( &enum_values[i].valuename, value_name );
9353 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9354 enum_values[i].type = regval_type( val );
9356 data_len = regval_size( val );
9358 if ( !(enum_values[i].data = TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9360 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9362 result = WERR_NOMEM;
9366 enum_values[i].data_len = data_len;
9368 /* keep track of the size of the array in bytes */
9370 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9373 /* housekeeping information in the reply */
9375 r_u->needed = needed;
9376 r_u->returned = num_entries;
9378 if (needed > in_size) {
9379 result = WERR_MORE_DATA;
9383 /* copy data into the reply */
9385 r_u->ctr.size = r_u->needed;
9386 r_u->ctr.size_of_array = r_u->returned;
9387 r_u->ctr.values = enum_values;
9393 free_a_printer(&printer, 2);
9398 /****************************************************************************
9399 ****************************************************************************/
9401 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, char *name)
9403 init_unistr(&info->name, name);
9406 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9407 UNISTR2 *environment,
9414 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9415 WERROR result = WERR_OK;
9417 unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1);
9419 if (!get_short_archi(long_archi))
9420 return WERR_INVALID_ENVIRONMENT;
9422 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9425 pstrcpy(path, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9427 fill_printprocessordirectory_1(info, path);
9429 *needed += spoolss_size_printprocessordirectory_info_1(info);
9431 if (*needed > offered) {
9432 result = WERR_INSUFFICIENT_BUFFER;
9436 if (!rpcbuf_alloc_size(buffer, *needed)) {
9437 result = WERR_INSUFFICIENT_BUFFER;
9441 smb_io_printprocessordirectory_1("", buffer, info, 0);
9449 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9451 uint32 level = q_u->level;
9452 RPC_BUFFER *buffer = NULL;
9453 uint32 offered = q_u->offered;
9454 uint32 *needed = &r_u->needed;
9457 /* that's an [in out] buffer */
9459 if ( q_u->buffer ) {
9460 rpcbuf_move(q_u->buffer, &r_u->buffer);
9461 buffer = r_u->buffer;
9464 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9470 result = getprintprocessordirectory_level_1
9471 (&q_u->name, &q_u->environment, buffer, offered, needed);
9474 result = WERR_UNKNOWN_LEVEL;
9482 WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
9483 SPOOL_R_REPLYOPENPRINTER *r_u)
9485 DEBUG(5,("_spoolss_replyopenprinter\n"));
9487 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
9492 WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
9493 SPOOL_R_REPLYCLOSEPRINTER *r_u)
9495 DEBUG(5,("_spoolss_replycloseprinter\n"));