2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info
;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 /* Table to map the driver version */
46 static const char * drv_ver_to_os
[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
53 static const char *get_drv_ver_to_os(int ver
)
55 if (ver
< 0 || ver
> 3)
57 return drv_ver_to_os
[ver
];
61 const char *long_archi
;
62 const char *short_archi
;
66 static Printer_entry
*printers_list
;
68 typedef struct _counter_printer_0
{
69 struct _counter_printer_0
*next
;
70 struct _counter_printer_0
*prev
;
76 static counter_printer_0
*counter_list
;
78 static struct cli_state notify_cli
; /* print notify back-channel */
79 static uint32 smb_connections
=0;
82 /* in printing/nt_printing.c */
84 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
86 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
87 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v
)
96 return JOB_STATUS_PAUSED
;
98 return JOB_STATUS_SPOOLING
;
100 return JOB_STATUS_PRINTING
;
102 return JOB_STATUS_ERROR
;
104 return JOB_STATUS_DELETING
;
106 return JOB_STATUS_OFFLINE
;
108 return JOB_STATUS_PAPEROUT
;
110 return JOB_STATUS_PRINTED
;
112 return JOB_STATUS_DELETED
;
114 return JOB_STATUS_BLOCKED
;
115 case LPQ_USER_INTERVENTION
:
116 return JOB_STATUS_USER_INTERVENTION
;
121 static int nt_printq_status(int v
)
125 return PRINTER_STATUS_PAUSED
;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
143 SAFE_FREE((*pp
)->ctr
.type
);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum
))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections
==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
171 if (!W_ERROR_IS_OK(result
))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result
)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections
==1) {
177 cli_nt_session_close(¬ify_cli
);
178 cli_ulogoff(¬ify_cli
);
179 cli_shutdown(¬ify_cli
);
180 message_deregister(MSG_PRINTER_NOTIFY2
);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static void free_printer_entry(void *ptr
)
197 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
199 if (Printer
->notify
.client_connected
==True
) {
202 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
204 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
205 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
206 snum
= print_queue_snum(Printer
->sharename
);
208 srv_spoolss_replycloseprinter(snum
,
209 &Printer
->notify
.client_hnd
);
213 Printer
->notify
.flags
=0;
214 Printer
->notify
.options
=0;
215 Printer
->notify
.localmachine
[0]='\0';
216 Printer
->notify
.printerlocal
=0;
217 free_spool_notify_option(&Printer
->notify
.option
);
218 Printer
->notify
.option
=NULL
;
219 Printer
->notify
.client_connected
=False
;
221 free_nt_devicemode( &Printer
->nt_devmode
);
222 free_a_printer( &Printer
->printer_info
, 2 );
224 talloc_destroy( Printer
->ctx
);
226 /* Remove from the internal list. */
227 DLIST_REMOVE(printers_list
, Printer
);
232 /****************************************************************************
233 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
234 ****************************************************************************/
236 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
238 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
243 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
250 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
252 if (!new_sp
->ctr
.type
) {
261 /****************************************************************************
262 find printer index by handle
263 ****************************************************************************/
265 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
267 Printer_entry
*find_printer
= NULL
;
269 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
270 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
277 /****************************************************************************
278 look for a printer object cached on an open printer handle
279 ****************************************************************************/
281 WERROR
find_printer_in_print_hnd_cache( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
**info2
,
282 const char *servername
, const char *printername
)
286 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
287 servername
, printername
));
289 for ( p
=printers_list
; p
; p
=p
->next
)
291 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
293 && strequal( p
->sharename
, printername
)
294 && strequal( p
->servername
, servername
) )
296 DEBUG(10,("Found printer\n"));
297 *info2
= dup_printer_2( ctx
, p
->printer_info
->info_2
);
303 return WERR_INVALID_PRINTER_NAME
;
306 /****************************************************************************
307 destroy any cached printer_info_2 structures on open handles
308 ****************************************************************************/
310 void invalidate_printer_hnd_cache( char *printername
)
314 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername
));
316 for ( p
=printers_list
; p
; p
=p
->next
)
318 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
320 && StrCaseCmp(p
->sharename
, printername
)==0)
322 DEBUG(10,("invalidating printer_info cache for handl:\n"));
323 free_a_printer( &p
->printer_info
, 2 );
324 p
->printer_info
= NULL
;
330 /****************************************************************************
331 Close printer index by handle.
332 ****************************************************************************/
334 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
336 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
339 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
343 close_policy_hnd(p
, hnd
);
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
354 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED
;
374 /* Check calling user has permission to delete printer. Note that
375 since we set the snum parameter to -1 only administrators can
376 delete the printer. This stops people with the Full Control
377 permission from deleting the printer. */
379 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
380 DEBUG(3, ("printer delete denied by security descriptor\n"));
381 return WERR_ACCESS_DENIED
;
385 /* this does not need a become root since the access check has been
386 done on the handle already */
388 if (del_a_printer( Printer
->sharename
) != 0) {
389 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
393 /* the delete printer script shoudl be run as root if the user has perms */
395 if (*lp_deleteprinter_cmd()) {
397 char *cmd
= lp_deleteprinter_cmd();
400 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
403 pstr_sprintf(command
, "%s \"%s\"", cmd
, Printer
->sharename
);
405 is_print_op
= user_has_privileges( p
->pipe_user
.nt_user_token
, &se_printop
);
407 DEBUG(10,("Running [%s]\n", command
));
409 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
414 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
415 /* Tell everyone we updated smb.conf. */
416 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
422 /********** END SePrintOperatorPrivlege BLOCK **********/
424 DEBUGADD(10,("returned [%d]\n", ret
));
427 return WERR_BADFID
; /* What to return here? */
429 /* go ahead and re-read the services immediately */
430 reload_services( False
);
432 if ( lp_servicenumber( Printer
->sharename
) < 0 )
433 return WERR_ACCESS_DENIED
;
439 /****************************************************************************
440 Return the snum of a printer corresponding to an handle.
441 ****************************************************************************/
443 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
445 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
452 switch (Printer
->printer_type
) {
453 case PRINTER_HANDLE_IS_PRINTER
:
454 DEBUG(4,("short name:%s\n", Printer
->sharename
));
455 *number
= print_queue_snum(Printer
->sharename
);
456 return (*number
!= -1);
457 case PRINTER_HANDLE_IS_PRINTSERVER
:
464 /****************************************************************************
465 Set printer handle type.
466 Check if it's \\server or \\server\printer
467 ****************************************************************************/
469 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
471 DEBUG(3,("Setting printer type=%s\n", handlename
));
473 if ( strlen(handlename
) < 3 ) {
474 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
478 /* it's a print server */
479 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
480 DEBUGADD(4,("Printer is a print server\n"));
481 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
485 DEBUGADD(4,("Printer is a printer\n"));
486 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
492 /****************************************************************************
493 Set printer handle name.
494 ****************************************************************************/
496 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
499 int n_services
=lp_numservices();
500 char *aprinter
, *printername
;
501 const char *servername
;
504 NT_PRINTER_INFO_LEVEL
*printer
;
507 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
509 aprinter
= handlename
;
510 if ( *handlename
== '\\' ) {
511 servername
= handlename
+ 2;
512 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
521 /* save the servername to fill in replies on this handle */
523 if ( !is_myname_or_ipaddr( servername
) )
526 fstrcpy( Printer
->servername
, servername
);
528 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
531 if ( Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTER
)
534 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
536 /* Search all sharenames first as this is easier than pulling
537 the printer_info_2 off of disk */
539 snum
= find_service(aprinter
);
541 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
543 fstrcpy( sname
, aprinter
);
546 /* do another loop to look for printernames */
548 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
550 /* no point in checking if this is not a printer or
551 we aren't allowing printername != sharename */
553 if ( !(lp_snum_ok(snum
)
555 && !lp_force_printername(snum
)) )
560 fstrcpy(sname
, lp_servicename(snum
));
563 result
= get_a_printer( NULL
, &printer
, 2, sname
);
564 if ( !W_ERROR_IS_OK(result
) ) {
565 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
566 sname
, dos_errstr(result
)));
570 /* printername is always returned as \\server\printername */
571 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
572 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
573 printer
->info_2
->printername
));
574 free_a_printer( &printer
, 2);
580 if ( strequal(printername
, aprinter
) ) {
584 DEBUGADD(10, ("printername: %s\n", printername
));
586 free_a_printer( &printer
, 2);
590 DEBUGADD(4,("Printer not found\n"));
594 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
596 fstrcpy(Printer
->sharename
, sname
);
601 /****************************************************************************
602 Find first available printer slot. creates a printer handle for you.
603 ****************************************************************************/
605 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
607 Printer_entry
*new_printer
;
609 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
611 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
614 ZERO_STRUCTP(new_printer
);
616 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
617 SAFE_FREE(new_printer
);
621 /* Add to the internal list. */
622 DLIST_ADD(printers_list
, new_printer
);
624 new_printer
->notify
.option
=NULL
;
626 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
627 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
628 close_printer_handle(p
, hnd
);
632 if (!set_printer_hnd_printertype(new_printer
, name
)) {
633 close_printer_handle(p
, hnd
);
637 if (!set_printer_hnd_name(new_printer
, name
)) {
638 close_printer_handle(p
, hnd
);
642 new_printer
->access_granted
= access_granted
;
644 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
649 /***************************************************************************
650 check to see if the client motify handle is monitoring the notification
651 given by (notify_type, notify_field).
652 **************************************************************************/
654 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
660 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
663 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
667 * Flags should always be zero when the change notify
668 * is registered by the client's spooler. A user Win32 app
669 * might use the flags though instead of the NOTIFY_OPTION_INFO
678 return is_monitoring_event_flags(
679 p
->notify
.flags
, notify_type
, notify_field
);
681 for (i
= 0; i
< option
->count
; i
++) {
683 /* Check match for notify_type */
685 if (option
->ctr
.type
[i
].type
!= notify_type
)
688 /* Check match for field */
690 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
691 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
697 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
698 p
->servername
, p
->sharename
, notify_type
, notify_field
));
703 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
705 static void notify_one_value(struct spoolss_notify_msg
*msg
,
706 SPOOL_NOTIFY_INFO_DATA
*data
,
709 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
710 data
->notify_data
.value
[1] = 0;
713 static void notify_string(struct spoolss_notify_msg
*msg
,
714 SPOOL_NOTIFY_INFO_DATA
*data
,
719 /* The length of the message includes the trailing \0 */
721 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
723 data
->notify_data
.data
.length
= msg
->len
* 2;
724 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
726 if (!data
->notify_data
.data
.string
) {
727 data
->notify_data
.data
.length
= 0;
731 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
734 static void notify_system_time(struct spoolss_notify_msg
*msg
,
735 SPOOL_NOTIFY_INFO_DATA
*data
,
741 if (msg
->len
!= sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
748 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
752 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
753 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
757 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
760 data
->notify_data
.data
.length
= prs_offset(&ps
);
761 data
->notify_data
.data
.string
= TALLOC(mem_ctx
, prs_offset(&ps
));
763 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
768 struct notify2_message_table
{
770 void (*fn
)(struct spoolss_notify_msg
*msg
,
771 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
774 static struct notify2_message_table printer_notify_table
[] = {
775 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
776 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
777 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
778 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
779 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
780 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
781 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
782 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
783 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
784 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
785 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
786 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
787 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
788 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
789 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
790 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
791 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
792 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
793 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
796 static struct notify2_message_table job_notify_table
[] = {
797 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
798 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
799 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
800 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
801 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
802 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
803 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
804 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
805 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
806 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
807 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
808 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
809 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
810 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
811 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
812 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
813 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
814 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
815 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
816 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
817 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
818 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
819 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
820 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
824 /***********************************************************************
825 Allocate talloc context for container object
826 **********************************************************************/
828 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
833 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
838 /***********************************************************************
839 release all allocated memory and zero out structure
840 **********************************************************************/
842 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
848 talloc_destroy(ctr
->ctx
);
855 /***********************************************************************
856 **********************************************************************/
858 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
866 /***********************************************************************
867 **********************************************************************/
869 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
871 if ( !ctr
|| !ctr
->msg_groups
)
874 if ( idx
>= ctr
->num_groups
)
877 return &ctr
->msg_groups
[idx
];
881 /***********************************************************************
882 How many groups of change messages do we have ?
883 **********************************************************************/
885 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
890 return ctr
->num_groups
;
893 /***********************************************************************
894 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
895 **********************************************************************/
897 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
899 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
900 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
901 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
907 /* loop over all groups looking for a matching printer name */
909 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
910 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
914 /* add a new group? */
916 if ( i
== ctr
->num_groups
) {
919 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
923 ctr
->msg_groups
= groups
;
925 /* clear the new entry and set the printer name */
927 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
928 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
931 /* add the change messages; 'i' is the correct index now regardless */
933 msg_grp
= &ctr
->msg_groups
[i
];
937 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
938 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
941 msg_grp
->msgs
= msg_list
;
943 new_slot
= msg_grp
->num_msgs
-1;
944 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
946 /* need to allocate own copy of data */
949 msg_grp
->msgs
[new_slot
].notify
.data
= TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
951 return ctr
->num_groups
;
954 /***********************************************************************
955 Send a change notication message on all handles which have a call
957 **********************************************************************/
959 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
962 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
963 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
964 SPOOLSS_NOTIFY_MSG
*messages
;
965 int sending_msg_count
;
968 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
972 messages
= msg_group
->msgs
;
975 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
979 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
981 /* loop over all printers */
983 for (p
= printers_list
; p
; p
= p
->next
) {
984 SPOOL_NOTIFY_INFO_DATA
*data
;
989 /* Is there notification on this handle? */
991 if ( !p
->notify
.client_connected
)
994 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
996 /* For this printer? Print servers always receive
999 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
1000 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
1003 DEBUG(10,("Our printer\n"));
1005 /* allocate the max entries possible */
1007 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
1010 /* build the array of change notifications */
1012 sending_msg_count
= 0;
1014 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1015 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1017 /* Are we monitoring this event? */
1019 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1022 sending_msg_count
++;
1025 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1026 msg
->type
, msg
->field
, p
->sharename
));
1029 * if the is a printer notification handle and not a job notification
1030 * type, then set the id to 0. Other wise just use what was specified
1033 * When registering change notification on a print server handle
1034 * we always need to send back the id (snum) matching the printer
1035 * for which the change took place. For change notify registered
1036 * on a printer handle, this does not matter and the id should be 0.
1041 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1047 /* Convert unix jobid to smb jobid */
1049 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1050 id
= sysjob_to_jobid(msg
->id
);
1053 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1058 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1061 case PRINTER_NOTIFY_TYPE
:
1062 if ( printer_notify_table
[msg
->field
].fn
)
1063 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1066 case JOB_NOTIFY_TYPE
:
1067 if ( job_notify_table
[msg
->field
].fn
)
1068 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1072 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1079 if ( sending_msg_count
) {
1080 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1081 data_len
, data
, p
->notify
.change
, 0 );
1086 DEBUG(8,("send_notify2_changes: Exit...\n"));
1090 /***********************************************************************
1091 **********************************************************************/
1093 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1096 uint32 tv_sec
, tv_usec
;
1099 /* Unpack message */
1101 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1104 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1106 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1109 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1110 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1112 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1113 &msg
->len
, &msg
->notify
.data
);
1115 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1116 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1118 tv
->tv_sec
= tv_sec
;
1119 tv
->tv_usec
= tv_usec
;
1122 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1123 msg
->notify
.value
[1]));
1125 dump_data(3, msg
->notify
.data
, msg
->len
);
1130 /********************************************************************
1131 Receive a notify2 message list
1132 ********************************************************************/
1134 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1136 size_t msg_count
, i
;
1137 char *buf
= (char *)msg
;
1140 SPOOLSS_NOTIFY_MSG notify
;
1141 SPOOLSS_NOTIFY_MSG_CTR messages
;
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1149 msg_count
= IVAL(buf
, 0);
1152 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1154 if (msg_count
== 0) {
1155 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1159 /* initialize the container */
1161 ZERO_STRUCT( messages
);
1162 notify_msg_ctr_init( &messages
);
1165 * build message groups for each printer identified
1166 * in a change_notify msg. Remember that a PCN message
1167 * includes the handle returned for the srv_spoolss_replyopenprinter()
1168 * call. Therefore messages are grouped according to printer handle.
1171 for ( i
=0; i
<msg_count
; i
++ ) {
1172 struct timeval msg_tv
;
1174 if (msg_ptr
+ 4 - buf
> len
) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1179 msg_len
= IVAL(msg_ptr
,0);
1182 if (msg_ptr
+ msg_len
- buf
> len
) {
1183 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1187 /* unpack messages */
1189 ZERO_STRUCT( notify
);
1190 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1193 /* add to correct list in container */
1195 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1197 /* free memory that might have been allocated by notify2_unpack_msg() */
1199 if ( notify
.len
!= 0 )
1200 SAFE_FREE( notify
.notify
.data
);
1203 /* process each group of messages */
1205 num_groups
= notify_msg_ctr_numgroups( &messages
);
1206 for ( i
=0; i
<num_groups
; i
++ )
1207 send_notify2_changes( &messages
, i
);
1212 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1214 notify_msg_ctr_destroy( &messages
);
1219 /********************************************************************
1220 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1221 one smbd, all of processes must clear their printer cache immediately.
1222 ********************************************************************/
1224 void receive_printer_mod_msg(int msg_type
, pid_t src
, void *buf
, size_t len
)
1226 fstring printername
;
1228 fstrcpy( printername
, buf
);
1230 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername
));
1232 invalidate_printer_hnd_cache( printername
);
1235 /********************************************************************
1236 Send a message to ourself about new driver being installed
1237 so we can upgrade the information for each printer bound to this
1239 ********************************************************************/
1241 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1243 int len
= strlen(drivername
);
1248 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1251 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1256 /**********************************************************************
1257 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1258 over all printers, upgrading ones as necessary
1259 **********************************************************************/
1261 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1265 int n_services
= lp_numservices();
1267 len
= MIN(len
,sizeof(drivername
)-1);
1268 strncpy(drivername
, buf
, len
);
1270 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1272 /* Iterate the printer list */
1274 for (snum
=0; snum
<n_services
; snum
++)
1276 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1279 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1281 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1282 if (!W_ERROR_IS_OK(result
))
1285 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1287 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1289 /* all we care about currently is the change_id */
1291 result
= mod_a_printer(printer
, 2);
1292 if (!W_ERROR_IS_OK(result
)) {
1293 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1294 dos_errstr(result
)));
1298 free_a_printer(&printer
, 2);
1305 /********************************************************************
1306 Update the cache for all printq's with a registered client
1308 ********************************************************************/
1310 void update_monitored_printq_cache( void )
1312 Printer_entry
*printer
= printers_list
;
1315 /* loop through all printers and update the cache where
1316 client_connected == True */
1319 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1320 && printer
->notify
.client_connected
)
1322 snum
= print_queue_snum(printer
->sharename
);
1323 print_queue_status( snum
, NULL
, NULL
);
1326 printer
= printer
->next
;
1331 /********************************************************************
1332 Send a message to ourself about new driver being installed
1333 so we can upgrade the information for each printer bound to this
1335 ********************************************************************/
1337 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1339 int len
= strlen(drivername
);
1344 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1347 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1352 /**********************************************************************
1353 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1354 over all printers, resetting printer data as neessary
1355 **********************************************************************/
1357 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1361 int n_services
= lp_numservices();
1363 len
= MIN( len
, sizeof(drivername
)-1 );
1364 strncpy( drivername
, buf
, len
);
1366 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1368 /* Iterate the printer list */
1370 for ( snum
=0; snum
<n_services
; snum
++ )
1372 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1375 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1377 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1378 if ( !W_ERROR_IS_OK(result
) )
1382 * if the printer is bound to the driver,
1383 * then reset to the new driver initdata
1386 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1388 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1390 if ( !set_driver_init(printer
, 2) ) {
1391 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1392 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1395 result
= mod_a_printer( printer
, 2 );
1396 if ( !W_ERROR_IS_OK(result
) ) {
1397 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1398 get_dos_error_msg(result
)));
1402 free_a_printer( &printer
, 2 );
1411 /********************************************************************
1412 Copy routines used by convert_to_openprinterex()
1413 *******************************************************************/
1415 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1423 DEBUG (8,("dup_devmode\n"));
1425 /* bulk copy first */
1427 d
= TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1431 /* dup the pointer members separately */
1433 len
= unistrlen(devmode
->devicename
.buffer
);
1435 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1436 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1441 len
= unistrlen(devmode
->formname
.buffer
);
1443 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1444 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1448 d
->private = TALLOC_MEMDUP(ctx
, devmode
->private, devmode
->driverextra
);
1453 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1455 if (!new_ctr
|| !ctr
)
1458 DEBUG(8,("copy_devmode_ctr\n"));
1460 new_ctr
->size
= ctr
->size
;
1461 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1463 if(ctr
->devmode_ptr
)
1464 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1467 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1469 if (!new_def
|| !def
)
1472 DEBUG(8,("copy_printer_defaults\n"));
1474 new_def
->datatype_ptr
= def
->datatype_ptr
;
1476 if (def
->datatype_ptr
)
1477 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1479 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1481 new_def
->access_required
= def
->access_required
;
1484 /********************************************************************
1485 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1486 * SPOOL_Q_OPEN_PRINTER_EX structure
1487 ********************************************************************/
1489 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1491 if (!q_u_ex
|| !q_u
)
1494 DEBUG(8,("convert_to_openprinterex\n"));
1496 if ( q_u
->printername
) {
1497 q_u_ex
->printername
= TALLOC_P( ctx
, UNISTR2
);
1498 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1501 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1504 /********************************************************************
1505 * spoolss_open_printer
1507 * called from the spoolss dispatcher
1508 ********************************************************************/
1510 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1512 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1513 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1518 ZERO_STRUCT(q_u_ex
);
1519 ZERO_STRUCT(r_u_ex
);
1521 /* convert the OpenPrinter() call to OpenPrinterEx() */
1523 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1525 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1527 /* convert back to OpenPrinter() */
1529 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1534 /********************************************************************
1535 * spoolss_open_printer
1537 * If the openprinterex rpc call contains a devmode,
1538 * it's a per-user one. This per-user devmode is derivated
1539 * from the global devmode. Openprinterex() contains a per-user
1540 * devmode for when you do EMF printing and spooling.
1541 * In the EMF case, the NT workstation is only doing half the job
1542 * of rendering the page. The other half is done by running the printer
1543 * driver on the server.
1544 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1545 * The EMF file only contains what is to be printed on the page.
1546 * So in order for the server to know how to print, the NT client sends
1547 * a devicemode attached to the openprinterex call.
1548 * But this devicemode is short lived, it's only valid for the current print job.
1550 * If Samba would have supported EMF spooling, this devicemode would
1551 * have been attached to the handle, to sent it to the driver to correctly
1552 * rasterize the EMF file.
1554 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1555 * we just act as a pass-thru between windows and the printer.
1557 * In order to know that Samba supports only RAW spooling, NT has to call
1558 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1559 * and until NT sends a RAW job, we refuse it.
1561 * But to call getprinter() or startdoc(), you first need a valid handle,
1562 * and to get an handle you have to call openprintex(). Hence why you have
1563 * a devicemode in the openprinterex() call.
1566 * Differences between NT4 and NT 2000.
1569 * On NT4, you only have a global devicemode. This global devicemode can be changed
1570 * by the administrator (or by a user with enough privs). Everytime a user
1571 * wants to print, the devicemode is resetted to the default. In Word, everytime
1572 * you print, the printer's characteristics are always reset to the global devicemode.
1576 * In W2K, there is the notion of per-user devicemode. The first time you use
1577 * a printer, a per-user devicemode is build from the global devicemode.
1578 * If you change your per-user devicemode, it is saved in the registry, under the
1579 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1580 * printer preferences available.
1582 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1583 * on the General Tab of the printer properties windows.
1585 * To change the global devicemode: it's the "Printing Defaults..." button
1586 * on the Advanced Tab of the printer properties window.
1589 ********************************************************************/
1591 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1593 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1594 POLICY_HND
*handle
= &r_u
->handle
;
1598 struct current_user user
;
1599 Printer_entry
*Printer
=NULL
;
1601 if ( !q_u
->printername
)
1602 return WERR_INVALID_PRINTER_NAME
;
1604 /* some sanity check because you can open a printer or a print server */
1605 /* aka: \\server\printer or \\server */
1607 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1609 DEBUGADD(3,("checking name: %s\n",name
));
1611 if (!open_printer_hnd(p
, handle
, name
, 0))
1612 return WERR_INVALID_PRINTER_NAME
;
1614 Printer
=find_printer_index_by_hnd(p
, handle
);
1616 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1617 "handle we created for printer %s\n", name
));
1618 close_printer_handle(p
,handle
);
1619 return WERR_INVALID_PRINTER_NAME
;
1622 get_current_user(&user
, p
);
1625 * First case: the user is opening the print server:
1627 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1628 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1630 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1631 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1632 * or if the user is listed in the smb.conf printer admin parameter.
1634 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1635 * client view printer folder, but does not show the MSAPW.
1637 * Note: this test needs code to check access rights here too. Jeremy
1638 * could you look at this?
1640 * Second case: the user is opening a printer:
1641 * NT doesn't let us connect to a printer if the connecting user
1642 * doesn't have print permission.
1645 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1647 /* Printserver handles use global struct... */
1651 /* Map standard access rights to object specific access rights */
1653 se_map_standard(&printer_default
->access_required
,
1654 &printserver_std_mapping
);
1656 /* Deny any object specific bits that don't apply to print
1657 servers (i.e printer and job specific bits) */
1659 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1661 if (printer_default
->access_required
&
1662 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1663 DEBUG(3, ("access DENIED for non-printserver bits"));
1664 close_printer_handle(p
, handle
);
1665 return WERR_ACCESS_DENIED
;
1668 /* Allow admin access */
1670 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1672 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1674 if (!lp_ms_add_printer_wizard()) {
1675 close_printer_handle(p
, handle
);
1676 return WERR_ACCESS_DENIED
;
1679 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1680 and not a printer admin, then fail */
1683 && !user_has_privileges( user
.nt_user_token
, &se_printop
)
1684 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1686 close_printer_handle(p
, handle
);
1687 return WERR_ACCESS_DENIED
;
1690 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1694 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1697 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1698 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1700 /* We fall through to return WERR_OK */
1705 /* NT doesn't let us connect to a printer if the connecting user
1706 doesn't have print permission. */
1708 if (!get_printer_snum(p
, handle
, &snum
)) {
1709 close_printer_handle(p
, handle
);
1713 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1715 /* map an empty access mask to the minimum access mask */
1716 if (printer_default
->access_required
== 0x0)
1717 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1720 * If we are not serving the printer driver for this printer,
1721 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1722 * will keep NT clients happy --jerry
1725 if (lp_use_client_driver(snum
)
1726 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1728 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1731 /* check smb.conf parameters and the the sec_desc */
1733 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1734 DEBUG(3, ("access DENIED for printer open\n"));
1735 close_printer_handle(p
, handle
);
1736 return WERR_ACCESS_DENIED
;
1739 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1740 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1741 close_printer_handle(p
, handle
);
1742 return WERR_ACCESS_DENIED
;
1745 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1746 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1748 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1750 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1751 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1755 Printer
->access_granted
= printer_default
->access_required
;
1758 * If the client sent a devmode in the OpenPrinter() call, then
1759 * save it here in case we get a job submission on this handle
1762 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1763 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1765 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1766 &Printer
->nt_devmode
);
1769 #if 0 /* JERRY -- I'm doubtful this is really effective */
1770 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1771 optimization in Windows 2000 clients --jerry */
1773 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1774 && (RA_WIN2K
== get_remote_arch()) )
1776 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1777 sys_usleep( 500000 );
1784 /****************************************************************************
1785 ****************************************************************************/
1787 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1788 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1794 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1803 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1804 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1810 printer
->info_3
=NULL
;
1811 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1815 printer
->info_6
=NULL
;
1816 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1826 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1827 NT_DEVICEMODE
**pp_nt_devmode
)
1829 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1832 * Ensure nt_devmode is a valid pointer
1833 * as we will be overwriting it.
1836 if (nt_devmode
== NULL
) {
1837 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1838 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1842 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1843 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1845 nt_devmode
->specversion
=devmode
->specversion
;
1846 nt_devmode
->driverversion
=devmode
->driverversion
;
1847 nt_devmode
->size
=devmode
->size
;
1848 nt_devmode
->fields
=devmode
->fields
;
1849 nt_devmode
->orientation
=devmode
->orientation
;
1850 nt_devmode
->papersize
=devmode
->papersize
;
1851 nt_devmode
->paperlength
=devmode
->paperlength
;
1852 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1853 nt_devmode
->scale
=devmode
->scale
;
1854 nt_devmode
->copies
=devmode
->copies
;
1855 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1856 nt_devmode
->printquality
=devmode
->printquality
;
1857 nt_devmode
->color
=devmode
->color
;
1858 nt_devmode
->duplex
=devmode
->duplex
;
1859 nt_devmode
->yresolution
=devmode
->yresolution
;
1860 nt_devmode
->ttoption
=devmode
->ttoption
;
1861 nt_devmode
->collate
=devmode
->collate
;
1863 nt_devmode
->logpixels
=devmode
->logpixels
;
1864 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1865 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1866 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1867 nt_devmode
->displayflags
=devmode
->displayflags
;
1868 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1869 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1870 nt_devmode
->icmintent
=devmode
->icmintent
;
1871 nt_devmode
->mediatype
=devmode
->mediatype
;
1872 nt_devmode
->dithertype
=devmode
->dithertype
;
1873 nt_devmode
->reserved1
=devmode
->reserved1
;
1874 nt_devmode
->reserved2
=devmode
->reserved2
;
1875 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1876 nt_devmode
->panningheight
=devmode
->panningheight
;
1879 * Only change private and driverextra if the incoming devmode
1880 * has a new one. JRA.
1883 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1884 SAFE_FREE(nt_devmode
->private);
1885 nt_devmode
->driverextra
=devmode
->driverextra
;
1886 if((nt_devmode
->private=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1888 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1891 *pp_nt_devmode
= nt_devmode
;
1896 /********************************************************************
1897 * _spoolss_enddocprinter_internal.
1898 ********************************************************************/
1900 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1902 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1906 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1910 if (!get_printer_snum(p
, handle
, &snum
))
1913 Printer
->document_started
=False
;
1914 print_job_end(snum
, Printer
->jobid
,True
);
1915 /* error codes unhandled so far ... */
1920 /********************************************************************
1921 * api_spoolss_closeprinter
1922 ********************************************************************/
1924 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1926 POLICY_HND
*handle
= &q_u
->handle
;
1928 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1930 if (Printer
&& Printer
->document_started
)
1931 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1933 if (!close_printer_handle(p
, handle
))
1936 /* clear the returned printer handle. Observed behavior
1937 from Win2k server. Don't think this really matters.
1938 Previous code just copied the value of the closed
1941 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1946 /********************************************************************
1947 * api_spoolss_deleteprinter
1949 ********************************************************************/
1951 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1953 POLICY_HND
*handle
= &q_u
->handle
;
1954 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1957 if (Printer
&& Printer
->document_started
)
1958 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1960 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1962 result
= delete_printer_handle(p
, handle
);
1964 update_c_setprinter(False
);
1969 /*******************************************************************
1970 * static function to lookup the version id corresponding to an
1971 * long architecture string
1972 ******************************************************************/
1974 static int get_version_id (char * arch
)
1977 struct table_node archi_table
[]= {
1979 {"Windows 4.0", "WIN40", 0 },
1980 {"Windows NT x86", "W32X86", 2 },
1981 {"Windows NT R4000", "W32MIPS", 2 },
1982 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1983 {"Windows NT PowerPC", "W32PPC", 2 },
1984 {"Windows IA64", "IA64", 3 },
1985 {"Windows x64", "x64", 3 },
1989 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1991 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1992 return (archi_table
[i
].version
);
1998 /********************************************************************
1999 * _spoolss_deleteprinterdriver
2000 ********************************************************************/
2002 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
2006 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2007 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2009 struct current_user user
;
2011 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2013 get_current_user(&user
, p
);
2015 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2016 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2018 /* check that we have a valid driver name first */
2020 if ((version
=get_version_id(arch
)) == -1)
2021 return WERR_INVALID_ENVIRONMENT
;
2024 ZERO_STRUCT(info_win2k
);
2026 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2028 /* try for Win2k driver if "Windows NT x86" */
2030 if ( version
== 2 ) {
2032 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2033 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2037 /* otherwise it was a failure */
2039 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2045 if (printer_driver_in_use(info
.info_3
)) {
2046 status
= WERR_PRINTER_DRIVER_IN_USE
;
2052 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2054 /* if we get to here, we now have 2 driver info structures to remove */
2055 /* remove the Win2k driver first*/
2057 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2058 free_a_printer_driver( info_win2k
, 3 );
2060 /* this should not have failed---if it did, report to client */
2061 if ( !W_ERROR_IS_OK(status_win2k
) )
2066 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2068 /* if at least one of the deletes succeeded return OK */
2070 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2074 free_a_printer_driver( info
, 3 );
2079 /********************************************************************
2080 * spoolss_deleteprinterdriverex
2081 ********************************************************************/
2083 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2087 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2088 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2090 uint32 flags
= q_u
->delete_flags
;
2092 struct current_user user
;
2094 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2096 get_current_user(&user
, p
);
2098 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2099 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2101 /* check that we have a valid driver name first */
2102 if ((version
=get_version_id(arch
)) == -1) {
2103 /* this is what NT returns */
2104 return WERR_INVALID_ENVIRONMENT
;
2107 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2108 version
= q_u
->version
;
2111 ZERO_STRUCT(info_win2k
);
2113 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2115 if ( !W_ERROR_IS_OK(status
) )
2118 * if the client asked for a specific version,
2119 * or this is something other than Windows NT x86,
2123 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2126 /* try for Win2k driver if "Windows NT x86" */
2129 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2130 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2135 if ( printer_driver_in_use(info
.info_3
) ) {
2136 status
= WERR_PRINTER_DRIVER_IN_USE
;
2141 * we have a couple of cases to consider.
2142 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2143 * then the delete should fail if **any** files overlap with
2145 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2146 * non-overlapping files
2147 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2148 * is set, the do not delete any files
2149 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2154 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2156 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2157 /* no idea of the correct error here */
2158 status
= WERR_ACCESS_DENIED
;
2163 /* also check for W32X86/3 if necessary; maybe we already have? */
2165 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2166 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2169 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2170 /* no idea of the correct error here */
2171 free_a_printer_driver( info_win2k
, 3 );
2172 status
= WERR_ACCESS_DENIED
;
2176 /* if we get to here, we now have 2 driver info structures to remove */
2177 /* remove the Win2k driver first*/
2179 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2180 free_a_printer_driver( info_win2k
, 3 );
2182 /* this should not have failed---if it did, report to client */
2184 if ( !W_ERROR_IS_OK(status_win2k
) )
2189 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2191 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2194 free_a_printer_driver( info
, 3 );
2200 /****************************************************************************
2201 Internal routine for retreiving printerdata
2202 ***************************************************************************/
2204 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2205 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2206 uint32
*needed
, uint32 in_size
)
2208 REGISTRY_VALUE
*val
;
2211 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2212 return WERR_BADFILE
;
2214 *type
= regval_type( val
);
2216 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2218 size
= regval_size( val
);
2220 /* copy the min(in_size, len) */
2223 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2225 /* special case for 0 length values */
2227 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2231 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2240 DEBUG(5,("get_printer_dataex: copy done\n"));
2245 /****************************************************************************
2246 Internal routine for removing printerdata
2247 ***************************************************************************/
2249 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2251 return delete_printer_data( printer
->info_2
, key
, value
);
2254 /****************************************************************************
2255 Internal routine for storing printerdata
2256 ***************************************************************************/
2258 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2259 uint32 type
, uint8
*data
, int real_len
)
2261 delete_printer_data( printer
->info_2
, key
, value
);
2263 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2266 /********************************************************************
2267 GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2270 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2274 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2276 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2278 if((*data
= (uint8
*)TALLOC_ZERO(ctx
, 4*sizeof(uint8
) )) == NULL
)
2284 if (!StrCaseCmp(value
, "BeepEnabled")) {
2286 if((*data
= (uint8
*)TALLOC(ctx
, 4*sizeof(uint8
) )) == NULL
)
2288 SIVAL(*data
, 0, 0x00);
2293 if (!StrCaseCmp(value
, "EventLog")) {
2295 if((*data
= (uint8
*)TALLOC(ctx
, 4 )) == NULL
)
2297 /* formally was 0x1b */
2298 SIVAL(*data
, 0, 0x0);
2303 if (!StrCaseCmp(value
, "NetPopup")) {
2305 if((*data
= (uint8
*)TALLOC(ctx
, 4 )) == NULL
)
2307 SIVAL(*data
, 0, 0x00);
2312 if (!StrCaseCmp(value
, "MajorVersion")) {
2314 if((*data
= (uint8
*)TALLOC(ctx
, 4 )) == NULL
)
2317 /* Windows NT 4.0 seems to not allow uploading of drivers
2318 to a server that reports 0x3 as the MajorVersion.
2319 need to investigate more how Win2k gets around this .
2322 if ( RA_WINNT
== get_remote_arch() )
2331 if (!StrCaseCmp(value
, "MinorVersion")) {
2333 if((*data
= (uint8
*)TALLOC(ctx
, 4 )) == NULL
)
2341 * uint32 size = 0x114
2343 * uint32 minor = [0|1]
2344 * uint32 build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!StrCaseCmp(value
, "OSVersion")) {
2351 if((*data
= (uint8
*)TALLOC(ctx
, *needed
)) == NULL
)
2353 ZERO_STRUCTP( *data
);
2355 SIVAL(*data
, 0, *needed
); /* size */
2356 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2358 SIVAL(*data
, 12, 2195); /* build */
2360 /* leave extra string empty */
2366 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2367 const char *string
="C:\\PRINTERS";
2369 *needed
= 2*(strlen(string
)+1);
2370 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2372 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2374 /* it's done by hand ready to go on the wire */
2375 for (i
=0; i
<strlen(string
); i
++) {
2376 (*data
)[2*i
]=string
[i
];
2377 (*data
)[2*i
+1]='\0';
2382 if (!StrCaseCmp(value
, "Architecture")) {
2383 const char *string
="Windows NT x86";
2385 *needed
= 2*(strlen(string
)+1);
2386 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2388 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2389 for (i
=0; i
<strlen(string
); i
++) {
2390 (*data
)[2*i
]=string
[i
];
2391 (*data
)[2*i
+1]='\0';
2396 if (!StrCaseCmp(value
, "DsPresent")) {
2398 if((*data
= (uint8
*)TALLOC(ctx
, 4 )) == NULL
)
2401 /* only show the publish check box if we are a
2402 memeber of a AD domain */
2404 if ( lp_security() == SEC_ADS
)
2405 SIVAL(*data
, 0, 0x01);
2407 SIVAL(*data
, 0, 0x00);
2413 if (!StrCaseCmp(value
, "DNSMachineName")) {
2416 if (!get_mydnsfullname(hostname
))
2417 return WERR_BADFILE
;
2419 *needed
= 2*(strlen(hostname
)+1);
2420 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2422 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2423 for (i
=0; i
<strlen(hostname
); i
++) {
2424 (*data
)[2*i
]=hostname
[i
];
2425 (*data
)[2*i
+1]='\0';
2431 return WERR_BADFILE
;
2434 /********************************************************************
2435 * spoolss_getprinterdata
2436 ********************************************************************/
2438 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2440 POLICY_HND
*handle
= &q_u
->handle
;
2441 UNISTR2
*valuename
= &q_u
->valuename
;
2442 uint32 in_size
= q_u
->size
;
2443 uint32
*type
= &r_u
->type
;
2444 uint32
*out_size
= &r_u
->size
;
2445 uint8
**data
= &r_u
->data
;
2446 uint32
*needed
= &r_u
->needed
;
2449 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2450 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2454 * Reminder: when it's a string, the length is in BYTES
2455 * even if UNICODE is negociated.
2460 *out_size
= in_size
;
2462 /* in case of problem, return some default values */
2467 DEBUG(4,("_spoolss_getprinterdata\n"));
2470 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2471 status
= WERR_BADFID
;
2475 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2477 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2478 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2481 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2482 status
= WERR_BADFID
;
2486 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2487 if ( !W_ERROR_IS_OK(status
) )
2490 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2492 if ( strequal(value
, "ChangeId") ) {
2494 *needed
= sizeof(uint32
);
2495 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2496 status
= WERR_NOMEM
;
2499 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2503 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2506 if (*needed
> *out_size
)
2507 status
= WERR_MORE_DATA
;
2510 if ( !W_ERROR_IS_OK(status
) )
2512 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2514 /* reply this param doesn't exist */
2517 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2519 free_a_printer( &printer
, 2 );
2528 /* cleanup & exit */
2531 free_a_printer( &printer
, 2 );
2536 /*********************************************************
2537 Connect to the client machine.
2538 **********************************************************/
2540 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
,
2541 struct in_addr
*client_ip
, const char *remote_machine
)
2543 ZERO_STRUCTP(the_cli
);
2545 if(cli_initialise(the_cli
) == NULL
) {
2546 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2550 if ( is_zero_ip(*client_ip
) ) {
2551 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2552 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2553 cli_shutdown(the_cli
);
2557 if (ismyip(the_cli
->dest_ip
)) {
2558 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2559 cli_shutdown(the_cli
);
2564 the_cli
->dest_ip
.s_addr
= client_ip
->s_addr
;
2565 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2566 inet_ntoa(*client_ip
) ));
2569 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2570 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
) ));
2571 cli_shutdown(the_cli
);
2575 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2576 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2578 cli_shutdown(the_cli
);
2582 the_cli
->protocol
= PROTOCOL_NT1
;
2583 cli_setup_signing_state(the_cli
, lp_client_signing());
2585 if (!cli_negprot(the_cli
)) {
2586 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2587 cli_shutdown(the_cli
);
2591 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2592 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2593 cli_shutdown(the_cli
);
2598 * Do an anonymous session setup.
2601 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2602 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2603 cli_shutdown(the_cli
);
2607 if (!(the_cli
->sec_mode
& 1)) {
2608 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2609 cli_shutdown(the_cli
);
2613 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2614 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
) ));
2615 cli_shutdown(the_cli
);
2620 * Ok - we have an anonymous connection to the IPC$ share.
2621 * Now start the NT Domain stuff :-).
2624 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2625 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
)));
2626 cli_nt_session_close(the_cli
);
2627 cli_ulogoff(the_cli
);
2628 cli_shutdown(the_cli
);
2635 /***************************************************************************
2636 Connect to the client.
2637 ****************************************************************************/
2639 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2640 uint32 localprinter
, uint32 type
,
2641 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2646 * If it's the first connection, contact the client
2647 * and connect to the IPC$ share anonymously
2649 if (smb_connections
==0) {
2650 fstring unix_printer
;
2652 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2654 ZERO_STRUCT(notify_cli
);
2656 if(!spoolss_connect_to_client(¬ify_cli
, client_ip
, unix_printer
))
2659 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2660 /* Tell the connections db we're now interested in printer
2661 * notify messages. */
2662 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2666 * Tell the specific printing tdb we want messages for this printer
2667 * by registering our PID.
2670 if (!print_notify_register_pid(snum
))
2671 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2675 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2678 if (!W_ERROR_IS_OK(result
))
2679 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2680 dos_errstr(result
)));
2682 return (W_ERROR_IS_OK(result
));
2685 /********************************************************************
2687 * ReplyFindFirstPrinterChangeNotifyEx
2689 * before replying OK: status=0 a rpc call is made to the workstation
2690 * asking ReplyOpenPrinter
2692 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2693 * called from api_spoolss_rffpcnex
2694 ********************************************************************/
2696 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2698 POLICY_HND
*handle
= &q_u
->handle
;
2699 uint32 flags
= q_u
->flags
;
2700 uint32 options
= q_u
->options
;
2701 UNISTR2
*localmachine
= &q_u
->localmachine
;
2702 uint32 printerlocal
= q_u
->printerlocal
;
2704 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2705 struct in_addr client_ip
;
2707 /* store the notify value in the printer struct */
2709 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2712 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2716 Printer
->notify
.flags
=flags
;
2717 Printer
->notify
.options
=options
;
2718 Printer
->notify
.printerlocal
=printerlocal
;
2720 if (Printer
->notify
.option
)
2721 free_spool_notify_option(&Printer
->notify
.option
);
2723 Printer
->notify
.option
=dup_spool_notify_option(option
);
2725 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2726 sizeof(Printer
->notify
.localmachine
)-1);
2728 /* Connect to the client machine and send a ReplyOpenPrinter */
2730 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2732 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2733 !get_printer_snum(p
, handle
, &snum
) )
2736 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2738 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2739 Printer
->notify
.printerlocal
, 1,
2740 &Printer
->notify
.client_hnd
, &client_ip
))
2741 return WERR_SERVER_UNAVAILABLE
;
2743 Printer
->notify
.client_connected
=True
;
2748 /*******************************************************************
2749 * fill a notify_info_data with the servername
2750 ********************************************************************/
2752 void spoolss_notify_server_name(int snum
,
2753 SPOOL_NOTIFY_INFO_DATA
*data
,
2754 print_queue_struct
*queue
,
2755 NT_PRINTER_INFO_LEVEL
*printer
,
2756 TALLOC_CTX
*mem_ctx
)
2761 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2763 data
->notify_data
.data
.length
= len
;
2764 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2766 if (!data
->notify_data
.data
.string
) {
2767 data
->notify_data
.data
.length
= 0;
2771 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2774 /*******************************************************************
2775 * fill a notify_info_data with the printername (not including the servername).
2776 ********************************************************************/
2778 void spoolss_notify_printer_name(int snum
,
2779 SPOOL_NOTIFY_INFO_DATA
*data
,
2780 print_queue_struct
*queue
,
2781 NT_PRINTER_INFO_LEVEL
*printer
,
2782 TALLOC_CTX
*mem_ctx
)
2787 /* the notify name should not contain the \\server\ part */
2788 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2791 p
= printer
->info_2
->printername
;
2796 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2798 data
->notify_data
.data
.length
= len
;
2799 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2801 if (!data
->notify_data
.data
.string
) {
2802 data
->notify_data
.data
.length
= 0;
2806 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2809 /*******************************************************************
2810 * fill a notify_info_data with the servicename
2811 ********************************************************************/
2813 void spoolss_notify_share_name(int snum
,
2814 SPOOL_NOTIFY_INFO_DATA
*data
,
2815 print_queue_struct
*queue
,
2816 NT_PRINTER_INFO_LEVEL
*printer
,
2817 TALLOC_CTX
*mem_ctx
)
2822 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2824 data
->notify_data
.data
.length
= len
;
2825 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2827 if (!data
->notify_data
.data
.string
) {
2828 data
->notify_data
.data
.length
= 0;
2832 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2835 /*******************************************************************
2836 * fill a notify_info_data with the port name
2837 ********************************************************************/
2839 void spoolss_notify_port_name(int snum
,
2840 SPOOL_NOTIFY_INFO_DATA
*data
,
2841 print_queue_struct
*queue
,
2842 NT_PRINTER_INFO_LEVEL
*printer
,
2843 TALLOC_CTX
*mem_ctx
)
2848 /* even if it's strange, that's consistant in all the code */
2850 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2852 data
->notify_data
.data
.length
= len
;
2853 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2855 if (!data
->notify_data
.data
.string
) {
2856 data
->notify_data
.data
.length
= 0;
2860 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2863 /*******************************************************************
2864 * fill a notify_info_data with the printername
2865 * but it doesn't exist, have to see what to do
2866 ********************************************************************/
2868 void spoolss_notify_driver_name(int snum
,
2869 SPOOL_NOTIFY_INFO_DATA
*data
,
2870 print_queue_struct
*queue
,
2871 NT_PRINTER_INFO_LEVEL
*printer
,
2872 TALLOC_CTX
*mem_ctx
)
2877 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2879 data
->notify_data
.data
.length
= len
;
2880 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2882 if (!data
->notify_data
.data
.string
) {
2883 data
->notify_data
.data
.length
= 0;
2887 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2890 /*******************************************************************
2891 * fill a notify_info_data with the comment
2892 ********************************************************************/
2894 void spoolss_notify_comment(int snum
,
2895 SPOOL_NOTIFY_INFO_DATA
*data
,
2896 print_queue_struct
*queue
,
2897 NT_PRINTER_INFO_LEVEL
*printer
,
2898 TALLOC_CTX
*mem_ctx
)
2903 if (*printer
->info_2
->comment
== '\0')
2904 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2906 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2908 data
->notify_data
.data
.length
= len
;
2909 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2911 if (!data
->notify_data
.data
.string
) {
2912 data
->notify_data
.data
.length
= 0;
2916 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2919 /*******************************************************************
2920 * fill a notify_info_data with the comment
2921 * location = "Room 1, floor 2, building 3"
2922 ********************************************************************/
2924 void spoolss_notify_location(int snum
,
2925 SPOOL_NOTIFY_INFO_DATA
*data
,
2926 print_queue_struct
*queue
,
2927 NT_PRINTER_INFO_LEVEL
*printer
,
2928 TALLOC_CTX
*mem_ctx
)
2933 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2935 data
->notify_data
.data
.length
= len
;
2936 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2938 if (!data
->notify_data
.data
.string
) {
2939 data
->notify_data
.data
.length
= 0;
2943 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2946 /*******************************************************************
2947 * fill a notify_info_data with the device mode
2948 * jfm:xxxx don't to it for know but that's a real problem !!!
2949 ********************************************************************/
2951 static void spoolss_notify_devmode(int snum
,
2952 SPOOL_NOTIFY_INFO_DATA
*data
,
2953 print_queue_struct
*queue
,
2954 NT_PRINTER_INFO_LEVEL
*printer
,
2955 TALLOC_CTX
*mem_ctx
)
2959 /*******************************************************************
2960 * fill a notify_info_data with the separator file name
2961 ********************************************************************/
2963 void spoolss_notify_sepfile(int snum
,
2964 SPOOL_NOTIFY_INFO_DATA
*data
,
2965 print_queue_struct
*queue
,
2966 NT_PRINTER_INFO_LEVEL
*printer
,
2967 TALLOC_CTX
*mem_ctx
)
2972 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2974 data
->notify_data
.data
.length
= len
;
2975 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2977 if (!data
->notify_data
.data
.string
) {
2978 data
->notify_data
.data
.length
= 0;
2982 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2985 /*******************************************************************
2986 * fill a notify_info_data with the print processor
2987 * jfm:xxxx return always winprint to indicate we don't do anything to it
2988 ********************************************************************/
2990 void spoolss_notify_print_processor(int snum
,
2991 SPOOL_NOTIFY_INFO_DATA
*data
,
2992 print_queue_struct
*queue
,
2993 NT_PRINTER_INFO_LEVEL
*printer
,
2994 TALLOC_CTX
*mem_ctx
)
2999 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
3001 data
->notify_data
.data
.length
= len
;
3002 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3004 if (!data
->notify_data
.data
.string
) {
3005 data
->notify_data
.data
.length
= 0;
3009 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3012 /*******************************************************************
3013 * fill a notify_info_data with the print processor options
3014 * jfm:xxxx send an empty string
3015 ********************************************************************/
3017 void spoolss_notify_parameters(int snum
,
3018 SPOOL_NOTIFY_INFO_DATA
*data
,
3019 print_queue_struct
*queue
,
3020 NT_PRINTER_INFO_LEVEL
*printer
,
3021 TALLOC_CTX
*mem_ctx
)
3026 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
3028 data
->notify_data
.data
.length
= len
;
3029 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3031 if (!data
->notify_data
.data
.string
) {
3032 data
->notify_data
.data
.length
= 0;
3036 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3039 /*******************************************************************
3040 * fill a notify_info_data with the data type
3041 * jfm:xxxx always send RAW as data type
3042 ********************************************************************/
3044 void spoolss_notify_datatype(int snum
,
3045 SPOOL_NOTIFY_INFO_DATA
*data
,
3046 print_queue_struct
*queue
,
3047 NT_PRINTER_INFO_LEVEL
*printer
,
3048 TALLOC_CTX
*mem_ctx
)
3053 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3055 data
->notify_data
.data
.length
= len
;
3056 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3058 if (!data
->notify_data
.data
.string
) {
3059 data
->notify_data
.data
.length
= 0;
3063 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3066 /*******************************************************************
3067 * fill a notify_info_data with the security descriptor
3068 * jfm:xxxx send an null pointer to say no security desc
3069 * have to implement security before !
3070 ********************************************************************/
3072 static void spoolss_notify_security_desc(int snum
,
3073 SPOOL_NOTIFY_INFO_DATA
*data
,
3074 print_queue_struct
*queue
,
3075 NT_PRINTER_INFO_LEVEL
*printer
,
3076 TALLOC_CTX
*mem_ctx
)
3078 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3079 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3082 /*******************************************************************
3083 * fill a notify_info_data with the attributes
3084 * jfm:xxxx a samba printer is always shared
3085 ********************************************************************/
3087 void spoolss_notify_attributes(int snum
,
3088 SPOOL_NOTIFY_INFO_DATA
*data
,
3089 print_queue_struct
*queue
,
3090 NT_PRINTER_INFO_LEVEL
*printer
,
3091 TALLOC_CTX
*mem_ctx
)
3093 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3094 data
->notify_data
.value
[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the priority
3099 ********************************************************************/
3101 static void spoolss_notify_priority(int snum
,
3102 SPOOL_NOTIFY_INFO_DATA
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3108 data
->notify_data
.value
[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the default priority
3113 ********************************************************************/
3115 static void spoolss_notify_default_priority(int snum
,
3116 SPOOL_NOTIFY_INFO_DATA
*data
,
3117 print_queue_struct
*queue
,
3118 NT_PRINTER_INFO_LEVEL
*printer
,
3119 TALLOC_CTX
*mem_ctx
)
3121 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3122 data
->notify_data
.value
[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the start time
3127 ********************************************************************/
3129 static void spoolss_notify_start_time(int snum
,
3130 SPOOL_NOTIFY_INFO_DATA
*data
,
3131 print_queue_struct
*queue
,
3132 NT_PRINTER_INFO_LEVEL
*printer
,
3133 TALLOC_CTX
*mem_ctx
)
3135 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3136 data
->notify_data
.value
[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the until time
3141 ********************************************************************/
3143 static void spoolss_notify_until_time(int snum
,
3144 SPOOL_NOTIFY_INFO_DATA
*data
,
3145 print_queue_struct
*queue
,
3146 NT_PRINTER_INFO_LEVEL
*printer
,
3147 TALLOC_CTX
*mem_ctx
)
3149 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3150 data
->notify_data
.value
[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the status
3155 ********************************************************************/
3157 static void spoolss_notify_status(int snum
,
3158 SPOOL_NOTIFY_INFO_DATA
*data
,
3159 print_queue_struct
*queue
,
3160 NT_PRINTER_INFO_LEVEL
*printer
,
3161 TALLOC_CTX
*mem_ctx
)
3163 print_status_struct status
;
3165 print_queue_length(snum
, &status
);
3166 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3167 data
->notify_data
.value
[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the number of jobs queued
3172 ********************************************************************/
3174 void spoolss_notify_cjobs(int snum
,
3175 SPOOL_NOTIFY_INFO_DATA
*data
,
3176 print_queue_struct
*queue
,
3177 NT_PRINTER_INFO_LEVEL
*printer
,
3178 TALLOC_CTX
*mem_ctx
)
3180 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3181 data
->notify_data
.value
[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the average ppm
3186 ********************************************************************/
3188 static void spoolss_notify_average_ppm(int snum
,
3189 SPOOL_NOTIFY_INFO_DATA
*data
,
3190 print_queue_struct
*queue
,
3191 NT_PRINTER_INFO_LEVEL
*printer
,
3192 TALLOC_CTX
*mem_ctx
)
3194 /* always respond 8 pages per minutes */
3195 /* a little hard ! */
3196 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3197 data
->notify_data
.value
[1] = 0;
3200 /*******************************************************************
3201 * fill a notify_info_data with username
3202 ********************************************************************/
3204 static void spoolss_notify_username(int snum
,
3205 SPOOL_NOTIFY_INFO_DATA
*data
,
3206 print_queue_struct
*queue
,
3207 NT_PRINTER_INFO_LEVEL
*printer
,
3208 TALLOC_CTX
*mem_ctx
)
3213 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3215 data
->notify_data
.data
.length
= len
;
3216 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3218 if (!data
->notify_data
.data
.string
) {
3219 data
->notify_data
.data
.length
= 0;
3223 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3226 /*******************************************************************
3227 * fill a notify_info_data with job status
3228 ********************************************************************/
3230 static void spoolss_notify_job_status(int snum
,
3231 SPOOL_NOTIFY_INFO_DATA
*data
,
3232 print_queue_struct
*queue
,
3233 NT_PRINTER_INFO_LEVEL
*printer
,
3234 TALLOC_CTX
*mem_ctx
)
3236 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3237 data
->notify_data
.value
[1] = 0;
3240 /*******************************************************************
3241 * fill a notify_info_data with job name
3242 ********************************************************************/
3244 static void spoolss_notify_job_name(int snum
,
3245 SPOOL_NOTIFY_INFO_DATA
*data
,
3246 print_queue_struct
*queue
,
3247 NT_PRINTER_INFO_LEVEL
*printer
,
3248 TALLOC_CTX
*mem_ctx
)
3253 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3255 data
->notify_data
.data
.length
= len
;
3256 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3258 if (!data
->notify_data
.data
.string
) {
3259 data
->notify_data
.data
.length
= 0;
3263 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3266 /*******************************************************************
3267 * fill a notify_info_data with job status
3268 ********************************************************************/
3270 static void spoolss_notify_job_status_string(int snum
,
3271 SPOOL_NOTIFY_INFO_DATA
*data
,
3272 print_queue_struct
*queue
,
3273 NT_PRINTER_INFO_LEVEL
*printer
,
3274 TALLOC_CTX
*mem_ctx
)
3277 * Now we're returning job status codes we just return a "" here. JRA.
3284 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3287 switch (queue
->status
) {
3292 p
= ""; /* NT provides the paused string */
3301 #endif /* NO LONGER NEEDED. */
3303 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3305 data
->notify_data
.data
.length
= len
;
3306 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3308 if (!data
->notify_data
.data
.string
) {
3309 data
->notify_data
.data
.length
= 0;
3313 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3316 /*******************************************************************
3317 * fill a notify_info_data with job time
3318 ********************************************************************/
3320 static void spoolss_notify_job_time(int snum
,
3321 SPOOL_NOTIFY_INFO_DATA
*data
,
3322 print_queue_struct
*queue
,
3323 NT_PRINTER_INFO_LEVEL
*printer
,
3324 TALLOC_CTX
*mem_ctx
)
3326 data
->notify_data
.value
[0]=0x0;
3327 data
->notify_data
.value
[1]=0;
3330 /*******************************************************************
3331 * fill a notify_info_data with job size
3332 ********************************************************************/
3334 static void spoolss_notify_job_size(int snum
,
3335 SPOOL_NOTIFY_INFO_DATA
*data
,
3336 print_queue_struct
*queue
,
3337 NT_PRINTER_INFO_LEVEL
*printer
,
3338 TALLOC_CTX
*mem_ctx
)
3340 data
->notify_data
.value
[0]=queue
->size
;
3341 data
->notify_data
.value
[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with page info
3346 ********************************************************************/
3347 static void spoolss_notify_total_pages(int snum
,
3348 SPOOL_NOTIFY_INFO_DATA
*data
,
3349 print_queue_struct
*queue
,
3350 NT_PRINTER_INFO_LEVEL
*printer
,
3351 TALLOC_CTX
*mem_ctx
)
3353 data
->notify_data
.value
[0]=queue
->page_count
;
3354 data
->notify_data
.value
[1]=0;
3357 /*******************************************************************
3358 * fill a notify_info_data with pages printed info.
3359 ********************************************************************/
3360 static void spoolss_notify_pages_printed(int snum
,
3361 SPOOL_NOTIFY_INFO_DATA
*data
,
3362 print_queue_struct
*queue
,
3363 NT_PRINTER_INFO_LEVEL
*printer
,
3364 TALLOC_CTX
*mem_ctx
)
3366 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3367 data
->notify_data
.value
[1]=0;
3370 /*******************************************************************
3371 Fill a notify_info_data with job position.
3372 ********************************************************************/
3374 static void spoolss_notify_job_position(int snum
,
3375 SPOOL_NOTIFY_INFO_DATA
*data
,
3376 print_queue_struct
*queue
,
3377 NT_PRINTER_INFO_LEVEL
*printer
,
3378 TALLOC_CTX
*mem_ctx
)
3380 data
->notify_data
.value
[0]=queue
->job
;
3381 data
->notify_data
.value
[1]=0;
3384 /*******************************************************************
3385 Fill a notify_info_data with submitted time.
3386 ********************************************************************/
3388 static void spoolss_notify_submitted_time(int snum
,
3389 SPOOL_NOTIFY_INFO_DATA
*data
,
3390 print_queue_struct
*queue
,
3391 NT_PRINTER_INFO_LEVEL
*printer
,
3392 TALLOC_CTX
*mem_ctx
)
3399 t
=gmtime(&queue
->time
);
3401 len
= sizeof(SYSTEMTIME
);
3403 data
->notify_data
.data
.length
= len
;
3404 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3406 if (!data
->notify_data
.data
.string
) {
3407 data
->notify_data
.data
.length
= 0;
3411 make_systemtime(&st
, t
);
3414 * Systemtime must be linearized as a set of UINT16's.
3415 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3418 p
= (char *)data
->notify_data
.data
.string
;
3419 SSVAL(p
, 0, st
.year
);
3420 SSVAL(p
, 2, st
.month
);
3421 SSVAL(p
, 4, st
.dayofweek
);
3422 SSVAL(p
, 6, st
.day
);
3423 SSVAL(p
, 8, st
.hour
);
3424 SSVAL(p
, 10, st
.minute
);
3425 SSVAL(p
, 12, st
.second
);
3426 SSVAL(p
, 14, st
.milliseconds
);
3429 struct s_notify_info_data_table
3435 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3436 print_queue_struct
*queue
,
3437 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3440 /* A table describing the various print notification constants and
3441 whether the notification data is a pointer to a variable sized
3442 buffer, a one value uint32 or a two value uint32. */
3444 static const struct s_notify_info_data_table notify_info_data_table
[] =
3446 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3447 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3448 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3449 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3450 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3451 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3452 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3453 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3454 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3455 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3456 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3457 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3458 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3459 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3460 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3461 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3462 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3463 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3464 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3465 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3466 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3467 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3468 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3469 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3470 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3471 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3472 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3473 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3474 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3475 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3476 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3477 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3478 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3479 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3480 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3481 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3482 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3483 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3484 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3485 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3486 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3487 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3488 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3489 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3490 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3491 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3492 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3493 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3494 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3495 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3498 /*******************************************************************
3499 Return the size of info_data structure.
3500 ********************************************************************/
3502 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3506 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3508 if ( (notify_info_data_table
[i
].type
== type
)
3509 && (notify_info_data_table
[i
].field
== field
) )
3511 switch(notify_info_data_table
[i
].size
)
3513 case NOTIFY_ONE_VALUE
:
3514 case NOTIFY_TWO_VALUE
:
3519 /* The only pointer notify data I have seen on
3520 the wire is the submitted time and this has
3521 the notify size set to 4. -tpot */
3523 case NOTIFY_POINTER
:
3526 case NOTIFY_SECDESC
:
3532 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3537 /*******************************************************************
3538 Return the type of notify_info_data.
3539 ********************************************************************/
3541 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3545 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3546 if (notify_info_data_table
[i
].type
== type
&&
3547 notify_info_data_table
[i
].field
== field
)
3548 return notify_info_data_table
[i
].size
;
3554 /****************************************************************************
3555 ****************************************************************************/
3557 static int search_notify(uint16 type
, uint16 field
, int *value
)
3561 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3562 if (notify_info_data_table
[i
].type
== type
&&
3563 notify_info_data_table
[i
].field
== field
&&
3564 notify_info_data_table
[i
].fn
!= NULL
) {
3573 /****************************************************************************
3574 ****************************************************************************/
3576 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3578 info_data
->type
= type
;
3579 info_data
->field
= field
;
3580 info_data
->reserved
= 0;
3582 info_data
->size
= size_of_notify_info_data(type
, field
);
3583 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3590 /*******************************************************************
3592 * fill a notify_info struct with info asked
3594 ********************************************************************/
3596 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3597 snum
, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type
, uint32 id
,
3599 TALLOC_CTX
*mem_ctx
)
3605 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3606 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3607 print_queue_struct
*queue
=NULL
;
3609 type
=option_type
->type
;
3611 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3612 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type
->count
, lp_servicename(snum
)));
3615 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3618 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3619 field
= option_type
->fields
[field_num
];
3621 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3623 if (!search_notify(type
, field
, &j
) )
3626 if((tid
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3627 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3632 current_data
= &info
->data
[info
->count
];
3634 construct_info_data(current_data
, type
, field
, id
);
3636 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3637 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3639 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3645 free_a_printer(&printer
, 2);
3649 /*******************************************************************
3651 * fill a notify_info struct with info asked
3653 ********************************************************************/
3655 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3656 SPOOL_NOTIFY_INFO
*info
,
3657 NT_PRINTER_INFO_LEVEL
*printer
,
3658 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3659 *option_type
, uint32 id
,
3660 TALLOC_CTX
*mem_ctx
)
3666 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3668 DEBUG(4,("construct_notify_jobs_info\n"));
3670 type
= option_type
->type
;
3672 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3673 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3674 option_type
->count
));
3676 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3677 field
= option_type
->fields
[field_num
];
3679 if (!search_notify(type
, field
, &j
) )
3682 if((tid
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3683 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3686 else info
->data
= tid
;
3688 current_data
=&(info
->data
[info
->count
]);
3690 construct_info_data(current_data
, type
, field
, id
);
3691 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3700 * JFM: The enumeration is not that simple, it's even non obvious.
3702 * let's take an example: I want to monitor the PRINTER SERVER for
3703 * the printer's name and the number of jobs currently queued.
3704 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3705 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3707 * I have 3 printers on the back of my server.
3709 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3712 * 1 printer 1 name 1
3713 * 2 printer 1 cjob 1
3714 * 3 printer 2 name 2
3715 * 4 printer 2 cjob 2
3716 * 5 printer 3 name 3
3717 * 6 printer 3 name 3
3719 * that's the print server case, the printer case is even worse.
3722 /*******************************************************************
3724 * enumerate all printers on the printserver
3725 * fill a notify_info struct with info asked
3727 ********************************************************************/
3729 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3730 SPOOL_NOTIFY_INFO
*info
,
3731 TALLOC_CTX
*mem_ctx
)
3734 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3735 int n_services
=lp_numservices();
3737 SPOOL_NOTIFY_OPTION
*option
;
3738 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3740 DEBUG(4,("printserver_notify_info\n"));
3745 option
=Printer
->notify
.option
;
3750 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3751 sending a ffpcn() request first */
3756 for (i
=0; i
<option
->count
; i
++) {
3757 option_type
=&(option
->ctr
.type
[i
]);
3759 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3762 for (snum
=0; snum
<n_services
; snum
++)
3764 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3765 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3771 * Debugging information, don't delete.
3774 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3775 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3776 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3778 for (i
=0; i
<info
->count
; i
++) {
3779 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3780 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3781 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3788 /*******************************************************************
3790 * fill a notify_info struct with info asked
3792 ********************************************************************/
3794 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3795 TALLOC_CTX
*mem_ctx
)
3798 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3801 SPOOL_NOTIFY_OPTION
*option
;
3802 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3804 print_queue_struct
*queue
=NULL
;
3805 print_status_struct status
;
3807 DEBUG(4,("printer_notify_info\n"));
3812 option
=Printer
->notify
.option
;
3818 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3819 sending a ffpcn() request first */
3824 get_printer_snum(p
, hnd
, &snum
);
3826 for (i
=0; i
<option
->count
; i
++) {
3827 option_type
=&option
->ctr
.type
[i
];
3829 switch ( option_type
->type
) {
3830 case PRINTER_NOTIFY_TYPE
:
3831 if(construct_notify_printer_info(Printer
, info
, snum
,
3837 case JOB_NOTIFY_TYPE
: {
3838 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3840 count
= print_queue_status(snum
, &queue
, &status
);
3842 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3845 for (j
=0; j
<count
; j
++) {
3846 construct_notify_jobs_info(&queue
[j
], info
,
3853 free_a_printer(&printer
, 2);
3863 * Debugging information, don't delete.
3866 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3867 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3868 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3870 for (i=0; i<info->count; i++) {
3871 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3872 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3873 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3879 /********************************************************************
3881 ********************************************************************/
3883 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3885 POLICY_HND
*handle
= &q_u
->handle
;
3886 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3888 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3889 WERROR result
= WERR_BADFID
;
3891 /* we always have a NOTIFY_INFO struct */
3895 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3896 OUR_HANDLE(handle
)));
3900 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3903 * We are now using the change value, and
3904 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3905 * I don't have a global notification system, I'm sending back all the
3906 * informations even when _NOTHING_ has changed.
3909 /* We need to keep track of the change value to send back in
3910 RRPCN replies otherwise our updates are ignored. */
3912 Printer
->notify
.fnpcn
= True
;
3914 if (Printer
->notify
.client_connected
) {
3915 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3916 Printer
->notify
.change
= q_u
->change
;
3919 /* just ignore the SPOOL_NOTIFY_OPTION */
3921 switch (Printer
->printer_type
) {
3922 case PRINTER_HANDLE_IS_PRINTSERVER
:
3923 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3926 case PRINTER_HANDLE_IS_PRINTER
:
3927 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3931 Printer
->notify
.fnpcn
= False
;
3937 /********************************************************************
3938 * construct_printer_info_0
3939 * fill a printer_info_0 struct
3940 ********************************************************************/
3942 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3946 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3947 counter_printer_0
*session_counter
;
3948 uint32 global_counter
;
3951 print_status_struct status
;
3953 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3956 count
= print_queue_length(snum
, &status
);
3958 /* check if we already have a counter for this printer */
3959 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3960 if (session_counter
->snum
== snum
)
3964 /* it's the first time, add it to the list */
3965 if (session_counter
==NULL
) {
3966 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3967 free_a_printer(&ntprinter
, 2);
3970 ZERO_STRUCTP(session_counter
);
3971 session_counter
->snum
=snum
;
3972 session_counter
->counter
=0;
3973 DLIST_ADD(counter_list
, session_counter
);
3977 session_counter
->counter
++;
3980 * the global_counter should be stored in a TDB as it's common to all the clients
3981 * and should be zeroed on samba startup
3983 global_counter
=session_counter
->counter
;
3985 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3987 init_unistr(&printer
->printername
, chaine
);
3989 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3990 init_unistr(&printer
->servername
, chaine
);
3992 printer
->cjobs
= count
;
3993 printer
->total_jobs
= 0;
3994 printer
->total_bytes
= 0;
3996 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3997 t
=gmtime(&setuptime
);
3999 printer
->year
= t
->tm_year
+1900;
4000 printer
->month
= t
->tm_mon
+1;
4001 printer
->dayofweek
= t
->tm_wday
;
4002 printer
->day
= t
->tm_mday
;
4003 printer
->hour
= t
->tm_hour
;
4004 printer
->minute
= t
->tm_min
;
4005 printer
->second
= t
->tm_sec
;
4006 printer
->milliseconds
= 0;
4008 printer
->global_counter
= global_counter
;
4009 printer
->total_pages
= 0;
4011 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4012 printer
->major_version
= 0x0005; /* NT 5 */
4013 printer
->build_version
= 0x0893; /* build 2195 */
4015 printer
->unknown7
= 0x1;
4016 printer
->unknown8
= 0x0;
4017 printer
->unknown9
= 0x0;
4018 printer
->session_counter
= session_counter
->counter
;
4019 printer
->unknown11
= 0x0;
4020 printer
->printer_errors
= 0x0; /* number of print failure */
4021 printer
->unknown13
= 0x0;
4022 printer
->unknown14
= 0x1;
4023 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4024 printer
->unknown16
= 0x0;
4025 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4026 printer
->unknown18
= 0x0;
4027 printer
->status
= nt_printq_status(status
.status
);
4028 printer
->unknown20
= 0x0;
4029 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4030 printer
->unknown22
= 0x0;
4031 printer
->unknown23
= 0x6; /* 6 ???*/
4032 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4033 printer
->unknown25
= 0;
4034 printer
->unknown26
= 0;
4035 printer
->unknown27
= 0;
4036 printer
->unknown28
= 0;
4037 printer
->unknown29
= 0;
4039 free_a_printer(&ntprinter
,2);
4043 /********************************************************************
4044 * construct_printer_info_1
4045 * fill a printer_info_1 struct
4046 ********************************************************************/
4047 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4051 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4053 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4056 printer
->flags
=flags
;
4058 if (*ntprinter
->info_2
->comment
== '\0') {
4059 init_unistr(&printer
->comment
, lp_comment(snum
));
4060 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4061 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4064 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4065 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4066 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4069 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4071 init_unistr(&printer
->description
, chaine
);
4072 init_unistr(&printer
->name
, chaine2
);
4074 free_a_printer(&ntprinter
,2);
4079 /****************************************************************************
4080 Free a DEVMODE struct.
4081 ****************************************************************************/
4083 static void free_dev_mode(DEVICEMODE
*dev
)
4088 SAFE_FREE(dev
->private);
4093 /****************************************************************************
4094 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4095 should be valid upon entry
4096 ****************************************************************************/
4098 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4100 if ( !devmode
|| !ntdevmode
)
4103 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4105 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4107 devmode
->specversion
= ntdevmode
->specversion
;
4108 devmode
->driverversion
= ntdevmode
->driverversion
;
4109 devmode
->size
= ntdevmode
->size
;
4110 devmode
->driverextra
= ntdevmode
->driverextra
;
4111 devmode
->fields
= ntdevmode
->fields
;
4113 devmode
->orientation
= ntdevmode
->orientation
;
4114 devmode
->papersize
= ntdevmode
->papersize
;
4115 devmode
->paperlength
= ntdevmode
->paperlength
;
4116 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4117 devmode
->scale
= ntdevmode
->scale
;
4118 devmode
->copies
= ntdevmode
->copies
;
4119 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4120 devmode
->printquality
= ntdevmode
->printquality
;
4121 devmode
->color
= ntdevmode
->color
;
4122 devmode
->duplex
= ntdevmode
->duplex
;
4123 devmode
->yresolution
= ntdevmode
->yresolution
;
4124 devmode
->ttoption
= ntdevmode
->ttoption
;
4125 devmode
->collate
= ntdevmode
->collate
;
4126 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4127 devmode
->icmintent
= ntdevmode
->icmintent
;
4128 devmode
->mediatype
= ntdevmode
->mediatype
;
4129 devmode
->dithertype
= ntdevmode
->dithertype
;
4131 if (ntdevmode
->private != NULL
) {
4132 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
4139 /****************************************************************************
4140 Create a DEVMODE struct. Returns malloced memory.
4141 ****************************************************************************/
4143 DEVICEMODE
*construct_dev_mode(int snum
)
4145 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4146 DEVICEMODE
*devmode
= NULL
;
4148 DEBUG(7,("construct_dev_mode\n"));
4150 DEBUGADD(8,("getting printer characteristics\n"));
4152 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4155 if ( !printer
->info_2
->devmode
) {
4156 DEBUG(5, ("BONG! There was no device mode!\n"));
4160 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4161 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4165 ZERO_STRUCTP(devmode
);
4167 DEBUGADD(8,("loading DEVICEMODE\n"));
4169 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4170 free_dev_mode( devmode
);
4175 free_a_printer(&printer
,2);
4180 /********************************************************************
4181 * construct_printer_info_2
4182 * fill a printer_info_2 struct
4183 ********************************************************************/
4185 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4188 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4190 print_status_struct status
;
4192 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4195 count
= print_queue_length(snum
, &status
);
4197 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4198 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4199 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4200 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4201 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4203 if (*ntprinter
->info_2
->comment
== '\0')
4204 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4206 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4208 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4209 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4210 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4211 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4212 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4214 printer
->attributes
= ntprinter
->info_2
->attributes
;
4216 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4217 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4218 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4219 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4220 printer
->status
= nt_printq_status(status
.status
); /* status */
4221 printer
->cjobs
= count
; /* jobs */
4222 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4224 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4225 DEBUG(8, ("Returning NULL Devicemode!\n"));
4228 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4229 /* steal the printer info sec_desc structure. [badly done]. */
4230 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4231 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4232 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4233 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4236 printer
->secdesc
= NULL
;
4239 free_a_printer(&ntprinter
, 2);
4243 /********************************************************************
4244 * construct_printer_info_3
4245 * fill a printer_info_3 struct
4246 ********************************************************************/
4248 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4250 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4251 PRINTER_INFO_3
*printer
= NULL
;
4253 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4257 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4258 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4262 ZERO_STRUCTP(printer
);
4264 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4265 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4266 /* steal the printer info sec_desc structure. [badly done]. */
4267 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4271 * Set the flags for the components we are returning.
4274 if (printer
->secdesc
->owner_sid
)
4275 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4277 if (printer
->secdesc
->grp_sid
)
4278 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4280 if (printer
->secdesc
->dacl
)
4281 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4283 if (printer
->secdesc
->sacl
)
4284 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4287 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4288 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4289 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4292 free_a_printer(&ntprinter
, 2);
4294 *pp_printer
= printer
;
4298 /********************************************************************
4299 * construct_printer_info_4
4300 * fill a printer_info_4 struct
4301 ********************************************************************/
4303 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4305 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4307 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4310 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4311 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4312 printer
->attributes
= ntprinter
->info_2
->attributes
;
4314 free_a_printer(&ntprinter
, 2);
4318 /********************************************************************
4319 * construct_printer_info_5
4320 * fill a printer_info_5 struct
4321 ********************************************************************/
4323 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4325 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4327 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4330 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4331 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4332 printer
->attributes
= ntprinter
->info_2
->attributes
;
4334 /* these two are not used by NT+ according to MSDN */
4336 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4337 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4339 free_a_printer(&ntprinter
, 2);
4344 /********************************************************************
4345 * construct_printer_info_7
4346 * fill a printer_info_7 struct
4347 ********************************************************************/
4349 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4351 char *guid_str
= NULL
;
4354 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4355 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4356 strupper_m(guid_str
);
4357 init_unistr(&printer
->guid
, guid_str
);
4358 printer
->action
= SPOOL_DS_PUBLISH
;
4360 init_unistr(&printer
->guid
, "");
4361 printer
->action
= SPOOL_DS_UNPUBLISH
;
4367 /********************************************************************
4368 Spoolss_enumprinters.
4369 ********************************************************************/
4371 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4375 int n_services
=lp_numservices();
4376 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4377 PRINTER_INFO_1 current_prt
;
4378 WERROR result
= WERR_OK
;
4380 DEBUG(4,("enum_all_printers_info_1\n"));
4382 for (snum
=0; snum
<n_services
; snum
++) {
4383 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4384 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4386 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4387 if((tp
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4388 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4389 SAFE_FREE(printers
);
4394 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4396 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4402 /* check the required size. */
4403 for (i
=0; i
<*returned
; i
++)
4404 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4406 if (*needed
> offered
) {
4407 result
= WERR_INSUFFICIENT_BUFFER
;
4411 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4412 result
= WERR_NOMEM
;
4416 /* fill the buffer with the structures */
4417 for (i
=0; i
<*returned
; i
++)
4418 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4423 SAFE_FREE(printers
);
4425 if ( !W_ERROR_IS_OK(result
) )
4431 /********************************************************************
4432 enum_all_printers_info_1_local.
4433 *********************************************************************/
4435 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4437 DEBUG(4,("enum_all_printers_info_1_local\n"));
4439 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4442 /********************************************************************
4443 enum_all_printers_info_1_name.
4444 *********************************************************************/
4446 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4450 DEBUG(4,("enum_all_printers_info_1_name\n"));
4452 if ((name
[0] == '\\') && (name
[1] == '\\'))
4455 if (is_myname_or_ipaddr(s
)) {
4456 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4459 return WERR_INVALID_NAME
;
4462 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4463 /********************************************************************
4464 enum_all_printers_info_1_remote.
4465 *********************************************************************/
4467 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4469 PRINTER_INFO_1
*printer
;
4470 fstring printername
;
4473 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 WERROR result
= WERR_OK
;
4476 /* JFM: currently it's more a place holder than anything else.
4477 * In the spooler world there is a notion of server registration.
4478 * the print servers are registered on the PDC (in the same domain)
4480 * We should have a TDB here. The registration is done thru an
4481 * undocumented RPC call.
4484 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4489 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4490 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4491 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4493 init_unistr(&printer
->description
, desc
);
4494 init_unistr(&printer
->name
, printername
);
4495 init_unistr(&printer
->comment
, comment
);
4496 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4498 /* check the required size. */
4499 *needed
+= spoolss_size_printer_info_1(printer
);
4501 if (*needed
> offered
) {
4502 result
= WERR_INSUFFICIENT_BUFFER
;
4506 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4507 result
= WERR_NOMEM
;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer
, printer
, 0);
4518 if ( !W_ERROR_IS_OK(result
) )
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name
[0] == '\\' && name
[1] == '\\')
4547 if (is_myname_or_ipaddr(s
))
4548 return WERR_CAN_NOT_COMPLETE
;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4563 int n_services
=lp_numservices();
4564 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4565 PRINTER_INFO_2 current_prt
;
4566 WERROR result
= WERR_OK
;
4568 for (snum
=0; snum
<n_services
; snum
++) {
4569 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4570 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4572 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4573 if((tp
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) == NULL
) {
4574 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4575 SAFE_FREE(printers
);
4580 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4581 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4587 /* check the required size. */
4588 for (i
=0; i
<*returned
; i
++)
4589 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4591 if (*needed
> offered
) {
4592 result
= WERR_INSUFFICIENT_BUFFER
;
4596 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4597 result
= WERR_NOMEM
;
4601 /* fill the buffer with the structures */
4602 for (i
=0; i
<*returned
; i
++)
4603 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4607 for (i
=0; i
<*returned
; i
++) {
4608 free_devmode(printers
[i
].devmode
);
4610 SAFE_FREE(printers
);
4612 if ( !W_ERROR_IS_OK(result
) )
4618 /********************************************************************
4619 * handle enumeration of printers at level 1
4620 ********************************************************************/
4622 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4623 RPC_BUFFER
*buffer
, uint32 offered
,
4624 uint32
*needed
, uint32
*returned
)
4626 /* Not all the flags are equals */
4628 if (flags
& PRINTER_ENUM_LOCAL
)
4629 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4631 if (flags
& PRINTER_ENUM_NAME
)
4632 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4634 #if 0 /* JERRY - disabled for now */
4635 if (flags
& PRINTER_ENUM_REMOTE
)
4636 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4639 if (flags
& PRINTER_ENUM_NETWORK
)
4640 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4642 return WERR_OK
; /* NT4sp5 does that */
4645 /********************************************************************
4646 * handle enumeration of printers at level 2
4647 ********************************************************************/
4649 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4650 RPC_BUFFER
*buffer
, uint32 offered
,
4651 uint32
*needed
, uint32
*returned
)
4653 char *s
= servername
;
4655 if (flags
& PRINTER_ENUM_LOCAL
) {
4656 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4659 if (flags
& PRINTER_ENUM_NAME
) {
4660 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4662 if (is_myname_or_ipaddr(s
))
4663 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4665 return WERR_INVALID_NAME
;
4668 if (flags
& PRINTER_ENUM_REMOTE
)
4669 return WERR_UNKNOWN_LEVEL
;
4674 /********************************************************************
4675 * handle enumeration of printers at level 5
4676 ********************************************************************/
4678 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4679 RPC_BUFFER
*buffer
, uint32 offered
,
4680 uint32
*needed
, uint32
*returned
)
4682 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4686 /********************************************************************
4687 * api_spoolss_enumprinters
4689 * called from api_spoolss_enumprinters (see this to understand)
4690 ********************************************************************/
4692 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4694 uint32 flags
= q_u
->flags
;
4695 UNISTR2
*servername
= &q_u
->servername
;
4696 uint32 level
= q_u
->level
;
4697 RPC_BUFFER
*buffer
= NULL
;
4698 uint32 offered
= q_u
->offered
;
4699 uint32
*needed
= &r_u
->needed
;
4700 uint32
*returned
= &r_u
->returned
;
4704 /* that's an [in out] buffer */
4706 if ( q_u
->buffer
) {
4707 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4708 buffer
= r_u
->buffer
;
4711 DEBUG(4,("_spoolss_enumprinters\n"));
4718 * flags==PRINTER_ENUM_NAME
4719 * if name=="" then enumerates all printers
4720 * if name!="" then enumerate the printer
4721 * flags==PRINTER_ENUM_REMOTE
4722 * name is NULL, enumerate printers
4723 * Level 2: name!="" enumerates printers, name can't be NULL
4724 * Level 3: doesn't exist
4725 * Level 4: does a local registry lookup
4726 * Level 5: same as Level 2
4729 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4734 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4736 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4738 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4743 return WERR_UNKNOWN_LEVEL
;
4746 /****************************************************************************
4747 ****************************************************************************/
4749 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4751 PRINTER_INFO_0
*printer
=NULL
;
4752 WERROR result
= WERR_OK
;
4754 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4757 construct_printer_info_0(print_hnd
, printer
, snum
);
4759 /* check the required size. */
4760 *needed
+= spoolss_size_printer_info_0(printer
);
4762 if (*needed
> offered
) {
4763 result
= WERR_INSUFFICIENT_BUFFER
;
4767 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4768 result
= WERR_NOMEM
;
4772 /* fill the buffer with the structures */
4773 smb_io_printer_info_0("", buffer
, printer
, 0);
4783 /****************************************************************************
4784 ****************************************************************************/
4786 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4788 PRINTER_INFO_1
*printer
=NULL
;
4789 WERROR result
= WERR_OK
;
4791 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4794 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4796 /* check the required size. */
4797 *needed
+= spoolss_size_printer_info_1(printer
);
4799 if (*needed
> offered
) {
4800 result
= WERR_INSUFFICIENT_BUFFER
;
4804 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4805 result
= WERR_NOMEM
;
4809 /* fill the buffer with the structures */
4810 smb_io_printer_info_1("", buffer
, printer
, 0);
4819 /****************************************************************************
4820 ****************************************************************************/
4822 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4824 PRINTER_INFO_2
*printer
=NULL
;
4825 WERROR result
= WERR_OK
;
4827 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4830 construct_printer_info_2(print_hnd
, printer
, snum
);
4832 /* check the required size. */
4833 *needed
+= spoolss_size_printer_info_2(printer
);
4835 if (*needed
> offered
) {
4836 result
= WERR_INSUFFICIENT_BUFFER
;
4840 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4841 result
= WERR_NOMEM
;
4845 /* fill the buffer with the structures */
4846 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4847 result
= WERR_NOMEM
;
4851 free_printer_info_2(printer
);
4856 /****************************************************************************
4857 ****************************************************************************/
4859 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4861 PRINTER_INFO_3
*printer
=NULL
;
4862 WERROR result
= WERR_OK
;
4864 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4867 /* check the required size. */
4868 *needed
+= spoolss_size_printer_info_3(printer
);
4870 if (*needed
> offered
) {
4871 result
= WERR_INSUFFICIENT_BUFFER
;
4875 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4876 result
= WERR_NOMEM
;
4880 /* fill the buffer with the structures */
4881 smb_io_printer_info_3("", buffer
, printer
, 0);
4885 free_printer_info_3(printer
);
4890 /****************************************************************************
4891 ****************************************************************************/
4893 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4895 PRINTER_INFO_4
*printer
=NULL
;
4896 WERROR result
= WERR_OK
;
4898 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4901 if (!construct_printer_info_4(print_hnd
, printer
, snum
))
4904 /* check the required size. */
4905 *needed
+= spoolss_size_printer_info_4(printer
);
4907 if (*needed
> offered
) {
4908 result
= WERR_INSUFFICIENT_BUFFER
;
4912 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4913 result
= WERR_NOMEM
;
4917 /* fill the buffer with the structures */
4918 smb_io_printer_info_4("", buffer
, printer
, 0);
4922 free_printer_info_4(printer
);
4927 /****************************************************************************
4928 ****************************************************************************/
4930 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4932 PRINTER_INFO_5
*printer
=NULL
;
4933 WERROR result
= WERR_OK
;
4935 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4938 if (!construct_printer_info_5(print_hnd
, printer
, snum
))
4941 /* check the required size. */
4942 *needed
+= spoolss_size_printer_info_5(printer
);
4944 if (*needed
> offered
) {
4945 result
= WERR_INSUFFICIENT_BUFFER
;
4949 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4950 result
= WERR_NOMEM
;
4954 /* fill the buffer with the structures */
4955 smb_io_printer_info_5("", buffer
, printer
, 0);
4959 free_printer_info_5(printer
);
4964 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4966 PRINTER_INFO_7
*printer
=NULL
;
4967 WERROR result
= WERR_OK
;
4969 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4972 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4975 /* check the required size. */
4976 *needed
+= spoolss_size_printer_info_7(printer
);
4978 if (*needed
> offered
) {
4979 result
= WERR_INSUFFICIENT_BUFFER
;
4983 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4984 result
= WERR_NOMEM
;
4989 /* fill the buffer with the structures */
4990 smb_io_printer_info_7("", buffer
, printer
, 0);
4994 free_printer_info_7(printer
);
4999 /****************************************************************************
5000 ****************************************************************************/
5002 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
5004 POLICY_HND
*handle
= &q_u
->handle
;
5005 uint32 level
= q_u
->level
;
5006 RPC_BUFFER
*buffer
= NULL
;
5007 uint32 offered
= q_u
->offered
;
5008 uint32
*needed
= &r_u
->needed
;
5009 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
5013 /* that's an [in out] buffer */
5015 if ( q_u
->buffer
) {
5016 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5017 buffer
= r_u
->buffer
;
5022 if (!get_printer_snum(p
, handle
, &snum
))
5027 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
5029 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
5031 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
5033 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
5035 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
5037 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
5039 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
5041 return WERR_UNKNOWN_LEVEL
;
5044 /********************************************************************
5045 * fill a DRIVER_INFO_1 struct
5046 ********************************************************************/
5048 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
5050 init_unistr( &info
->name
, driver
.info_3
->name
);
5053 /********************************************************************
5054 * construct_printer_driver_info_1
5055 ********************************************************************/
5057 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5059 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5060 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5062 ZERO_STRUCT(driver
);
5064 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5065 return WERR_INVALID_PRINTER_NAME
;
5067 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5068 return WERR_UNKNOWN_PRINTER_DRIVER
;
5070 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5072 free_a_printer(&printer
,2);
5077 /********************************************************************
5078 * construct_printer_driver_info_2
5079 * fill a printer_info_2 struct
5080 ********************************************************************/
5082 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5086 info
->version
=driver
.info_3
->cversion
;
5088 init_unistr( &info
->name
, driver
.info_3
->name
);
5089 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5092 if (strlen(driver
.info_3
->driverpath
)) {
5093 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5094 init_unistr( &info
->driverpath
, temp
);
5096 init_unistr( &info
->driverpath
, "" );
5098 if (strlen(driver
.info_3
->datafile
)) {
5099 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5100 init_unistr( &info
->datafile
, temp
);
5102 init_unistr( &info
->datafile
, "" );
5104 if (strlen(driver
.info_3
->configfile
)) {
5105 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5106 init_unistr( &info
->configfile
, temp
);
5108 init_unistr( &info
->configfile
, "" );
5111 /********************************************************************
5112 * construct_printer_driver_info_2
5113 * fill a printer_info_2 struct
5114 ********************************************************************/
5116 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5118 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5119 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5121 ZERO_STRUCT(printer
);
5122 ZERO_STRUCT(driver
);
5124 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5125 return WERR_INVALID_PRINTER_NAME
;
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5128 return WERR_UNKNOWN_PRINTER_DRIVER
;
5130 fill_printer_driver_info_2(info
, driver
, servername
);
5132 free_a_printer(&printer
,2);
5137 /********************************************************************
5138 * copy a strings array and convert to UNICODE
5140 * convert an array of ascii string to a UNICODE string
5141 ********************************************************************/
5143 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5151 DEBUG(6,("init_unistr_array\n"));
5162 v
= ""; /* hack to handle null lists */
5165 /* hack to allow this to be used in places other than when generating
5166 the list of dependent files */
5169 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5173 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5175 /* add one extra unit16 for the second terminating NULL */
5177 if ( (tuary
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5178 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5186 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5191 /* special case for ""; we need to add both NULL's here */
5193 (*uni_array
)[j
++]=0x0000;
5194 (*uni_array
)[j
]=0x0000;
5197 DEBUGADD(6,("last one:done\n"));
5199 /* return size of array in uint16's */
5204 /********************************************************************
5205 * construct_printer_info_3
5206 * fill a printer_info_3 struct
5207 ********************************************************************/
5209 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5215 info
->version
=driver
.info_3
->cversion
;
5217 init_unistr( &info
->name
, driver
.info_3
->name
);
5218 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5220 if (strlen(driver
.info_3
->driverpath
)) {
5221 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5222 init_unistr( &info
->driverpath
, temp
);
5224 init_unistr( &info
->driverpath
, "" );
5226 if (strlen(driver
.info_3
->datafile
)) {
5227 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5228 init_unistr( &info
->datafile
, temp
);
5230 init_unistr( &info
->datafile
, "" );
5232 if (strlen(driver
.info_3
->configfile
)) {
5233 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5234 init_unistr( &info
->configfile
, temp
);
5236 init_unistr( &info
->configfile
, "" );
5238 if (strlen(driver
.info_3
->helpfile
)) {
5239 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5240 init_unistr( &info
->helpfile
, temp
);
5242 init_unistr( &info
->helpfile
, "" );
5244 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5245 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5247 info
->dependentfiles
=NULL
;
5248 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5251 /********************************************************************
5252 * construct_printer_info_3
5253 * fill a printer_info_3 struct
5254 ********************************************************************/
5256 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5258 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5259 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5261 ZERO_STRUCT(driver
);
5263 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5264 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5265 if (!W_ERROR_IS_OK(status
))
5266 return WERR_INVALID_PRINTER_NAME
;
5268 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5269 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5274 * I put this code in during testing. Helpful when commenting out the
5275 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5276 * as win2k always queries the driver using an infor level of 6.
5277 * I've left it in (but ifdef'd out) because I'll probably
5278 * use it in experimentation again in the future. --jerry 22/01/2002
5281 if (!W_ERROR_IS_OK(status
)) {
5283 * Is this a W2k client ?
5286 /* Yes - try again with a WinNT driver. */
5288 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5289 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5293 if (!W_ERROR_IS_OK(status
)) {
5294 free_a_printer(&printer
,2);
5295 return WERR_UNKNOWN_PRINTER_DRIVER
;
5303 fill_printer_driver_info_3(info
, driver
, servername
);
5305 free_a_printer(&printer
,2);
5310 /********************************************************************
5311 * construct_printer_info_6
5312 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5313 ********************************************************************/
5315 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5321 memset(&nullstr
, '\0', sizeof(fstring
));
5323 info
->version
=driver
.info_3
->cversion
;
5325 init_unistr( &info
->name
, driver
.info_3
->name
);
5326 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5328 if (strlen(driver
.info_3
->driverpath
)) {
5329 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5330 init_unistr( &info
->driverpath
, temp
);
5332 init_unistr( &info
->driverpath
, "" );
5334 if (strlen(driver
.info_3
->datafile
)) {
5335 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5336 init_unistr( &info
->datafile
, temp
);
5338 init_unistr( &info
->datafile
, "" );
5340 if (strlen(driver
.info_3
->configfile
)) {
5341 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5342 init_unistr( &info
->configfile
, temp
);
5344 init_unistr( &info
->configfile
, "" );
5346 if (strlen(driver
.info_3
->helpfile
)) {
5347 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5348 init_unistr( &info
->helpfile
, temp
);
5350 init_unistr( &info
->helpfile
, "" );
5352 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5353 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5355 info
->dependentfiles
= NULL
;
5356 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5358 info
->previousdrivernames
=NULL
;
5359 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5361 info
->driver_date
.low
=0;
5362 info
->driver_date
.high
=0;
5365 info
->driver_version_low
=0;
5366 info
->driver_version_high
=0;
5368 init_unistr( &info
->mfgname
, "");
5369 init_unistr( &info
->oem_url
, "");
5370 init_unistr( &info
->hardware_id
, "");
5371 init_unistr( &info
->provider
, "");
5374 /********************************************************************
5375 * construct_printer_info_6
5376 * fill a printer_info_6 struct
5377 ********************************************************************/
5379 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5380 fstring servername
, fstring architecture
, uint32 version
)
5382 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5383 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5386 ZERO_STRUCT(driver
);
5388 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5390 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5392 if (!W_ERROR_IS_OK(status
))
5393 return WERR_INVALID_PRINTER_NAME
;
5395 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5397 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5399 if (!W_ERROR_IS_OK(status
))
5402 * Is this a W2k client ?
5406 free_a_printer(&printer
,2);
5407 return WERR_UNKNOWN_PRINTER_DRIVER
;
5410 /* Yes - try again with a WinNT driver. */
5412 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5413 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5414 if (!W_ERROR_IS_OK(status
)) {
5415 free_a_printer(&printer
,2);
5416 return WERR_UNKNOWN_PRINTER_DRIVER
;
5420 fill_printer_driver_info_6(info
, driver
, servername
);
5422 free_a_printer(&printer
,2);
5423 free_a_printer_driver(driver
, 3);
5428 /****************************************************************************
5429 ****************************************************************************/
5431 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5433 SAFE_FREE(info
->dependentfiles
);
5436 /****************************************************************************
5437 ****************************************************************************/
5439 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5441 SAFE_FREE(info
->dependentfiles
);
5444 /****************************************************************************
5445 ****************************************************************************/
5447 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5449 DRIVER_INFO_1
*info
=NULL
;
5452 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5455 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5456 if (!W_ERROR_IS_OK(result
))
5459 /* check the required size. */
5460 *needed
+= spoolss_size_printer_driver_info_1(info
);
5462 if (*needed
> offered
) {
5463 result
= WERR_INSUFFICIENT_BUFFER
;
5467 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5468 result
= WERR_NOMEM
;
5472 /* fill the buffer with the structures */
5473 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5487 DRIVER_INFO_2
*info
=NULL
;
5490 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5493 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5494 if (!W_ERROR_IS_OK(result
))
5497 /* check the required size. */
5498 *needed
+= spoolss_size_printer_driver_info_2(info
);
5500 if (*needed
> offered
) {
5501 result
= WERR_INSUFFICIENT_BUFFER
;
5505 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5506 result
= WERR_NOMEM
;
5510 /* fill the buffer with the structures */
5511 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5520 /****************************************************************************
5521 ****************************************************************************/
5523 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5530 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5531 if (!W_ERROR_IS_OK(result
))
5534 /* check the required size. */
5535 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5537 if (*needed
> offered
) {
5538 result
= WERR_INSUFFICIENT_BUFFER
;
5542 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5543 result
= WERR_NOMEM
;
5547 /* fill the buffer with the structures */
5548 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5551 free_printer_driver_info_3(&info
);
5556 /****************************************************************************
5557 ****************************************************************************/
5559 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5566 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5567 if (!W_ERROR_IS_OK(result
))
5570 /* check the required size. */
5571 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5573 if (*needed
> offered
) {
5574 result
= WERR_INSUFFICIENT_BUFFER
;
5578 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5579 result
= WERR_NOMEM
;
5583 /* fill the buffer with the structures */
5584 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5587 free_printer_driver_info_6(&info
);
5592 /****************************************************************************
5593 ****************************************************************************/
5595 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5597 POLICY_HND
*handle
= &q_u
->handle
;
5598 UNISTR2
*uni_arch
= &q_u
->architecture
;
5599 uint32 level
= q_u
->level
;
5600 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5601 RPC_BUFFER
*buffer
= NULL
;
5602 uint32 offered
= q_u
->offered
;
5603 uint32
*needed
= &r_u
->needed
;
5604 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5605 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5606 Printer_entry
*printer
;
5609 fstring architecture
;
5612 /* that's an [in out] buffer */
5614 if ( q_u
->buffer
) {
5615 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5616 buffer
= r_u
->buffer
;
5619 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5621 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5622 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5623 return WERR_INVALID_PRINTER_NAME
;
5627 *servermajorversion
= 0;
5628 *serverminorversion
= 0;
5630 fstrcpy(servername
, get_server_name( printer
));
5631 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5633 if (!get_printer_snum(p
, handle
, &snum
))
5638 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5640 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5642 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5644 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5647 /* apparently this call is the equivalent of
5648 EnumPrinterDataEx() for the DsDriver key */
5653 return WERR_UNKNOWN_LEVEL
;
5656 /****************************************************************************
5657 ****************************************************************************/
5659 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5661 POLICY_HND
*handle
= &q_u
->handle
;
5663 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5666 DEBUG(3,("Error in startpageprinter printer handle\n"));
5670 Printer
->page_started
=True
;
5674 /****************************************************************************
5675 ****************************************************************************/
5677 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5679 POLICY_HND
*handle
= &q_u
->handle
;
5682 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5685 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5689 if (!get_printer_snum(p
, handle
, &snum
))
5692 Printer
->page_started
=False
;
5693 print_job_endpage(snum
, Printer
->jobid
);
5698 /********************************************************************
5699 * api_spoolss_getprinter
5700 * called from the spoolss dispatcher
5702 ********************************************************************/
5704 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5706 POLICY_HND
*handle
= &q_u
->handle
;
5707 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5708 uint32
*jobid
= &r_u
->jobid
;
5710 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5714 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5715 struct current_user user
;
5718 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5722 get_current_user(&user
, p
);
5725 * a nice thing with NT is it doesn't listen to what you tell it.
5726 * when asked to send _only_ RAW datas, it tries to send datas
5729 * So I add checks like in NT Server ...
5732 if (info_1
->p_datatype
!= 0) {
5733 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5734 if (strcmp(datatype
, "RAW") != 0) {
5736 return WERR_INVALID_DATATYPE
;
5740 /* get the share number of the printer */
5741 if (!get_printer_snum(p
, handle
, &snum
)) {
5745 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5747 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5749 /* An error occured in print_job_start() so return an appropriate
5752 if (Printer
->jobid
== -1) {
5753 return map_werror_from_unix(errno
);
5756 Printer
->document_started
=True
;
5757 (*jobid
) = Printer
->jobid
;
5762 /********************************************************************
5763 * api_spoolss_getprinter
5764 * called from the spoolss dispatcher
5766 ********************************************************************/
5768 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5770 POLICY_HND
*handle
= &q_u
->handle
;
5772 return _spoolss_enddocprinter_internal(p
, handle
);
5775 /****************************************************************************
5776 ****************************************************************************/
5778 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5780 POLICY_HND
*handle
= &q_u
->handle
;
5781 uint32 buffer_size
= q_u
->buffer_size
;
5782 uint8
*buffer
= q_u
->buffer
;
5783 uint32
*buffer_written
= &q_u
->buffer_size2
;
5785 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5788 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5789 r_u
->buffer_written
= q_u
->buffer_size2
;
5793 if (!get_printer_snum(p
, handle
, &snum
))
5796 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5797 if (*buffer_written
== -1) {
5798 r_u
->buffer_written
= 0;
5799 if (errno
== ENOSPC
)
5800 return WERR_NO_SPOOL_SPACE
;
5802 return WERR_ACCESS_DENIED
;
5805 r_u
->buffer_written
= q_u
->buffer_size2
;
5810 /********************************************************************
5811 * api_spoolss_getprinter
5812 * called from the spoolss dispatcher
5814 ********************************************************************/
5816 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5819 struct current_user user
;
5821 WERROR errcode
= WERR_BADFUNC
;
5822 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5824 get_current_user(&user
, p
);
5827 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5831 if (!get_printer_snum(p
, handle
, &snum
))
5835 case PRINTER_CONTROL_PAUSE
:
5836 if (print_queue_pause(&user
, snum
, &errcode
)) {
5840 case PRINTER_CONTROL_RESUME
:
5841 case PRINTER_CONTROL_UNPAUSE
:
5842 if (print_queue_resume(&user
, snum
, &errcode
)) {
5846 case PRINTER_CONTROL_PURGE
:
5847 if (print_queue_purge(&user
, snum
, &errcode
)) {
5852 return WERR_UNKNOWN_LEVEL
;
5858 /********************************************************************
5859 * api_spoolss_abortprinter
5860 * From MSDN: "Deletes printer's spool file if printer is configured
5862 ********************************************************************/
5864 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5866 POLICY_HND
*handle
= &q_u
->handle
;
5867 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5869 struct current_user user
;
5870 WERROR errcode
= WERR_OK
;
5873 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5877 if (!get_printer_snum(p
, handle
, &snum
))
5880 get_current_user( &user
, p
);
5882 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5887 /********************************************************************
5888 * called by spoolss_api_setprinter
5889 * when updating a printer description
5890 ********************************************************************/
5892 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5893 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5894 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5896 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5900 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5902 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5903 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5904 OUR_HANDLE(handle
)));
5906 result
= WERR_BADFID
;
5910 /* Check the user has permissions to change the security
5911 descriptor. By experimentation with two NT machines, the user
5912 requires Full Access to the printer to change security
5915 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5916 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5917 result
= WERR_ACCESS_DENIED
;
5921 /* NT seems to like setting the security descriptor even though
5922 nothing may have actually changed. */
5924 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5926 if (DEBUGLEVEL
>= 10) {
5930 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5931 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5932 PRINTERNAME(snum
), the_acl
->num_aces
));
5934 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5937 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5939 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5940 the_acl
->ace
[i
].info
.mask
));
5943 the_acl
= secdesc_ctr
->sec
->dacl
;
5946 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5947 PRINTERNAME(snum
), the_acl
->num_aces
));
5949 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5952 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5954 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5955 the_acl
->ace
[i
].info
.mask
));
5958 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5962 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5964 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5969 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5976 /********************************************************************
5977 Canonicalize printer info from a client
5979 ATTN: It does not matter what we set the servername to hear
5980 since we do the necessary work in get_a_printer() to set it to
5981 the correct value based on what the client sent in the
5982 _spoolss_open_printer_ex().
5983 ********************************************************************/
5985 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5987 fstring printername
;
5990 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5991 "portname=%s drivername=%s comment=%s location=%s\n",
5992 info
->servername
, info
->printername
, info
->sharename
,
5993 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5995 /* we force some elements to "correct" values */
5996 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5997 fstrcpy(info
->sharename
, lp_servicename(snum
));
5999 /* check to see if we allow printername != sharename */
6001 if ( lp_force_printername(snum
) ) {
6002 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6003 global_myname(), info
->sharename
);
6006 /* make sure printername is in \\server\printername format */
6008 fstrcpy( printername
, info
->printername
);
6010 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6011 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6015 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6016 global_myname(), p
);
6019 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6020 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6027 /****************************************************************************
6028 ****************************************************************************/
6030 static BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6032 char *cmd
= lp_addprinter_cmd();
6038 fstring remote_machine
= "%m";
6039 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6042 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
6044 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6045 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6046 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6047 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6049 is_print_op
= user_has_privileges( token
, &se_printop
);
6051 DEBUG(10,("Running [%s]\n", command
));
6053 /********* BEGIN SePrintOperatorPrivilege **********/
6058 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6059 /* Tell everyone we updated smb.conf. */
6060 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6066 /********* END SePrintOperatorPrivilege **********/
6068 DEBUGADD(10,("returned [%d]\n", ret
));
6076 /* reload our services immediately */
6077 reload_services( False
);
6080 /* Get lines and convert them back to dos-codepage */
6081 qlines
= fd_lines_load(fd
, &numlines
);
6082 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6085 /* Set the portname to what the script says the portname should be. */
6086 /* but don't require anything to be return from the script exit a good error code */
6089 /* Set the portname to what the script says the portname should be. */
6090 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6091 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6094 file_lines_free(qlines
);
6098 /********************************************************************
6099 * Called by spoolss_api_setprinter
6100 * when updating a printer description.
6101 ********************************************************************/
6103 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6104 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6105 DEVICEMODE
*devmode
)
6108 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6109 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6114 DEBUG(8,("update_printer\n"));
6119 result
= WERR_BADFID
;
6123 if (!get_printer_snum(p
, handle
, &snum
)) {
6124 result
= WERR_BADFID
;
6128 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6129 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6130 result
= WERR_BADFID
;
6134 DEBUGADD(8,("Converting info_2 struct\n"));
6137 * convert_printer_info converts the incoming
6138 * info from the client and overwrites the info
6139 * just read from the tdb in the pointer 'printer'.
6142 if (!convert_printer_info(info
, printer
, level
)) {
6143 result
= WERR_NOMEM
;
6148 /* we have a valid devmode
6149 convert it and link it*/
6151 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6152 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6153 &printer
->info_2
->devmode
)) {
6154 result
= WERR_NOMEM
;
6159 /* Do sanity check on the requested changes for Samba */
6161 if (!check_printer_ok(printer
->info_2
, snum
)) {
6162 result
= WERR_INVALID_PARAM
;
6166 /* FIXME!!! If the driver has changed we really should verify that
6167 it is installed before doing much else --jerry */
6169 /* Check calling user has permission to update printer description */
6171 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6172 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6173 result
= WERR_ACCESS_DENIED
;
6177 /* Call addprinter hook */
6178 /* Check changes to see if this is really needed */
6180 if ( *lp_addprinter_cmd()
6181 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6182 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6183 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6184 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6186 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6187 result
= WERR_ACCESS_DENIED
;
6192 * make sure we actually reload the services after
6193 * this as smb.conf could have a new section in it
6194 * .... shouldn't .... but could
6196 reload_services(False
);
6200 * When a *new* driver is bound to a printer, the drivername is used to
6201 * lookup previously saved driver initialization info, which is then
6202 * bound to the printer, simulating what happens in the Windows arch.
6204 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6206 if (!set_driver_init(printer
, 2))
6208 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6209 printer
->info_2
->drivername
));
6212 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6213 printer
->info_2
->drivername
));
6215 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6219 * flag which changes actually occured. This is a small subset of
6220 * all the possible changes. We also have to update things in the
6224 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6225 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6226 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6227 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6229 notify_printer_comment(snum
, printer
->info_2
->comment
);
6232 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6233 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6234 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6235 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6237 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6240 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6243 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6246 pname
= printer
->info_2
->printername
;
6249 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6250 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6251 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6253 notify_printer_printername( snum
, pname
);
6256 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6257 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6258 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6259 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6261 notify_printer_port(snum
, printer
->info_2
->portname
);
6264 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6265 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6266 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6267 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6269 notify_printer_location(snum
, printer
->info_2
->location
);
6272 /* here we need to update some more DsSpooler keys */
6273 /* uNCName, serverName, shortServerName */
6275 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6276 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6277 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6278 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6279 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6281 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6282 global_myname(), printer
->info_2
->sharename
);
6283 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6284 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6285 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6287 /* Update printer info */
6288 result
= mod_a_printer(printer
, 2);
6291 free_a_printer(&printer
, 2);
6292 free_a_printer(&old_printer
, 2);
6298 /****************************************************************************
6299 ****************************************************************************/
6300 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6301 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6304 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6306 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6308 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6313 if (!get_printer_snum(p
, handle
, &snum
))
6316 nt_printer_publish(Printer
, snum
, info7
->action
);
6320 return WERR_UNKNOWN_LEVEL
;
6323 /****************************************************************************
6324 ****************************************************************************/
6326 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6328 POLICY_HND
*handle
= &q_u
->handle
;
6329 uint32 level
= q_u
->level
;
6330 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6331 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6332 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6333 uint32 command
= q_u
->command
;
6336 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6339 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6343 /* check the level */
6346 return control_printer(handle
, command
, p
);
6348 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6349 if (!W_ERROR_IS_OK(result
))
6352 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6355 return update_printer_sec(handle
, level
, info
, p
,
6358 return publish_or_unpublish_printer(p
, handle
, info
);
6360 return WERR_UNKNOWN_LEVEL
;
6364 /****************************************************************************
6365 ****************************************************************************/
6367 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6369 POLICY_HND
*handle
= &q_u
->handle
;
6370 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6373 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6377 if (Printer
->notify
.client_connected
==True
) {
6380 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6382 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6383 !get_printer_snum(p
, handle
, &snum
) )
6386 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6389 Printer
->notify
.flags
=0;
6390 Printer
->notify
.options
=0;
6391 Printer
->notify
.localmachine
[0]='\0';
6392 Printer
->notify
.printerlocal
=0;
6393 if (Printer
->notify
.option
)
6394 free_spool_notify_option(&Printer
->notify
.option
);
6395 Printer
->notify
.client_connected
=False
;
6400 /****************************************************************************
6401 ****************************************************************************/
6403 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6405 /* that's an [in out] buffer */
6408 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6411 return WERR_INVALID_PARAM
; /* this is what a NT server
6412 returns for AddJob. AddJob
6413 must fail on non-local
6417 /****************************************************************************
6418 ****************************************************************************/
6420 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6421 int position
, int snum
,
6422 NT_PRINTER_INFO_LEVEL
*ntprinter
)
6426 t
=gmtime(&queue
->time
);
6428 job_info
->jobid
=queue
->job
;
6429 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6430 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6431 init_unistr(&job_info
->username
, queue
->fs_user
);
6432 init_unistr(&job_info
->document
, queue
->fs_file
);
6433 init_unistr(&job_info
->datatype
, "RAW");
6434 init_unistr(&job_info
->text_status
, "");
6435 job_info
->status
=nt_printj_status(queue
->status
);
6436 job_info
->priority
=queue
->priority
;
6437 job_info
->position
=position
;
6438 job_info
->totalpages
=queue
->page_count
;
6439 job_info
->pagesprinted
=0;
6441 make_systemtime(&job_info
->submitted
, t
);
6444 /****************************************************************************
6445 ****************************************************************************/
6447 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6448 int position
, int snum
,
6449 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6450 DEVICEMODE
*devmode
)
6454 t
=gmtime(&queue
->time
);
6456 job_info
->jobid
=queue
->job
;
6458 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6460 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6461 init_unistr(&job_info
->username
, queue
->fs_user
);
6462 init_unistr(&job_info
->document
, queue
->fs_file
);
6463 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6464 init_unistr(&job_info
->datatype
, "RAW");
6465 init_unistr(&job_info
->printprocessor
, "winprint");
6466 init_unistr(&job_info
->parameters
, "");
6467 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6468 init_unistr(&job_info
->text_status
, "");
6470 /* and here the security descriptor */
6472 job_info
->status
=nt_printj_status(queue
->status
);
6473 job_info
->priority
=queue
->priority
;
6474 job_info
->position
=position
;
6475 job_info
->starttime
=0;
6476 job_info
->untiltime
=0;
6477 job_info
->totalpages
=queue
->page_count
;
6478 job_info
->size
=queue
->size
;
6479 make_systemtime(&(job_info
->submitted
), t
);
6480 job_info
->timeelapsed
=0;
6481 job_info
->pagesprinted
=0;
6483 job_info
->devmode
= devmode
;
6488 /****************************************************************************
6489 Enumjobs at level 1.
6490 ****************************************************************************/
6492 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6493 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6494 RPC_BUFFER
*buffer
, uint32 offered
,
6495 uint32
*needed
, uint32
*returned
)
6499 WERROR result
= WERR_OK
;
6501 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6508 for (i
=0; i
<*returned
; i
++)
6509 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6513 /* check the required size. */
6514 for (i
=0; i
<*returned
; i
++)
6515 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6517 if (*needed
> offered
) {
6518 result
= WERR_INSUFFICIENT_BUFFER
;
6522 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6523 result
= WERR_NOMEM
;
6527 /* fill the buffer with the structures */
6528 for (i
=0; i
<*returned
; i
++)
6529 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6535 if ( !W_ERROR_IS_OK(result
) )
6541 /****************************************************************************
6542 Enumjobs at level 2.
6543 ****************************************************************************/
6545 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6546 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6547 RPC_BUFFER
*buffer
, uint32 offered
,
6548 uint32
*needed
, uint32
*returned
)
6550 JOB_INFO_2
*info
= NULL
;
6552 WERROR result
= WERR_OK
;
6553 DEVICEMODE
*devmode
= NULL
;
6555 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6560 /* this should not be a failure condition if the devmode is NULL */
6562 devmode
= construct_dev_mode(snum
);
6564 for (i
=0; i
<*returned
; i
++)
6565 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6567 free_a_printer(&ntprinter
, 2);
6570 /* check the required size. */
6571 for (i
=0; i
<*returned
; i
++)
6572 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6574 if (*needed
> offered
) {
6575 result
= WERR_INSUFFICIENT_BUFFER
;
6579 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6580 result
= WERR_NOMEM
;
6584 /* fill the buffer with the structures */
6585 for (i
=0; i
<*returned
; i
++)
6586 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6589 free_devmode(devmode
);
6592 if ( !W_ERROR_IS_OK(result
) )
6599 /****************************************************************************
6601 ****************************************************************************/
6603 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6605 POLICY_HND
*handle
= &q_u
->handle
;
6606 uint32 level
= q_u
->level
;
6607 RPC_BUFFER
*buffer
= NULL
;
6608 uint32 offered
= q_u
->offered
;
6609 uint32
*needed
= &r_u
->needed
;
6610 uint32
*returned
= &r_u
->returned
;
6612 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6614 print_status_struct prt_status
;
6615 print_queue_struct
*queue
=NULL
;
6617 /* that's an [in out] buffer */
6619 if ( q_u
->buffer
) {
6620 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6621 buffer
= r_u
->buffer
;
6624 DEBUG(4,("_spoolss_enumjobs\n"));
6629 /* lookup the printer snum and tdb entry */
6631 if (!get_printer_snum(p
, handle
, &snum
))
6634 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6635 if ( !W_ERROR_IS_OK(wret
) )
6638 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6639 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6641 if (*returned
== 0) {
6648 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6651 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6656 wret
= WERR_UNKNOWN_LEVEL
;
6659 free_a_printer( &ntprinter
, 2 );
6663 /****************************************************************************
6664 ****************************************************************************/
6666 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6671 /****************************************************************************
6672 ****************************************************************************/
6674 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6676 POLICY_HND
*handle
= &q_u
->handle
;
6677 uint32 jobid
= q_u
->jobid
;
6678 uint32 command
= q_u
->command
;
6680 struct current_user user
;
6682 WERROR errcode
= WERR_BADFUNC
;
6684 if (!get_printer_snum(p
, handle
, &snum
)) {
6688 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6689 return WERR_INVALID_PRINTER_NAME
;
6692 get_current_user(&user
, p
);
6695 case JOB_CONTROL_CANCEL
:
6696 case JOB_CONTROL_DELETE
:
6697 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6701 case JOB_CONTROL_PAUSE
:
6702 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6706 case JOB_CONTROL_RESTART
:
6707 case JOB_CONTROL_RESUME
:
6708 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6713 return WERR_UNKNOWN_LEVEL
;
6719 /****************************************************************************
6720 Enumerates all printer drivers at level 1.
6721 ****************************************************************************/
6723 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6728 fstring
*list
= NULL
;
6729 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6730 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6731 WERROR result
= WERR_OK
;
6735 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6737 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6738 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6744 if((tdi1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6745 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6746 SAFE_FREE(driver_info_1
);
6750 else driver_info_1
= tdi1
;
6753 for (i
=0; i
<ndrivers
; i
++) {
6755 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6756 ZERO_STRUCT(driver
);
6757 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6758 architecture
, version
);
6759 if (!W_ERROR_IS_OK(status
)) {
6763 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6764 free_a_printer_driver(driver
, 3);
6767 *returned
+=ndrivers
;
6771 /* check the required size. */
6772 for (i
=0; i
<*returned
; i
++) {
6773 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6774 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6777 if (*needed
> offered
) {
6778 result
= WERR_INSUFFICIENT_BUFFER
;
6782 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6783 result
= WERR_NOMEM
;
6787 /* fill the buffer with the driver structures */
6788 for (i
=0; i
<*returned
; i
++) {
6789 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6790 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6794 SAFE_FREE(driver_info_1
);
6796 if ( !W_ERROR_IS_OK(result
) )
6802 /****************************************************************************
6803 Enumerates all printer drivers at level 2.
6804 ****************************************************************************/
6806 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6811 fstring
*list
= NULL
;
6812 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6813 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6814 WERROR result
= WERR_OK
;
6818 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6820 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6821 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6827 if((tdi2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6828 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6829 SAFE_FREE(driver_info_2
);
6833 else driver_info_2
= tdi2
;
6836 for (i
=0; i
<ndrivers
; i
++) {
6839 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6840 ZERO_STRUCT(driver
);
6841 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6842 architecture
, version
);
6843 if (!W_ERROR_IS_OK(status
)) {
6847 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6848 free_a_printer_driver(driver
, 3);
6851 *returned
+=ndrivers
;
6855 /* check the required size. */
6856 for (i
=0; i
<*returned
; i
++) {
6857 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6858 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6861 if (*needed
> offered
) {
6862 result
= WERR_INSUFFICIENT_BUFFER
;
6866 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6867 result
= WERR_NOMEM
;
6871 /* fill the buffer with the form structures */
6872 for (i
=0; i
<*returned
; i
++) {
6873 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6874 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6878 SAFE_FREE(driver_info_2
);
6880 if ( !W_ERROR_IS_OK(result
) )
6886 /****************************************************************************
6887 Enumerates all printer drivers at level 3.
6888 ****************************************************************************/
6890 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6895 fstring
*list
= NULL
;
6896 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6897 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6898 WERROR result
= WERR_OK
;
6902 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6904 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6905 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6911 if((tdi3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6912 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6913 SAFE_FREE(driver_info_3
);
6917 else driver_info_3
= tdi3
;
6920 for (i
=0; i
<ndrivers
; i
++) {
6923 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6924 ZERO_STRUCT(driver
);
6925 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6926 architecture
, version
);
6927 if (!W_ERROR_IS_OK(status
)) {
6931 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6932 free_a_printer_driver(driver
, 3);
6935 *returned
+=ndrivers
;
6939 /* check the required size. */
6940 for (i
=0; i
<*returned
; i
++) {
6941 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6942 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6945 if (*needed
> offered
) {
6946 result
= WERR_INSUFFICIENT_BUFFER
;
6950 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6951 result
= WERR_NOMEM
;
6955 /* fill the buffer with the driver structures */
6956 for (i
=0; i
<*returned
; i
++) {
6957 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6958 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6962 for (i
=0; i
<*returned
; i
++)
6963 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6965 SAFE_FREE(driver_info_3
);
6967 if ( !W_ERROR_IS_OK(result
) )
6973 /****************************************************************************
6974 Enumerates all printer drivers.
6975 ****************************************************************************/
6977 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6979 uint32 level
= q_u
->level
;
6980 RPC_BUFFER
*buffer
= NULL
;
6981 uint32 offered
= q_u
->offered
;
6982 uint32
*needed
= &r_u
->needed
;
6983 uint32
*returned
= &r_u
->returned
;
6986 fstring architecture
;
6988 /* that's an [in out] buffer */
6990 if ( q_u
->buffer
) {
6991 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6992 buffer
= r_u
->buffer
;
6995 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7000 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
7001 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
7003 if ( !is_myname_or_ipaddr( servername
) )
7004 return WERR_UNKNOWN_PRINTER_DRIVER
;
7008 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
7010 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
7012 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
7014 return WERR_UNKNOWN_LEVEL
;
7018 /****************************************************************************
7019 ****************************************************************************/
7021 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7023 form
->flag
=list
->flag
;
7024 init_unistr(&form
->name
, list
->name
);
7025 form
->width
=list
->width
;
7026 form
->length
=list
->length
;
7027 form
->left
=list
->left
;
7028 form
->top
=list
->top
;
7029 form
->right
=list
->right
;
7030 form
->bottom
=list
->bottom
;
7033 /****************************************************************************
7034 ****************************************************************************/
7036 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7038 uint32 level
= q_u
->level
;
7039 RPC_BUFFER
*buffer
= NULL
;
7040 uint32 offered
= q_u
->offered
;
7041 uint32
*needed
= &r_u
->needed
;
7042 uint32
*numofforms
= &r_u
->numofforms
;
7043 uint32 numbuiltinforms
;
7045 nt_forms_struct
*list
=NULL
;
7046 nt_forms_struct
*builtinlist
=NULL
;
7051 /* that's an [in out] buffer */
7053 if ( q_u
->buffer
) {
7054 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7055 buffer
= r_u
->buffer
;
7058 DEBUG(4,("_spoolss_enumforms\n"));
7059 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7060 DEBUGADD(5,("Info level [%d]\n", level
));
7062 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7063 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7064 *numofforms
= get_ntforms(&list
);
7065 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7066 *numofforms
+= numbuiltinforms
;
7068 if (*numofforms
== 0)
7069 return WERR_NO_MORE_ITEMS
;
7073 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7078 /* construct the list of form structures */
7079 for (i
=0; i
<numbuiltinforms
; i
++) {
7080 DEBUGADD(6,("Filling form number [%d]\n",i
));
7081 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7084 SAFE_FREE(builtinlist
);
7086 for (; i
<*numofforms
; i
++) {
7087 DEBUGADD(6,("Filling form number [%d]\n",i
));
7088 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7093 /* check the required size. */
7094 for (i
=0; i
<numbuiltinforms
; i
++) {
7095 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7096 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7098 for (; i
<*numofforms
; i
++) {
7099 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7100 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7103 *needed
=buffer_size
;
7105 if (*needed
> offered
) {
7108 return WERR_INSUFFICIENT_BUFFER
;
7111 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7117 /* fill the buffer with the form structures */
7118 for (i
=0; i
<numbuiltinforms
; i
++) {
7119 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7120 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7122 for (; i
<*numofforms
; i
++) {
7123 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7124 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7133 SAFE_FREE(builtinlist
);
7134 return WERR_UNKNOWN_LEVEL
;
7139 /****************************************************************************
7140 ****************************************************************************/
7142 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7144 uint32 level
= q_u
->level
;
7145 UNISTR2
*uni_formname
= &q_u
->formname
;
7146 RPC_BUFFER
*buffer
= NULL
;
7147 uint32 offered
= q_u
->offered
;
7148 uint32
*needed
= &r_u
->needed
;
7150 nt_forms_struct
*list
=NULL
;
7151 nt_forms_struct builtin_form
;
7156 int numofforms
=0, i
=0;
7158 /* that's an [in out] buffer */
7160 if ( q_u
->buffer
) {
7161 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7162 buffer
= r_u
->buffer
;
7165 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7167 DEBUG(4,("_spoolss_getform\n"));
7168 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7169 DEBUGADD(5,("Info level [%d]\n", level
));
7171 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7172 if (!foundBuiltin
) {
7173 numofforms
= get_ntforms(&list
);
7174 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7176 if (numofforms
== 0)
7183 fill_form_1(&form_1
, &builtin_form
);
7186 /* Check if the requested name is in the list of form structures */
7187 for (i
=0; i
<numofforms
; i
++) {
7189 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7191 if (strequal(form_name
, list
[i
].name
)) {
7192 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7193 fill_form_1(&form_1
, &list
[i
]);
7199 if (i
== numofforms
) {
7203 /* check the required size. */
7205 *needed
=spoolss_size_form_1(&form_1
);
7207 if (*needed
> offered
)
7208 return WERR_INSUFFICIENT_BUFFER
;
7210 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7213 /* fill the buffer with the form structures */
7214 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7215 smb_io_form_1("", buffer
, &form_1
, 0);
7221 return WERR_UNKNOWN_LEVEL
;
7225 /****************************************************************************
7226 ****************************************************************************/
7228 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7230 init_unistr(&port
->port_name
, name
);
7233 /****************************************************************************
7234 ****************************************************************************/
7236 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7238 init_unistr(&port
->port_name
, name
);
7239 init_unistr(&port
->monitor_name
, "Local Monitor");
7240 init_unistr(&port
->description
, "Local Port");
7241 port
->port_type
=PORT_TYPE_WRITE
;
7245 /****************************************************************************
7247 ****************************************************************************/
7249 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7251 PORT_INFO_1
*ports
=NULL
;
7253 WERROR result
= WERR_OK
;
7255 if (*lp_enumports_cmd()) {
7256 char *cmd
= lp_enumports_cmd();
7263 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7265 DEBUG(10,("Running [%s]\n", command
));
7266 ret
= smbrun(command
, &fd
);
7267 DEBUG(10,("Returned [%d]\n", ret
));
7271 /* Is this the best error to return here? */
7272 return WERR_ACCESS_DENIED
;
7276 qlines
= fd_lines_load(fd
, &numlines
);
7277 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7281 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7282 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7283 dos_errstr(WERR_NOMEM
)));
7284 file_lines_free(qlines
);
7288 for (i
=0; i
<numlines
; i
++) {
7289 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7290 fill_port_1(&ports
[i
], qlines
[i
]);
7293 file_lines_free(qlines
);
7296 *returned
= numlines
;
7299 *returned
= 1; /* Sole Samba port returned. */
7301 if((ports
=SMB_MALLOC_P(PORT_INFO_1
)) == NULL
)
7304 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7306 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7309 /* check the required size. */
7310 for (i
=0; i
<*returned
; i
++) {
7311 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7312 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7315 if (*needed
> offered
) {
7316 result
= WERR_INSUFFICIENT_BUFFER
;
7320 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7321 result
= WERR_NOMEM
;
7325 /* fill the buffer with the ports structures */
7326 for (i
=0; i
<*returned
; i
++) {
7327 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7328 smb_io_port_1("", buffer
, &ports
[i
], 0);
7334 if ( !W_ERROR_IS_OK(result
) )
7340 /****************************************************************************
7342 ****************************************************************************/
7344 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7346 PORT_INFO_2
*ports
=NULL
;
7348 WERROR result
= WERR_OK
;
7350 if (*lp_enumports_cmd()) {
7351 char *cmd
= lp_enumports_cmd();
7360 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7361 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7363 path
= lp_lockdir();
7365 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7366 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7369 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7370 ret
= smbrun(command
, &fd
);
7371 DEBUGADD(10,("returned [%d]\n", ret
));
7375 /* Is this the best error to return here? */
7376 return WERR_ACCESS_DENIED
;
7380 qlines
= fd_lines_load(fd
, &numlines
);
7381 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7385 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7386 file_lines_free(qlines
);
7390 for (i
=0; i
<numlines
; i
++) {
7391 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7392 fill_port_2(&(ports
[i
]), qlines
[i
]);
7395 file_lines_free(qlines
);
7398 *returned
= numlines
;
7404 if((ports
=SMB_MALLOC_P(PORT_INFO_2
)) == NULL
)
7407 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7409 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7412 /* check the required size. */
7413 for (i
=0; i
<*returned
; i
++) {
7414 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7415 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7418 if (*needed
> offered
) {
7419 result
= WERR_INSUFFICIENT_BUFFER
;
7423 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7424 result
= WERR_NOMEM
;
7428 /* fill the buffer with the ports structures */
7429 for (i
=0; i
<*returned
; i
++) {
7430 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7431 smb_io_port_2("", buffer
, &ports
[i
], 0);
7437 if ( !W_ERROR_IS_OK(result
) )
7443 /****************************************************************************
7445 ****************************************************************************/
7447 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7449 uint32 level
= q_u
->level
;
7450 RPC_BUFFER
*buffer
= NULL
;
7451 uint32 offered
= q_u
->offered
;
7452 uint32
*needed
= &r_u
->needed
;
7453 uint32
*returned
= &r_u
->returned
;
7455 /* that's an [in out] buffer */
7457 if ( q_u
->buffer
) {
7458 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7459 buffer
= r_u
->buffer
;
7462 DEBUG(4,("_spoolss_enumports\n"));
7469 return enumports_level_1(buffer
, offered
, needed
, returned
);
7471 return enumports_level_2(buffer
, offered
, needed
, returned
);
7473 return WERR_UNKNOWN_LEVEL
;
7477 /****************************************************************************
7478 ****************************************************************************/
7480 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7481 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7482 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7483 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7486 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7489 WERROR err
= WERR_OK
;
7491 if ((printer
= SMB_MALLOC_P(NT_PRINTER_INFO_LEVEL
)) == NULL
) {
7492 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7496 ZERO_STRUCTP(printer
);
7498 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7499 if (!convert_printer_info(info
, printer
, 2)) {
7500 free_a_printer(&printer
, 2);
7504 /* check to see if the printer already exists */
7506 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7507 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7508 printer
->info_2
->sharename
));
7509 free_a_printer(&printer
, 2);
7510 return WERR_PRINTER_ALREADY_EXISTS
;
7513 /* FIXME!!! smbd should check to see if the driver is installed before
7514 trying to add a printer like this --jerry */
7516 if (*lp_addprinter_cmd() ) {
7517 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7518 free_a_printer(&printer
,2);
7519 return WERR_ACCESS_DENIED
;
7523 /* use our primary netbios name since get_a_printer() will convert
7524 it to what the client expects on a case by case basis */
7526 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7527 printer
->info_2
->sharename
);
7530 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7531 free_a_printer(&printer
,2);
7532 return WERR_ACCESS_DENIED
;
7535 /* you must be a printer admin to add a new printer */
7536 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7537 free_a_printer(&printer
,2);
7538 return WERR_ACCESS_DENIED
;
7542 * Do sanity check on the requested changes for Samba.
7545 if (!check_printer_ok(printer
->info_2
, snum
)) {
7546 free_a_printer(&printer
,2);
7547 return WERR_INVALID_PARAM
;
7551 * When a printer is created, the drivername bound to the printer is used
7552 * to lookup previously saved driver initialization info, which is then
7553 * bound to the new printer, simulating what happens in the Windows arch.
7558 set_driver_init(printer
, 2);
7562 /* A valid devmode was included, convert and link it
7564 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7566 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7567 &printer
->info_2
->devmode
))
7571 /* write the ASCII on disk */
7572 err
= mod_a_printer(printer
, 2);
7573 if (!W_ERROR_IS_OK(err
)) {
7574 free_a_printer(&printer
,2);
7578 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7579 /* Handle open failed - remove addition. */
7580 del_a_printer(printer
->info_2
->sharename
);
7581 free_a_printer(&printer
,2);
7582 return WERR_ACCESS_DENIED
;
7585 update_c_setprinter(False
);
7586 free_a_printer(&printer
,2);
7591 /****************************************************************************
7592 ****************************************************************************/
7594 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7596 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7597 uint32 level
= q_u
->level
;
7598 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7599 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7600 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7601 uint32 user_switch
= q_u
->user_switch
;
7602 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7603 POLICY_HND
*handle
= &r_u
->handle
;
7607 /* we don't handle yet */
7608 /* but I know what to do ... */
7609 return WERR_UNKNOWN_LEVEL
;
7611 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7613 user_switch
, user
, handle
);
7615 return WERR_UNKNOWN_LEVEL
;
7619 /****************************************************************************
7620 ****************************************************************************/
7622 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7624 uint32 level
= q_u
->level
;
7625 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7626 WERROR err
= WERR_OK
;
7627 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7628 struct current_user user
;
7629 fstring driver_name
;
7632 ZERO_STRUCT(driver
);
7634 get_current_user(&user
, p
);
7636 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7641 DEBUG(5,("Cleaning driver's information\n"));
7642 err
= clean_up_driver_struct(driver
, level
, &user
);
7643 if (!W_ERROR_IS_OK(err
))
7646 DEBUG(5,("Moving driver to final destination\n"));
7647 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7648 if (W_ERROR_IS_OK(err
))
7649 err
= WERR_ACCESS_DENIED
;
7653 if (add_a_printer_driver(driver
, level
)!=0) {
7654 err
= WERR_ACCESS_DENIED
;
7658 /* BEGIN_ADMIN_LOG */
7661 fstrcpy(driver_name
, driver
.info_3
->name
? driver
.info_3
->name
: "");
7662 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7663 driver_name
, get_drv_ver_to_os(driver
.info_3
->cversion
),uidtoname(user
.uid
));
7666 fstrcpy(driver_name
, driver
.info_6
->name
? driver
.info_6
->name
: "");
7667 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7668 driver_name
, get_drv_ver_to_os(driver
.info_6
->version
),uidtoname(user
.uid
));
7674 * I think this is where he DrvUpgradePrinter() hook would be
7675 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7676 * server. Right now, we just need to send ourselves a message
7677 * to update each printer bound to this driver. --jerry
7680 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7681 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7686 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7687 * decide if the driver init data should be deleted. The rules are:
7688 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7689 * 2) delete init data only if there is no 2k/Xp driver
7690 * 3) always delete init data
7691 * The generalized rule is always use init data from the highest order driver.
7692 * It is necessary to follow the driver install by an initialization step to
7693 * finish off this process.
7696 version
= driver
.info_3
->cversion
;
7697 else if (level
== 6)
7698 version
= driver
.info_6
->version
;
7703 * 9x printer driver - never delete init data
7706 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7711 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7712 * there is no 2k/Xp driver init data for this driver name.
7716 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7718 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7720 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7722 if (!del_driver_init(driver_name
))
7723 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7726 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7728 free_a_printer_driver(driver1
,3);
7729 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7736 * 2k or Xp printer driver - always delete init data
7739 if (!del_driver_init(driver_name
))
7740 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7744 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7750 free_a_printer_driver(driver
, level
);
7754 /********************************************************************
7755 * spoolss_addprinterdriverex
7756 ********************************************************************/
7758 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7760 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7761 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7764 * we only support the semantics of AddPrinterDriver()
7765 * i.e. only copy files that are newer than existing ones
7768 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7769 return WERR_ACCESS_DENIED
;
7771 ZERO_STRUCT(q_u_local
);
7772 ZERO_STRUCT(r_u_local
);
7774 /* just pass the information off to _spoolss_addprinterdriver() */
7775 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7776 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7777 q_u_local
.level
= q_u
->level
;
7778 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7780 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7783 /****************************************************************************
7784 ****************************************************************************/
7786 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7788 init_unistr(&info
->name
, name
);
7791 /****************************************************************************
7792 ****************************************************************************/
7794 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7800 const char *short_archi
;
7801 DRIVER_DIRECTORY_1
*info
=NULL
;
7802 WERROR result
= WERR_OK
;
7804 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7805 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7807 /* check for beginning double '\'s and that the server
7810 pservername
= servername
;
7811 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7815 if ( !is_myname_or_ipaddr( pservername
) )
7816 return WERR_INVALID_PARAM
;
7818 if (!(short_archi
= get_short_archi(long_archi
)))
7819 return WERR_INVALID_ENVIRONMENT
;
7821 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7824 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7826 DEBUG(4,("printer driver directory: [%s]\n", path
));
7828 fill_driverdir_1(info
, path
);
7830 *needed
+= spoolss_size_driverdir_info_1(info
);
7832 if (*needed
> offered
) {
7833 result
= WERR_INSUFFICIENT_BUFFER
;
7837 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7838 result
= WERR_NOMEM
;
7842 smb_io_driverdir_1("", buffer
, info
, 0);
7850 /****************************************************************************
7851 ****************************************************************************/
7853 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7855 UNISTR2
*name
= &q_u
->name
;
7856 UNISTR2
*uni_environment
= &q_u
->environment
;
7857 uint32 level
= q_u
->level
;
7858 RPC_BUFFER
*buffer
= NULL
;
7859 uint32 offered
= q_u
->offered
;
7860 uint32
*needed
= &r_u
->needed
;
7862 /* that's an [in out] buffer */
7864 if ( q_u
->buffer
) {
7865 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7866 buffer
= r_u
->buffer
;
7869 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7875 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7877 return WERR_UNKNOWN_LEVEL
;
7881 /****************************************************************************
7882 ****************************************************************************/
7884 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7886 POLICY_HND
*handle
= &q_u
->handle
;
7887 uint32 idx
= q_u
->index
;
7888 uint32 in_value_len
= q_u
->valuesize
;
7889 uint32 in_data_len
= q_u
->datasize
;
7890 uint32
*out_max_value_len
= &r_u
->valuesize
;
7891 uint16
**out_value
= &r_u
->value
;
7892 uint32
*out_value_len
= &r_u
->realvaluesize
;
7893 uint32
*out_type
= &r_u
->type
;
7894 uint32
*out_max_data_len
= &r_u
->datasize
;
7895 uint8
**data_out
= &r_u
->data
;
7896 uint32
*out_data_len
= &r_u
->realdatasize
;
7898 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7900 uint32 biggest_valuesize
;
7901 uint32 biggest_datasize
;
7903 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7906 REGISTRY_VALUE
*val
= NULL
;
7907 NT_PRINTER_DATA
*p_data
;
7908 int i
, key_index
, num_values
;
7911 ZERO_STRUCT( printer
);
7915 *out_max_data_len
= 0;
7919 DEBUG(5,("spoolss_enumprinterdata\n"));
7922 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7926 if (!get_printer_snum(p
,handle
, &snum
))
7929 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7930 if (!W_ERROR_IS_OK(result
))
7933 p_data
= &printer
->info_2
->data
;
7934 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7939 * The NT machine wants to know the biggest size of value and data
7941 * cf: MSDN EnumPrinterData remark section
7944 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7946 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7948 biggest_valuesize
= 0;
7949 biggest_datasize
= 0;
7951 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7953 for ( i
=0; i
<num_values
; i
++ )
7955 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7957 name_length
= strlen(val
->valuename
);
7958 if ( strlen(val
->valuename
) > biggest_valuesize
)
7959 biggest_valuesize
= name_length
;
7961 if ( val
->size
> biggest_datasize
)
7962 biggest_datasize
= val
->size
;
7964 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7968 /* the value is an UNICODE string but real_value_size is the length
7969 in bytes including the trailing 0 */
7971 *out_value_len
= 2 * (1+biggest_valuesize
);
7972 *out_data_len
= biggest_datasize
;
7974 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7980 * the value len is wrong in NT sp3
7981 * that's the number of bytes not the number of unicode chars
7984 if ( key_index
!= -1 )
7985 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7990 /* out_value should default to "" or else NT4 has
7991 problems unmarshalling the response */
7993 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7995 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7997 result
= WERR_NOMEM
;
8001 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
8003 /* the data is counted in bytes */
8005 *out_max_data_len
= in_data_len
;
8006 *out_data_len
= in_data_len
;
8008 /* only allocate when given a non-zero data_len */
8010 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
8012 result
= WERR_NOMEM
;
8016 result
= WERR_NO_MORE_ITEMS
;
8022 * - counted in bytes in the request
8023 * - counted in UNICODE chars in the max reply
8024 * - counted in bytes in the real size
8026 * take a pause *before* coding not *during* coding
8030 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8031 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8033 result
= WERR_NOMEM
;
8037 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
8041 *out_type
= regval_type( val
);
8043 /* data - counted in bytes */
8045 *out_max_data_len
= in_data_len
;
8046 if ( (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8048 result
= WERR_NOMEM
;
8051 data_len
= (size_t)regval_size(val
);
8052 memcpy( *data_out
, regval_data_p(val
), data_len
);
8053 *out_data_len
= data_len
;
8057 free_a_printer(&printer
, 2);
8061 /****************************************************************************
8062 ****************************************************************************/
8064 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8066 POLICY_HND
*handle
= &q_u
->handle
;
8067 UNISTR2
*value
= &q_u
->value
;
8068 uint32 type
= q_u
->type
;
8069 uint8
*data
= q_u
->data
;
8070 uint32 real_len
= q_u
->real_len
;
8072 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8074 WERROR status
= WERR_OK
;
8075 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8078 DEBUG(5,("spoolss_setprinterdata\n"));
8081 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8085 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8086 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8087 return WERR_INVALID_PARAM
;
8090 if (!get_printer_snum(p
,handle
, &snum
))
8094 * Access check : NT returns "access denied" if you make a
8095 * SetPrinterData call without the necessary privildge.
8096 * we were originally returning OK if nothing changed
8097 * which made Win2k issue **a lot** of SetPrinterData
8098 * when connecting to a printer --jerry
8101 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8103 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8104 status
= WERR_ACCESS_DENIED
;
8108 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8109 if (!W_ERROR_IS_OK(status
))
8112 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8115 * When client side code sets a magic printer data key, detect it and save
8116 * the current printer data and the magic key's data (its the DEVMODE) for
8117 * future printer/driver initializations.
8119 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8121 /* Set devmode and printer initialization info */
8122 status
= save_driver_init( printer
, 2, data
, real_len
);
8124 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8128 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8129 type
, data
, real_len
);
8130 if ( W_ERROR_IS_OK(status
) )
8131 status
= mod_a_printer(printer
, 2);
8135 free_a_printer(&printer
, 2);
8140 /****************************************************************************
8141 ****************************************************************************/
8143 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8145 POLICY_HND
*handle
= &q_u
->handle
;
8146 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8149 DEBUG(5,("_spoolss_resetprinter\n"));
8152 * All we do is to check to see if the handle and queue is valid.
8153 * This call really doesn't mean anything to us because we only
8154 * support RAW printing. --jerry
8158 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8162 if (!get_printer_snum(p
,handle
, &snum
))
8166 /* blindly return success */
8171 /****************************************************************************
8172 ****************************************************************************/
8174 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8176 POLICY_HND
*handle
= &q_u
->handle
;
8177 UNISTR2
*value
= &q_u
->valuename
;
8179 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8181 WERROR status
= WERR_OK
;
8182 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8185 DEBUG(5,("spoolss_deleteprinterdata\n"));
8188 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8192 if (!get_printer_snum(p
, handle
, &snum
))
8195 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8196 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8197 return WERR_ACCESS_DENIED
;
8200 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8201 if (!W_ERROR_IS_OK(status
))
8204 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8206 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8208 if ( W_ERROR_IS_OK(status
) )
8209 mod_a_printer( printer
, 2 );
8211 free_a_printer(&printer
, 2);
8216 /****************************************************************************
8217 ****************************************************************************/
8219 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8221 POLICY_HND
*handle
= &q_u
->handle
;
8222 FORM
*form
= &q_u
->form
;
8223 nt_forms_struct tmpForm
;
8225 WERROR status
= WERR_OK
;
8226 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8229 nt_forms_struct
*list
=NULL
;
8230 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8232 DEBUG(5,("spoolss_addform\n"));
8235 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8240 /* forms can be added on printer of on the print server handle */
8242 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8244 if (!get_printer_snum(p
,handle
, &snum
))
8247 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8248 if (!W_ERROR_IS_OK(status
))
8252 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8253 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8254 status
= WERR_ACCESS_DENIED
;
8258 /* can't add if builtin */
8260 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8261 status
= WERR_ALREADY_EXISTS
;
8265 count
= get_ntforms(&list
);
8267 if(!add_a_form(&list
, form
, &count
)) {
8268 status
= WERR_NOMEM
;
8272 write_ntforms(&list
, count
);
8275 * ChangeID must always be set if this is a printer
8278 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8279 status
= mod_a_printer(printer
, 2);
8283 free_a_printer(&printer
, 2);
8289 /****************************************************************************
8290 ****************************************************************************/
8292 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8294 POLICY_HND
*handle
= &q_u
->handle
;
8295 UNISTR2
*form_name
= &q_u
->name
;
8296 nt_forms_struct tmpForm
;
8298 nt_forms_struct
*list
=NULL
;
8299 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8301 WERROR status
= WERR_OK
;
8302 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8304 DEBUG(5,("spoolss_deleteform\n"));
8307 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8311 /* forms can be deleted on printer of on the print server handle */
8313 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8315 if (!get_printer_snum(p
,handle
, &snum
))
8318 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8319 if (!W_ERROR_IS_OK(status
))
8323 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8324 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8325 status
= WERR_ACCESS_DENIED
;
8329 /* can't delete if builtin */
8331 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8332 status
= WERR_INVALID_PARAM
;
8336 count
= get_ntforms(&list
);
8338 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8342 * ChangeID must always be set if this is a printer
8345 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8346 status
= mod_a_printer(printer
, 2);
8350 free_a_printer(&printer
, 2);
8356 /****************************************************************************
8357 ****************************************************************************/
8359 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8361 POLICY_HND
*handle
= &q_u
->handle
;
8362 FORM
*form
= &q_u
->form
;
8363 nt_forms_struct tmpForm
;
8365 WERROR status
= WERR_OK
;
8366 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8369 nt_forms_struct
*list
=NULL
;
8370 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8372 DEBUG(5,("spoolss_setform\n"));
8375 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8379 /* forms can be modified on printer of on the print server handle */
8381 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8383 if (!get_printer_snum(p
,handle
, &snum
))
8386 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8387 if (!W_ERROR_IS_OK(status
))
8391 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8392 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8393 status
= WERR_ACCESS_DENIED
;
8397 /* can't set if builtin */
8398 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8399 status
= WERR_INVALID_PARAM
;
8403 count
= get_ntforms(&list
);
8404 update_a_form(&list
, form
, count
);
8405 write_ntforms(&list
, count
);
8408 * ChangeID must always be set if this is a printer
8411 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8412 status
= mod_a_printer(printer
, 2);
8417 free_a_printer(&printer
, 2);
8423 /****************************************************************************
8424 enumprintprocessors level 1.
8425 ****************************************************************************/
8427 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8429 PRINTPROCESSOR_1
*info_1
=NULL
;
8430 WERROR result
= WERR_OK
;
8432 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8437 init_unistr(&info_1
->name
, "winprint");
8439 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8441 if (*needed
> offered
) {
8442 result
= WERR_INSUFFICIENT_BUFFER
;
8446 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8447 result
= WERR_NOMEM
;
8451 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8456 if ( !W_ERROR_IS_OK(result
) )
8462 /****************************************************************************
8463 ****************************************************************************/
8465 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8467 uint32 level
= q_u
->level
;
8468 RPC_BUFFER
*buffer
= NULL
;
8469 uint32 offered
= q_u
->offered
;
8470 uint32
*needed
= &r_u
->needed
;
8471 uint32
*returned
= &r_u
->returned
;
8473 /* that's an [in out] buffer */
8475 if ( q_u
->buffer
) {
8476 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8477 buffer
= r_u
->buffer
;
8480 DEBUG(5,("spoolss_enumprintprocessors\n"));
8483 * Enumerate the print processors ...
8485 * Just reply with "winprint", to keep NT happy
8486 * and I can use my nice printer checker.
8494 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8496 return WERR_UNKNOWN_LEVEL
;
8500 /****************************************************************************
8501 enumprintprocdatatypes level 1.
8502 ****************************************************************************/
8504 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8506 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8507 WERROR result
= WERR_NOMEM
;
8509 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8514 init_unistr(&info_1
->name
, "RAW");
8516 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8518 if (*needed
> offered
) {
8519 result
= WERR_INSUFFICIENT_BUFFER
;
8523 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8524 result
= WERR_NOMEM
;
8528 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8533 if ( !W_ERROR_IS_OK(result
) )
8539 /****************************************************************************
8540 ****************************************************************************/
8542 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8544 uint32 level
= q_u
->level
;
8545 RPC_BUFFER
*buffer
= NULL
;
8546 uint32 offered
= q_u
->offered
;
8547 uint32
*needed
= &r_u
->needed
;
8548 uint32
*returned
= &r_u
->returned
;
8550 /* that's an [in out] buffer */
8552 if ( q_u
->buffer
) {
8553 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8554 buffer
= r_u
->buffer
;
8557 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8564 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8566 return WERR_UNKNOWN_LEVEL
;
8570 /****************************************************************************
8571 enumprintmonitors level 1.
8572 ****************************************************************************/
8574 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8576 PRINTMONITOR_1
*info_1
=NULL
;
8577 WERROR result
= WERR_OK
;
8579 if((info_1
= SMB_MALLOC_P(PRINTMONITOR_1
)) == NULL
)
8584 init_unistr(&info_1
->name
, "Local Port");
8586 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8588 if (*needed
> offered
) {
8589 result
= WERR_INSUFFICIENT_BUFFER
;
8593 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8594 result
= WERR_NOMEM
;
8598 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8603 if ( !W_ERROR_IS_OK(result
) )
8609 /****************************************************************************
8610 enumprintmonitors level 2.
8611 ****************************************************************************/
8613 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8615 PRINTMONITOR_2
*info_2
=NULL
;
8616 WERROR result
= WERR_OK
;
8618 if((info_2
= SMB_MALLOC_P(PRINTMONITOR_2
)) == NULL
)
8623 init_unistr(&info_2
->name
, "Local Port");
8624 init_unistr(&info_2
->environment
, "Windows NT X86");
8625 init_unistr(&info_2
->dll_name
, "localmon.dll");
8627 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8629 if (*needed
> offered
) {
8630 result
= WERR_INSUFFICIENT_BUFFER
;
8634 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8635 result
= WERR_NOMEM
;
8639 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8644 if ( !W_ERROR_IS_OK(result
) )
8650 /****************************************************************************
8651 ****************************************************************************/
8653 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8655 uint32 level
= q_u
->level
;
8656 RPC_BUFFER
*buffer
= NULL
;
8657 uint32 offered
= q_u
->offered
;
8658 uint32
*needed
= &r_u
->needed
;
8659 uint32
*returned
= &r_u
->returned
;
8661 /* that's an [in out] buffer */
8663 if ( q_u
->buffer
) {
8664 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8665 buffer
= r_u
->buffer
;
8668 DEBUG(5,("spoolss_enumprintmonitors\n"));
8671 * Enumerate the print monitors ...
8673 * Just reply with "Local Port", to keep NT happy
8674 * and I can use my nice printer checker.
8682 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8684 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8686 return WERR_UNKNOWN_LEVEL
;
8690 /****************************************************************************
8691 ****************************************************************************/
8693 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8694 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8695 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8700 JOB_INFO_1
*info_1
=NULL
;
8701 WERROR result
= WERR_OK
;
8703 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8705 if (info_1
== NULL
) {
8709 for (i
=0; i
<count
&& found
==False
; i
++) {
8710 if ((*queue
)[i
].job
==(int)jobid
)
8716 /* NT treats not found as bad param... yet another bad choice */
8717 return WERR_INVALID_PARAM
;
8720 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8722 *needed
+= spoolss_size_job_info_1(info_1
);
8724 if (*needed
> offered
) {
8725 result
= WERR_INSUFFICIENT_BUFFER
;
8729 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8730 result
= WERR_NOMEM
;
8734 smb_io_job_info_1("", buffer
, info_1
, 0);
8742 /****************************************************************************
8743 ****************************************************************************/
8745 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8746 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8747 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8754 DEVICEMODE
*devmode
= NULL
;
8755 NT_DEVICEMODE
*nt_devmode
= NULL
;
8757 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8760 ZERO_STRUCTP(info_2
);
8762 for ( i
=0; i
<count
&& found
==False
; i
++ )
8764 if ((*queue
)[i
].job
== (int)jobid
)
8769 /* NT treats not found as bad param... yet another bad
8771 result
= WERR_INVALID_PARAM
;
8776 * if the print job does not have a DEVMODE associated with it,
8777 * just use the one for the printer. A NULL devicemode is not
8778 * a failure condition
8781 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8782 devmode
= construct_dev_mode(snum
);
8784 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8785 ZERO_STRUCTP( devmode
);
8786 convert_nt_devicemode( devmode
, nt_devmode
);
8790 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8792 *needed
+= spoolss_size_job_info_2(info_2
);
8794 if (*needed
> offered
) {
8795 result
= WERR_INSUFFICIENT_BUFFER
;
8799 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8800 result
= WERR_NOMEM
;
8804 smb_io_job_info_2("", buffer
, info_2
, 0);
8809 /* Cleanup allocated memory */
8811 free_job_info_2(info_2
); /* Also frees devmode */
8817 /****************************************************************************
8818 ****************************************************************************/
8820 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8822 POLICY_HND
*handle
= &q_u
->handle
;
8823 uint32 jobid
= q_u
->jobid
;
8824 uint32 level
= q_u
->level
;
8825 RPC_BUFFER
*buffer
= NULL
;
8826 uint32 offered
= q_u
->offered
;
8827 uint32
*needed
= &r_u
->needed
;
8828 WERROR wstatus
= WERR_OK
;
8829 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8832 print_queue_struct
*queue
= NULL
;
8833 print_status_struct prt_status
;
8835 /* that's an [in out] buffer */
8837 if ( q_u
->buffer
) {
8838 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8839 buffer
= r_u
->buffer
;
8842 DEBUG(5,("spoolss_getjob\n"));
8846 if (!get_printer_snum(p
, handle
, &snum
))
8849 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8850 if ( !W_ERROR_IS_OK(wstatus
) )
8853 count
= print_queue_status(snum
, &queue
, &prt_status
);
8855 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8856 count
, prt_status
.status
, prt_status
.message
));
8860 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8861 buffer
, offered
, needed
);
8864 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8865 buffer
, offered
, needed
);
8868 wstatus
= WERR_UNKNOWN_LEVEL
;
8873 free_a_printer( &ntprinter
, 2 );
8878 /********************************************************************
8879 spoolss_getprinterdataex
8881 From MSDN documentation of GetPrinterDataEx: pass request
8882 to GetPrinterData if key is "PrinterDriverData".
8883 ********************************************************************/
8885 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8887 POLICY_HND
*handle
= &q_u
->handle
;
8888 uint32 in_size
= q_u
->size
;
8889 uint32
*type
= &r_u
->type
;
8890 uint32
*out_size
= &r_u
->size
;
8891 uint8
**data
= &r_u
->data
;
8892 uint32
*needed
= &r_u
->needed
;
8893 fstring keyname
, valuename
;
8895 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8897 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8899 WERROR status
= WERR_OK
;
8901 DEBUG(4,("_spoolss_getprinterdataex\n"));
8903 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8904 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8906 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8907 keyname
, valuename
));
8909 /* in case of problem, return some default values */
8913 *out_size
= in_size
;
8916 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8917 status
= WERR_BADFID
;
8921 /* Is the handle to a printer or to the server? */
8923 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8924 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8925 status
= WERR_INVALID_PARAM
;
8929 if ( !get_printer_snum(p
,handle
, &snum
) )
8932 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8933 if ( !W_ERROR_IS_OK(status
) )
8936 /* check to see if the keyname is valid */
8937 if ( !strlen(keyname
) ) {
8938 status
= WERR_INVALID_PARAM
;
8942 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8943 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8944 free_a_printer( &printer
, 2 );
8945 status
= WERR_BADFILE
;
8949 /* When given a new keyname, we should just create it */
8951 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8953 if (*needed
> *out_size
)
8954 status
= WERR_MORE_DATA
;
8957 if ( !W_ERROR_IS_OK(status
) )
8959 DEBUG(5, ("error: allocating %d\n", *out_size
));
8961 /* reply this param doesn't exist */
8965 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8966 status
= WERR_NOMEM
;
8976 free_a_printer( &printer
, 2 );
8981 /********************************************************************
8982 * spoolss_setprinterdataex
8983 ********************************************************************/
8985 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8987 POLICY_HND
*handle
= &q_u
->handle
;
8988 uint32 type
= q_u
->type
;
8989 uint8
*data
= q_u
->data
;
8990 uint32 real_len
= q_u
->real_len
;
8992 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8994 WERROR status
= WERR_OK
;
8995 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9000 DEBUG(4,("_spoolss_setprinterdataex\n"));
9002 /* From MSDN documentation of SetPrinterDataEx: pass request to
9003 SetPrinterData if key is "PrinterDriverData" */
9006 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9010 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
9011 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9012 return WERR_INVALID_PARAM
;
9015 if ( !get_printer_snum(p
,handle
, &snum
) )
9019 * Access check : NT returns "access denied" if you make a
9020 * SetPrinterData call without the necessary privildge.
9021 * we were originally returning OK if nothing changed
9022 * which made Win2k issue **a lot** of SetPrinterData
9023 * when connecting to a printer --jerry
9026 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9028 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9029 return WERR_ACCESS_DENIED
;
9032 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9033 if (!W_ERROR_IS_OK(status
))
9036 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9037 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9039 /* check for OID in valuename */
9041 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9047 /* save the registry data */
9049 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9051 if ( W_ERROR_IS_OK(status
) )
9053 /* save the OID if one was specified */
9055 fstrcat( keyname
, "\\" );
9056 fstrcat( keyname
, SPOOL_OID_KEY
);
9059 * I'm not checking the status here on purpose. Don't know
9060 * if this is right, but I'm returning the status from the
9061 * previous set_printer_dataex() call. I have no idea if
9062 * this is right. --jerry
9065 set_printer_dataex( printer
, keyname
, valuename
,
9066 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
9069 status
= mod_a_printer(printer
, 2);
9072 free_a_printer(&printer
, 2);
9078 /********************************************************************
9079 * spoolss_deleteprinterdataex
9080 ********************************************************************/
9082 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9084 POLICY_HND
*handle
= &q_u
->handle
;
9085 UNISTR2
*value
= &q_u
->valuename
;
9086 UNISTR2
*key
= &q_u
->keyname
;
9088 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9090 WERROR status
= WERR_OK
;
9091 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9092 pstring valuename
, keyname
;
9094 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9097 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9101 if (!get_printer_snum(p
, handle
, &snum
))
9104 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9105 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9106 return WERR_ACCESS_DENIED
;
9109 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9110 if (!W_ERROR_IS_OK(status
))
9113 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9114 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9116 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9118 if ( W_ERROR_IS_OK(status
) )
9119 mod_a_printer( printer
, 2 );
9121 free_a_printer(&printer
, 2);
9126 /********************************************************************
9127 * spoolss_enumprinterkey
9128 ********************************************************************/
9131 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9134 fstring
*keynames
= NULL
;
9135 uint16
*enumkeys
= NULL
;
9138 POLICY_HND
*handle
= &q_u
->handle
;
9139 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9140 NT_PRINTER_DATA
*data
;
9141 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9143 WERROR status
= WERR_BADFILE
;
9146 DEBUG(4,("_spoolss_enumprinterkey\n"));
9149 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9153 if ( !get_printer_snum(p
,handle
, &snum
) )
9156 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9157 if (!W_ERROR_IS_OK(status
))
9160 /* get the list of subkey names */
9162 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9163 data
= &printer
->info_2
->data
;
9165 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9167 if ( num_keys
== -1 ) {
9168 status
= WERR_BADFILE
;
9172 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9174 r_u
->needed
= printerkey_len
*2;
9176 if ( q_u
->size
< r_u
->needed
) {
9177 status
= WERR_MORE_DATA
;
9181 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9182 status
= WERR_NOMEM
;
9188 if ( q_u
->size
< r_u
->needed
)
9189 status
= WERR_MORE_DATA
;
9192 free_a_printer( &printer
, 2 );
9193 SAFE_FREE( keynames
);
9198 /********************************************************************
9199 * spoolss_deleteprinterkey
9200 ********************************************************************/
9202 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9204 POLICY_HND
*handle
= &q_u
->handle
;
9205 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9207 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9211 DEBUG(5,("spoolss_deleteprinterkey\n"));
9214 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9218 /* if keyname == NULL, return error */
9220 if ( !q_u
->keyname
.buffer
)
9221 return WERR_INVALID_PARAM
;
9223 if (!get_printer_snum(p
, handle
, &snum
))
9226 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9227 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9228 return WERR_ACCESS_DENIED
;
9231 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9232 if (!W_ERROR_IS_OK(status
))
9235 /* delete the key and all subneys */
9237 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9239 status
= delete_all_printer_data( printer
->info_2
, key
);
9241 if ( W_ERROR_IS_OK(status
) )
9242 status
= mod_a_printer(printer
, 2);
9244 free_a_printer( &printer
, 2 );
9250 /********************************************************************
9251 * spoolss_enumprinterdataex
9252 ********************************************************************/
9254 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9256 POLICY_HND
*handle
= &q_u
->handle
;
9257 uint32 in_size
= q_u
->size
;
9260 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9261 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9262 NT_PRINTER_DATA
*p_data
;
9264 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9269 REGISTRY_VALUE
*val
;
9274 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9277 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9282 * first check for a keyname of NULL or "". Win2k seems to send
9283 * this a lot and we should send back WERR_INVALID_PARAM
9284 * no need to spend time looking up the printer in this case.
9288 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9289 if ( !strlen(key
) ) {
9290 result
= WERR_INVALID_PARAM
;
9294 /* get the printer off of disk */
9296 if (!get_printer_snum(p
,handle
, &snum
))
9299 ZERO_STRUCT(printer
);
9300 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9301 if (!W_ERROR_IS_OK(result
))
9304 /* now look for a match on the key name */
9306 p_data
= &printer
->info_2
->data
;
9308 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9309 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9311 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9312 result
= WERR_INVALID_PARAM
;
9319 /* allocate the memory for the array of pointers -- if necessary */
9321 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
9324 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9326 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9327 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9328 result
= WERR_NOMEM
;
9332 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9336 * loop through all params and build the array to pass
9337 * back to the client
9340 for ( i
=0; i
<num_entries
; i
++ )
9342 /* lookup the registry value */
9344 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
9345 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9349 value_name
= regval_name( val
);
9350 init_unistr( &enum_values
[i
].valuename
, value_name
);
9351 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9352 enum_values
[i
].type
= regval_type( val
);
9354 data_len
= regval_size( val
);
9356 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9358 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9360 result
= WERR_NOMEM
;
9364 enum_values
[i
].data_len
= data_len
;
9366 /* keep track of the size of the array in bytes */
9368 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9371 /* housekeeping information in the reply */
9373 r_u
->needed
= needed
;
9374 r_u
->returned
= num_entries
;
9376 if (needed
> in_size
) {
9377 result
= WERR_MORE_DATA
;
9381 /* copy data into the reply */
9383 r_u
->ctr
.size
= r_u
->needed
;
9384 r_u
->ctr
.size_of_array
= r_u
->returned
;
9385 r_u
->ctr
.values
= enum_values
;
9391 free_a_printer(&printer
, 2);
9396 /****************************************************************************
9397 ****************************************************************************/
9399 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9401 init_unistr(&info
->name
, name
);
9404 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9405 UNISTR2
*environment
,
9412 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9413 WERROR result
= WERR_OK
;
9415 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9417 if (!get_short_archi(long_archi
))
9418 return WERR_INVALID_ENVIRONMENT
;
9420 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9423 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9425 fill_printprocessordirectory_1(info
, path
);
9427 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9429 if (*needed
> offered
) {
9430 result
= WERR_INSUFFICIENT_BUFFER
;
9434 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9435 result
= WERR_INSUFFICIENT_BUFFER
;
9439 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9447 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9449 uint32 level
= q_u
->level
;
9450 RPC_BUFFER
*buffer
= NULL
;
9451 uint32 offered
= q_u
->offered
;
9452 uint32
*needed
= &r_u
->needed
;
9455 /* that's an [in out] buffer */
9457 if ( q_u
->buffer
) {
9458 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9459 buffer
= r_u
->buffer
;
9462 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9468 result
= getprintprocessordirectory_level_1
9469 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9472 result
= WERR_UNKNOWN_LEVEL
;
9480 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9481 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9483 DEBUG(5,("_spoolss_replyopenprinter\n"));
9485 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9490 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9491 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9493 DEBUG(5,("_spoolss_replycloseprinter\n"));