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-2003,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os
[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver
)
53 if (ver
< 0 || ver
> 3)
55 return drv_ver_to_os
[ver
];
59 const char *long_archi
;
60 const char *short_archi
;
64 static Printer_entry
*printers_list
;
66 typedef struct _counter_printer_0
{
74 static ubi_dlList counter_list
;
76 static struct cli_state notify_cli
; /* print notify back-channel */
77 static uint32 smb_connections
=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v
)
94 return JOB_STATUS_PAUSED
;
96 return JOB_STATUS_SPOOLING
;
98 return JOB_STATUS_PRINTING
;
100 return JOB_STATUS_ERROR
;
102 return JOB_STATUS_DELETING
;
104 return JOB_STATUS_OFFLINE
;
106 return JOB_STATUS_PAPEROUT
;
108 return JOB_STATUS_PRINTED
;
110 return JOB_STATUS_DELETED
;
112 return JOB_STATUS_BLOCKED
;
113 case LPQ_USER_INTERVENTION
:
114 return JOB_STATUS_USER_INTERVENTION
;
119 static int nt_printq_status(int v
)
123 return PRINTER_STATUS_PAUSED
;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
141 SAFE_FREE((*pp
)->ctr
.type
);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum
))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections
==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
169 if (!W_ERROR_IS_OK(result
))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result
)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections
==1) {
175 cli_nt_session_close(¬ify_cli
);
176 cli_ulogoff(¬ify_cli
);
177 cli_shutdown(¬ify_cli
);
178 message_deregister(MSG_PRINTER_NOTIFY2
);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False
, FLAG_MSG_PRINTING
);
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr
)
195 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
197 if (Printer
->notify
.client_connected
==True
) {
200 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
202 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
203 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
204 snum
= print_queue_snum(Printer
->dev
.handlename
);
206 srv_spoolss_replycloseprinter(snum
,
207 &Printer
->notify
.client_hnd
);
211 Printer
->notify
.flags
=0;
212 Printer
->notify
.options
=0;
213 Printer
->notify
.localmachine
[0]='\0';
214 Printer
->notify
.printerlocal
=0;
215 free_spool_notify_option(&Printer
->notify
.option
);
216 Printer
->notify
.option
=NULL
;
217 Printer
->notify
.client_connected
=False
;
219 free_nt_devicemode( &Printer
->nt_devmode
);
220 free_a_printer( &Printer
->printer_info
, 2 );
222 talloc_destroy( Printer
->ctx
);
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list
, Printer
);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
236 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
241 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
248 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
250 if (!new_sp
->ctr
.type
) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
265 Printer_entry
*find_printer
= NULL
;
267 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR
find_printer_in_print_hnd_cache( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
**info2
,
280 const char *printername
)
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername
));
286 for ( p
=printers_list
; p
; p
=p
->next
)
288 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
290 && StrCaseCmp(p
->dev
.handlename
, printername
) == 0 )
292 DEBUG(10,("Found printer\n"));
293 *info2
= dup_printer_2( ctx
, p
->printer_info
->info_2
);
299 return WERR_INVALID_PRINTER_NAME
;
302 /****************************************************************************
303 destroy any cached printer_info_2 structures on open handles
304 ****************************************************************************/
306 void invalidate_printer_hnd_cache( char *printername
)
310 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername
));
312 for ( p
=printers_list
; p
; p
=p
->next
)
314 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
315 && StrCaseCmp(p
->dev
.handlename
, printername
)==0)
317 DEBUG(10,("invalidating printer_info cache for handl:\n"));
318 free_a_printer( &p
->printer_info
, 2 );
319 p
->printer_info
= NULL
;
325 /****************************************************************************
326 Close printer index by handle.
327 ****************************************************************************/
329 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
331 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
334 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
338 close_policy_hnd(p
, hnd
);
343 /****************************************************************************
344 Delete a printer given a handle.
345 ****************************************************************************/
347 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
349 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
352 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
357 * It turns out that Windows allows delete printer on a handle
358 * opened by an admin user, then used on a pipe handle created
359 * by an anonymous user..... but they're working on security.... riiight !
363 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
364 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
365 return WERR_ACCESS_DENIED
;
369 /* Check calling user has permission to delete printer. Note that
370 since we set the snum parameter to -1 only administrators can
371 delete the printer. This stops people with the Full Control
372 permission from deleting the printer. */
374 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
375 DEBUG(3, ("printer delete denied by security descriptor\n"));
376 return WERR_ACCESS_DENIED
;
380 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
381 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
385 if (*lp_deleteprinter_cmd()) {
387 char *cmd
= lp_deleteprinter_cmd();
391 /* Printer->dev.handlename equals portname equals sharename */
392 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
393 Printer
->dev
.handlename
);
395 DEBUG(10,("Running [%s]\n", command
));
396 ret
= smbrun(command
, NULL
);
398 return WERR_BADFID
; /* What to return here? */
400 DEBUGADD(10,("returned [%d]\n", ret
));
402 /* Send SIGHUP to process group... is there a better way? */
405 /* go ahead and re-read the services immediately */
406 reload_services( False
);
408 if ( lp_servicenumber( Printer
->dev
.handlename
) < 0 )
409 return WERR_ACCESS_DENIED
;
415 /****************************************************************************
416 Return the snum of a printer corresponding to an handle.
417 ****************************************************************************/
419 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
421 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
424 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
428 switch (Printer
->printer_type
) {
429 case PRINTER_HANDLE_IS_PRINTER
:
430 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
431 *number
= print_queue_snum(Printer
->dev
.handlename
);
432 return (*number
!= -1);
433 case PRINTER_HANDLE_IS_PRINTSERVER
:
440 /****************************************************************************
441 Set printer handle type.
442 Check if it's \\server or \\server\printer
443 ****************************************************************************/
445 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
447 DEBUG(3,("Setting printer type=%s\n", handlename
));
449 if ( strlen(handlename
) < 3 ) {
450 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
454 /* it's a print server */
455 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
456 DEBUGADD(4,("Printer is a print server\n"));
457 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
461 DEBUGADD(4,("Printer is a printer\n"));
462 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
468 /****************************************************************************
469 Set printer handle name.
470 ****************************************************************************/
472 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
475 int n_services
=lp_numservices();
480 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
482 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
483 ZERO_STRUCT(Printer
->dev
.printerservername
);
484 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
488 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
491 if (*handlename
=='\\') {
492 aprinter
=strchr_m(handlename
+2, '\\');
499 DEBUGADD(5,("searching for [%s] (len=%lu)\n", aprinter
, (unsigned long)strlen(aprinter
)));
502 * The original code allowed smbd to store a printer name that
503 * was different from the share name. This is not possible
504 * anymore, so I've simplified this loop greatly. Here
505 * we are just verifying that the printer name is a valid
506 * printer service defined in smb.conf
507 * --jerry [Fri Feb 15 11:17:46 CST 2002]
510 for (snum
=0; snum
<n_services
; snum
++) {
512 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
515 fstrcpy(sname
, lp_servicename(snum
));
517 DEBUGADD(5,("share:%s\n",sname
));
519 if (! StrCaseCmp(sname
, aprinter
)) {
528 DEBUGADD(4,("Printer not found\n"));
532 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
534 ZERO_STRUCT(Printer
->dev
.handlename
);
535 fstrcpy(Printer
->dev
.handlename
, sname
);
540 /****************************************************************************
541 Find first available printer slot. creates a printer handle for you.
542 ****************************************************************************/
544 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
546 Printer_entry
*new_printer
;
548 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
550 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
553 ZERO_STRUCTP(new_printer
);
555 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
556 SAFE_FREE(new_printer
);
560 /* Add to the internal list. */
561 DLIST_ADD(printers_list
, new_printer
);
563 new_printer
->notify
.option
=NULL
;
565 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
566 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
567 close_printer_handle(p
, hnd
);
571 if (!set_printer_hnd_printertype(new_printer
, name
)) {
572 close_printer_handle(p
, hnd
);
576 if (!set_printer_hnd_name(new_printer
, name
)) {
577 close_printer_handle(p
, hnd
);
581 new_printer
->access_granted
= access_granted
;
583 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
588 /****************************************************************************
589 Allocate more memory for a BUFFER.
590 ****************************************************************************/
592 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
600 /* damn, I'm doing the reverse operation of prs_grow() :) */
601 if (buffer_size
< prs_data_size(ps
))
604 extra_space
= buffer_size
- prs_data_size(ps
);
607 * save the offset and move to the end of the buffer
608 * prs_grow() checks the extra_space against the offset
610 old_offset
=prs_offset(ps
);
611 prs_set_offset(ps
, prs_data_size(ps
));
613 if (!prs_grow(ps
, extra_space
))
616 prs_set_offset(ps
, old_offset
);
618 buffer
->string_at_end
=prs_data_size(ps
);
623 /***************************************************************************
624 check to see if the client motify handle is monitoring the notification
625 given by (notify_type, notify_field).
626 **************************************************************************/
628 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
634 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
637 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
641 * Flags should always be zero when the change notify
642 * is registered by the client's spooler. A user Win32 app
643 * might use the flags though instead of the NOTIFY_OPTION_INFO
648 return is_monitoring_event_flags(
649 p
->notify
.flags
, notify_type
, notify_field
);
651 for (i
= 0; i
< option
->count
; i
++) {
653 /* Check match for notify_type */
655 if (option
->ctr
.type
[i
].type
!= notify_type
)
658 /* Check match for field */
660 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
661 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
667 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
668 (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) ?
669 p
->dev
.handlename
: p
->dev
.printerservername
,
670 notify_type
, notify_field
));
675 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
677 static void notify_one_value(struct spoolss_notify_msg
*msg
,
678 SPOOL_NOTIFY_INFO_DATA
*data
,
681 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
682 data
->notify_data
.value
[1] = 0;
685 static void notify_string(struct spoolss_notify_msg
*msg
,
686 SPOOL_NOTIFY_INFO_DATA
*data
,
691 /* The length of the message includes the trailing \0 */
693 init_unistr2(&unistr
, msg
->notify
.data
, msg
->len
);
695 data
->notify_data
.data
.length
= msg
->len
* 2;
696 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
698 if (!data
->notify_data
.data
.string
) {
699 data
->notify_data
.data
.length
= 0;
703 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
706 static void notify_system_time(struct spoolss_notify_msg
*msg
,
707 SPOOL_NOTIFY_INFO_DATA
*data
,
713 if (msg
->len
!= sizeof(time_t)) {
714 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
719 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
720 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
724 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
725 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
729 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
732 data
->notify_data
.data
.length
= prs_offset(&ps
);
733 data
->notify_data
.data
.string
= talloc(mem_ctx
, prs_offset(&ps
));
735 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
740 struct notify2_message_table
{
742 void (*fn
)(struct spoolss_notify_msg
*msg
,
743 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
746 static struct notify2_message_table printer_notify_table
[] = {
747 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
748 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
749 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
750 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
751 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
752 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
753 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
754 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
755 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
756 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
757 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
758 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
759 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
760 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
761 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
762 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
763 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
764 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
765 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
768 static struct notify2_message_table job_notify_table
[] = {
769 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
770 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
771 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
772 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
773 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
774 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
775 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
776 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
777 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
778 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
779 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
780 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
781 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
782 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
783 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
784 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
785 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
786 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
787 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
788 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
789 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
790 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
791 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
792 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
796 /***********************************************************************
797 Allocate talloc context for container object
798 **********************************************************************/
800 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
805 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
810 /***********************************************************************
811 release all allocated memory and zero out structure
812 **********************************************************************/
814 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
820 talloc_destroy(ctr
->ctx
);
827 /***********************************************************************
828 **********************************************************************/
830 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
838 /***********************************************************************
839 **********************************************************************/
841 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
843 if ( !ctr
|| !ctr
->msg_groups
)
846 if ( idx
>= ctr
->num_groups
)
849 return &ctr
->msg_groups
[idx
];
853 /***********************************************************************
854 How many groups of change messages do we have ?
855 **********************************************************************/
857 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
862 return ctr
->num_groups
;
865 /***********************************************************************
866 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
867 **********************************************************************/
869 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
871 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
872 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
873 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
879 /* loop over all groups looking for a matching printer name */
881 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
882 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
886 /* add a new group? */
888 if ( i
== ctr
->num_groups
) {
891 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
892 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
895 ctr
->msg_groups
= groups
;
897 /* clear the new entry and set the printer name */
899 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
900 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
903 /* add the change messages; 'i' is the correct index now regardless */
905 msg_grp
= &ctr
->msg_groups
[i
];
909 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
910 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
913 msg_grp
->msgs
= msg_list
;
915 new_slot
= msg_grp
->num_msgs
-1;
916 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
918 /* need to allocate own copy of data */
921 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
923 return ctr
->num_groups
;
926 /***********************************************************************
927 Send a change notication message on all handles which have a call
929 **********************************************************************/
931 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
934 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
935 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
936 SPOOLSS_NOTIFY_MSG
*messages
;
937 int sending_msg_count
;
940 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
944 messages
= msg_group
->msgs
;
947 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
951 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
953 /* loop over all printers */
955 for (p
= printers_list
; p
; p
= p
->next
) {
956 SPOOL_NOTIFY_INFO_DATA
*data
;
961 /* Is there notification on this handle? */
963 if ( !p
->notify
.client_connected
)
966 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
968 /* For this printer? Print servers always receive
971 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
972 ( !strequal(msg_group
->printername
, p
->dev
.handlename
) ) )
975 DEBUG(10,("Our printer\n"));
977 /* allocate the max entries possible */
979 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
982 /* build the array of change notifications */
984 sending_msg_count
= 0;
986 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
987 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
989 /* Are we monitoring this event? */
991 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
997 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
998 msg
->type
, msg
->field
, p
->dev
.handlename
));
1001 * if the is a printer notification handle and not a job notification
1002 * type, then set the id to 0. Other wise just use what was specified
1005 * When registering change notification on a print server handle
1006 * we always need to send back the id (snum) matching the printer
1007 * for which the change took place. For change notify registered
1008 * on a printer handle, this does not matter and the id should be 0.
1013 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1019 /* Convert unix jobid to smb jobid */
1021 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1022 id
= sysjob_to_jobid(msg
->id
);
1025 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1030 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1033 case PRINTER_NOTIFY_TYPE
:
1034 if ( printer_notify_table
[msg
->field
].fn
)
1035 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1038 case JOB_NOTIFY_TYPE
:
1039 if ( job_notify_table
[msg
->field
].fn
)
1040 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1044 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1051 if ( sending_msg_count
) {
1052 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1053 data_len
, data
, p
->notify
.change
, 0 );
1058 DEBUG(8,("send_notify2_changes: Exit...\n"));
1062 /***********************************************************************
1063 **********************************************************************/
1065 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1068 uint32 tv_sec
, tv_usec
;
1071 /* Unpack message */
1073 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1076 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1078 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1081 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1082 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1084 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1085 &msg
->len
, &msg
->notify
.data
);
1087 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1088 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1090 tv
->tv_sec
= tv_sec
;
1091 tv
->tv_usec
= tv_usec
;
1094 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1095 msg
->notify
.value
[1]));
1097 dump_data(3, msg
->notify
.data
, msg
->len
);
1102 /* ENUMJOB last timestamp list. */
1104 struct ejts_list
*next
, *prev
;
1109 static struct ejts_list
*ejts_head
;
1111 static struct ejts_list
*find_enumjobs_timestamp(const char *printer_name
)
1113 struct ejts_list
*ejtsl
;
1115 for( ejtsl
= ejts_head
; ejtsl
; ejtsl
= ejtsl
->next
)
1116 if (strequal(ejtsl
->printer_name
, printer_name
))
1121 static void set_enumjobs_timestamp(int snum
)
1123 const char *printer_name
= lp_const_servicename(snum
);
1124 struct ejts_list
*ejtsl
= find_enumjobs_timestamp(printer_name
);
1127 ejtsl
= (struct ejts_list
*)malloc(sizeof(struct ejts_list
));
1130 ejtsl
->printer_name
= strdup(printer_name
);
1131 if (!ejtsl
->printer_name
) {
1135 DLIST_ADD(ejts_head
, ejtsl
);
1138 gettimeofday(&ejtsl
->tv
, NULL
);
1141 static int timeval_diff(struct timeval
*tv1
, struct timeval
*tv2
)
1143 if (tv1
->tv_sec
> tv2
->tv_sec
)
1145 if (tv1
->tv_sec
< tv2
->tv_sec
)
1147 if (tv1
->tv_usec
> tv2
->tv_usec
)
1149 if (tv1
->tv_usec
< tv2
->tv_usec
)
1154 /********************************************************************
1155 Receive a notify2 message list
1156 ********************************************************************/
1158 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1160 size_t msg_count
, i
;
1161 char *buf
= (char *)msg
;
1164 SPOOLSS_NOTIFY_MSG notify
;
1165 SPOOLSS_NOTIFY_MSG_CTR messages
;
1169 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1173 msg_count
= IVAL(buf
, 0);
1176 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1178 if (msg_count
== 0) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1183 /* initialize the container */
1185 ZERO_STRUCT( messages
);
1186 notify_msg_ctr_init( &messages
);
1189 * build message groups for each printer identified
1190 * in a change_notify msg. Remember that a PCN message
1191 * includes the handle returned for the srv_spoolss_replyopenprinter()
1192 * call. Therefore messages are grouped according to printer handle.
1195 for ( i
=0; i
<msg_count
; i
++ ) {
1196 struct timeval msg_tv
;
1198 if (msg_ptr
+ 4 - buf
> len
) {
1199 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1203 msg_len
= IVAL(msg_ptr
,0);
1206 if (msg_ptr
+ msg_len
- buf
> len
) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1211 /* unpack messages */
1213 ZERO_STRUCT( notify
);
1214 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1217 /* See if it is still relevent. */
1218 if (notify
.type
== JOB_NOTIFY_TYPE
) {
1219 BOOL status_is_deleting
= False
;
1221 if (notify
.field
== JOB_NOTIFY_STATUS
&& (notify
.notify
.value
[0] & (JOB_STATUS_DELETING
|JOB_STATUS_DELETED
)))
1222 status_is_deleting
= True
;
1224 if (!status_is_deleting
) {
1225 struct ejts_list
*ejtsl
= find_enumjobs_timestamp(notify
.printer
);
1227 if (ejtsl
&& (timeval_diff(&ejtsl
->tv
, &msg_tv
) > 0)) {
1229 DEBUG(10, ("receive_notify2_message_list: enumjobs ts = %u, %u, msg ts = %u, %u discarding\n",
1230 (unsigned int)ejtsl
->tv
.tv_sec
, (unsigned int)ejtsl
->tv
.tv_usec
,
1231 (unsigned int)msg_tv
.tv_sec
, (unsigned int)msg_tv
.tv_usec
));
1233 /* Message no longer relevent. Ignore it. */
1234 if ( notify
.len
!= 0 )
1235 SAFE_FREE( notify
.notify
.data
);
1240 /* add to correct list in container */
1242 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1244 /* free memory that might have been allocated by notify2_unpack_msg() */
1246 if ( notify
.len
!= 0 )
1247 SAFE_FREE( notify
.notify
.data
);
1250 /* process each group of messages */
1252 num_groups
= notify_msg_ctr_numgroups( &messages
);
1253 for ( i
=0; i
<num_groups
; i
++ )
1254 send_notify2_changes( &messages
, i
);
1259 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1261 notify_msg_ctr_destroy( &messages
);
1266 /********************************************************************
1267 Send a message to ourself about new driver being installed
1268 so we can upgrade the information for each printer bound to this
1270 ********************************************************************/
1272 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1274 int len
= strlen(drivername
);
1279 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1282 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1287 /**********************************************************************
1288 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1289 over all printers, upgrading ones as necessary
1290 **********************************************************************/
1292 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1296 int n_services
= lp_numservices();
1298 len
= MIN(len
,sizeof(drivername
)-1);
1299 strncpy(drivername
, buf
, len
);
1301 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1303 /* Iterate the printer list */
1305 for (snum
=0; snum
<n_services
; snum
++)
1307 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1310 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1312 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1313 if (!W_ERROR_IS_OK(result
))
1316 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1318 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1320 /* all we care about currently is the change_id */
1322 result
= mod_a_printer(*printer
, 2);
1323 if (!W_ERROR_IS_OK(result
)) {
1324 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1325 dos_errstr(result
)));
1329 free_a_printer(&printer
, 2);
1336 /********************************************************************
1337 Update the cache for all printq's with a registered client
1339 ********************************************************************/
1341 void update_monitored_printq_cache( void )
1343 Printer_entry
*printer
= printers_list
;
1346 /* loop through all printers and update the cache where
1347 client_connected == True */
1350 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1351 && printer
->notify
.client_connected
)
1353 snum
= print_queue_snum(printer
->dev
.handlename
);
1354 print_queue_status( snum
, NULL
, NULL
);
1357 printer
= printer
->next
;
1362 /********************************************************************
1363 Send a message to ourself about new driver being installed
1364 so we can upgrade the information for each printer bound to this
1366 ********************************************************************/
1368 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1370 int len
= strlen(drivername
);
1375 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1378 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1383 /**********************************************************************
1384 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1385 over all printers, resetting printer data as neessary
1386 **********************************************************************/
1388 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1392 int n_services
= lp_numservices();
1394 len
= MIN( len
, sizeof(drivername
)-1 );
1395 strncpy( drivername
, buf
, len
);
1397 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1399 /* Iterate the printer list */
1401 for ( snum
=0; snum
<n_services
; snum
++ )
1403 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1406 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1408 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1409 if ( !W_ERROR_IS_OK(result
) )
1413 * if the printer is bound to the driver,
1414 * then reset to the new driver initdata
1417 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1419 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1421 if ( !set_driver_init(printer
, 2) ) {
1422 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1423 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1426 result
= mod_a_printer( *printer
, 2 );
1427 if ( !W_ERROR_IS_OK(result
) ) {
1428 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1429 get_dos_error_msg(result
)));
1433 free_a_printer( &printer
, 2 );
1442 /********************************************************************
1443 Copy routines used by convert_to_openprinterex()
1444 *******************************************************************/
1446 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1454 DEBUG (8,("dup_devmode\n"));
1456 /* bulk copy first */
1458 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1462 /* dup the pointer members separately */
1464 len
= unistrlen(devmode
->devicename
.buffer
);
1466 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1467 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1472 len
= unistrlen(devmode
->formname
.buffer
);
1474 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1475 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1479 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1484 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1486 if (!new_ctr
|| !ctr
)
1489 DEBUG(8,("copy_devmode_ctr\n"));
1491 new_ctr
->size
= ctr
->size
;
1492 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1494 if(ctr
->devmode_ptr
)
1495 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1498 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1500 if (!new_def
|| !def
)
1503 DEBUG(8,("copy_printer_defaults\n"));
1505 new_def
->datatype_ptr
= def
->datatype_ptr
;
1507 if (def
->datatype_ptr
)
1508 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1510 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1512 new_def
->access_required
= def
->access_required
;
1515 /********************************************************************
1516 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1517 * SPOOL_Q_OPEN_PRINTER_EX structure
1518 ********************************************************************/
1520 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1522 if (!q_u_ex
|| !q_u
)
1525 DEBUG(8,("convert_to_openprinterex\n"));
1527 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1529 if (q_u
->printername_ptr
)
1530 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1532 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1535 /********************************************************************
1536 * spoolss_open_printer
1538 * called from the spoolss dispatcher
1539 ********************************************************************/
1541 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1543 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1544 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1549 ZERO_STRUCT(q_u_ex
);
1550 ZERO_STRUCT(r_u_ex
);
1552 /* convert the OpenPrinter() call to OpenPrinterEx() */
1554 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1556 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1558 /* convert back to OpenPrinter() */
1560 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1565 /********************************************************************
1566 * spoolss_open_printer
1568 * If the openprinterex rpc call contains a devmode,
1569 * it's a per-user one. This per-user devmode is derivated
1570 * from the global devmode. Openprinterex() contains a per-user
1571 * devmode for when you do EMF printing and spooling.
1572 * In the EMF case, the NT workstation is only doing half the job
1573 * of rendering the page. The other half is done by running the printer
1574 * driver on the server.
1575 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1576 * The EMF file only contains what is to be printed on the page.
1577 * So in order for the server to know how to print, the NT client sends
1578 * a devicemode attached to the openprinterex call.
1579 * But this devicemode is short lived, it's only valid for the current print job.
1581 * If Samba would have supported EMF spooling, this devicemode would
1582 * have been attached to the handle, to sent it to the driver to correctly
1583 * rasterize the EMF file.
1585 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1586 * we just act as a pass-thru between windows and the printer.
1588 * In order to know that Samba supports only RAW spooling, NT has to call
1589 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1590 * and until NT sends a RAW job, we refuse it.
1592 * But to call getprinter() or startdoc(), you first need a valid handle,
1593 * and to get an handle you have to call openprintex(). Hence why you have
1594 * a devicemode in the openprinterex() call.
1597 * Differences between NT4 and NT 2000.
1600 * On NT4, you only have a global devicemode. This global devicemode can be changed
1601 * by the administrator (or by a user with enough privs). Everytime a user
1602 * wants to print, the devicemode is resetted to the default. In Word, everytime
1603 * you print, the printer's characteristics are always reset to the global devicemode.
1607 * In W2K, there is the notion of per-user devicemode. The first time you use
1608 * a printer, a per-user devicemode is build from the global devicemode.
1609 * If you change your per-user devicemode, it is saved in the registry, under the
1610 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1611 * printer preferences available.
1613 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1614 * on the General Tab of the printer properties windows.
1616 * To change the global devicemode: it's the "Printing Defaults..." button
1617 * on the Advanced Tab of the printer properties window.
1620 ********************************************************************/
1622 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1624 UNISTR2
*printername
= NULL
;
1625 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1626 POLICY_HND
*handle
= &r_u
->handle
;
1630 struct current_user user
;
1631 Printer_entry
*Printer
=NULL
;
1633 if (q_u
->printername_ptr
!= 0)
1634 printername
= &q_u
->printername
;
1636 if (printername
== NULL
)
1637 return WERR_INVALID_PRINTER_NAME
;
1639 /* some sanity check because you can open a printer or a print server */
1640 /* aka: \\server\printer or \\server */
1641 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1643 DEBUGADD(3,("checking name: %s\n",name
));
1645 if (!open_printer_hnd(p
, handle
, name
, 0))
1646 return WERR_INVALID_PRINTER_NAME
;
1648 Printer
=find_printer_index_by_hnd(p
, handle
);
1650 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1651 Can't find printer handle we created for printer %s\n", name
));
1652 close_printer_handle(p
,handle
);
1653 return WERR_INVALID_PRINTER_NAME
;
1656 get_current_user(&user
, p
);
1659 * First case: the user is opening the print server:
1661 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1662 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1664 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1665 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1666 * or if the user is listed in the smb.conf printer admin parameter.
1668 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1669 * client view printer folder, but does not show the MSAPW.
1671 * Note: this test needs code to check access rights here too. Jeremy
1672 * could you look at this?
1674 * Second case: the user is opening a printer:
1675 * NT doesn't let us connect to a printer if the connecting user
1676 * doesn't have print permission.
1679 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1681 /* Printserver handles use global struct... */
1685 /* Map standard access rights to object specific access rights */
1687 se_map_standard(&printer_default
->access_required
,
1688 &printserver_std_mapping
);
1690 /* Deny any object specific bits that don't apply to print
1691 servers (i.e printer and job specific bits) */
1693 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1695 if (printer_default
->access_required
&
1696 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1697 DEBUG(3, ("access DENIED for non-printserver bits"));
1698 close_printer_handle(p
, handle
);
1699 return WERR_ACCESS_DENIED
;
1702 /* Allow admin access */
1704 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1706 if (!lp_ms_add_printer_wizard()) {
1707 close_printer_handle(p
, handle
);
1708 return WERR_ACCESS_DENIED
;
1711 /* if the user is not root and not a printer admin, then fail */
1714 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1716 close_printer_handle(p
, handle
);
1717 return WERR_ACCESS_DENIED
;
1720 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1724 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1727 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1728 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1730 /* We fall through to return WERR_OK */
1735 /* NT doesn't let us connect to a printer if the connecting user
1736 doesn't have print permission. */
1738 if (!get_printer_snum(p
, handle
, &snum
)) {
1739 close_printer_handle(p
, handle
);
1743 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1745 /* map an empty access mask to the minimum access mask */
1746 if (printer_default
->access_required
== 0x0)
1747 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1750 * If we are not serving the printer driver for this printer,
1751 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1752 * will keep NT clients happy --jerry
1755 if (lp_use_client_driver(snum
)
1756 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1758 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1761 /* check smb.conf parameters and the the sec_desc */
1763 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1764 DEBUG(3, ("access DENIED for printer open\n"));
1765 close_printer_handle(p
, handle
);
1766 return WERR_ACCESS_DENIED
;
1769 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1770 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1771 close_printer_handle(p
, handle
);
1772 return WERR_ACCESS_DENIED
;
1775 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1776 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1778 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1780 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1781 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1785 Printer
->access_granted
= printer_default
->access_required
;
1788 * If the client sent a devmode in the OpenPrinter() call, then
1789 * save it here in case we get a job submission on this handle
1792 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1793 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1795 convert_devicemode( Printer
->dev
.handlename
, q_u
->printer_default
.devmode_cont
.devmode
,
1796 &Printer
->nt_devmode
);
1799 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1800 optimization in Windows 2000 clients --jerry */
1802 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1803 && (RA_WIN2K
== get_remote_arch()) )
1805 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1812 /****************************************************************************
1813 ****************************************************************************/
1815 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1816 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1822 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1831 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1832 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1838 printer
->info_3
=NULL
;
1839 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1843 printer
->info_6
=NULL
;
1844 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1854 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1855 NT_DEVICEMODE
**pp_nt_devmode
)
1857 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1860 * Ensure nt_devmode is a valid pointer
1861 * as we will be overwriting it.
1864 if (nt_devmode
== NULL
) {
1865 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1866 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1870 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1871 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1873 nt_devmode
->specversion
=devmode
->specversion
;
1874 nt_devmode
->driverversion
=devmode
->driverversion
;
1875 nt_devmode
->size
=devmode
->size
;
1876 nt_devmode
->fields
=devmode
->fields
;
1877 nt_devmode
->orientation
=devmode
->orientation
;
1878 nt_devmode
->papersize
=devmode
->papersize
;
1879 nt_devmode
->paperlength
=devmode
->paperlength
;
1880 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1881 nt_devmode
->scale
=devmode
->scale
;
1882 nt_devmode
->copies
=devmode
->copies
;
1883 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1884 nt_devmode
->printquality
=devmode
->printquality
;
1885 nt_devmode
->color
=devmode
->color
;
1886 nt_devmode
->duplex
=devmode
->duplex
;
1887 nt_devmode
->yresolution
=devmode
->yresolution
;
1888 nt_devmode
->ttoption
=devmode
->ttoption
;
1889 nt_devmode
->collate
=devmode
->collate
;
1891 nt_devmode
->logpixels
=devmode
->logpixels
;
1892 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1893 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1894 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1895 nt_devmode
->displayflags
=devmode
->displayflags
;
1896 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1897 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1898 nt_devmode
->icmintent
=devmode
->icmintent
;
1899 nt_devmode
->mediatype
=devmode
->mediatype
;
1900 nt_devmode
->dithertype
=devmode
->dithertype
;
1901 nt_devmode
->reserved1
=devmode
->reserved1
;
1902 nt_devmode
->reserved2
=devmode
->reserved2
;
1903 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1904 nt_devmode
->panningheight
=devmode
->panningheight
;
1907 * Only change private and driverextra if the incoming devmode
1908 * has a new one. JRA.
1911 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1912 SAFE_FREE(nt_devmode
->private);
1913 nt_devmode
->driverextra
=devmode
->driverextra
;
1914 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1916 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1919 *pp_nt_devmode
= nt_devmode
;
1924 /********************************************************************
1925 * _spoolss_enddocprinter_internal.
1926 ********************************************************************/
1928 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1930 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1934 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1938 if (!get_printer_snum(p
, handle
, &snum
))
1941 Printer
->document_started
=False
;
1942 print_job_end(snum
, Printer
->jobid
,True
);
1943 /* error codes unhandled so far ... */
1948 /********************************************************************
1949 * api_spoolss_closeprinter
1950 ********************************************************************/
1952 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1954 POLICY_HND
*handle
= &q_u
->handle
;
1956 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1958 if (Printer
&& Printer
->document_started
)
1959 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1961 if (!close_printer_handle(p
, handle
))
1964 /* clear the returned printer handle. Observed behavior
1965 from Win2k server. Don't think this really matters.
1966 Previous code just copied the value of the closed
1969 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1974 /********************************************************************
1975 * api_spoolss_deleteprinter
1977 ********************************************************************/
1979 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1981 POLICY_HND
*handle
= &q_u
->handle
;
1982 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1985 if (Printer
&& Printer
->document_started
)
1986 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1988 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1990 result
= delete_printer_handle(p
, handle
);
1992 update_c_setprinter(False
);
1997 /*******************************************************************
1998 * static function to lookup the version id corresponding to an
1999 * long architecture string
2000 ******************************************************************/
2002 static int get_version_id (char * arch
)
2005 struct table_node archi_table
[]= {
2007 {"Windows 4.0", "WIN40", 0 },
2008 {"Windows NT x86", "W32X86", 2 },
2009 {"Windows NT R4000", "W32MIPS", 2 },
2010 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
2011 {"Windows NT PowerPC", "W32PPC", 2 },
2015 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2017 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2018 return (archi_table
[i
].version
);
2024 /********************************************************************
2025 * _spoolss_deleteprinterdriver
2026 ********************************************************************/
2028 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
2032 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2033 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2035 struct current_user user
;
2037 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2039 get_current_user(&user
, p
);
2041 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2042 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2044 /* check that we have a valid driver name first */
2046 if ((version
=get_version_id(arch
)) == -1)
2047 return WERR_INVALID_ENVIRONMENT
;
2050 ZERO_STRUCT(info_win2k
);
2052 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2054 /* try for Win2k driver if "Windows NT x86" */
2056 if ( version
== 2 ) {
2058 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2059 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2063 /* otherwise it was a failure */
2065 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2071 if (printer_driver_in_use(info
.info_3
)) {
2072 status
= WERR_PRINTER_DRIVER_IN_USE
;
2078 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2080 /* if we get to here, we now have 2 driver info structures to remove */
2081 /* remove the Win2k driver first*/
2083 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2084 free_a_printer_driver( info_win2k
, 3 );
2086 /* this should not have failed---if it did, report to client */
2087 if ( !W_ERROR_IS_OK(status_win2k
) )
2092 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2094 /* if at least one of the deletes succeeded return OK */
2096 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2100 free_a_printer_driver( info
, 3 );
2105 /********************************************************************
2106 * spoolss_deleteprinterdriverex
2107 ********************************************************************/
2109 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2113 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2114 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2116 uint32 flags
= q_u
->delete_flags
;
2118 struct current_user user
;
2120 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2122 get_current_user(&user
, p
);
2124 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2125 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2127 /* check that we have a valid driver name first */
2128 if ((version
=get_version_id(arch
)) == -1) {
2129 /* this is what NT returns */
2130 return WERR_INVALID_ENVIRONMENT
;
2133 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2134 version
= q_u
->version
;
2137 ZERO_STRUCT(info_win2k
);
2139 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2141 if ( !W_ERROR_IS_OK(status
) )
2144 * if the client asked for a specific version,
2145 * or this is something other than Windows NT x86,
2149 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2152 /* try for Win2k driver if "Windows NT x86" */
2155 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2156 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2161 if ( printer_driver_in_use(info
.info_3
) ) {
2162 status
= WERR_PRINTER_DRIVER_IN_USE
;
2167 * we have a couple of cases to consider.
2168 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2169 * then the delete should fail if **any** files overlap with
2171 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2172 * non-overlapping files
2173 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2174 * is set, the do not delete any files
2175 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2178 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2180 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2182 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2183 /* no idea of the correct error here */
2184 status
= WERR_ACCESS_DENIED
;
2189 /* also check for W32X86/3 if necessary; maybe we already have? */
2191 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2192 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2195 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2196 /* no idea of the correct error here */
2197 free_a_printer_driver( info_win2k
, 3 );
2198 status
= WERR_ACCESS_DENIED
;
2202 /* if we get to here, we now have 2 driver info structures to remove */
2203 /* remove the Win2k driver first*/
2205 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2206 free_a_printer_driver( info_win2k
, 3 );
2208 /* this should not have failed---if it did, report to client */
2210 if ( !W_ERROR_IS_OK(status_win2k
) )
2215 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2217 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2220 free_a_printer_driver( info
, 3 );
2226 /****************************************************************************
2227 Internal routine for retreiving printerdata
2228 ***************************************************************************/
2230 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2231 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2232 uint32
*needed
, uint32 in_size
)
2234 REGISTRY_VALUE
*val
;
2237 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2238 return WERR_BADFILE
;
2240 *type
= regval_type( val
);
2242 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2244 size
= regval_size( val
);
2246 /* copy the min(in_size, len) */
2249 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2251 /* special case for 0 length values */
2253 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2257 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2266 DEBUG(5,("get_printer_dataex: copy done\n"));
2271 /****************************************************************************
2272 Internal routine for removing printerdata
2273 ***************************************************************************/
2275 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2277 return delete_printer_data( printer
->info_2
, key
, value
);
2280 /****************************************************************************
2281 Internal routine for storing printerdata
2282 ***************************************************************************/
2284 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2285 uint32 type
, uint8
*data
, int real_len
)
2287 delete_printer_data( printer
->info_2
, key
, value
);
2289 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2292 /********************************************************************
2293 GetPrinterData on a printer server Handle.
2294 ********************************************************************/
2296 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2300 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2302 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2304 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2310 if (!StrCaseCmp(value
, "BeepEnabled")) {
2312 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2314 SIVAL(*data
, 0, 0x00);
2319 if (!StrCaseCmp(value
, "EventLog")) {
2321 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2323 /* formally was 0x1b */
2324 SIVAL(*data
, 0, 0x0);
2329 if (!StrCaseCmp(value
, "NetPopup")) {
2331 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2333 SIVAL(*data
, 0, 0x00);
2338 if (!StrCaseCmp(value
, "MajorVersion")) {
2340 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2343 /* Windows NT 4.0 seems to not allow uploading of drivers
2344 to a server that reports 0x3 as the MajorVersion.
2345 need to investigate more how Win2k gets around this .
2348 if ( RA_WINNT
== get_remote_arch() )
2357 if (!StrCaseCmp(value
, "MinorVersion")) {
2359 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2367 * uint32 size = 0x114
2369 * uint32 minor = [0|1]
2370 * uint32 build = [2195|2600]
2371 * extra unicode string = e.g. "Service Pack 3"
2373 if (!StrCaseCmp(value
, "OSVersion")) {
2377 if((*data
= (uint8
*)talloc(ctx
, (*needed
)*sizeof(uint8
) )) == NULL
)
2379 ZERO_STRUCTP( *data
);
2381 SIVAL(*data
, 0, *needed
); /* size */
2382 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2384 SIVAL(*data
, 12, 2195); /* build */
2386 /* leave extra string empty */
2392 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2393 const char *string
="C:\\PRINTERS";
2395 *needed
= 2*(strlen(string
)+1);
2396 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2398 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2400 /* it's done by hand ready to go on the wire */
2401 for (i
=0; i
<strlen(string
); i
++) {
2402 (*data
)[2*i
]=string
[i
];
2403 (*data
)[2*i
+1]='\0';
2408 if (!StrCaseCmp(value
, "Architecture")) {
2409 const char *string
="Windows NT x86";
2411 *needed
= 2*(strlen(string
)+1);
2412 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2414 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2415 for (i
=0; i
<strlen(string
); i
++) {
2416 (*data
)[2*i
]=string
[i
];
2417 (*data
)[2*i
+1]='\0';
2422 if (!StrCaseCmp(value
, "DsPresent")) {
2424 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2426 SIVAL(*data
, 0, 0x01);
2431 if (!StrCaseCmp(value
, "DNSMachineName")) {
2434 if (!get_myfullname(hostname
))
2435 return WERR_BADFILE
;
2437 *needed
= 2*(strlen(hostname
)+1);
2438 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2440 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2441 for (i
=0; i
<strlen(hostname
); i
++) {
2442 (*data
)[2*i
]=hostname
[i
];
2443 (*data
)[2*i
+1]='\0';
2449 return WERR_BADFILE
;
2452 /********************************************************************
2453 * spoolss_getprinterdata
2454 ********************************************************************/
2456 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2458 POLICY_HND
*handle
= &q_u
->handle
;
2459 UNISTR2
*valuename
= &q_u
->valuename
;
2460 uint32 in_size
= q_u
->size
;
2461 uint32
*type
= &r_u
->type
;
2462 uint32
*out_size
= &r_u
->size
;
2463 uint8
**data
= &r_u
->data
;
2464 uint32
*needed
= &r_u
->needed
;
2467 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2468 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2472 * Reminder: when it's a string, the length is in BYTES
2473 * even if UNICODE is negociated.
2478 *out_size
= in_size
;
2480 /* in case of problem, return some default values */
2485 DEBUG(4,("_spoolss_getprinterdata\n"));
2488 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2489 status
= WERR_BADFID
;
2493 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2495 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2496 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2499 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2500 status
= WERR_BADFID
;
2504 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2505 if ( !W_ERROR_IS_OK(status
) )
2508 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2510 if ( strequal(value
, "ChangeId") ) {
2512 *needed
= sizeof(uint32
);
2513 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2514 status
= WERR_NOMEM
;
2517 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2521 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2524 if (*needed
> *out_size
)
2525 status
= WERR_MORE_DATA
;
2528 if ( !W_ERROR_IS_OK(status
) )
2530 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2532 /* reply this param doesn't exist */
2535 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2537 free_a_printer( &printer
, 2 );
2546 /* cleanup & exit */
2549 free_a_printer( &printer
, 2 );
2554 /*********************************************************
2555 Connect to the client machine.
2556 **********************************************************/
2558 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
,
2559 struct in_addr
*client_ip
, const char *remote_machine
)
2561 ZERO_STRUCTP(the_cli
);
2563 if(cli_initialise(the_cli
) == NULL
) {
2564 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2568 if ( is_zero_ip(*client_ip
) ) {
2569 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2570 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2571 cli_shutdown(the_cli
);
2575 if (ismyip(the_cli
->dest_ip
)) {
2576 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2577 cli_shutdown(the_cli
);
2582 the_cli
->dest_ip
.s_addr
= client_ip
->s_addr
;
2583 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2584 inet_ntoa(*client_ip
) ));
2587 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2588 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
) ));
2589 cli_shutdown(the_cli
);
2593 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2594 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2596 cli_shutdown(the_cli
);
2600 the_cli
->protocol
= PROTOCOL_NT1
;
2602 if (!cli_negprot(the_cli
)) {
2603 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2604 cli_shutdown(the_cli
);
2608 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2609 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2610 cli_shutdown(the_cli
);
2615 * Do an anonymous session setup.
2618 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2619 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2620 cli_shutdown(the_cli
);
2624 if (!(the_cli
->sec_mode
& 1)) {
2625 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2626 cli_shutdown(the_cli
);
2630 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2631 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
) ));
2632 cli_shutdown(the_cli
);
2637 * Ok - we have an anonymous connection to the IPC$ share.
2638 * Now start the NT Domain stuff :-).
2641 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2642 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
)));
2643 cli_nt_session_close(the_cli
);
2644 cli_ulogoff(the_cli
);
2645 cli_shutdown(the_cli
);
2652 /***************************************************************************
2653 Connect to the client.
2654 ****************************************************************************/
2656 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2657 uint32 localprinter
, uint32 type
,
2658 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2663 * If it's the first connection, contact the client
2664 * and connect to the IPC$ share anonymously
2666 if (smb_connections
==0) {
2667 fstring unix_printer
;
2669 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2671 if(!spoolss_connect_to_client(¬ify_cli
, client_ip
, unix_printer
))
2674 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2675 /* Tell the connections db we're now interested in printer
2676 * notify messages. */
2677 register_message_flags( True
, FLAG_MSG_PRINTING
);
2681 * Tell the specific printing tdb we want messages for this printer
2682 * by registering our PID.
2685 if (!print_notify_register_pid(snum
))
2686 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2690 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2693 if (!W_ERROR_IS_OK(result
))
2694 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2695 dos_errstr(result
)));
2697 return (W_ERROR_IS_OK(result
));
2700 /********************************************************************
2702 * ReplyFindFirstPrinterChangeNotifyEx
2704 * before replying OK: status=0 a rpc call is made to the workstation
2705 * asking ReplyOpenPrinter
2707 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2708 * called from api_spoolss_rffpcnex
2709 ********************************************************************/
2711 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2713 POLICY_HND
*handle
= &q_u
->handle
;
2714 uint32 flags
= q_u
->flags
;
2715 uint32 options
= q_u
->options
;
2716 UNISTR2
*localmachine
= &q_u
->localmachine
;
2717 uint32 printerlocal
= q_u
->printerlocal
;
2719 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2720 struct in_addr client_ip
;
2722 /* store the notify value in the printer struct */
2724 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2727 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2731 Printer
->notify
.flags
=flags
;
2732 Printer
->notify
.options
=options
;
2733 Printer
->notify
.printerlocal
=printerlocal
;
2735 if (Printer
->notify
.option
)
2736 free_spool_notify_option(&Printer
->notify
.option
);
2738 Printer
->notify
.option
=dup_spool_notify_option(option
);
2740 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2741 sizeof(Printer
->notify
.localmachine
)-1);
2743 /* Connect to the client machine and send a ReplyOpenPrinter */
2745 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2747 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2748 !get_printer_snum(p
, handle
, &snum
) )
2751 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2753 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2754 Printer
->notify
.printerlocal
, 1,
2755 &Printer
->notify
.client_hnd
, &client_ip
))
2756 return WERR_SERVER_UNAVAILABLE
;
2758 Printer
->notify
.client_connected
=True
;
2763 /*******************************************************************
2764 * fill a notify_info_data with the servername
2765 ********************************************************************/
2767 void spoolss_notify_server_name(int snum
,
2768 SPOOL_NOTIFY_INFO_DATA
*data
,
2769 print_queue_struct
*queue
,
2770 NT_PRINTER_INFO_LEVEL
*printer
,
2771 TALLOC_CTX
*mem_ctx
)
2773 pstring temp_name
, temp
;
2776 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2778 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2780 data
->notify_data
.data
.length
= len
;
2781 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2783 if (!data
->notify_data
.data
.string
) {
2784 data
->notify_data
.data
.length
= 0;
2788 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2791 /*******************************************************************
2792 * fill a notify_info_data with the printername (not including the servername).
2793 ********************************************************************/
2795 void spoolss_notify_printer_name(int snum
,
2796 SPOOL_NOTIFY_INFO_DATA
*data
,
2797 print_queue_struct
*queue
,
2798 NT_PRINTER_INFO_LEVEL
*printer
,
2799 TALLOC_CTX
*mem_ctx
)
2804 /* the notify name should not contain the \\server\ part */
2805 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2808 p
= printer
->info_2
->printername
;
2813 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2815 data
->notify_data
.data
.length
= len
;
2816 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2818 if (!data
->notify_data
.data
.string
) {
2819 data
->notify_data
.data
.length
= 0;
2823 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2826 /*******************************************************************
2827 * fill a notify_info_data with the servicename
2828 ********************************************************************/
2830 void spoolss_notify_share_name(int snum
,
2831 SPOOL_NOTIFY_INFO_DATA
*data
,
2832 print_queue_struct
*queue
,
2833 NT_PRINTER_INFO_LEVEL
*printer
,
2834 TALLOC_CTX
*mem_ctx
)
2839 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2841 data
->notify_data
.data
.length
= len
;
2842 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2844 if (!data
->notify_data
.data
.string
) {
2845 data
->notify_data
.data
.length
= 0;
2849 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2852 /*******************************************************************
2853 * fill a notify_info_data with the port name
2854 ********************************************************************/
2856 void spoolss_notify_port_name(int snum
,
2857 SPOOL_NOTIFY_INFO_DATA
*data
,
2858 print_queue_struct
*queue
,
2859 NT_PRINTER_INFO_LEVEL
*printer
,
2860 TALLOC_CTX
*mem_ctx
)
2865 /* even if it's strange, that's consistant in all the code */
2867 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2869 data
->notify_data
.data
.length
= len
;
2870 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2872 if (!data
->notify_data
.data
.string
) {
2873 data
->notify_data
.data
.length
= 0;
2877 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2880 /*******************************************************************
2881 * fill a notify_info_data with the printername
2882 * but it doesn't exist, have to see what to do
2883 ********************************************************************/
2885 void spoolss_notify_driver_name(int snum
,
2886 SPOOL_NOTIFY_INFO_DATA
*data
,
2887 print_queue_struct
*queue
,
2888 NT_PRINTER_INFO_LEVEL
*printer
,
2889 TALLOC_CTX
*mem_ctx
)
2894 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2896 data
->notify_data
.data
.length
= len
;
2897 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2899 if (!data
->notify_data
.data
.string
) {
2900 data
->notify_data
.data
.length
= 0;
2904 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2907 /*******************************************************************
2908 * fill a notify_info_data with the comment
2909 ********************************************************************/
2911 void spoolss_notify_comment(int snum
,
2912 SPOOL_NOTIFY_INFO_DATA
*data
,
2913 print_queue_struct
*queue
,
2914 NT_PRINTER_INFO_LEVEL
*printer
,
2915 TALLOC_CTX
*mem_ctx
)
2920 if (*printer
->info_2
->comment
== '\0')
2921 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2923 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2925 data
->notify_data
.data
.length
= len
;
2926 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2928 if (!data
->notify_data
.data
.string
) {
2929 data
->notify_data
.data
.length
= 0;
2933 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2936 /*******************************************************************
2937 * fill a notify_info_data with the comment
2938 * location = "Room 1, floor 2, building 3"
2939 ********************************************************************/
2941 void spoolss_notify_location(int snum
,
2942 SPOOL_NOTIFY_INFO_DATA
*data
,
2943 print_queue_struct
*queue
,
2944 NT_PRINTER_INFO_LEVEL
*printer
,
2945 TALLOC_CTX
*mem_ctx
)
2950 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2952 data
->notify_data
.data
.length
= len
;
2953 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2955 if (!data
->notify_data
.data
.string
) {
2956 data
->notify_data
.data
.length
= 0;
2960 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2963 /*******************************************************************
2964 * fill a notify_info_data with the device mode
2965 * jfm:xxxx don't to it for know but that's a real problem !!!
2966 ********************************************************************/
2968 static void spoolss_notify_devmode(int snum
,
2969 SPOOL_NOTIFY_INFO_DATA
*data
,
2970 print_queue_struct
*queue
,
2971 NT_PRINTER_INFO_LEVEL
*printer
,
2972 TALLOC_CTX
*mem_ctx
)
2976 /*******************************************************************
2977 * fill a notify_info_data with the separator file name
2978 ********************************************************************/
2980 void spoolss_notify_sepfile(int snum
,
2981 SPOOL_NOTIFY_INFO_DATA
*data
,
2982 print_queue_struct
*queue
,
2983 NT_PRINTER_INFO_LEVEL
*printer
,
2984 TALLOC_CTX
*mem_ctx
)
2989 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2991 data
->notify_data
.data
.length
= len
;
2992 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2994 if (!data
->notify_data
.data
.string
) {
2995 data
->notify_data
.data
.length
= 0;
2999 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3002 /*******************************************************************
3003 * fill a notify_info_data with the print processor
3004 * jfm:xxxx return always winprint to indicate we don't do anything to it
3005 ********************************************************************/
3007 void spoolss_notify_print_processor(int snum
,
3008 SPOOL_NOTIFY_INFO_DATA
*data
,
3009 print_queue_struct
*queue
,
3010 NT_PRINTER_INFO_LEVEL
*printer
,
3011 TALLOC_CTX
*mem_ctx
)
3016 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
3018 data
->notify_data
.data
.length
= len
;
3019 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3021 if (!data
->notify_data
.data
.string
) {
3022 data
->notify_data
.data
.length
= 0;
3026 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3029 /*******************************************************************
3030 * fill a notify_info_data with the print processor options
3031 * jfm:xxxx send an empty string
3032 ********************************************************************/
3034 void spoolss_notify_parameters(int snum
,
3035 SPOOL_NOTIFY_INFO_DATA
*data
,
3036 print_queue_struct
*queue
,
3037 NT_PRINTER_INFO_LEVEL
*printer
,
3038 TALLOC_CTX
*mem_ctx
)
3043 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
3045 data
->notify_data
.data
.length
= len
;
3046 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3048 if (!data
->notify_data
.data
.string
) {
3049 data
->notify_data
.data
.length
= 0;
3053 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3056 /*******************************************************************
3057 * fill a notify_info_data with the data type
3058 * jfm:xxxx always send RAW as data type
3059 ********************************************************************/
3061 void spoolss_notify_datatype(int snum
,
3062 SPOOL_NOTIFY_INFO_DATA
*data
,
3063 print_queue_struct
*queue
,
3064 NT_PRINTER_INFO_LEVEL
*printer
,
3065 TALLOC_CTX
*mem_ctx
)
3070 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3072 data
->notify_data
.data
.length
= len
;
3073 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3075 if (!data
->notify_data
.data
.string
) {
3076 data
->notify_data
.data
.length
= 0;
3080 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3083 /*******************************************************************
3084 * fill a notify_info_data with the security descriptor
3085 * jfm:xxxx send an null pointer to say no security desc
3086 * have to implement security before !
3087 ********************************************************************/
3089 static void spoolss_notify_security_desc(int snum
,
3090 SPOOL_NOTIFY_INFO_DATA
*data
,
3091 print_queue_struct
*queue
,
3092 NT_PRINTER_INFO_LEVEL
*printer
,
3093 TALLOC_CTX
*mem_ctx
)
3095 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3096 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3099 /*******************************************************************
3100 * fill a notify_info_data with the attributes
3101 * jfm:xxxx a samba printer is always shared
3102 ********************************************************************/
3104 void spoolss_notify_attributes(int snum
,
3105 SPOOL_NOTIFY_INFO_DATA
*data
,
3106 print_queue_struct
*queue
,
3107 NT_PRINTER_INFO_LEVEL
*printer
,
3108 TALLOC_CTX
*mem_ctx
)
3110 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3111 data
->notify_data
.value
[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the priority
3116 ********************************************************************/
3118 static void spoolss_notify_priority(int snum
,
3119 SPOOL_NOTIFY_INFO_DATA
*data
,
3120 print_queue_struct
*queue
,
3121 NT_PRINTER_INFO_LEVEL
*printer
,
3122 TALLOC_CTX
*mem_ctx
)
3124 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3125 data
->notify_data
.value
[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the default priority
3130 ********************************************************************/
3132 static void spoolss_notify_default_priority(int snum
,
3133 SPOOL_NOTIFY_INFO_DATA
*data
,
3134 print_queue_struct
*queue
,
3135 NT_PRINTER_INFO_LEVEL
*printer
,
3136 TALLOC_CTX
*mem_ctx
)
3138 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3139 data
->notify_data
.value
[1] = 0;
3142 /*******************************************************************
3143 * fill a notify_info_data with the start time
3144 ********************************************************************/
3146 static void spoolss_notify_start_time(int snum
,
3147 SPOOL_NOTIFY_INFO_DATA
*data
,
3148 print_queue_struct
*queue
,
3149 NT_PRINTER_INFO_LEVEL
*printer
,
3150 TALLOC_CTX
*mem_ctx
)
3152 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3153 data
->notify_data
.value
[1] = 0;
3156 /*******************************************************************
3157 * fill a notify_info_data with the until time
3158 ********************************************************************/
3160 static void spoolss_notify_until_time(int snum
,
3161 SPOOL_NOTIFY_INFO_DATA
*data
,
3162 print_queue_struct
*queue
,
3163 NT_PRINTER_INFO_LEVEL
*printer
,
3164 TALLOC_CTX
*mem_ctx
)
3166 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3167 data
->notify_data
.value
[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the status
3172 ********************************************************************/
3174 static void spoolss_notify_status(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 print_status_struct status
;
3182 print_queue_length(snum
, &status
);
3183 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3184 data
->notify_data
.value
[1] = 0;
3187 /*******************************************************************
3188 * fill a notify_info_data with the number of jobs queued
3189 ********************************************************************/
3191 void spoolss_notify_cjobs(int snum
,
3192 SPOOL_NOTIFY_INFO_DATA
*data
,
3193 print_queue_struct
*queue
,
3194 NT_PRINTER_INFO_LEVEL
*printer
,
3195 TALLOC_CTX
*mem_ctx
)
3197 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3198 data
->notify_data
.value
[1] = 0;
3201 /*******************************************************************
3202 * fill a notify_info_data with the average ppm
3203 ********************************************************************/
3205 static void spoolss_notify_average_ppm(int snum
,
3206 SPOOL_NOTIFY_INFO_DATA
*data
,
3207 print_queue_struct
*queue
,
3208 NT_PRINTER_INFO_LEVEL
*printer
,
3209 TALLOC_CTX
*mem_ctx
)
3211 /* always respond 8 pages per minutes */
3212 /* a little hard ! */
3213 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3214 data
->notify_data
.value
[1] = 0;
3217 /*******************************************************************
3218 * fill a notify_info_data with username
3219 ********************************************************************/
3221 static void spoolss_notify_username(int snum
,
3222 SPOOL_NOTIFY_INFO_DATA
*data
,
3223 print_queue_struct
*queue
,
3224 NT_PRINTER_INFO_LEVEL
*printer
,
3225 TALLOC_CTX
*mem_ctx
)
3230 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3232 data
->notify_data
.data
.length
= len
;
3233 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3235 if (!data
->notify_data
.data
.string
) {
3236 data
->notify_data
.data
.length
= 0;
3240 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3243 /*******************************************************************
3244 * fill a notify_info_data with job status
3245 ********************************************************************/
3247 static void spoolss_notify_job_status(int snum
,
3248 SPOOL_NOTIFY_INFO_DATA
*data
,
3249 print_queue_struct
*queue
,
3250 NT_PRINTER_INFO_LEVEL
*printer
,
3251 TALLOC_CTX
*mem_ctx
)
3253 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3254 data
->notify_data
.value
[1] = 0;
3257 /*******************************************************************
3258 * fill a notify_info_data with job name
3259 ********************************************************************/
3261 static void spoolss_notify_job_name(int snum
,
3262 SPOOL_NOTIFY_INFO_DATA
*data
,
3263 print_queue_struct
*queue
,
3264 NT_PRINTER_INFO_LEVEL
*printer
,
3265 TALLOC_CTX
*mem_ctx
)
3270 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3272 data
->notify_data
.data
.length
= len
;
3273 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3275 if (!data
->notify_data
.data
.string
) {
3276 data
->notify_data
.data
.length
= 0;
3280 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3283 /*******************************************************************
3284 * fill a notify_info_data with job status
3285 ********************************************************************/
3287 static void spoolss_notify_job_status_string(int snum
,
3288 SPOOL_NOTIFY_INFO_DATA
*data
,
3289 print_queue_struct
*queue
,
3290 NT_PRINTER_INFO_LEVEL
*printer
,
3291 TALLOC_CTX
*mem_ctx
)
3294 * Now we're returning job status codes we just return a "" here. JRA.
3301 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3304 switch (queue
->status
) {
3309 p
= ""; /* NT provides the paused string */
3318 #endif /* NO LONGER NEEDED. */
3320 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3322 data
->notify_data
.data
.length
= len
;
3323 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3325 if (!data
->notify_data
.data
.string
) {
3326 data
->notify_data
.data
.length
= 0;
3330 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3333 /*******************************************************************
3334 * fill a notify_info_data with job time
3335 ********************************************************************/
3337 static void spoolss_notify_job_time(int snum
,
3338 SPOOL_NOTIFY_INFO_DATA
*data
,
3339 print_queue_struct
*queue
,
3340 NT_PRINTER_INFO_LEVEL
*printer
,
3341 TALLOC_CTX
*mem_ctx
)
3343 data
->notify_data
.value
[0]=0x0;
3344 data
->notify_data
.value
[1]=0;
3347 /*******************************************************************
3348 * fill a notify_info_data with job size
3349 ********************************************************************/
3351 static void spoolss_notify_job_size(int snum
,
3352 SPOOL_NOTIFY_INFO_DATA
*data
,
3353 print_queue_struct
*queue
,
3354 NT_PRINTER_INFO_LEVEL
*printer
,
3355 TALLOC_CTX
*mem_ctx
)
3357 data
->notify_data
.value
[0]=queue
->size
;
3358 data
->notify_data
.value
[1]=0;
3361 /*******************************************************************
3362 * fill a notify_info_data with page info
3363 ********************************************************************/
3364 static void spoolss_notify_total_pages(int snum
,
3365 SPOOL_NOTIFY_INFO_DATA
*data
,
3366 print_queue_struct
*queue
,
3367 NT_PRINTER_INFO_LEVEL
*printer
,
3368 TALLOC_CTX
*mem_ctx
)
3370 data
->notify_data
.value
[0]=queue
->page_count
;
3371 data
->notify_data
.value
[1]=0;
3374 /*******************************************************************
3375 * fill a notify_info_data with pages printed info.
3376 ********************************************************************/
3377 static void spoolss_notify_pages_printed(int snum
,
3378 SPOOL_NOTIFY_INFO_DATA
*data
,
3379 print_queue_struct
*queue
,
3380 NT_PRINTER_INFO_LEVEL
*printer
,
3381 TALLOC_CTX
*mem_ctx
)
3383 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3384 data
->notify_data
.value
[1]=0;
3387 /*******************************************************************
3388 Fill a notify_info_data with job position.
3389 ********************************************************************/
3391 static void spoolss_notify_job_position(int snum
,
3392 SPOOL_NOTIFY_INFO_DATA
*data
,
3393 print_queue_struct
*queue
,
3394 NT_PRINTER_INFO_LEVEL
*printer
,
3395 TALLOC_CTX
*mem_ctx
)
3397 data
->notify_data
.value
[0]=queue
->job
;
3398 data
->notify_data
.value
[1]=0;
3401 /*******************************************************************
3402 Fill a notify_info_data with submitted time.
3403 ********************************************************************/
3405 static void spoolss_notify_submitted_time(int snum
,
3406 SPOOL_NOTIFY_INFO_DATA
*data
,
3407 print_queue_struct
*queue
,
3408 NT_PRINTER_INFO_LEVEL
*printer
,
3409 TALLOC_CTX
*mem_ctx
)
3416 t
=gmtime(&queue
->time
);
3418 len
= sizeof(SYSTEMTIME
);
3420 data
->notify_data
.data
.length
= len
;
3421 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3423 if (!data
->notify_data
.data
.string
) {
3424 data
->notify_data
.data
.length
= 0;
3428 make_systemtime(&st
, t
);
3431 * Systemtime must be linearized as a set of UINT16's.
3432 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3435 p
= (char *)data
->notify_data
.data
.string
;
3436 SSVAL(p
, 0, st
.year
);
3437 SSVAL(p
, 2, st
.month
);
3438 SSVAL(p
, 4, st
.dayofweek
);
3439 SSVAL(p
, 6, st
.day
);
3440 SSVAL(p
, 8, st
.hour
);
3441 SSVAL(p
, 10, st
.minute
);
3442 SSVAL(p
, 12, st
.second
);
3443 SSVAL(p
, 14, st
.milliseconds
);
3446 struct s_notify_info_data_table
3452 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3453 print_queue_struct
*queue
,
3454 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3457 /* A table describing the various print notification constants and
3458 whether the notification data is a pointer to a variable sized
3459 buffer, a one value uint32 or a two value uint32. */
3461 static const struct s_notify_info_data_table notify_info_data_table
[] =
3463 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3464 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3465 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3466 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3467 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3468 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3469 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3470 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3471 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3472 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3473 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3474 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3475 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3476 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3477 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3478 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3479 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3480 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3481 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3482 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3483 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3484 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3485 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3486 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3487 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3488 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3489 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3490 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3491 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3492 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3493 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3494 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3495 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3496 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3497 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3498 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3499 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3500 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3501 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3502 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3503 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3504 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3505 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3506 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3507 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3508 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3509 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3510 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3511 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3514 /*******************************************************************
3515 Return the size of info_data structure.
3516 ********************************************************************/
3518 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3522 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3524 if ( (notify_info_data_table
[i
].type
== type
)
3525 && (notify_info_data_table
[i
].field
== field
) )
3527 switch(notify_info_data_table
[i
].size
)
3529 case NOTIFY_ONE_VALUE
:
3530 case NOTIFY_TWO_VALUE
:
3535 /* The only pointer notify data I have seen on
3536 the wire is the submitted time and this has
3537 the notify size set to 4. -tpot */
3539 case NOTIFY_POINTER
:
3542 case NOTIFY_SECDESC
:
3548 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3553 /*******************************************************************
3554 Return the type of notify_info_data.
3555 ********************************************************************/
3557 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3561 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3562 if (notify_info_data_table
[i
].type
== type
&&
3563 notify_info_data_table
[i
].field
== field
)
3564 return notify_info_data_table
[i
].size
;
3570 /****************************************************************************
3571 ****************************************************************************/
3573 static int search_notify(uint16 type
, uint16 field
, int *value
)
3577 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3578 if (notify_info_data_table
[i
].type
== type
&&
3579 notify_info_data_table
[i
].field
== field
&&
3580 notify_info_data_table
[i
].fn
!= NULL
) {
3589 /****************************************************************************
3590 ****************************************************************************/
3592 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3594 info_data
->type
= type
;
3595 info_data
->field
= field
;
3596 info_data
->reserved
= 0;
3598 info_data
->size
= size_of_notify_info_data(type
, field
);
3599 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3606 /*******************************************************************
3608 * fill a notify_info struct with info asked
3610 ********************************************************************/
3612 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3613 snum
, SPOOL_NOTIFY_OPTION_TYPE
3614 *option_type
, uint32 id
,
3615 TALLOC_CTX
*mem_ctx
)
3621 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3622 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3623 print_queue_struct
*queue
=NULL
;
3625 type
=option_type
->type
;
3627 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3628 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3629 option_type
->count
, lp_servicename(snum
)));
3631 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3634 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3635 field
= option_type
->fields
[field_num
];
3637 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3639 if (!search_notify(type
, field
, &j
) )
3642 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3643 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3648 current_data
= &info
->data
[info
->count
];
3650 construct_info_data(current_data
, type
, field
, id
);
3652 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3653 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3655 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3661 free_a_printer(&printer
, 2);
3665 /*******************************************************************
3667 * fill a notify_info struct with info asked
3669 ********************************************************************/
3671 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3672 SPOOL_NOTIFY_INFO
*info
,
3673 NT_PRINTER_INFO_LEVEL
*printer
,
3674 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3675 *option_type
, uint32 id
,
3676 TALLOC_CTX
*mem_ctx
)
3682 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3684 DEBUG(4,("construct_notify_jobs_info\n"));
3686 type
= option_type
->type
;
3688 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3689 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3690 option_type
->count
));
3692 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3693 field
= option_type
->fields
[field_num
];
3695 if (!search_notify(type
, field
, &j
) )
3698 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3699 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3702 else info
->data
= tid
;
3704 current_data
=&(info
->data
[info
->count
]);
3706 construct_info_data(current_data
, type
, field
, id
);
3707 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3716 * JFM: The enumeration is not that simple, it's even non obvious.
3718 * let's take an example: I want to monitor the PRINTER SERVER for
3719 * the printer's name and the number of jobs currently queued.
3720 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3721 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3723 * I have 3 printers on the back of my server.
3725 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3728 * 1 printer 1 name 1
3729 * 2 printer 1 cjob 1
3730 * 3 printer 2 name 2
3731 * 4 printer 2 cjob 2
3732 * 5 printer 3 name 3
3733 * 6 printer 3 name 3
3735 * that's the print server case, the printer case is even worse.
3738 /*******************************************************************
3740 * enumerate all printers on the printserver
3741 * fill a notify_info struct with info asked
3743 ********************************************************************/
3745 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3746 SPOOL_NOTIFY_INFO
*info
,
3747 TALLOC_CTX
*mem_ctx
)
3750 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3751 int n_services
=lp_numservices();
3753 SPOOL_NOTIFY_OPTION
*option
;
3754 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3756 DEBUG(4,("printserver_notify_info\n"));
3761 option
=Printer
->notify
.option
;
3766 for (i
=0; i
<option
->count
; i
++) {
3767 option_type
=&(option
->ctr
.type
[i
]);
3769 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3772 for (snum
=0; snum
<n_services
; snum
++)
3774 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3775 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3781 * Debugging information, don't delete.
3784 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3785 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3786 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3788 for (i
=0; i
<info
->count
; i
++) {
3789 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3790 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3791 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3798 /*******************************************************************
3800 * fill a notify_info struct with info asked
3802 ********************************************************************/
3804 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3805 TALLOC_CTX
*mem_ctx
)
3808 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3811 SPOOL_NOTIFY_OPTION
*option
;
3812 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3814 print_queue_struct
*queue
=NULL
;
3815 print_status_struct status
;
3817 DEBUG(4,("printer_notify_info\n"));
3822 option
=Printer
->notify
.option
;
3828 get_printer_snum(p
, hnd
, &snum
);
3830 for (i
=0; i
<option
->count
; i
++) {
3831 option_type
=&option
->ctr
.type
[i
];
3833 switch ( option_type
->type
) {
3834 case PRINTER_NOTIFY_TYPE
:
3835 if(construct_notify_printer_info(Printer
, info
, snum
,
3841 case JOB_NOTIFY_TYPE
: {
3842 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3844 count
= print_queue_status(snum
, &queue
, &status
);
3846 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3849 for (j
=0; j
<count
; j
++) {
3850 construct_notify_jobs_info(&queue
[j
], info
,
3857 free_a_printer(&printer
, 2);
3867 * Debugging information, don't delete.
3870 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3871 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3872 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3874 for (i=0; i<info->count; i++) {
3875 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3876 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3877 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3883 /********************************************************************
3885 ********************************************************************/
3887 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3889 POLICY_HND
*handle
= &q_u
->handle
;
3890 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3892 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3893 WERROR result
= WERR_BADFID
;
3895 /* we always have a NOTIFY_INFO struct */
3899 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3900 OUR_HANDLE(handle
)));
3904 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3907 * We are now using the change value, and
3908 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3909 * I don't have a global notification system, I'm sending back all the
3910 * informations even when _NOTHING_ has changed.
3913 /* We need to keep track of the change value to send back in
3914 RRPCN replies otherwise our updates are ignored. */
3916 Printer
->notify
.fnpcn
= True
;
3918 if (Printer
->notify
.client_connected
) {
3919 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3920 Printer
->notify
.change
= q_u
->change
;
3923 /* just ignore the SPOOL_NOTIFY_OPTION */
3925 switch (Printer
->printer_type
) {
3926 case PRINTER_HANDLE_IS_PRINTSERVER
:
3927 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3930 case PRINTER_HANDLE_IS_PRINTER
:
3931 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3935 Printer
->notify
.fnpcn
= False
;
3941 /********************************************************************
3942 * construct_printer_info_0
3943 * fill a printer_info_0 struct
3944 ********************************************************************/
3946 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3950 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3951 counter_printer_0
*session_counter
;
3952 uint32 global_counter
;
3955 print_status_struct status
;
3957 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3960 count
= print_queue_length(snum
, &status
);
3962 /* check if we already have a counter for this printer */
3963 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3965 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3966 if (session_counter
->snum
== snum
)
3970 /* it's the first time, add it to the list */
3971 if (session_counter
==NULL
) {
3972 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3973 free_a_printer(&ntprinter
, 2);
3976 ZERO_STRUCTP(session_counter
);
3977 session_counter
->snum
=snum
;
3978 session_counter
->counter
=0;
3979 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3983 session_counter
->counter
++;
3986 * the global_counter should be stored in a TDB as it's common to all the clients
3987 * and should be zeroed on samba startup
3989 global_counter
=session_counter
->counter
;
3991 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3993 init_unistr(&printer
->printername
, chaine
);
3995 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3996 init_unistr(&printer
->servername
, chaine
);
3998 printer
->cjobs
= count
;
3999 printer
->total_jobs
= 0;
4000 printer
->total_bytes
= 0;
4002 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
4003 t
=gmtime(&setuptime
);
4005 printer
->year
= t
->tm_year
+1900;
4006 printer
->month
= t
->tm_mon
+1;
4007 printer
->dayofweek
= t
->tm_wday
;
4008 printer
->day
= t
->tm_mday
;
4009 printer
->hour
= t
->tm_hour
;
4010 printer
->minute
= t
->tm_min
;
4011 printer
->second
= t
->tm_sec
;
4012 printer
->milliseconds
= 0;
4014 printer
->global_counter
= global_counter
;
4015 printer
->total_pages
= 0;
4017 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4018 printer
->major_version
= 0x0005; /* NT 5 */
4019 printer
->build_version
= 0x0893; /* build 2195 */
4021 printer
->unknown7
= 0x1;
4022 printer
->unknown8
= 0x0;
4023 printer
->unknown9
= 0x0;
4024 printer
->session_counter
= session_counter
->counter
;
4025 printer
->unknown11
= 0x0;
4026 printer
->printer_errors
= 0x0; /* number of print failure */
4027 printer
->unknown13
= 0x0;
4028 printer
->unknown14
= 0x1;
4029 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4030 printer
->unknown16
= 0x0;
4031 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4032 printer
->unknown18
= 0x0;
4033 printer
->status
= nt_printq_status(status
.status
);
4034 printer
->unknown20
= 0x0;
4035 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4036 printer
->unknown22
= 0x0;
4037 printer
->unknown23
= 0x6; /* 6 ???*/
4038 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4039 printer
->unknown25
= 0;
4040 printer
->unknown26
= 0;
4041 printer
->unknown27
= 0;
4042 printer
->unknown28
= 0;
4043 printer
->unknown29
= 0;
4045 free_a_printer(&ntprinter
,2);
4049 /********************************************************************
4050 * construct_printer_info_1
4051 * fill a printer_info_1 struct
4052 ********************************************************************/
4053 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4057 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4059 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4062 printer
->flags
=flags
;
4064 if (*ntprinter
->info_2
->comment
== '\0') {
4065 init_unistr(&printer
->comment
, lp_comment(snum
));
4066 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4067 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4070 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4071 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4072 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4075 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4077 init_unistr(&printer
->description
, chaine
);
4078 init_unistr(&printer
->name
, chaine2
);
4080 free_a_printer(&ntprinter
,2);
4085 /****************************************************************************
4086 Free a DEVMODE struct.
4087 ****************************************************************************/
4089 static void free_dev_mode(DEVICEMODE
*dev
)
4094 SAFE_FREE(dev
->private);
4099 /****************************************************************************
4100 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4101 should be valid upon entry
4102 ****************************************************************************/
4104 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4106 if ( !devmode
|| !ntdevmode
)
4109 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4111 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4113 devmode
->specversion
= ntdevmode
->specversion
;
4114 devmode
->driverversion
= ntdevmode
->driverversion
;
4115 devmode
->size
= ntdevmode
->size
;
4116 devmode
->driverextra
= ntdevmode
->driverextra
;
4117 devmode
->fields
= ntdevmode
->fields
;
4119 devmode
->orientation
= ntdevmode
->orientation
;
4120 devmode
->papersize
= ntdevmode
->papersize
;
4121 devmode
->paperlength
= ntdevmode
->paperlength
;
4122 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4123 devmode
->scale
= ntdevmode
->scale
;
4124 devmode
->copies
= ntdevmode
->copies
;
4125 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4126 devmode
->printquality
= ntdevmode
->printquality
;
4127 devmode
->color
= ntdevmode
->color
;
4128 devmode
->duplex
= ntdevmode
->duplex
;
4129 devmode
->yresolution
= ntdevmode
->yresolution
;
4130 devmode
->ttoption
= ntdevmode
->ttoption
;
4131 devmode
->collate
= ntdevmode
->collate
;
4132 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4133 devmode
->icmintent
= ntdevmode
->icmintent
;
4134 devmode
->mediatype
= ntdevmode
->mediatype
;
4135 devmode
->dithertype
= ntdevmode
->dithertype
;
4137 if (ntdevmode
->private != NULL
) {
4138 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
4145 /****************************************************************************
4146 Create a DEVMODE struct. Returns malloced memory.
4147 ****************************************************************************/
4149 DEVICEMODE
*construct_dev_mode(int snum
)
4151 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4152 DEVICEMODE
*devmode
= NULL
;
4154 DEBUG(7,("construct_dev_mode\n"));
4156 DEBUGADD(8,("getting printer characteristics\n"));
4158 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4161 if ( !printer
->info_2
->devmode
) {
4162 DEBUG(5, ("BONG! There was no device mode!\n"));
4166 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
4167 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171 ZERO_STRUCTP(devmode
);
4173 DEBUGADD(8,("loading DEVICEMODE\n"));
4175 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4176 free_dev_mode( devmode
);
4181 free_a_printer(&printer
,2);
4186 /********************************************************************
4187 * construct_printer_info_2
4188 * fill a printer_info_2 struct
4189 ********************************************************************/
4191 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4194 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4196 print_status_struct status
;
4198 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4201 count
= print_queue_length(snum
, &status
);
4203 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4204 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4205 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4206 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4207 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4209 if (*ntprinter
->info_2
->comment
== '\0')
4210 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4212 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4214 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4215 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4216 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4217 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4218 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4220 printer
->attributes
= ntprinter
->info_2
->attributes
;
4222 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4223 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4224 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4225 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4226 printer
->status
= nt_printq_status(status
.status
); /* status */
4227 printer
->cjobs
= count
; /* jobs */
4228 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4230 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4231 DEBUG(8, ("Returning NULL Devicemode!\n"));
4234 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4235 /* steal the printer info sec_desc structure. [badly done]. */
4236 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4237 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4238 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4239 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4242 printer
->secdesc
= NULL
;
4245 free_a_printer(&ntprinter
, 2);
4249 /********************************************************************
4250 * construct_printer_info_3
4251 * fill a printer_info_3 struct
4252 ********************************************************************/
4254 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4256 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4257 PRINTER_INFO_3
*printer
= NULL
;
4259 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4263 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4264 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4268 ZERO_STRUCTP(printer
);
4270 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4271 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4272 /* steal the printer info sec_desc structure. [badly done]. */
4273 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4277 * Set the flags for the components we are returning.
4280 if (printer
->secdesc
->owner_sid
)
4281 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4283 if (printer
->secdesc
->grp_sid
)
4284 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4286 if (printer
->secdesc
->dacl
)
4287 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4289 if (printer
->secdesc
->sacl
)
4290 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4293 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4294 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4295 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4298 free_a_printer(&ntprinter
, 2);
4300 *pp_printer
= printer
;
4304 /********************************************************************
4305 * construct_printer_info_4
4306 * fill a printer_info_4 struct
4307 ********************************************************************/
4309 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4311 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4313 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4316 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4317 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4318 printer
->attributes
= ntprinter
->info_2
->attributes
;
4320 free_a_printer(&ntprinter
, 2);
4324 /********************************************************************
4325 * construct_printer_info_5
4326 * fill a printer_info_5 struct
4327 ********************************************************************/
4329 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4331 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4333 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4336 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4337 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4338 printer
->attributes
= ntprinter
->info_2
->attributes
;
4340 /* these two are not used by NT+ according to MSDN */
4342 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4343 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4345 free_a_printer(&ntprinter
, 2);
4350 /********************************************************************
4351 * construct_printer_info_7
4352 * fill a printer_info_7 struct
4353 ********************************************************************/
4355 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4357 char *guid_str
= NULL
;
4360 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4361 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4362 strupper_m(guid_str
);
4363 init_unistr(&printer
->guid
, guid_str
);
4364 printer
->action
= SPOOL_DS_PUBLISH
;
4366 init_unistr(&printer
->guid
, "");
4367 printer
->action
= SPOOL_DS_UNPUBLISH
;
4373 /********************************************************************
4374 Spoolss_enumprinters.
4375 ********************************************************************/
4377 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4381 int n_services
=lp_numservices();
4382 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4383 PRINTER_INFO_1 current_prt
;
4385 DEBUG(4,("enum_all_printers_info_1\n"));
4387 for (snum
=0; snum
<n_services
; snum
++) {
4388 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4389 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4391 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4392 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4393 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4394 SAFE_FREE(printers
);
4399 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4401 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4407 /* check the required size. */
4408 for (i
=0; i
<*returned
; i
++)
4409 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4411 if (!alloc_buffer_size(buffer
, *needed
))
4412 return WERR_INSUFFICIENT_BUFFER
;
4414 /* fill the buffer with the structures */
4415 for (i
=0; i
<*returned
; i
++)
4416 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4419 SAFE_FREE(printers
);
4421 if (*needed
> offered
) {
4423 return WERR_INSUFFICIENT_BUFFER
;
4429 /********************************************************************
4430 enum_all_printers_info_1_local.
4431 *********************************************************************/
4433 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4435 DEBUG(4,("enum_all_printers_info_1_local\n"));
4437 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4440 /********************************************************************
4441 enum_all_printers_info_1_name.
4442 *********************************************************************/
4444 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4448 DEBUG(4,("enum_all_printers_info_1_name\n"));
4450 if ((name
[0] == '\\') && (name
[1] == '\\'))
4453 if (is_myname_or_ipaddr(s
)) {
4454 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4457 return WERR_INVALID_NAME
;
4460 /********************************************************************
4461 enum_all_printers_info_1_remote.
4462 *********************************************************************/
4464 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4466 PRINTER_INFO_1
*printer
;
4467 fstring printername
;
4470 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4472 /* JFM: currently it's more a place holder than anything else.
4473 * In the spooler world there is a notion of server registration.
4474 * the print servers are registring (sp ?) on the PDC (in the same domain)
4476 * We should have a TDB here. The registration is done thru an undocumented RPC call.
4479 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4484 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
4485 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
4486 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4488 init_unistr(&printer
->description
, desc
);
4489 init_unistr(&printer
->name
, printername
);
4490 init_unistr(&printer
->comment
, comment
);
4491 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4493 /* check the required size. */
4494 *needed
+= spoolss_size_printer_info_1(printer
);
4496 if (!alloc_buffer_size(buffer
, *needed
)) {
4498 return WERR_INSUFFICIENT_BUFFER
;
4501 /* fill the buffer with the structures */
4502 smb_io_printer_info_1("", buffer
, printer
, 0);
4507 if (*needed
> offered
) {
4509 return WERR_INSUFFICIENT_BUFFER
;
4515 /********************************************************************
4516 enum_all_printers_info_1_network.
4517 *********************************************************************/
4519 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4523 DEBUG(4,("enum_all_printers_info_1_network\n"));
4525 /* If we respond to a enum_printers level 1 on our name with flags
4526 set to PRINTER_ENUM_REMOTE with a list of printers then these
4527 printers incorrectly appear in the APW browse list.
4528 Specifically the printers for the server appear at the workgroup
4529 level where all the other servers in the domain are
4530 listed. Windows responds to this call with a
4531 WERR_CAN_NOT_COMPLETE so we should do the same. */
4533 if (name
[0] == '\\' && name
[1] == '\\')
4536 if (is_myname_or_ipaddr(s
))
4537 return WERR_CAN_NOT_COMPLETE
;
4539 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4542 /********************************************************************
4543 * api_spoolss_enumprinters
4545 * called from api_spoolss_enumprinters (see this to understand)
4546 ********************************************************************/
4548 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4552 int n_services
=lp_numservices();
4553 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4554 PRINTER_INFO_2 current_prt
;
4556 for (snum
=0; snum
<n_services
; snum
++) {
4557 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4558 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4560 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4561 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4562 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4563 SAFE_FREE(printers
);
4568 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4569 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4575 /* check the required size. */
4576 for (i
=0; i
<*returned
; i
++)
4577 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4579 if (!alloc_buffer_size(buffer
, *needed
)) {
4580 for (i
=0; i
<*returned
; i
++) {
4581 free_devmode(printers
[i
].devmode
);
4583 SAFE_FREE(printers
);
4584 return WERR_INSUFFICIENT_BUFFER
;
4587 /* fill the buffer with the structures */
4588 for (i
=0; i
<*returned
; i
++)
4589 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4592 for (i
=0; i
<*returned
; i
++) {
4593 free_devmode(printers
[i
].devmode
);
4595 SAFE_FREE(printers
);
4597 if (*needed
> offered
) {
4599 return WERR_INSUFFICIENT_BUFFER
;
4605 /********************************************************************
4606 * handle enumeration of printers at level 1
4607 ********************************************************************/
4609 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4610 NEW_BUFFER
*buffer
, uint32 offered
,
4611 uint32
*needed
, uint32
*returned
)
4613 /* Not all the flags are equals */
4615 if (flags
& PRINTER_ENUM_LOCAL
)
4616 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4618 if (flags
& PRINTER_ENUM_NAME
)
4619 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4621 if (flags
& PRINTER_ENUM_REMOTE
)
4622 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4624 if (flags
& PRINTER_ENUM_NETWORK
)
4625 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4627 return WERR_OK
; /* NT4sp5 does that */
4630 /********************************************************************
4631 * handle enumeration of printers at level 2
4632 ********************************************************************/
4634 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4635 NEW_BUFFER
*buffer
, uint32 offered
,
4636 uint32
*needed
, uint32
*returned
)
4638 char *s
= servername
;
4640 if (flags
& PRINTER_ENUM_LOCAL
) {
4641 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4644 if (flags
& PRINTER_ENUM_NAME
) {
4645 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4647 if (is_myname_or_ipaddr(s
))
4648 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4650 return WERR_INVALID_NAME
;
4653 if (flags
& PRINTER_ENUM_REMOTE
)
4654 return WERR_UNKNOWN_LEVEL
;
4659 /********************************************************************
4660 * handle enumeration of printers at level 5
4661 ********************************************************************/
4663 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4664 NEW_BUFFER
*buffer
, uint32 offered
,
4665 uint32
*needed
, uint32
*returned
)
4667 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4671 /********************************************************************
4672 * api_spoolss_enumprinters
4674 * called from api_spoolss_enumprinters (see this to understand)
4675 ********************************************************************/
4677 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4679 uint32 flags
= q_u
->flags
;
4680 UNISTR2
*servername
= &q_u
->servername
;
4681 uint32 level
= q_u
->level
;
4682 NEW_BUFFER
*buffer
= NULL
;
4683 uint32 offered
= q_u
->offered
;
4684 uint32
*needed
= &r_u
->needed
;
4685 uint32
*returned
= &r_u
->returned
;
4689 /* that's an [in out] buffer */
4690 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4691 buffer
= r_u
->buffer
;
4693 DEBUG(4,("_spoolss_enumprinters\n"));
4700 * flags==PRINTER_ENUM_NAME
4701 * if name=="" then enumerates all printers
4702 * if name!="" then enumerate the printer
4703 * flags==PRINTER_ENUM_REMOTE
4704 * name is NULL, enumerate printers
4705 * Level 2: name!="" enumerates printers, name can't be NULL
4706 * Level 3: doesn't exist
4707 * Level 4: does a local registry lookup
4708 * Level 5: same as Level 2
4711 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4716 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4718 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4720 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4725 return WERR_UNKNOWN_LEVEL
;
4728 /****************************************************************************
4729 ****************************************************************************/
4731 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4733 PRINTER_INFO_0
*printer
=NULL
;
4735 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4738 construct_printer_info_0(print_hnd
, printer
, snum
);
4740 /* check the required size. */
4741 *needed
+= spoolss_size_printer_info_0(printer
);
4743 if (!alloc_buffer_size(buffer
, *needed
)) {
4745 return WERR_INSUFFICIENT_BUFFER
;
4748 /* fill the buffer with the structures */
4749 smb_io_printer_info_0("", buffer
, printer
, 0);
4754 if (*needed
> offered
) {
4755 return WERR_INSUFFICIENT_BUFFER
;
4761 /****************************************************************************
4762 ****************************************************************************/
4764 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4766 PRINTER_INFO_1
*printer
=NULL
;
4768 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4771 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4773 /* check the required size. */
4774 *needed
+= spoolss_size_printer_info_1(printer
);
4776 if (!alloc_buffer_size(buffer
, *needed
)) {
4778 return WERR_INSUFFICIENT_BUFFER
;
4781 /* fill the buffer with the structures */
4782 smb_io_printer_info_1("", buffer
, printer
, 0);
4787 if (*needed
> offered
) {
4788 return WERR_INSUFFICIENT_BUFFER
;
4794 /****************************************************************************
4795 ****************************************************************************/
4797 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4799 PRINTER_INFO_2
*printer
=NULL
;
4801 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4804 construct_printer_info_2(print_hnd
, printer
, snum
);
4806 /* check the required size. */
4807 *needed
+= spoolss_size_printer_info_2(printer
);
4809 if (!alloc_buffer_size(buffer
, *needed
)) {
4810 free_printer_info_2(printer
);
4811 return WERR_INSUFFICIENT_BUFFER
;
4814 /* fill the buffer with the structures */
4815 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4816 free_printer_info_2(printer
);
4821 free_printer_info_2(printer
);
4823 if (*needed
> offered
) {
4824 return WERR_INSUFFICIENT_BUFFER
;
4830 /****************************************************************************
4831 ****************************************************************************/
4833 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4835 PRINTER_INFO_3
*printer
=NULL
;
4837 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4840 /* check the required size. */
4841 *needed
+= spoolss_size_printer_info_3(printer
);
4843 if (!alloc_buffer_size(buffer
, *needed
)) {
4844 free_printer_info_3(printer
);
4845 return WERR_INSUFFICIENT_BUFFER
;
4848 /* fill the buffer with the structures */
4849 smb_io_printer_info_3("", buffer
, printer
, 0);
4852 free_printer_info_3(printer
);
4854 if (*needed
> offered
) {
4855 return WERR_INSUFFICIENT_BUFFER
;
4861 /****************************************************************************
4862 ****************************************************************************/
4864 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4866 PRINTER_INFO_4
*printer
=NULL
;
4868 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4871 if (!construct_printer_info_4(print_hnd
, printer
, snum
))
4874 /* check the required size. */
4875 *needed
+= spoolss_size_printer_info_4(printer
);
4877 if (!alloc_buffer_size(buffer
, *needed
)) {
4878 free_printer_info_4(printer
);
4879 return WERR_INSUFFICIENT_BUFFER
;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_4("", buffer
, printer
, 0);
4886 free_printer_info_4(printer
);
4888 if (*needed
> offered
) {
4889 return WERR_INSUFFICIENT_BUFFER
;
4895 /****************************************************************************
4896 ****************************************************************************/
4898 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4900 PRINTER_INFO_5
*printer
=NULL
;
4902 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4905 if (!construct_printer_info_5(print_hnd
, printer
, snum
))
4908 /* check the required size. */
4909 *needed
+= spoolss_size_printer_info_5(printer
);
4911 if (!alloc_buffer_size(buffer
, *needed
)) {
4912 free_printer_info_5(printer
);
4913 return WERR_INSUFFICIENT_BUFFER
;
4916 /* fill the buffer with the structures */
4917 smb_io_printer_info_5("", buffer
, printer
, 0);
4920 free_printer_info_5(printer
);
4922 if (*needed
> offered
) {
4923 return WERR_INSUFFICIENT_BUFFER
;
4929 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4931 PRINTER_INFO_7
*printer
=NULL
;
4933 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4936 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4939 /* check the required size. */
4940 *needed
+= spoolss_size_printer_info_7(printer
);
4942 if (!alloc_buffer_size(buffer
, *needed
)) {
4943 free_printer_info_7(printer
);
4944 return WERR_INSUFFICIENT_BUFFER
;
4947 /* fill the buffer with the structures */
4948 smb_io_printer_info_7("", buffer
, printer
, 0);
4951 free_printer_info_7(printer
);
4953 if (*needed
> offered
) {
4954 return WERR_INSUFFICIENT_BUFFER
;
4960 /****************************************************************************
4961 ****************************************************************************/
4963 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4965 POLICY_HND
*handle
= &q_u
->handle
;
4966 uint32 level
= q_u
->level
;
4967 NEW_BUFFER
*buffer
= NULL
;
4968 uint32 offered
= q_u
->offered
;
4969 uint32
*needed
= &r_u
->needed
;
4970 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4974 /* that's an [in out] buffer */
4975 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4976 buffer
= r_u
->buffer
;
4980 if (!get_printer_snum(p
, handle
, &snum
))
4985 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
4987 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
4989 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
4991 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
4993 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
4995 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
4997 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
4999 return WERR_UNKNOWN_LEVEL
;
5002 /********************************************************************
5003 * fill a DRIVER_INFO_1 struct
5004 ********************************************************************/
5006 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
5008 init_unistr( &info
->name
, driver
.info_3
->name
);
5011 /********************************************************************
5012 * construct_printer_driver_info_1
5013 ********************************************************************/
5015 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5017 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5018 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5020 ZERO_STRUCT(driver
);
5022 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5023 return WERR_INVALID_PRINTER_NAME
;
5025 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5026 return WERR_UNKNOWN_PRINTER_DRIVER
;
5028 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5030 free_a_printer(&printer
,2);
5035 /********************************************************************
5036 * construct_printer_driver_info_2
5037 * fill a printer_info_2 struct
5038 ********************************************************************/
5040 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5044 info
->version
=driver
.info_3
->cversion
;
5046 init_unistr( &info
->name
, driver
.info_3
->name
);
5047 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5050 if (strlen(driver
.info_3
->driverpath
)) {
5051 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5052 init_unistr( &info
->driverpath
, temp
);
5054 init_unistr( &info
->driverpath
, "" );
5056 if (strlen(driver
.info_3
->datafile
)) {
5057 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5058 init_unistr( &info
->datafile
, temp
);
5060 init_unistr( &info
->datafile
, "" );
5062 if (strlen(driver
.info_3
->configfile
)) {
5063 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5064 init_unistr( &info
->configfile
, temp
);
5066 init_unistr( &info
->configfile
, "" );
5069 /********************************************************************
5070 * construct_printer_driver_info_2
5071 * fill a printer_info_2 struct
5072 ********************************************************************/
5074 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5076 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5077 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5079 ZERO_STRUCT(printer
);
5080 ZERO_STRUCT(driver
);
5082 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5083 return WERR_INVALID_PRINTER_NAME
;
5085 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5086 return WERR_UNKNOWN_PRINTER_DRIVER
;
5088 fill_printer_driver_info_2(info
, driver
, servername
);
5090 free_a_printer(&printer
,2);
5095 /********************************************************************
5096 * copy a strings array and convert to UNICODE
5098 * convert an array of ascii string to a UNICODE string
5099 ********************************************************************/
5101 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5109 DEBUG(6,("init_unistr_array\n"));
5120 v
= ""; /* hack to handle null lists */
5123 /* hack to allow this to be used in places other than when generating
5124 the list of dependent files */
5127 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5131 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5133 /* add one extra unit16 for the second terminating NULL */
5135 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
5136 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5144 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5149 /* special case for ""; we need to add both NULL's here */
5151 (*uni_array
)[j
++]=0x0000;
5152 (*uni_array
)[j
]=0x0000;
5155 DEBUGADD(6,("last one:done\n"));
5157 /* return size of array in uint16's */
5162 /********************************************************************
5163 * construct_printer_info_3
5164 * fill a printer_info_3 struct
5165 ********************************************************************/
5167 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5173 info
->version
=driver
.info_3
->cversion
;
5175 init_unistr( &info
->name
, driver
.info_3
->name
);
5176 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5178 if (strlen(driver
.info_3
->driverpath
)) {
5179 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5180 init_unistr( &info
->driverpath
, temp
);
5182 init_unistr( &info
->driverpath
, "" );
5184 if (strlen(driver
.info_3
->datafile
)) {
5185 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5186 init_unistr( &info
->datafile
, temp
);
5188 init_unistr( &info
->datafile
, "" );
5190 if (strlen(driver
.info_3
->configfile
)) {
5191 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5192 init_unistr( &info
->configfile
, temp
);
5194 init_unistr( &info
->configfile
, "" );
5196 if (strlen(driver
.info_3
->helpfile
)) {
5197 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5198 init_unistr( &info
->helpfile
, temp
);
5200 init_unistr( &info
->helpfile
, "" );
5202 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5203 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5205 info
->dependentfiles
=NULL
;
5206 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5209 /********************************************************************
5210 * construct_printer_info_3
5211 * fill a printer_info_3 struct
5212 ********************************************************************/
5214 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5216 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5217 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5219 ZERO_STRUCT(driver
);
5221 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5222 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5223 if (!W_ERROR_IS_OK(status
))
5224 return WERR_INVALID_PRINTER_NAME
;
5226 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5227 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5232 * I put this code in during testing. Helpful when commenting out the
5233 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5234 * as win2k always queries the driver using an infor level of 6.
5235 * I've left it in (but ifdef'd out) because I'll probably
5236 * use it in experimentation again in the future. --jerry 22/01/2002
5239 if (!W_ERROR_IS_OK(status
)) {
5241 * Is this a W2k client ?
5244 /* Yes - try again with a WinNT driver. */
5246 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5247 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5251 if (!W_ERROR_IS_OK(status
)) {
5252 free_a_printer(&printer
,2);
5253 return WERR_UNKNOWN_PRINTER_DRIVER
;
5261 fill_printer_driver_info_3(info
, driver
, servername
);
5263 free_a_printer(&printer
,2);
5268 /********************************************************************
5269 * construct_printer_info_6
5270 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5271 ********************************************************************/
5273 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5279 memset(&nullstr
, '\0', sizeof(fstring
));
5281 info
->version
=driver
.info_3
->cversion
;
5283 init_unistr( &info
->name
, driver
.info_3
->name
);
5284 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5286 if (strlen(driver
.info_3
->driverpath
)) {
5287 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5288 init_unistr( &info
->driverpath
, temp
);
5290 init_unistr( &info
->driverpath
, "" );
5292 if (strlen(driver
.info_3
->datafile
)) {
5293 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5294 init_unistr( &info
->datafile
, temp
);
5296 init_unistr( &info
->datafile
, "" );
5298 if (strlen(driver
.info_3
->configfile
)) {
5299 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5300 init_unistr( &info
->configfile
, temp
);
5302 init_unistr( &info
->configfile
, "" );
5304 if (strlen(driver
.info_3
->helpfile
)) {
5305 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5306 init_unistr( &info
->helpfile
, temp
);
5308 init_unistr( &info
->helpfile
, "" );
5310 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5311 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5313 info
->dependentfiles
= NULL
;
5314 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5316 info
->previousdrivernames
=NULL
;
5317 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5319 info
->driver_date
.low
=0;
5320 info
->driver_date
.high
=0;
5323 info
->driver_version_low
=0;
5324 info
->driver_version_high
=0;
5326 init_unistr( &info
->mfgname
, "");
5327 init_unistr( &info
->oem_url
, "");
5328 init_unistr( &info
->hardware_id
, "");
5329 init_unistr( &info
->provider
, "");
5332 /********************************************************************
5333 * construct_printer_info_6
5334 * fill a printer_info_6 struct
5335 ********************************************************************/
5337 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5338 fstring servername
, fstring architecture
, uint32 version
)
5340 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5341 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5344 ZERO_STRUCT(driver
);
5346 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5348 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5350 if (!W_ERROR_IS_OK(status
))
5351 return WERR_INVALID_PRINTER_NAME
;
5353 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5355 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5357 if (!W_ERROR_IS_OK(status
))
5360 * Is this a W2k client ?
5364 free_a_printer(&printer
,2);
5365 return WERR_UNKNOWN_PRINTER_DRIVER
;
5368 /* Yes - try again with a WinNT driver. */
5370 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5371 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5372 if (!W_ERROR_IS_OK(status
)) {
5373 free_a_printer(&printer
,2);
5374 return WERR_UNKNOWN_PRINTER_DRIVER
;
5378 fill_printer_driver_info_6(info
, driver
, servername
);
5380 free_a_printer(&printer
,2);
5381 free_a_printer_driver(driver
, 3);
5386 /****************************************************************************
5387 ****************************************************************************/
5389 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5391 SAFE_FREE(info
->dependentfiles
);
5394 /****************************************************************************
5395 ****************************************************************************/
5397 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5399 SAFE_FREE(info
->dependentfiles
);
5403 /****************************************************************************
5404 ****************************************************************************/
5406 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5408 DRIVER_INFO_1
*info
=NULL
;
5411 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5414 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5415 if (!W_ERROR_IS_OK(status
)) {
5420 /* check the required size. */
5421 *needed
+= spoolss_size_printer_driver_info_1(info
);
5423 if (!alloc_buffer_size(buffer
, *needed
)) {
5425 return WERR_INSUFFICIENT_BUFFER
;
5428 /* fill the buffer with the structures */
5429 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5434 if (*needed
> offered
)
5435 return WERR_INSUFFICIENT_BUFFER
;
5440 /****************************************************************************
5441 ****************************************************************************/
5443 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5445 DRIVER_INFO_2
*info
=NULL
;
5448 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5451 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5452 if (!W_ERROR_IS_OK(status
)) {
5457 /* check the required size. */
5458 *needed
+= spoolss_size_printer_driver_info_2(info
);
5460 if (!alloc_buffer_size(buffer
, *needed
)) {
5462 return WERR_INSUFFICIENT_BUFFER
;
5465 /* fill the buffer with the structures */
5466 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5471 if (*needed
> offered
)
5472 return WERR_INSUFFICIENT_BUFFER
;
5477 /****************************************************************************
5478 ****************************************************************************/
5480 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5487 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5488 if (!W_ERROR_IS_OK(status
)) {
5492 /* check the required size. */
5493 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5495 if (!alloc_buffer_size(buffer
, *needed
)) {
5496 free_printer_driver_info_3(&info
);
5497 return WERR_INSUFFICIENT_BUFFER
;
5500 /* fill the buffer with the structures */
5501 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5503 free_printer_driver_info_3(&info
);
5505 if (*needed
> offered
)
5506 return WERR_INSUFFICIENT_BUFFER
;
5511 /****************************************************************************
5512 ****************************************************************************/
5514 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5521 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5522 if (!W_ERROR_IS_OK(status
)) {
5526 /* check the required size. */
5527 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5529 if (!alloc_buffer_size(buffer
, *needed
)) {
5530 free_printer_driver_info_6(&info
);
5531 return WERR_INSUFFICIENT_BUFFER
;
5534 /* fill the buffer with the structures */
5535 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5537 free_printer_driver_info_6(&info
);
5539 if (*needed
> offered
)
5540 return WERR_INSUFFICIENT_BUFFER
;
5545 /****************************************************************************
5546 ****************************************************************************/
5548 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5550 POLICY_HND
*handle
= &q_u
->handle
;
5551 UNISTR2
*uni_arch
= &q_u
->architecture
;
5552 uint32 level
= q_u
->level
;
5553 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5554 NEW_BUFFER
*buffer
= NULL
;
5555 uint32 offered
= q_u
->offered
;
5556 uint32
*needed
= &r_u
->needed
;
5557 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5558 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5561 fstring architecture
;
5564 /* that's an [in out] buffer */
5565 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5566 buffer
= r_u
->buffer
;
5568 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5571 *servermajorversion
= 0;
5572 *serverminorversion
= 0;
5574 fstrcpy(servername
, get_called_name());
5575 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5577 if (!get_printer_snum(p
, handle
, &snum
))
5582 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5584 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5586 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5588 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5591 return WERR_UNKNOWN_LEVEL
;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5599 POLICY_HND
*handle
= &q_u
->handle
;
5601 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5604 DEBUG(3,("Error in startpageprinter printer handle\n"));
5608 Printer
->page_started
=True
;
5612 /****************************************************************************
5613 ****************************************************************************/
5615 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5617 POLICY_HND
*handle
= &q_u
->handle
;
5620 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5623 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5627 if (!get_printer_snum(p
, handle
, &snum
))
5630 Printer
->page_started
=False
;
5631 print_job_endpage(snum
, Printer
->jobid
);
5636 /********************************************************************
5637 * api_spoolss_getprinter
5638 * called from the spoolss dispatcher
5640 ********************************************************************/
5642 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5644 POLICY_HND
*handle
= &q_u
->handle
;
5645 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5646 uint32
*jobid
= &r_u
->jobid
;
5648 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5652 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5653 struct current_user user
;
5656 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5660 get_current_user(&user
, p
);
5663 * a nice thing with NT is it doesn't listen to what you tell it.
5664 * when asked to send _only_ RAW datas, it tries to send datas
5667 * So I add checks like in NT Server ...
5670 if (info_1
->p_datatype
!= 0) {
5671 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5672 if (strcmp(datatype
, "RAW") != 0) {
5674 return WERR_INVALID_DATATYPE
;
5678 /* get the share number of the printer */
5679 if (!get_printer_snum(p
, handle
, &snum
)) {
5683 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5685 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5687 /* An error occured in print_job_start() so return an appropriate
5690 if (Printer
->jobid
== -1) {
5691 return map_werror_from_unix(errno
);
5694 Printer
->document_started
=True
;
5695 (*jobid
) = Printer
->jobid
;
5700 /********************************************************************
5701 * api_spoolss_getprinter
5702 * called from the spoolss dispatcher
5704 ********************************************************************/
5706 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5708 POLICY_HND
*handle
= &q_u
->handle
;
5710 return _spoolss_enddocprinter_internal(p
, handle
);
5713 /****************************************************************************
5714 ****************************************************************************/
5716 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5718 POLICY_HND
*handle
= &q_u
->handle
;
5719 uint32 buffer_size
= q_u
->buffer_size
;
5720 uint8
*buffer
= q_u
->buffer
;
5721 uint32
*buffer_written
= &q_u
->buffer_size2
;
5723 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5726 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5727 r_u
->buffer_written
= q_u
->buffer_size2
;
5731 if (!get_printer_snum(p
, handle
, &snum
))
5734 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5735 if (*buffer_written
== -1) {
5736 r_u
->buffer_written
= 0;
5737 if (errno
== ENOSPC
)
5738 return WERR_NO_SPOOL_SPACE
;
5740 return WERR_ACCESS_DENIED
;
5743 r_u
->buffer_written
= q_u
->buffer_size2
;
5748 /********************************************************************
5749 * api_spoolss_getprinter
5750 * called from the spoolss dispatcher
5752 ********************************************************************/
5754 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5757 struct current_user user
;
5759 WERROR errcode
= WERR_BADFUNC
;
5760 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5762 get_current_user(&user
, p
);
5765 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5769 if (!get_printer_snum(p
, handle
, &snum
))
5773 case PRINTER_CONTROL_PAUSE
:
5774 if (print_queue_pause(&user
, snum
, &errcode
)) {
5778 case PRINTER_CONTROL_RESUME
:
5779 case PRINTER_CONTROL_UNPAUSE
:
5780 if (print_queue_resume(&user
, snum
, &errcode
)) {
5784 case PRINTER_CONTROL_PURGE
:
5785 if (print_queue_purge(&user
, snum
, &errcode
)) {
5790 return WERR_UNKNOWN_LEVEL
;
5796 /********************************************************************
5797 * api_spoolss_abortprinter
5798 * From MSDN: "Deletes printer's spool file if printer is configured
5800 ********************************************************************/
5802 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5804 POLICY_HND
*handle
= &q_u
->handle
;
5805 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5807 struct current_user user
;
5808 WERROR errcode
= WERR_OK
;
5811 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5815 if (!get_printer_snum(p
, handle
, &snum
))
5818 get_current_user( &user
, p
);
5820 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5825 /********************************************************************
5826 * called by spoolss_api_setprinter
5827 * when updating a printer description
5828 ********************************************************************/
5830 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5831 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5832 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5834 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5835 struct current_user user
;
5839 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5841 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5842 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5843 OUR_HANDLE(handle
)));
5845 result
= WERR_BADFID
;
5849 /* NT seems to like setting the security descriptor even though
5850 nothing may have actually changed. This causes annoying
5851 dialog boxes when the user doesn't have permission to change
5852 the security descriptor. */
5854 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5856 if (DEBUGLEVEL
>= 10) {
5860 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5861 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5862 PRINTERNAME(snum
), the_acl
->num_aces
));
5864 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5867 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5869 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5870 the_acl
->ace
[i
].info
.mask
));
5873 the_acl
= secdesc_ctr
->sec
->dacl
;
5876 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5877 PRINTERNAME(snum
), the_acl
->num_aces
));
5879 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5882 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5884 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5885 the_acl
->ace
[i
].info
.mask
));
5888 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5892 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5894 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5899 /* Work out which user is performing the operation */
5901 get_current_user(&user
, p
);
5903 /* Check the user has permissions to change the security
5904 descriptor. By experimentation with two NT machines, the user
5905 requires Full Access to the printer to change security
5908 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5909 result
= WERR_ACCESS_DENIED
;
5913 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5920 /********************************************************************
5921 Do Samba sanity checks on a printer info struct.
5922 this has changed purpose: it now "canonicalises" printer
5923 info from a client rather than just checking it is correct
5924 ********************************************************************/
5926 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5928 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5929 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5931 /* we force some elements to "correct" values */
5932 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5933 fstrcpy(info
->sharename
, lp_servicename(snum
));
5934 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5935 get_called_name(), info
->sharename
);
5936 info
->attributes
= PRINTER_ATTRIBUTE_SAMBA
;
5942 /****************************************************************************
5943 ****************************************************************************/
5945 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5947 extern userdom_struct current_user_info
;
5948 char *cmd
= lp_addprinter_cmd();
5954 fstring remote_machine
= "%m";
5956 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5958 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5959 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5960 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5961 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5963 DEBUG(10,("Running [%s]\n", command
));
5964 ret
= smbrun(command
, &fd
);
5965 DEBUGADD(10,("returned [%d]\n", ret
));
5974 /* Get lines and convert them back to dos-codepage */
5975 qlines
= fd_lines_load(fd
, &numlines
);
5976 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5980 /* Set the portname to what the script says the portname should be. */
5981 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5982 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5984 /* Send SIGHUP to process group... is there a better way? */
5987 /* reload our services immediately */
5988 reload_services( False
);
5991 file_lines_free(qlines
);
5995 /********************************************************************
5996 * Called by spoolss_api_setprinter
5997 * when updating a printer description.
5998 ********************************************************************/
6000 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6001 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6002 DEVICEMODE
*devmode
)
6005 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6006 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6011 DEBUG(8,("update_printer\n"));
6016 result
= WERR_BADFID
;
6020 if (!get_printer_snum(p
, handle
, &snum
)) {
6021 result
= WERR_BADFID
;
6025 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6026 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6027 result
= WERR_BADFID
;
6031 DEBUGADD(8,("Converting info_2 struct\n"));
6034 * convert_printer_info converts the incoming
6035 * info from the client and overwrites the info
6036 * just read from the tdb in the pointer 'printer'.
6039 if (!convert_printer_info(info
, printer
, level
)) {
6040 result
= WERR_NOMEM
;
6045 /* we have a valid devmode
6046 convert it and link it*/
6048 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6049 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6050 &printer
->info_2
->devmode
)) {
6051 result
= WERR_NOMEM
;
6056 /* Do sanity check on the requested changes for Samba */
6058 if (!check_printer_ok(printer
->info_2
, snum
)) {
6059 result
= WERR_INVALID_PARAM
;
6063 /* FIXME!!! If the driver has changed we really should verify that
6064 it is installed before doing much else --jerry */
6066 /* Check calling user has permission to update printer description */
6068 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6069 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6070 result
= WERR_ACCESS_DENIED
;
6074 /* Call addprinter hook */
6075 /* Check changes to see if this is really needed */
6077 if ( *lp_addprinter_cmd()
6078 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6079 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6080 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6081 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6083 if ( !add_printer_hook(printer
) ) {
6084 result
= WERR_ACCESS_DENIED
;
6089 * make sure we actually reload the services after
6090 * this as smb.conf could have a new section in it
6091 * .... shouldn't .... but could
6093 reload_services(False
);
6097 * When a *new* driver is bound to a printer, the drivername is used to
6098 * lookup previously saved driver initialization info, which is then
6099 * bound to the printer, simulating what happens in the Windows arch.
6101 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6103 if (!set_driver_init(printer
, 2))
6105 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6106 printer
->info_2
->drivername
));
6109 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6110 printer
->info_2
->drivername
));
6112 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6116 * flag which changes actually occured. This is a small subset of
6117 * all the possible changes. We also have to update things in the
6121 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6122 init_unistr2( &buffer
, printer
->info_2
->comment
, strlen(printer
->info_2
->comment
)+1 );
6123 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6124 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6126 notify_printer_comment(snum
, printer
->info_2
->comment
);
6129 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6130 init_unistr2( &buffer
, printer
->info_2
->sharename
, strlen(printer
->info_2
->sharename
)+1 );
6131 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6132 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6133 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6134 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6136 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6139 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6140 init_unistr2( &buffer
, printer
->info_2
->portname
, strlen(printer
->info_2
->portname
)+1 );
6141 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6142 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6144 notify_printer_port(snum
, printer
->info_2
->portname
);
6147 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6148 init_unistr2( &buffer
, printer
->info_2
->location
, strlen(printer
->info_2
->location
)+1 );
6149 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6150 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6152 notify_printer_location(snum
, printer
->info_2
->location
);
6155 /* here we need to update some more DsSpooler keys */
6156 /* uNCName, serverName, shortServerName */
6158 init_unistr2( &buffer
, global_myname(), strlen(global_myname())+1 );
6159 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6160 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6161 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6162 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6164 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6165 global_myname(), printer
->info_2
->sharename
);
6166 init_unistr2( &buffer
, asc_buffer
, strlen(asc_buffer
)+1 );
6167 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6168 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6170 /* Update printer info */
6171 result
= mod_a_printer(*printer
, 2);
6174 free_a_printer(&printer
, 2);
6175 free_a_printer(&old_printer
, 2);
6181 /****************************************************************************
6182 ****************************************************************************/
6183 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6184 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6187 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6189 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6191 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6196 if (!get_printer_snum(p
, handle
, &snum
))
6199 nt_printer_publish(Printer
, snum
, info7
->action
);
6203 return WERR_UNKNOWN_LEVEL
;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6211 POLICY_HND
*handle
= &q_u
->handle
;
6212 uint32 level
= q_u
->level
;
6213 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6214 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6215 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6216 uint32 command
= q_u
->command
;
6218 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6221 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6225 /* check the level */
6228 return control_printer(handle
, command
, p
);
6230 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6232 return update_printer_sec(handle
, level
, info
, p
,
6235 return publish_or_unpublish_printer(p
, handle
, info
);
6237 return WERR_UNKNOWN_LEVEL
;
6241 /****************************************************************************
6242 ****************************************************************************/
6244 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6246 POLICY_HND
*handle
= &q_u
->handle
;
6247 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6250 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6254 if (Printer
->notify
.client_connected
==True
) {
6257 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6259 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6260 !get_printer_snum(p
, handle
, &snum
) )
6263 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6266 Printer
->notify
.flags
=0;
6267 Printer
->notify
.options
=0;
6268 Printer
->notify
.localmachine
[0]='\0';
6269 Printer
->notify
.printerlocal
=0;
6270 if (Printer
->notify
.option
)
6271 free_spool_notify_option(&Printer
->notify
.option
);
6272 Printer
->notify
.client_connected
=False
;
6277 /****************************************************************************
6278 ****************************************************************************/
6280 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6282 /* that's an [in out] buffer (despite appearences to the contrary) */
6283 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6286 return WERR_INVALID_PARAM
; /* this is what a NT server
6287 returns for AddJob. AddJob
6288 must fail on non-local
6292 /****************************************************************************
6293 ****************************************************************************/
6295 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6296 int position
, int snum
)
6302 t
=gmtime(&queue
->time
);
6303 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6305 job_info
->jobid
=queue
->job
;
6306 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6307 init_unistr(&job_info
->machinename
, temp_name
);
6308 init_unistr(&job_info
->username
, queue
->fs_user
);
6309 init_unistr(&job_info
->document
, queue
->fs_file
);
6310 init_unistr(&job_info
->datatype
, "RAW");
6311 init_unistr(&job_info
->text_status
, "");
6312 job_info
->status
=nt_printj_status(queue
->status
);
6313 job_info
->priority
=queue
->priority
;
6314 job_info
->position
=position
;
6315 job_info
->totalpages
=queue
->page_count
;
6316 job_info
->pagesprinted
=0;
6318 make_systemtime(&job_info
->submitted
, t
);
6321 /****************************************************************************
6322 ****************************************************************************/
6324 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6325 int position
, int snum
,
6326 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6327 DEVICEMODE
*devmode
)
6332 t
=gmtime(&queue
->time
);
6333 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
6335 job_info
->jobid
=queue
->job
;
6337 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6339 init_unistr(&job_info
->machinename
, temp_name
);
6340 init_unistr(&job_info
->username
, queue
->fs_user
);
6341 init_unistr(&job_info
->document
, queue
->fs_file
);
6342 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6343 init_unistr(&job_info
->datatype
, "RAW");
6344 init_unistr(&job_info
->printprocessor
, "winprint");
6345 init_unistr(&job_info
->parameters
, "");
6346 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6347 init_unistr(&job_info
->text_status
, "");
6349 /* and here the security descriptor */
6351 job_info
->status
=nt_printj_status(queue
->status
);
6352 job_info
->priority
=queue
->priority
;
6353 job_info
->position
=position
;
6354 job_info
->starttime
=0;
6355 job_info
->untiltime
=0;
6356 job_info
->totalpages
=queue
->page_count
;
6357 job_info
->size
=queue
->size
;
6358 make_systemtime(&(job_info
->submitted
), t
);
6359 job_info
->timeelapsed
=0;
6360 job_info
->pagesprinted
=0;
6362 job_info
->devmode
= devmode
;
6367 /****************************************************************************
6368 Enumjobs at level 1.
6369 ****************************************************************************/
6371 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6372 NEW_BUFFER
*buffer
, uint32 offered
,
6373 uint32
*needed
, uint32
*returned
)
6378 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6385 for (i
=0; i
<*returned
; i
++)
6386 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
6390 /* check the required size. */
6391 for (i
=0; i
<*returned
; i
++)
6392 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6394 if (!alloc_buffer_size(buffer
, *needed
)) {
6396 return WERR_INSUFFICIENT_BUFFER
;
6399 /* fill the buffer with the structures */
6400 for (i
=0; i
<*returned
; i
++)
6401 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6406 if (*needed
> offered
) {
6408 return WERR_INSUFFICIENT_BUFFER
;
6414 /****************************************************************************
6415 Enumjobs at level 2.
6416 ****************************************************************************/
6418 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6419 NEW_BUFFER
*buffer
, uint32 offered
,
6420 uint32
*needed
, uint32
*returned
)
6422 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6423 JOB_INFO_2
*info
= NULL
;
6426 DEVICEMODE
*devmode
= NULL
;
6428 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6431 result
= WERR_NOMEM
;
6435 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6436 if (!W_ERROR_IS_OK(result
)) {
6441 /* this should not be a failure condition if the devmode is NULL */
6443 devmode
= construct_dev_mode(snum
);
6445 for (i
=0; i
<*returned
; i
++)
6446 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6449 free_a_printer(&ntprinter
, 2);
6452 /* check the required size. */
6453 for (i
=0; i
<*returned
; i
++)
6454 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6456 if (*needed
> offered
) {
6458 result
= WERR_INSUFFICIENT_BUFFER
;
6462 if (!alloc_buffer_size(buffer
, *needed
)) {
6464 result
= WERR_INSUFFICIENT_BUFFER
;
6468 /* fill the buffer with the structures */
6469 for (i
=0; i
<*returned
; i
++)
6470 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6475 free_a_printer(&ntprinter
, 2);
6476 free_devmode(devmode
);
6484 /****************************************************************************
6486 ****************************************************************************/
6488 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6490 POLICY_HND
*handle
= &q_u
->handle
;
6491 uint32 level
= q_u
->level
;
6492 NEW_BUFFER
*buffer
= NULL
;
6493 uint32 offered
= q_u
->offered
;
6494 uint32
*needed
= &r_u
->needed
;
6495 uint32
*returned
= &r_u
->returned
;
6499 print_status_struct prt_status
;
6500 print_queue_struct
*queue
=NULL
;
6502 /* that's an [in out] buffer */
6503 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6504 buffer
= r_u
->buffer
;
6506 DEBUG(4,("_spoolss_enumjobs\n"));
6511 if (!get_printer_snum(p
, handle
, &snum
))
6514 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6515 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6517 if (*returned
== 0) {
6518 set_enumjobs_timestamp(snum
);
6525 wret
= enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
6526 set_enumjobs_timestamp(snum
);
6529 wret
= enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
6530 set_enumjobs_timestamp(snum
);
6535 return WERR_UNKNOWN_LEVEL
;
6539 /****************************************************************************
6540 ****************************************************************************/
6542 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6547 /****************************************************************************
6548 ****************************************************************************/
6550 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6552 POLICY_HND
*handle
= &q_u
->handle
;
6553 uint32 jobid
= q_u
->jobid
;
6554 uint32 command
= q_u
->command
;
6556 struct current_user user
;
6558 WERROR errcode
= WERR_BADFUNC
;
6560 if (!get_printer_snum(p
, handle
, &snum
)) {
6564 if (!print_job_exists(snum
, jobid
)) {
6565 return WERR_INVALID_PRINTER_NAME
;
6568 get_current_user(&user
, p
);
6571 case JOB_CONTROL_CANCEL
:
6572 case JOB_CONTROL_DELETE
:
6573 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6577 case JOB_CONTROL_PAUSE
:
6578 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6582 case JOB_CONTROL_RESTART
:
6583 case JOB_CONTROL_RESUME
:
6584 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6589 return WERR_UNKNOWN_LEVEL
;
6595 /****************************************************************************
6596 Enumerates all printer drivers at level 1.
6597 ****************************************************************************/
6599 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6604 fstring
*list
= NULL
;
6606 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6607 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6611 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6613 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6614 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6620 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6621 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6622 SAFE_FREE(driver_info_1
);
6626 else driver_info_1
= tdi1
;
6629 for (i
=0; i
<ndrivers
; i
++) {
6631 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6632 ZERO_STRUCT(driver
);
6633 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6634 architecture
, version
);
6635 if (!W_ERROR_IS_OK(status
)) {
6639 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6640 free_a_printer_driver(driver
, 3);
6643 *returned
+=ndrivers
;
6647 /* check the required size. */
6648 for (i
=0; i
<*returned
; i
++) {
6649 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6650 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6653 if (!alloc_buffer_size(buffer
, *needed
)) {
6654 SAFE_FREE(driver_info_1
);
6655 return WERR_INSUFFICIENT_BUFFER
;
6658 /* fill the buffer with the driver structures */
6659 for (i
=0; i
<*returned
; i
++) {
6660 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6661 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6664 SAFE_FREE(driver_info_1
);
6666 if (*needed
> offered
) {
6668 return WERR_INSUFFICIENT_BUFFER
;
6674 /****************************************************************************
6675 Enumerates all printer drivers at level 2.
6676 ****************************************************************************/
6678 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6683 fstring
*list
= NULL
;
6685 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6686 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6690 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6692 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6693 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6699 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6700 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6701 SAFE_FREE(driver_info_2
);
6705 else driver_info_2
= tdi2
;
6708 for (i
=0; i
<ndrivers
; i
++) {
6711 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6712 ZERO_STRUCT(driver
);
6713 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6714 architecture
, version
);
6715 if (!W_ERROR_IS_OK(status
)) {
6719 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6720 free_a_printer_driver(driver
, 3);
6723 *returned
+=ndrivers
;
6727 /* check the required size. */
6728 for (i
=0; i
<*returned
; i
++) {
6729 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6730 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6733 if (!alloc_buffer_size(buffer
, *needed
)) {
6734 SAFE_FREE(driver_info_2
);
6735 return WERR_INSUFFICIENT_BUFFER
;
6738 /* fill the buffer with the form structures */
6739 for (i
=0; i
<*returned
; i
++) {
6740 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6741 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6744 SAFE_FREE(driver_info_2
);
6746 if (*needed
> offered
) {
6748 return WERR_INSUFFICIENT_BUFFER
;
6754 /****************************************************************************
6755 Enumerates all printer drivers at level 3.
6756 ****************************************************************************/
6758 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6763 fstring
*list
= NULL
;
6765 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6766 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6770 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6772 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6773 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6779 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6780 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6781 SAFE_FREE(driver_info_3
);
6785 else driver_info_3
= tdi3
;
6788 for (i
=0; i
<ndrivers
; i
++) {
6791 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6792 ZERO_STRUCT(driver
);
6793 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6794 architecture
, version
);
6795 if (!W_ERROR_IS_OK(status
)) {
6799 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6800 free_a_printer_driver(driver
, 3);
6803 *returned
+=ndrivers
;
6807 /* check the required size. */
6808 for (i
=0; i
<*returned
; i
++) {
6809 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6810 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6813 if (!alloc_buffer_size(buffer
, *needed
)) {
6814 SAFE_FREE(driver_info_3
);
6815 return WERR_INSUFFICIENT_BUFFER
;
6818 /* fill the buffer with the driver structures */
6819 for (i
=0; i
<*returned
; i
++) {
6820 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6821 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6824 for (i
=0; i
<*returned
; i
++)
6825 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6827 SAFE_FREE(driver_info_3
);
6829 if (*needed
> offered
) {
6831 return WERR_INSUFFICIENT_BUFFER
;
6837 /****************************************************************************
6838 Enumerates all printer drivers.
6839 ****************************************************************************/
6841 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6843 UNISTR2
*environment
= &q_u
->environment
;
6844 uint32 level
= q_u
->level
;
6845 NEW_BUFFER
*buffer
= NULL
;
6846 uint32 offered
= q_u
->offered
;
6847 uint32
*needed
= &r_u
->needed
;
6848 uint32
*returned
= &r_u
->returned
;
6850 fstring
*list
= NULL
;
6852 fstring architecture
;
6854 /* that's an [in out] buffer */
6855 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6856 buffer
= r_u
->buffer
;
6858 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6859 fstrcpy(servername
, get_called_name());
6863 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6867 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6869 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6871 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6875 return WERR_UNKNOWN_LEVEL
;
6879 /****************************************************************************
6880 ****************************************************************************/
6882 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6884 form
->flag
=list
->flag
;
6885 init_unistr(&form
->name
, list
->name
);
6886 form
->width
=list
->width
;
6887 form
->length
=list
->length
;
6888 form
->left
=list
->left
;
6889 form
->top
=list
->top
;
6890 form
->right
=list
->right
;
6891 form
->bottom
=list
->bottom
;
6894 /****************************************************************************
6895 ****************************************************************************/
6897 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6899 uint32 level
= q_u
->level
;
6900 NEW_BUFFER
*buffer
= NULL
;
6901 uint32 offered
= q_u
->offered
;
6902 uint32
*needed
= &r_u
->needed
;
6903 uint32
*numofforms
= &r_u
->numofforms
;
6904 uint32 numbuiltinforms
;
6906 nt_forms_struct
*list
=NULL
;
6907 nt_forms_struct
*builtinlist
=NULL
;
6912 /* that's an [in out] buffer */
6913 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6914 buffer
= r_u
->buffer
;
6916 DEBUG(4,("_spoolss_enumforms\n"));
6917 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6918 DEBUGADD(5,("Info level [%d]\n", level
));
6920 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6921 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6922 *numofforms
= get_ntforms(&list
);
6923 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6924 *numofforms
+= numbuiltinforms
;
6926 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6930 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6935 /* construct the list of form structures */
6936 for (i
=0; i
<numbuiltinforms
; i
++) {
6937 DEBUGADD(6,("Filling form number [%d]\n",i
));
6938 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6941 SAFE_FREE(builtinlist
);
6943 for (; i
<*numofforms
; i
++) {
6944 DEBUGADD(6,("Filling form number [%d]\n",i
));
6945 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6950 /* check the required size. */
6951 for (i
=0; i
<numbuiltinforms
; i
++) {
6952 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6953 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6955 for (; i
<*numofforms
; i
++) {
6956 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6957 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6960 *needed
=buffer_size
;
6962 if (!alloc_buffer_size(buffer
, buffer_size
)){
6964 return WERR_INSUFFICIENT_BUFFER
;
6967 /* fill the buffer with the form structures */
6968 for (i
=0; i
<numbuiltinforms
; i
++) {
6969 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6970 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6972 for (; i
<*numofforms
; i
++) {
6973 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6974 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6979 if (*needed
> offered
) {
6981 return WERR_INSUFFICIENT_BUFFER
;
6988 SAFE_FREE(builtinlist
);
6989 return WERR_UNKNOWN_LEVEL
;
6994 /****************************************************************************
6995 ****************************************************************************/
6997 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6999 uint32 level
= q_u
->level
;
7000 UNISTR2
*uni_formname
= &q_u
->formname
;
7001 NEW_BUFFER
*buffer
= NULL
;
7002 uint32 offered
= q_u
->offered
;
7003 uint32
*needed
= &r_u
->needed
;
7005 nt_forms_struct
*list
=NULL
;
7006 nt_forms_struct builtin_form
;
7011 int numofforms
=0, i
=0;
7013 /* that's an [in out] buffer */
7014 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7015 buffer
= r_u
->buffer
;
7017 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7019 DEBUG(4,("_spoolss_getform\n"));
7020 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7021 DEBUGADD(5,("Info level [%d]\n", level
));
7023 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7024 if (!foundBuiltin
) {
7025 numofforms
= get_ntforms(&list
);
7026 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7028 if (numofforms
== 0)
7035 fill_form_1(&form_1
, &builtin_form
);
7038 /* Check if the requested name is in the list of form structures */
7039 for (i
=0; i
<numofforms
; i
++) {
7041 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7043 if (strequal(form_name
, list
[i
].name
)) {
7044 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7045 fill_form_1(&form_1
, &list
[i
]);
7051 if (i
== numofforms
) {
7055 /* check the required size. */
7057 *needed
=spoolss_size_form_1(&form_1
);
7059 if (!alloc_buffer_size(buffer
, buffer_size
)){
7060 return WERR_INSUFFICIENT_BUFFER
;
7063 if (*needed
> offered
) {
7064 return WERR_INSUFFICIENT_BUFFER
;
7067 /* fill the buffer with the form structures */
7068 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7069 smb_io_form_1("", buffer
, &form_1
, 0);
7075 return WERR_UNKNOWN_LEVEL
;
7079 /****************************************************************************
7080 ****************************************************************************/
7082 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7084 init_unistr(&port
->port_name
, name
);
7087 /****************************************************************************
7088 ****************************************************************************/
7090 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7092 init_unistr(&port
->port_name
, name
);
7093 init_unistr(&port
->monitor_name
, "Local Monitor");
7094 init_unistr(&port
->description
, "Local Port");
7095 port
->port_type
=PORT_TYPE_WRITE
;
7099 /****************************************************************************
7101 ****************************************************************************/
7103 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7105 PORT_INFO_1
*ports
=NULL
;
7108 if (*lp_enumports_cmd()) {
7109 char *cmd
= lp_enumports_cmd();
7116 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7118 DEBUG(10,("Running [%s]\n", command
));
7119 ret
= smbrun(command
, &fd
);
7120 DEBUG(10,("Returned [%d]\n", ret
));
7124 /* Is this the best error to return here? */
7125 return WERR_ACCESS_DENIED
;
7129 qlines
= fd_lines_load(fd
, &numlines
);
7130 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7134 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
7135 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7136 dos_errstr(WERR_NOMEM
)));
7137 file_lines_free(qlines
);
7141 for (i
=0; i
<numlines
; i
++) {
7142 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7143 fill_port_1(&ports
[i
], qlines
[i
]);
7146 file_lines_free(qlines
);
7149 *returned
= numlines
;
7152 *returned
= 1; /* Sole Samba port returned. */
7154 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
7157 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7159 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7162 /* check the required size. */
7163 for (i
=0; i
<*returned
; i
++) {
7164 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7165 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7168 if (!alloc_buffer_size(buffer
, *needed
)) {
7170 return WERR_INSUFFICIENT_BUFFER
;
7173 /* fill the buffer with the ports structures */
7174 for (i
=0; i
<*returned
; i
++) {
7175 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7176 smb_io_port_1("", buffer
, &ports
[i
], 0);
7181 if (*needed
> offered
) {
7183 return WERR_INSUFFICIENT_BUFFER
;
7189 /****************************************************************************
7191 ****************************************************************************/
7193 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7195 PORT_INFO_2
*ports
=NULL
;
7198 if (*lp_enumports_cmd()) {
7199 char *cmd
= lp_enumports_cmd();
7208 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7209 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7211 path
= lp_lockdir();
7213 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7214 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7217 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7218 ret
= smbrun(command
, &fd
);
7219 DEBUGADD(10,("returned [%d]\n", ret
));
7223 /* Is this the best error to return here? */
7224 return WERR_ACCESS_DENIED
;
7228 qlines
= fd_lines_load(fd
, &numlines
);
7229 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7233 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7234 file_lines_free(qlines
);
7238 for (i
=0; i
<numlines
; i
++) {
7239 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7240 fill_port_2(&(ports
[i
]), qlines
[i
]);
7243 file_lines_free(qlines
);
7246 *returned
= numlines
;
7252 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7255 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7257 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7260 /* check the required size. */
7261 for (i
=0; i
<*returned
; i
++) {
7262 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7263 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7266 if (!alloc_buffer_size(buffer
, *needed
)) {
7268 return WERR_INSUFFICIENT_BUFFER
;
7271 /* fill the buffer with the ports structures */
7272 for (i
=0; i
<*returned
; i
++) {
7273 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7274 smb_io_port_2("", buffer
, &ports
[i
], 0);
7279 if (*needed
> offered
) {
7281 return WERR_INSUFFICIENT_BUFFER
;
7287 /****************************************************************************
7289 ****************************************************************************/
7291 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7293 uint32 level
= q_u
->level
;
7294 NEW_BUFFER
*buffer
= NULL
;
7295 uint32 offered
= q_u
->offered
;
7296 uint32
*needed
= &r_u
->needed
;
7297 uint32
*returned
= &r_u
->returned
;
7299 /* that's an [in out] buffer */
7300 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7301 buffer
= r_u
->buffer
;
7303 DEBUG(4,("_spoolss_enumports\n"));
7310 return enumports_level_1(buffer
, offered
, needed
, returned
);
7312 return enumports_level_2(buffer
, offered
, needed
, returned
);
7314 return WERR_UNKNOWN_LEVEL
;
7318 /****************************************************************************
7319 ****************************************************************************/
7321 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7322 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7323 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7324 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7327 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7330 WERROR err
= WERR_OK
;
7332 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7333 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7337 ZERO_STRUCTP(printer
);
7339 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7340 if (!convert_printer_info(info
, printer
, 2)) {
7341 free_a_printer(&printer
, 2);
7345 /* check to see if the printer already exists */
7347 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7348 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7349 printer
->info_2
->sharename
));
7350 free_a_printer(&printer
, 2);
7351 return WERR_PRINTER_ALREADY_EXISTS
;
7354 /* FIXME!!! smbd should check to see if the driver is installed before
7355 trying to add a printer like this --jerry */
7357 if (*lp_addprinter_cmd() ) {
7358 if ( !add_printer_hook(printer
) ) {
7359 free_a_printer(&printer
,2);
7360 return WERR_ACCESS_DENIED
;
7364 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
7365 printer
->info_2
->sharename
);
7368 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7369 free_a_printer(&printer
,2);
7370 return WERR_ACCESS_DENIED
;
7373 /* you must be a printer admin to add a new printer */
7374 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7375 free_a_printer(&printer
,2);
7376 return WERR_ACCESS_DENIED
;
7380 * Do sanity check on the requested changes for Samba.
7383 if (!check_printer_ok(printer
->info_2
, snum
)) {
7384 free_a_printer(&printer
,2);
7385 return WERR_INVALID_PARAM
;
7389 * When a printer is created, the drivername bound to the printer is used
7390 * to lookup previously saved driver initialization info, which is then
7391 * bound to the new printer, simulating what happens in the Windows arch.
7396 set_driver_init(printer
, 2);
7400 /* A valid devmode was included, convert and link it
7402 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7404 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7405 &printer
->info_2
->devmode
))
7409 /* write the ASCII on disk */
7410 err
= mod_a_printer(*printer
, 2);
7411 if (!W_ERROR_IS_OK(err
)) {
7412 free_a_printer(&printer
,2);
7416 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7417 /* Handle open failed - remove addition. */
7418 del_a_printer(printer
->info_2
->sharename
);
7419 free_a_printer(&printer
,2);
7420 return WERR_ACCESS_DENIED
;
7423 update_c_setprinter(False
);
7424 free_a_printer(&printer
,2);
7429 /****************************************************************************
7430 ****************************************************************************/
7432 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7434 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7435 uint32 level
= q_u
->level
;
7436 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7437 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7438 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7439 uint32 user_switch
= q_u
->user_switch
;
7440 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7441 POLICY_HND
*handle
= &r_u
->handle
;
7445 /* we don't handle yet */
7446 /* but I know what to do ... */
7447 return WERR_UNKNOWN_LEVEL
;
7449 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7451 user_switch
, user
, handle
);
7453 return WERR_UNKNOWN_LEVEL
;
7457 /****************************************************************************
7458 ****************************************************************************/
7460 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7462 uint32 level
= q_u
->level
;
7463 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7464 WERROR err
= WERR_OK
;
7465 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7466 struct current_user user
;
7467 fstring driver_name
;
7470 ZERO_STRUCT(driver
);
7472 get_current_user(&user
, p
);
7474 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7479 DEBUG(5,("Cleaning driver's information\n"));
7480 err
= clean_up_driver_struct(driver
, level
, &user
);
7481 if (!W_ERROR_IS_OK(err
))
7484 DEBUG(5,("Moving driver to final destination\n"));
7485 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7486 if (W_ERROR_IS_OK(err
))
7487 err
= WERR_ACCESS_DENIED
;
7491 if (add_a_printer_driver(driver
, level
)!=0) {
7492 err
= WERR_ACCESS_DENIED
;
7496 /* BEGIN_ADMIN_LOG */
7499 fstrcpy(driver_name
, driver
.info_3
->name
? driver
.info_3
->name
: "");
7500 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7501 driver_name
, get_drv_ver_to_os(driver
.info_3
->cversion
),uidtoname(user
.uid
));
7504 fstrcpy(driver_name
, driver
.info_6
->name
? driver
.info_6
->name
: "");
7505 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7506 driver_name
, get_drv_ver_to_os(driver
.info_6
->version
),uidtoname(user
.uid
));
7512 * I think this is where he DrvUpgradePrinter() hook would be
7513 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7514 * server. Right now, we just need to send ourselves a message
7515 * to update each printer bound to this driver. --jerry
7518 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7519 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7524 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7525 * decide if the driver init data should be deleted. The rules are:
7526 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7527 * 2) delete init data only if there is no 2k/Xp driver
7528 * 3) always delete init data
7529 * The generalized rule is always use init data from the highest order driver.
7530 * It is necessary to follow the driver install by an initialization step to
7531 * finish off this process.
7534 version
= driver
.info_3
->cversion
;
7535 else if (level
== 6)
7536 version
= driver
.info_6
->version
;
7541 * 9x printer driver - never delete init data
7544 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7549 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7550 * there is no 2k/Xp driver init data for this driver name.
7554 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7556 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7558 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7560 if (!del_driver_init(driver_name
))
7561 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7564 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7566 free_a_printer_driver(driver1
,3);
7567 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7574 * 2k or Xp printer driver - always delete init data
7577 if (!del_driver_init(driver_name
))
7578 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7582 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7588 free_a_printer_driver(driver
, level
);
7592 /********************************************************************
7593 * spoolss_addprinterdriverex
7594 ********************************************************************/
7596 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7598 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7599 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7602 * we only support the semantics of AddPrinterDriver()
7603 * i.e. only copy files that are newer than existing ones
7606 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7607 return WERR_ACCESS_DENIED
;
7609 ZERO_STRUCT(q_u_local
);
7610 ZERO_STRUCT(r_u_local
);
7612 /* just pass the information off to _spoolss_addprinterdriver() */
7613 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7614 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7615 q_u_local
.level
= q_u
->level
;
7616 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7618 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7621 /****************************************************************************
7622 ****************************************************************************/
7624 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7626 init_unistr(&info
->name
, name
);
7629 /****************************************************************************
7630 ****************************************************************************/
7632 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7636 const char *short_archi
;
7637 DRIVER_DIRECTORY_1
*info
=NULL
;
7639 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7641 if (!(short_archi
= get_short_archi(long_archi
)))
7642 return WERR_INVALID_ENVIRONMENT
;
7644 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7647 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7649 DEBUG(4,("printer driver directory: [%s]\n", path
));
7651 fill_driverdir_1(info
, path
);
7653 *needed
+= spoolss_size_driverdir_info_1(info
);
7655 if (!alloc_buffer_size(buffer
, *needed
)) {
7657 return WERR_INSUFFICIENT_BUFFER
;
7660 smb_io_driverdir_1("", buffer
, info
, 0);
7664 if (*needed
> offered
)
7665 return WERR_INSUFFICIENT_BUFFER
;
7670 /****************************************************************************
7671 ****************************************************************************/
7673 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7675 UNISTR2
*name
= &q_u
->name
;
7676 UNISTR2
*uni_environment
= &q_u
->environment
;
7677 uint32 level
= q_u
->level
;
7678 NEW_BUFFER
*buffer
= NULL
;
7679 uint32 offered
= q_u
->offered
;
7680 uint32
*needed
= &r_u
->needed
;
7682 /* that's an [in out] buffer */
7683 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7684 buffer
= r_u
->buffer
;
7686 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7692 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7694 return WERR_UNKNOWN_LEVEL
;
7698 /****************************************************************************
7699 ****************************************************************************/
7701 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7703 POLICY_HND
*handle
= &q_u
->handle
;
7704 uint32 idx
= q_u
->index
;
7705 uint32 in_value_len
= q_u
->valuesize
;
7706 uint32 in_data_len
= q_u
->datasize
;
7707 uint32
*out_max_value_len
= &r_u
->valuesize
;
7708 uint16
**out_value
= &r_u
->value
;
7709 uint32
*out_value_len
= &r_u
->realvaluesize
;
7710 uint32
*out_type
= &r_u
->type
;
7711 uint32
*out_max_data_len
= &r_u
->datasize
;
7712 uint8
**data_out
= &r_u
->data
;
7713 uint32
*out_data_len
= &r_u
->realdatasize
;
7715 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7717 uint32 biggest_valuesize
;
7718 uint32 biggest_datasize
;
7720 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7723 REGISTRY_VALUE
*val
= NULL
;
7724 NT_PRINTER_DATA
*p_data
;
7725 int i
, key_index
, num_values
;
7728 ZERO_STRUCT( printer
);
7732 *out_max_data_len
= 0;
7736 DEBUG(5,("spoolss_enumprinterdata\n"));
7739 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7743 if (!get_printer_snum(p
,handle
, &snum
))
7746 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7747 if (!W_ERROR_IS_OK(result
))
7750 p_data
= &printer
->info_2
->data
;
7751 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7756 * The NT machine wants to know the biggest size of value and data
7758 * cf: MSDN EnumPrinterData remark section
7761 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7763 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7765 biggest_valuesize
= 0;
7766 biggest_datasize
= 0;
7768 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7770 for ( i
=0; i
<num_values
; i
++ )
7772 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7774 name_length
= strlen(val
->valuename
);
7775 if ( strlen(val
->valuename
) > biggest_valuesize
)
7776 biggest_valuesize
= name_length
;
7778 if ( val
->size
> biggest_datasize
)
7779 biggest_datasize
= val
->size
;
7781 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7785 /* the value is an UNICODE string but real_value_size is the length
7786 in bytes including the trailing 0 */
7788 *out_value_len
= 2 * (1+biggest_valuesize
);
7789 *out_data_len
= biggest_datasize
;
7791 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7797 * the value len is wrong in NT sp3
7798 * that's the number of bytes not the number of unicode chars
7801 if ( key_index
!= -1 )
7802 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7807 /* out_value should default to "" or else NT4 has
7808 problems unmarshalling the response */
7810 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7812 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7814 result
= WERR_NOMEM
;
7818 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7820 /* the data is counted in bytes */
7822 *out_max_data_len
= in_data_len
;
7823 *out_data_len
= in_data_len
;
7825 /* only allocate when given a non-zero data_len */
7827 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7829 result
= WERR_NOMEM
;
7833 result
= WERR_NO_MORE_ITEMS
;
7839 * - counted in bytes in the request
7840 * - counted in UNICODE chars in the max reply
7841 * - counted in bytes in the real size
7843 * take a pause *before* coding not *during* coding
7847 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7848 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7850 result
= WERR_NOMEM
;
7854 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7858 *out_type
= regval_type( val
);
7860 /* data - counted in bytes */
7862 *out_max_data_len
= in_data_len
;
7863 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7865 result
= WERR_NOMEM
;
7868 data_len
= (size_t)regval_size(val
);
7869 memcpy( *data_out
, regval_data_p(val
), data_len
);
7870 *out_data_len
= data_len
;
7874 free_a_printer(&printer
, 2);
7878 /****************************************************************************
7879 ****************************************************************************/
7881 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7883 POLICY_HND
*handle
= &q_u
->handle
;
7884 UNISTR2
*value
= &q_u
->value
;
7885 uint32 type
= q_u
->type
;
7886 uint8
*data
= q_u
->data
;
7887 uint32 real_len
= q_u
->real_len
;
7889 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7891 WERROR status
= WERR_OK
;
7892 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7895 DEBUG(5,("spoolss_setprinterdata\n"));
7898 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7902 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
7903 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7904 return WERR_INVALID_PARAM
;
7907 if (!get_printer_snum(p
,handle
, &snum
))
7911 * Access check : NT returns "access denied" if you make a
7912 * SetPrinterData call without the necessary privildge.
7913 * we were originally returning OK if nothing changed
7914 * which made Win2k issue **a lot** of SetPrinterData
7915 * when connecting to a printer --jerry
7918 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
7920 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7921 status
= WERR_ACCESS_DENIED
;
7925 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7926 if (!W_ERROR_IS_OK(status
))
7929 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7932 * When client side code sets a magic printer data key, detect it and save
7933 * the current printer data and the magic key's data (its the DEVMODE) for
7934 * future printer/driver initializations.
7936 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
7938 /* Set devmode and printer initialization info */
7939 status
= save_driver_init( printer
, 2, data
, real_len
);
7941 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
7945 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
7946 type
, data
, real_len
);
7947 if ( W_ERROR_IS_OK(status
) )
7948 status
= mod_a_printer(*printer
, 2);
7952 free_a_printer(&printer
, 2);
7957 /****************************************************************************
7958 ****************************************************************************/
7960 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7962 POLICY_HND
*handle
= &q_u
->handle
;
7963 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7966 DEBUG(5,("_spoolss_resetprinter\n"));
7969 * All we do is to check to see if the handle and queue is valid.
7970 * This call really doesn't mean anything to us because we only
7971 * support RAW printing. --jerry
7975 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7979 if (!get_printer_snum(p
,handle
, &snum
))
7983 /* blindly return success */
7988 /****************************************************************************
7989 ****************************************************************************/
7991 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7993 POLICY_HND
*handle
= &q_u
->handle
;
7994 UNISTR2
*value
= &q_u
->valuename
;
7996 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7998 WERROR status
= WERR_OK
;
7999 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8002 DEBUG(5,("spoolss_deleteprinterdata\n"));
8005 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8009 if (!get_printer_snum(p
, handle
, &snum
))
8012 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8013 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8014 return WERR_ACCESS_DENIED
;
8017 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8018 if (!W_ERROR_IS_OK(status
))
8021 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8023 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8025 free_a_printer(&printer
, 2);
8030 /****************************************************************************
8031 ****************************************************************************/
8033 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8035 POLICY_HND
*handle
= &q_u
->handle
;
8036 FORM
*form
= &q_u
->form
;
8037 nt_forms_struct tmpForm
;
8039 WERROR status
= WERR_OK
;
8040 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8043 nt_forms_struct
*list
=NULL
;
8044 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8046 DEBUG(5,("spoolss_addform\n"));
8049 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8054 /* forms can be added on printer of on the print server handle */
8056 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8058 if (!get_printer_snum(p
,handle
, &snum
))
8061 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8062 if (!W_ERROR_IS_OK(status
))
8066 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8067 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8068 status
= WERR_ACCESS_DENIED
;
8072 /* can't add if builtin */
8074 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8075 status
= WERR_ALREADY_EXISTS
;
8079 count
= get_ntforms(&list
);
8081 if(!add_a_form(&list
, form
, &count
)) {
8082 status
= WERR_NOMEM
;
8086 write_ntforms(&list
, count
);
8089 * ChangeID must always be set if this is a printer
8092 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8093 status
= mod_a_printer(*printer
, 2);
8097 free_a_printer(&printer
, 2);
8103 /****************************************************************************
8104 ****************************************************************************/
8106 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8108 POLICY_HND
*handle
= &q_u
->handle
;
8109 UNISTR2
*form_name
= &q_u
->name
;
8110 nt_forms_struct tmpForm
;
8112 nt_forms_struct
*list
=NULL
;
8113 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8115 WERROR status
= WERR_OK
;
8116 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8118 DEBUG(5,("spoolss_deleteform\n"));
8121 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8125 /* forms can be deleted on printer of on the print server handle */
8127 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8129 if (!get_printer_snum(p
,handle
, &snum
))
8132 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8133 if (!W_ERROR_IS_OK(status
))
8137 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8138 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8139 status
= WERR_ACCESS_DENIED
;
8143 /* can't delete if builtin */
8145 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8146 status
= WERR_INVALID_PARAM
;
8150 count
= get_ntforms(&list
);
8152 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8156 * ChangeID must always be set if this is a printer
8159 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8160 status
= mod_a_printer(*printer
, 2);
8164 free_a_printer(&printer
, 2);
8170 /****************************************************************************
8171 ****************************************************************************/
8173 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8175 POLICY_HND
*handle
= &q_u
->handle
;
8176 FORM
*form
= &q_u
->form
;
8177 nt_forms_struct tmpForm
;
8179 WERROR status
= WERR_OK
;
8180 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8183 nt_forms_struct
*list
=NULL
;
8184 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8186 DEBUG(5,("spoolss_setform\n"));
8189 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8193 /* forms can be modified on printer of on the print server handle */
8195 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8197 if (!get_printer_snum(p
,handle
, &snum
))
8200 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8201 if (!W_ERROR_IS_OK(status
))
8205 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8206 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8207 status
= WERR_ACCESS_DENIED
;
8211 /* can't set if builtin */
8212 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8213 status
= WERR_INVALID_PARAM
;
8217 count
= get_ntforms(&list
);
8218 update_a_form(&list
, form
, count
);
8219 write_ntforms(&list
, count
);
8222 * ChangeID must always be set if this is a printer
8225 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8226 status
= mod_a_printer(*printer
, 2);
8231 free_a_printer(&printer
, 2);
8237 /****************************************************************************
8238 enumprintprocessors level 1.
8239 ****************************************************************************/
8241 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8243 PRINTPROCESSOR_1
*info_1
=NULL
;
8245 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8250 init_unistr(&info_1
->name
, "winprint");
8252 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8254 if (!alloc_buffer_size(buffer
, *needed
))
8255 return WERR_INSUFFICIENT_BUFFER
;
8257 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8261 if (*needed
> offered
) {
8263 return WERR_INSUFFICIENT_BUFFER
;
8269 /****************************************************************************
8270 ****************************************************************************/
8272 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8274 uint32 level
= q_u
->level
;
8275 NEW_BUFFER
*buffer
= NULL
;
8276 uint32 offered
= q_u
->offered
;
8277 uint32
*needed
= &r_u
->needed
;
8278 uint32
*returned
= &r_u
->returned
;
8280 /* that's an [in out] buffer */
8281 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8282 buffer
= r_u
->buffer
;
8284 DEBUG(5,("spoolss_enumprintprocessors\n"));
8287 * Enumerate the print processors ...
8289 * Just reply with "winprint", to keep NT happy
8290 * and I can use my nice printer checker.
8298 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8300 return WERR_UNKNOWN_LEVEL
;
8304 /****************************************************************************
8305 enumprintprocdatatypes level 1.
8306 ****************************************************************************/
8308 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8310 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8312 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8317 init_unistr(&info_1
->name
, "RAW");
8319 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8321 if (!alloc_buffer_size(buffer
, *needed
))
8322 return WERR_INSUFFICIENT_BUFFER
;
8324 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8328 if (*needed
> offered
) {
8330 return WERR_INSUFFICIENT_BUFFER
;
8336 /****************************************************************************
8337 ****************************************************************************/
8339 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8341 uint32 level
= q_u
->level
;
8342 NEW_BUFFER
*buffer
= NULL
;
8343 uint32 offered
= q_u
->offered
;
8344 uint32
*needed
= &r_u
->needed
;
8345 uint32
*returned
= &r_u
->returned
;
8347 /* that's an [in out] buffer */
8348 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8349 buffer
= r_u
->buffer
;
8351 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8358 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8360 return WERR_UNKNOWN_LEVEL
;
8364 /****************************************************************************
8365 enumprintmonitors level 1.
8366 ****************************************************************************/
8368 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8370 PRINTMONITOR_1
*info_1
=NULL
;
8372 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8377 init_unistr(&info_1
->name
, "Local Port");
8379 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8381 if (!alloc_buffer_size(buffer
, *needed
))
8382 return WERR_INSUFFICIENT_BUFFER
;
8384 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8388 if (*needed
> offered
) {
8390 return WERR_INSUFFICIENT_BUFFER
;
8396 /****************************************************************************
8397 enumprintmonitors level 2.
8398 ****************************************************************************/
8400 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8402 PRINTMONITOR_2
*info_2
=NULL
;
8404 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8409 init_unistr(&info_2
->name
, "Local Port");
8410 init_unistr(&info_2
->environment
, "Windows NT X86");
8411 init_unistr(&info_2
->dll_name
, "localmon.dll");
8413 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8415 if (!alloc_buffer_size(buffer
, *needed
))
8416 return WERR_INSUFFICIENT_BUFFER
;
8418 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8422 if (*needed
> offered
) {
8424 return WERR_INSUFFICIENT_BUFFER
;
8430 /****************************************************************************
8431 ****************************************************************************/
8433 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8435 uint32 level
= q_u
->level
;
8436 NEW_BUFFER
*buffer
= NULL
;
8437 uint32 offered
= q_u
->offered
;
8438 uint32
*needed
= &r_u
->needed
;
8439 uint32
*returned
= &r_u
->returned
;
8441 /* that's an [in out] buffer */
8442 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8443 buffer
= r_u
->buffer
;
8445 DEBUG(5,("spoolss_enumprintmonitors\n"));
8448 * Enumerate the print monitors ...
8450 * Just reply with "Local Port", to keep NT happy
8451 * and I can use my nice printer checker.
8459 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8461 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8463 return WERR_UNKNOWN_LEVEL
;
8467 /****************************************************************************
8468 ****************************************************************************/
8470 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8474 JOB_INFO_1
*info_1
=NULL
;
8476 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8478 if (info_1
== NULL
) {
8482 for (i
=0; i
<count
&& found
==False
; i
++) {
8483 if ((*queue
)[i
].job
==(int)jobid
)
8489 /* NT treats not found as bad param... yet another bad choice */
8490 return WERR_INVALID_PARAM
;
8493 fill_job_info_1(info_1
, &((*queue
)[i
-1]), i
, snum
);
8495 *needed
+= spoolss_size_job_info_1(info_1
);
8497 if (!alloc_buffer_size(buffer
, *needed
)) {
8499 return WERR_INSUFFICIENT_BUFFER
;
8502 smb_io_job_info_1("", buffer
, info_1
, 0);
8506 if (*needed
> offered
)
8507 return WERR_INSUFFICIENT_BUFFER
;
8512 /****************************************************************************
8513 ****************************************************************************/
8515 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
8520 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8522 DEVICEMODE
*devmode
= NULL
;
8523 NT_DEVICEMODE
*nt_devmode
= NULL
;
8525 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8527 ZERO_STRUCTP(info_2
);
8529 if (info_2
== NULL
) {
8534 for ( i
=0; i
<count
&& found
==False
; i
++ )
8536 if ((*queue
)[i
].job
== (int)jobid
)
8542 /* NT treats not found as bad param... yet another bad
8544 ret
= WERR_INVALID_PARAM
;
8548 ret
= get_a_printer(NULL
, &ntprinter
, 2, lp_const_servicename(snum
));
8549 if (!W_ERROR_IS_OK(ret
))
8553 * if the print job does not have a DEVMODE associated with it,
8554 * just use the one for the printer. A NULL devicemode is not
8555 * a failure condition
8558 if ( !(nt_devmode
=print_job_devmode( snum
, jobid
)) )
8559 devmode
= construct_dev_mode(snum
);
8561 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8562 ZERO_STRUCTP( devmode
);
8563 convert_nt_devicemode( devmode
, nt_devmode
);
8567 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8569 *needed
+= spoolss_size_job_info_2(info_2
);
8571 if (!alloc_buffer_size(buffer
, *needed
)) {
8572 ret
= WERR_INSUFFICIENT_BUFFER
;
8576 smb_io_job_info_2("", buffer
, info_2
, 0);
8578 if (*needed
> offered
) {
8579 ret
= WERR_INSUFFICIENT_BUFFER
;
8586 /* Cleanup allocated memory */
8588 free_job_info_2(info_2
); /* Also frees devmode */
8590 free_a_printer(&ntprinter
, 2);
8595 /****************************************************************************
8596 ****************************************************************************/
8598 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8600 POLICY_HND
*handle
= &q_u
->handle
;
8601 uint32 jobid
= q_u
->jobid
;
8602 uint32 level
= q_u
->level
;
8603 NEW_BUFFER
*buffer
= NULL
;
8604 uint32 offered
= q_u
->offered
;
8605 uint32
*needed
= &r_u
->needed
;
8606 WERROR wstatus
= WERR_OK
;
8610 print_queue_struct
*queue
= NULL
;
8611 print_status_struct prt_status
;
8613 /* that's an [in out] buffer */
8614 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8615 buffer
= r_u
->buffer
;
8617 DEBUG(5,("spoolss_getjob\n"));
8621 if (!get_printer_snum(p
, handle
, &snum
))
8624 count
= print_queue_status(snum
, &queue
, &prt_status
);
8626 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8627 count
, prt_status
.status
, prt_status
.message
));
8631 wstatus
= getjob_level_1(&queue
, count
, snum
, jobid
,
8632 buffer
, offered
, needed
);
8635 wstatus
= getjob_level_2(&queue
, count
, snum
, jobid
,
8636 buffer
, offered
, needed
);
8639 wstatus
= WERR_UNKNOWN_LEVEL
;
8647 /********************************************************************
8648 spoolss_getprinterdataex
8650 From MSDN documentation of GetPrinterDataEx: pass request
8651 to GetPrinterData if key is "PrinterDriverData".
8652 ********************************************************************/
8654 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8656 POLICY_HND
*handle
= &q_u
->handle
;
8657 uint32 in_size
= q_u
->size
;
8658 uint32
*type
= &r_u
->type
;
8659 uint32
*out_size
= &r_u
->size
;
8660 uint8
**data
= &r_u
->data
;
8661 uint32
*needed
= &r_u
->needed
;
8662 fstring keyname
, valuename
;
8664 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8666 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8668 WERROR status
= WERR_OK
;
8670 DEBUG(4,("_spoolss_getprinterdataex\n"));
8672 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8673 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8675 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8676 keyname
, valuename
));
8678 /* in case of problem, return some default values */
8682 *out_size
= in_size
;
8685 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8686 status
= WERR_BADFID
;
8690 /* Is the handle to a printer or to the server? */
8692 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8693 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8694 status
= WERR_INVALID_PARAM
;
8698 if ( !get_printer_snum(p
,handle
, &snum
) )
8701 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8702 if ( !W_ERROR_IS_OK(status
) )
8705 /* check to see if the keyname is valid */
8706 if ( !strlen(keyname
) ) {
8707 status
= WERR_INVALID_PARAM
;
8711 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8712 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8713 free_a_printer( &printer
, 2 );
8714 status
= WERR_BADFILE
;
8718 /* When given a new keyname, we should just create it */
8720 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8722 if (*needed
> *out_size
)
8723 status
= WERR_MORE_DATA
;
8726 if ( !W_ERROR_IS_OK(status
) )
8728 DEBUG(5, ("error: allocating %d\n", *out_size
));
8730 /* reply this param doesn't exist */
8734 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8735 status
= WERR_NOMEM
;
8745 free_a_printer( &printer
, 2 );
8750 /********************************************************************
8751 * spoolss_setprinterdataex
8752 ********************************************************************/
8754 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8756 POLICY_HND
*handle
= &q_u
->handle
;
8757 uint32 type
= q_u
->type
;
8758 uint8
*data
= q_u
->data
;
8759 uint32 real_len
= q_u
->real_len
;
8761 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8763 WERROR status
= WERR_OK
;
8764 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8769 DEBUG(4,("_spoolss_setprinterdataex\n"));
8771 /* From MSDN documentation of SetPrinterDataEx: pass request to
8772 SetPrinterData if key is "PrinterDriverData" */
8775 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8779 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8780 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8781 return WERR_INVALID_PARAM
;
8784 if ( !get_printer_snum(p
,handle
, &snum
) )
8788 * Access check : NT returns "access denied" if you make a
8789 * SetPrinterData call without the necessary privildge.
8790 * we were originally returning OK if nothing changed
8791 * which made Win2k issue **a lot** of SetPrinterData
8792 * when connecting to a printer --jerry
8795 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8797 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8798 return WERR_ACCESS_DENIED
;
8801 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8802 if (!W_ERROR_IS_OK(status
))
8805 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8806 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8808 /* check for OID in valuename */
8810 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8816 /* save the registry data */
8818 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8820 if ( W_ERROR_IS_OK(status
) )
8822 /* save the OID if one was specified */
8824 fstrcat( keyname
, "\\" );
8825 fstrcat( keyname
, SPOOL_OID_KEY
);
8828 * I'm not checking the status here on purpose. Don't know
8829 * if this is right, but I'm returning the status from the
8830 * previous set_printer_dataex() call. I have no idea if
8831 * this is right. --jerry
8834 set_printer_dataex( printer
, keyname
, valuename
,
8835 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8838 status
= mod_a_printer(*printer
, 2);
8841 free_a_printer(&printer
, 2);
8847 /********************************************************************
8848 * spoolss_deleteprinterdataex
8849 ********************************************************************/
8851 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8853 POLICY_HND
*handle
= &q_u
->handle
;
8854 UNISTR2
*value
= &q_u
->valuename
;
8855 UNISTR2
*key
= &q_u
->keyname
;
8857 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8859 WERROR status
= WERR_OK
;
8860 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8861 pstring valuename
, keyname
;
8863 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8866 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8870 if (!get_printer_snum(p
, handle
, &snum
))
8873 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8874 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8875 return WERR_ACCESS_DENIED
;
8878 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8879 if (!W_ERROR_IS_OK(status
))
8882 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8883 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8885 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8887 free_a_printer(&printer
, 2);
8892 /********************************************************************
8893 * spoolss_enumprinterkey
8894 ********************************************************************/
8897 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8900 fstring
*keynames
= NULL
;
8901 uint16
*enumkeys
= NULL
;
8904 POLICY_HND
*handle
= &q_u
->handle
;
8905 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8906 NT_PRINTER_DATA
*data
;
8907 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8909 WERROR status
= WERR_BADFILE
;
8912 DEBUG(4,("_spoolss_enumprinterkey\n"));
8915 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8919 if ( !get_printer_snum(p
,handle
, &snum
) )
8922 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8923 if (!W_ERROR_IS_OK(status
))
8926 /* get the list of subkey names */
8928 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
8929 data
= &printer
->info_2
->data
;
8931 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
8933 if ( num_keys
== -1 ) {
8934 status
= WERR_BADFILE
;
8938 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
8940 r_u
->needed
= printerkey_len
*2;
8942 if ( q_u
->size
< r_u
->needed
) {
8943 status
= WERR_MORE_DATA
;
8947 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
8948 status
= WERR_NOMEM
;
8954 if ( q_u
->size
< r_u
->needed
)
8955 status
= WERR_MORE_DATA
;
8958 free_a_printer( &printer
, 2 );
8959 SAFE_FREE( keynames
);
8964 /********************************************************************
8965 * spoolss_deleteprinterkey
8966 ********************************************************************/
8968 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8970 POLICY_HND
*handle
= &q_u
->handle
;
8971 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8973 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8977 DEBUG(5,("spoolss_deleteprinterkey\n"));
8980 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8984 /* if keyname == NULL, return error */
8986 if ( !q_u
->keyname
.buffer
)
8987 return WERR_INVALID_PARAM
;
8989 if (!get_printer_snum(p
, handle
, &snum
))
8992 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8993 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
8994 return WERR_ACCESS_DENIED
;
8997 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8998 if (!W_ERROR_IS_OK(status
))
9001 /* delete the key and all subneys */
9003 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9005 status
= delete_all_printer_data( printer
->info_2
, key
);
9007 if ( W_ERROR_IS_OK(status
) )
9008 status
= mod_a_printer(*printer
, 2);
9010 free_a_printer( &printer
, 2 );
9016 /********************************************************************
9017 * spoolss_enumprinterdataex
9018 ********************************************************************/
9020 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9022 POLICY_HND
*handle
= &q_u
->handle
;
9023 uint32 in_size
= q_u
->size
;
9026 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9027 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9028 NT_PRINTER_DATA
*p_data
;
9030 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9035 REGISTRY_VALUE
*val
;
9040 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9043 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9048 * first check for a keyname of NULL or "". Win2k seems to send
9049 * this a lot and we should send back WERR_INVALID_PARAM
9050 * no need to spend time looking up the printer in this case.
9054 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9055 if ( !strlen(key
) ) {
9056 result
= WERR_INVALID_PARAM
;
9060 /* get the printer off of disk */
9062 if (!get_printer_snum(p
,handle
, &snum
))
9065 ZERO_STRUCT(printer
);
9066 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9067 if (!W_ERROR_IS_OK(result
))
9070 /* now look for a match on the key name */
9072 p_data
= &printer
->info_2
->data
;
9074 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9075 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9077 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9078 result
= WERR_INVALID_PARAM
;
9085 /* allocate the memory for the array of pointers -- if necessary */
9087 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
9090 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
9092 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9093 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9094 result
= WERR_NOMEM
;
9098 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9102 * loop through all params and build the array to pass
9103 * back to the client
9106 for ( i
=0; i
<num_entries
; i
++ )
9108 /* lookup the registry value */
9110 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
9111 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9115 value_name
= regval_name( val
);
9116 init_unistr( &enum_values
[i
].valuename
, value_name
);
9117 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9118 enum_values
[i
].type
= regval_type( val
);
9120 data_len
= regval_size( val
);
9122 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9124 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9126 result
= WERR_NOMEM
;
9130 enum_values
[i
].data_len
= data_len
;
9132 /* keep track of the size of the array in bytes */
9134 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9137 /* housekeeping information in the reply */
9139 r_u
->needed
= needed
;
9140 r_u
->returned
= num_entries
;
9142 if (needed
> in_size
) {
9143 result
= WERR_MORE_DATA
;
9147 /* copy data into the reply */
9149 r_u
->ctr
.size
= r_u
->needed
;
9150 r_u
->ctr
.size_of_array
= r_u
->returned
;
9151 r_u
->ctr
.values
= enum_values
;
9157 free_a_printer(&printer
, 2);
9162 /****************************************************************************
9163 ****************************************************************************/
9165 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9167 init_unistr(&info
->name
, name
);
9170 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9171 UNISTR2
*environment
,
9178 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9180 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9182 if (!get_short_archi(long_archi
))
9183 return WERR_INVALID_ENVIRONMENT
;
9185 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
9188 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9190 fill_printprocessordirectory_1(info
, path
);
9192 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9194 if (!alloc_buffer_size(buffer
, *needed
)) {
9196 return WERR_INSUFFICIENT_BUFFER
;
9199 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9203 if (*needed
> offered
)
9204 return WERR_INSUFFICIENT_BUFFER
;
9209 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9211 uint32 level
= q_u
->level
;
9212 NEW_BUFFER
*buffer
= NULL
;
9213 uint32 offered
= q_u
->offered
;
9214 uint32
*needed
= &r_u
->needed
;
9217 /* that's an [in out] buffer */
9218 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
9219 buffer
= r_u
->buffer
;
9221 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9227 result
= getprintprocessordirectory_level_1
9228 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9231 result
= WERR_UNKNOWN_LEVEL
;
9239 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9240 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9242 DEBUG(5,("_spoolss_replyopenprinter\n"));
9244 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9249 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9250 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9252 DEBUG(5,("_spoolss_replycloseprinter\n"));