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,
8 * Copyright (C) Gerald Carter 2000-2002,
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
33 /* #define EMULATE_WIN2K_HACK 1 */
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
41 #define PRINTER_HANDLE_IS_PRINTER 0
42 #define PRINTER_HANDLE_IS_PRINTSERVER 1
44 /* Table to map the driver version */
46 char * drv_ver_to_os
[] = {
47 "WIN9X", /* driver version/cversion 0 */
49 "WINNT", /* driver version/cversion 2 */
50 "WIN2K", /* driver version/cversion 3 */
60 /* structure to store the printer handles */
61 /* and a reference to what it's pointing to */
62 /* and the notify info asked about */
63 /* that's the central struct */
64 typedef struct _Printer
{
65 struct _Printer
*prev
, *next
;
66 BOOL document_started
;
68 uint32 jobid
; /* jobid in printing backend */
72 fstring printerservername
;
75 uint32 access_granted
;
81 SPOOL_NOTIFY_OPTION
*option
;
82 POLICY_HND client_hnd
;
83 uint32 client_connected
;
92 static Printer_entry
*printers_list
;
94 typedef struct _counter_printer_0
{
102 static ubi_dlList counter_list
;
104 static struct cli_state notify_cli
; /* print notify back-channel */
105 static uint32 smb_connections
=0;
108 /* in printing/nt_printing.c */
110 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
112 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
113 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
115 /* translate between internal status numbers and NT status numbers */
116 static int nt_printj_status(int v
)
122 return JOB_STATUS_PAUSED
;
124 return JOB_STATUS_SPOOLING
;
126 return JOB_STATUS_PRINTING
;
128 return JOB_STATUS_ERROR
;
130 return JOB_STATUS_DELETING
;
132 return JOB_STATUS_OFFLINE
;
134 return JOB_STATUS_PAPEROUT
;
136 return JOB_STATUS_PRINTED
;
138 return JOB_STATUS_DELETED
;
140 return JOB_STATUS_BLOCKED
;
141 case LPQ_USER_INTERVENTION
:
142 return JOB_STATUS_USER_INTERVENTION
;
147 static int nt_printq_status(int v
)
151 return PRINTER_STATUS_PAUSED
;
160 /****************************************************************************
161 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
162 ****************************************************************************/
164 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
169 SAFE_FREE((*pp
)->ctr
.type
);
173 /***************************************************************************
174 Disconnect from the client
175 ****************************************************************************/
177 static void srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
181 /* weird if the test succeds !!! */
182 if (smb_connections
==0) {
183 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
187 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
189 if (!W_ERROR_IS_OK(result
))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 dos_errstr(result
)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections
==1) {
195 cli_nt_session_close(¬ify_cli
);
196 cli_ulogoff(¬ify_cli
);
197 cli_shutdown(¬ify_cli
);
198 message_deregister(MSG_PRINTER_NOTIFY2
);
204 /****************************************************************************
205 Functions to free a printer entry datastruct.
206 ****************************************************************************/
208 static void free_printer_entry(void *ptr
)
210 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
212 if (Printer
->notify
.client_connected
==True
)
213 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
215 Printer
->notify
.flags
=0;
216 Printer
->notify
.options
=0;
217 Printer
->notify
.localmachine
[0]='\0';
218 Printer
->notify
.printerlocal
=0;
219 free_spool_notify_option(&Printer
->notify
.option
);
220 Printer
->notify
.option
=NULL
;
221 Printer
->notify
.client_connected
=False
;
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list
, Printer
);
229 /****************************************************************************
230 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
231 ****************************************************************************/
233 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
235 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
240 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
247 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
249 if (!new_sp
->ctr
.type
) {
258 /****************************************************************************
259 find printer index by handle
260 ****************************************************************************/
262 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
264 Printer_entry
*find_printer
= NULL
;
266 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
280 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
287 close_policy_hnd(p
, hnd
);
292 /****************************************************************************
293 Delete a printer given a handle.
294 ****************************************************************************/
296 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
298 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
301 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
305 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
306 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
310 /* Check calling user has permission to delete printer. Note that
311 since we set the snum parameter to -1 only administrators can
312 delete the printer. This stops people with the Full Control
313 permission from deleting the printer. */
315 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
316 DEBUG(3, ("printer delete denied by security descriptor\n"));
317 return WERR_ACCESS_DENIED
;
320 if (*lp_deleteprinter_cmd()) {
322 char *cmd
= lp_deleteprinter_cmd();
327 /* Printer->dev.handlename equals portname equals sharename */
328 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
329 Printer
->dev
.handlename
);
331 DEBUG(10,("Running [%s]\n", command
));
332 ret
= smbrun(command
, NULL
);
334 return WERR_BADFID
; /* What to return here? */
336 DEBUGADD(10,("returned [%d]\n", ret
));
338 /* Send SIGHUP to process group... is there a better way? */
341 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) >= 0 ) {
345 return WERR_ACCESS_DENIED
;
351 /****************************************************************************
352 Return the snum of a printer corresponding to an handle.
353 ****************************************************************************/
355 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
357 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
360 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
364 switch (Printer
->printer_type
) {
365 case PRINTER_HANDLE_IS_PRINTER
:
366 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
367 *number
= print_queue_snum(Printer
->dev
.handlename
);
368 return (*number
!= -1);
369 case PRINTER_HANDLE_IS_PRINTSERVER
:
376 /****************************************************************************
377 Set printer handle type.
378 Check if it's \\server or \\server\printer
379 ****************************************************************************/
381 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
383 DEBUG(3,("Setting printer type=%s\n", handlename
));
385 if ( strlen(handlename
) < 3 ) {
386 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
390 /* it's a print server */
391 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
392 DEBUGADD(4,("Printer is a print server\n"));
393 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
397 DEBUGADD(4,("Printer is a printer\n"));
398 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
404 /****************************************************************************
405 Set printer handle name.
406 ****************************************************************************/
408 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
411 int n_services
=lp_numservices();
416 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
418 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
419 ZERO_STRUCT(Printer
->dev
.printerservername
);
420 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
424 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
427 if (*handlename
=='\\') {
428 aprinter
=strchr_m(handlename
+2, '\\');
435 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
438 * The original code allowed smbd to store a printer name that
439 * was different from the share name. This is not possible
440 * anymore, so I've simplified this loop greatly. Here
441 * we are just verifying that the printer name is a valid
442 * printer service defined in smb.conf
443 * --jerry [Fri Feb 15 11:17:46 CST 2002]
446 for (snum
=0; snum
<n_services
; snum
++) {
448 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
451 fstrcpy(sname
, lp_servicename(snum
));
453 DEBUGADD(5,("share:%s\n",sname
));
455 if (! StrCaseCmp(sname
, aprinter
)) {
464 DEBUGADD(4,("Printer not found\n"));
468 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
470 ZERO_STRUCT(Printer
->dev
.handlename
);
471 fstrcpy(Printer
->dev
.handlename
, sname
);
476 /****************************************************************************
477 Find first available printer slot. creates a printer handle for you.
478 ****************************************************************************/
480 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
482 Printer_entry
*new_printer
;
484 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
486 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
489 ZERO_STRUCTP(new_printer
);
491 new_printer
->notify
.option
=NULL
;
493 /* Add to the internal list. */
494 DLIST_ADD(printers_list
, new_printer
);
496 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
497 SAFE_FREE(new_printer
);
501 if (!set_printer_hnd_printertype(new_printer
, name
)) {
502 close_printer_handle(p
, hnd
);
506 if (!set_printer_hnd_name(new_printer
, name
)) {
507 close_printer_handle(p
, hnd
);
511 new_printer
->access_granted
= access_granted
;
513 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
518 /****************************************************************************
519 Allocate more memory for a BUFFER.
520 ****************************************************************************/
522 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
530 /* damn, I'm doing the reverse operation of prs_grow() :) */
531 if (buffer_size
< prs_data_size(ps
))
534 extra_space
= buffer_size
- prs_data_size(ps
);
537 * save the offset and move to the end of the buffer
538 * prs_grow() checks the extra_space against the offset
540 old_offset
=prs_offset(ps
);
541 prs_set_offset(ps
, prs_data_size(ps
));
543 if (!prs_grow(ps
, extra_space
))
546 prs_set_offset(ps
, old_offset
);
548 buffer
->string_at_end
=prs_data_size(ps
);
553 /***************************************************************************
554 check to see if the client motify handle is monitoring the notification
555 given by (notify_type, notify_field).
556 **************************************************************************/
558 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
564 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
567 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
571 return is_monitoring_event_flags(
572 p
->notify
.flags
, notify_type
, notify_field
);
574 for (i
= 0; i
< option
->count
; i
++) {
576 /* Check match for notify_type */
578 if (option
->ctr
.type
[i
].type
!= notify_type
)
581 /* Check match for field */
583 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
584 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
590 DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
591 (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) ?
592 p
->dev
.handlename
: p
->dev
.printerservername
,
593 notify_type
, notify_field
));
598 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
600 static void notify_one_value(struct spoolss_notify_msg
*msg
,
601 SPOOL_NOTIFY_INFO_DATA
*data
,
604 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
605 data
->notify_data
.value
[1] = 0;
608 static void notify_string(struct spoolss_notify_msg
*msg
,
609 SPOOL_NOTIFY_INFO_DATA
*data
,
614 /* The length of the message includes the trailing \0 */
616 init_unistr2(&unistr
, msg
->notify
.data
, msg
->len
);
618 data
->notify_data
.data
.length
= msg
->len
* 2;
619 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
621 if (!data
->notify_data
.data
.string
) {
622 data
->notify_data
.data
.length
= 0;
626 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
629 static void notify_system_time(struct spoolss_notify_msg
*msg
,
630 SPOOL_NOTIFY_INFO_DATA
*data
,
636 if (msg
->len
!= sizeof(time_t)) {
637 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
642 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
643 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
647 if (!make_systemtime(&systime
, localtime((time_t *)msg
->notify
.data
))) {
648 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
652 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
655 data
->notify_data
.data
.length
= prs_offset(&ps
);
656 data
->notify_data
.data
.string
=
657 talloc(mem_ctx
, prs_offset(&ps
));
659 memcpy(data
->notify_data
.data
.string
, prs_data_p(&ps
), prs_offset(&ps
));
664 struct notify2_message_table
{
666 void (*fn
)(struct spoolss_notify_msg
*msg
,
667 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
670 static struct notify2_message_table printer_notify_table
[] = {
671 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
686 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
687 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
688 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
689 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
692 static struct notify2_message_table job_notify_table
[] = {
693 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
694 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
695 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
696 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
697 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
698 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
699 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
700 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
701 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
702 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
703 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
704 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
705 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
706 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
707 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
708 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
709 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
710 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
711 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
712 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
713 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
714 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
715 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
716 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
719 /***********************************************************************
720 Send a change notication message on all handles which have a call
722 **********************************************************************/
724 static void process_notify2_message(struct spoolss_notify_msg
*msg
,
729 DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg
->printer
));
731 for (p
= printers_list
; p
; p
= p
->next
) {
732 SPOOL_NOTIFY_INFO_DATA
*data
;
736 /* Is there notification on this handle? */
738 if (!p
->notify
.client_connected
)
741 DEBUG(10,("Client connected! [%s]\n", p
->dev
.handlename
));
743 /* For this printer? Print servers always receive
746 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
747 ( !strequal(msg
->printer
, p
->dev
.handlename
) ) )
750 DEBUG(10,("Our printer\n"));
752 /* Are we monitoring this event? */
754 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
757 DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
758 msg
->type
, msg
->field
, p
->dev
.handlename
));
760 /* OK - send the event to the client */
762 data
= talloc(mem_ctx
, sizeof(SPOOL_NOTIFY_INFO_DATA
));
767 * if the is a printer notification handle and not a job notification
768 * type, then set the id to 0. Other wise just use what was specified
771 * When registering change notification on a print server handle
772 * we always need to send back the id (snum) matching the printer
773 * for which the change took place. For change notify registered
774 * on a printer handle, this does not matter and the id should be 0.
779 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
785 /* Convert unix jobid to smb jobid */
787 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
789 id
= sysjob_to_jobid(msg
->id
);
792 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
797 construct_info_data(data
, msg
->type
, msg
->field
, id
);
800 case PRINTER_NOTIFY_TYPE
:
801 if ( !printer_notify_table
[msg
->field
].fn
)
804 printer_notify_table
[msg
->field
].fn(msg
, data
, mem_ctx
);
808 case JOB_NOTIFY_TYPE
:
809 if ( !job_notify_table
[msg
->field
].fn
)
812 job_notify_table
[msg
->field
].fn(msg
, data
, mem_ctx
);
817 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
821 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
822 data_len
, data
, p
->notify
.change
, 0 );
825 DEBUG(8,("process_notify2_message: Exit...\n"));
829 /* Receive a notify2 message */
831 static void receive_notify2_message(int msg_type
, pid_t src
, void *buf
,
834 struct spoolss_notify_msg msg
;
836 TALLOC_CTX
*mem_ctx
= talloc_init();
842 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
845 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddd",
846 &msg
.type
, &msg
.field
, &msg
.id
, &msg
.len
, &msg
.flags
);
849 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
850 &msg
.notify
.value
[0], &msg
.notify
.value
[1]);
852 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
853 &msg
.len
, &msg
.notify
.data
);
855 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
856 msg
.type
, msg
.field
, msg
.flags
));
859 DEBUG(3, ("value1 = %d, value2 = %d\n", msg
.notify
.value
[0],
860 msg
.notify
.value
[1]));
862 dump_data(3, msg
.notify
.data
, msg
.len
);
864 /* Process message */
866 process_notify2_message(&msg
, mem_ctx
);
871 free(msg
.notify
.data
);
873 talloc_destroy(mem_ctx
);
876 /********************************************************************
877 Send a message to ourself about new driver being installed
878 so we can upgrade the information for each printer bound to this
880 ********************************************************************/
882 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
884 int len
= strlen(drivername
);
889 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
892 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
897 /**********************************************************************
898 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
899 over all printers, upgrading ones as neessary
900 **********************************************************************/
902 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
906 int n_services
= lp_numservices();
908 len
= MIN(len
,sizeof(drivername
)-1);
909 strncpy(drivername
, buf
, len
);
911 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
913 /* Iterate the printer list */
915 for (snum
=0; snum
<n_services
; snum
++)
917 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
920 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
922 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
923 if (!W_ERROR_IS_OK(result
))
926 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
928 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
930 /* all we care about currently is the change_id */
932 result
= mod_a_printer(*printer
, 2);
933 if (!W_ERROR_IS_OK(result
)) {
934 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
935 dos_errstr(result
)));
939 free_a_printer(&printer
, 2);
946 /********************************************************************
947 Send a message to ourself about new driver being installed
948 so we can upgrade the information for each printer bound to this
950 ********************************************************************/
952 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
954 int len
= strlen(drivername
);
959 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
962 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
967 /**********************************************************************
968 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
969 over all printers, resetting printer data as neessary
970 **********************************************************************/
972 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
976 int n_services
= lp_numservices();
978 len
= MIN( len
, sizeof(drivername
)-1 );
979 strncpy( drivername
, buf
, len
);
981 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
983 /* Iterate the printer list */
985 for ( snum
=0; snum
<n_services
; snum
++ )
987 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
990 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
992 result
= get_a_printer( &printer
, 2, lp_servicename(snum
) );
993 if ( !W_ERROR_IS_OK(result
) )
997 * if the printer is bound to the driver,
998 * then reset to the new driver initdata
1001 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1003 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1005 if ( !set_driver_init(printer
, 2) ) {
1006 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1007 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1011 free_a_printer( &printer
, 2 );
1020 /********************************************************************
1021 Copy routines used by convert_to_openprinterex()
1022 *******************************************************************/
1024 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1032 DEBUG (8,("dup_devmode\n"));
1034 /* bulk copy first */
1036 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1040 /* dup the pointer members separately */
1042 len
= unistrlen(devmode
->devicename
.buffer
);
1044 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1045 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1050 len
= unistrlen(devmode
->formname
.buffer
);
1052 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1053 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1057 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1062 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1064 if (!new_ctr
|| !ctr
)
1067 DEBUG(8,("copy_devmode_ctr\n"));
1069 new_ctr
->size
= ctr
->size
;
1070 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1072 if(ctr
->devmode_ptr
)
1073 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1076 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1078 if (!new_def
|| !def
)
1081 DEBUG(8,("copy_printer_defaults\n"));
1083 new_def
->datatype_ptr
= def
->datatype_ptr
;
1085 if (def
->datatype_ptr
)
1086 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1088 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1090 new_def
->access_required
= def
->access_required
;
1093 /********************************************************************
1094 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1095 * SPOOL_Q_OPEN_PRINTER_EX structure
1096 ********************************************************************/
1098 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1100 if (!q_u_ex
|| !q_u
)
1103 DEBUG(8,("convert_to_openprinterex\n"));
1105 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1107 if (q_u
->printername_ptr
)
1108 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1110 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1113 /********************************************************************
1114 * spoolss_open_printer
1116 * called from the spoolss dispatcher
1117 ********************************************************************/
1119 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1121 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1122 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1127 ZERO_STRUCT(q_u_ex
);
1128 ZERO_STRUCT(r_u_ex
);
1130 /* convert the OpenPrinter() call to OpenPrinterEx() */
1132 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1134 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1136 /* convert back to OpenPrinter() */
1138 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1143 /********************************************************************
1144 * spoolss_open_printer
1146 * called from the spoolss dispatcher
1147 ********************************************************************/
1149 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1151 UNISTR2
*printername
= NULL
;
1152 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1153 POLICY_HND
*handle
= &r_u
->handle
;
1157 struct current_user user
;
1158 Printer_entry
*Printer
=NULL
;
1160 if (q_u
->printername_ptr
!= 0)
1161 printername
= &q_u
->printername
;
1163 if (printername
== NULL
)
1164 return WERR_INVALID_PRINTER_NAME
;
1166 /* some sanity check because you can open a printer or a print server */
1167 /* aka: \\server\printer or \\server */
1168 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1170 DEBUGADD(3,("checking name: %s\n",name
));
1172 if (!open_printer_hnd(p
, handle
, name
, 0))
1173 return WERR_INVALID_PRINTER_NAME
;
1175 Printer
=find_printer_index_by_hnd(p
, handle
);
1177 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1178 Can't find printer handle we created for printer %s\n", name
));
1179 close_printer_handle(p
,handle
);
1180 return WERR_INVALID_PRINTER_NAME
;
1184 First case: the user is opening the print server:
1186 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1187 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1189 Then both Win2k and WinNT clients try an OpenPrinterEx with
1190 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1191 or if the user is listed in the smb.conf printer admin parameter.
1193 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1194 client view printer folder, but does not show the MSAPW.
1196 Note: this test needs code to check access rights here too. Jeremy
1197 could you look at this?
1200 Second case: the user is opening a printer:
1201 NT doesn't let us connect to a printer if the connecting user
1202 doesn't have print permission.
1206 get_current_user(&user
, p
);
1208 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
1210 /* Printserver handles use global struct... */
1214 /* Map standard access rights to object specific access
1217 se_map_standard(&printer_default
->access_required
,
1218 &printserver_std_mapping
);
1220 /* Deny any object specific bits that don't apply to print
1221 servers (i.e printer and job specific bits) */
1223 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1225 if (printer_default
->access_required
&
1226 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1227 DEBUG(3, ("access DENIED for non-printserver bits"));
1228 close_printer_handle(p
, handle
);
1229 return WERR_ACCESS_DENIED
;
1232 /* Allow admin access */
1234 if (printer_default
->access_required
&
1235 SERVER_ACCESS_ADMINISTER
) {
1237 if (!lp_ms_add_printer_wizard()) {
1238 close_printer_handle(p
, handle
);
1239 return WERR_ACCESS_DENIED
;
1242 if (user
.uid
== 0 ||
1243 user_in_list(uidtoname(user
.uid
),
1244 lp_printer_admin(snum
)))
1247 close_printer_handle(p
, handle
);
1248 return WERR_ACCESS_DENIED
;
1251 /* We fall through to return WERR_OK */
1256 /* NT doesn't let us connect to a printer if the connecting user
1257 doesn't have print permission. */
1259 if (!get_printer_snum(p
, handle
, &snum
))
1262 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1264 /* map an empty access mask to the minimum access mask */
1265 if (printer_default
->access_required
== 0x0)
1266 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1269 * If we are not serving the printer driver for this printer,
1270 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1271 * will keep NT clients happy --jerry
1274 if (lp_use_client_driver(snum
)
1275 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1277 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1280 /* check smb.conf parameters and the the sec_desc */
1282 if (!user_ok(uidtoname(user
.uid
), snum
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1283 DEBUG(3, ("access DENIED for printer open\n"));
1284 close_printer_handle(p
, handle
);
1285 return WERR_ACCESS_DENIED
;
1288 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1289 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1290 close_printer_handle(p
, handle
);
1291 return WERR_ACCESS_DENIED
;
1294 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1295 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1297 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1299 DEBUG(4,("Setting printer access=%x\n", printer_default
->access_required
));
1300 Printer
->access_granted
= printer_default
->access_required
;
1303 * If we have a default device pointer in the
1304 * printer_default struct, then we need to get
1305 * the printer info from the tdb and if there is
1306 * no default devicemode there then we do a *SET*
1307 * here ! This is insanity.... JRA.
1311 * If the openprinterex rpc call contains a devmode,
1312 * it's a per-user one. This per-user devmode is derivated
1313 * from the global devmode. Openprinterex() contains a per-user
1314 * devmode for when you do EMF printing and spooling.
1315 * In the EMF case, the NT workstation is only doing half the job
1316 * of rendering the page. The other half is done by running the printer
1317 * driver on the server.
1318 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1319 * The EMF file only contains what is to be printed on the page.
1320 * So in order for the server to know how to print, the NT client sends
1321 * a devicemode attached to the openprinterex call.
1322 * But this devicemode is short lived, it's only valid for the current print job.
1324 * If Samba would have supported EMF spooling, this devicemode would
1325 * have been attached to the handle, to sent it to the driver to correctly
1326 * rasterize the EMF file.
1328 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1329 * we just act as a pass-thru between windows and the printer.
1331 * In order to know that Samba supports only RAW spooling, NT has to call
1332 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1333 * and until NT sends a RAW job, we refuse it.
1335 * But to call getprinter() or startdoc(), you first need a valid handle,
1336 * and to get an handle you have to call openprintex(). Hence why you have
1337 * a devicemode in the openprinterex() call.
1340 * Differences between NT4 and NT 2000.
1343 * On NT4, you only have a global devicemode. This global devicemode can be changed
1344 * by the administrator (or by a user with enough privs). Everytime a user
1345 * wants to print, the devicemode is resetted to the default. In Word, everytime
1346 * you print, the printer's characteristics are always reset to the global devicemode.
1350 * In W2K, there is the notion of per-user devicemode. The first time you use
1351 * a printer, a per-user devicemode is build from the global devicemode.
1352 * If you change your per-user devicemode, it is saved in the registry, under the
1353 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1354 * printer preferences available.
1356 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1357 * on the General Tab of the printer properties windows.
1359 * To change the global devicemode: it's the "Printing Defaults..." button
1360 * on the Advanced Tab of the printer properties window.
1368 if (printer_default
->devmode_cont
.devmode
!= NULL
) {
1369 result
= printer_write_default_dev( snum
, printer_default
);
1371 close_printer_handle(p
, handle
);
1381 /****************************************************************************
1382 ****************************************************************************/
1384 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1385 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1391 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1400 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1401 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1407 printer
->info_3
=NULL
;
1408 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1412 printer
->info_6
=NULL
;
1413 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1423 BOOL
convert_devicemode(char *printername
, const DEVICEMODE
*devmode
,
1424 NT_DEVICEMODE
**pp_nt_devmode
)
1426 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1429 * Ensure nt_devmode is a valid pointer
1430 * as we will be overwriting it.
1433 if (nt_devmode
== NULL
) {
1434 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1435 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1439 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1440 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1442 nt_devmode
->specversion
=devmode
->specversion
;
1443 nt_devmode
->driverversion
=devmode
->driverversion
;
1444 nt_devmode
->size
=devmode
->size
;
1445 nt_devmode
->fields
=devmode
->fields
;
1446 nt_devmode
->orientation
=devmode
->orientation
;
1447 nt_devmode
->papersize
=devmode
->papersize
;
1448 nt_devmode
->paperlength
=devmode
->paperlength
;
1449 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1450 nt_devmode
->scale
=devmode
->scale
;
1451 nt_devmode
->copies
=devmode
->copies
;
1452 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1453 nt_devmode
->printquality
=devmode
->printquality
;
1454 nt_devmode
->color
=devmode
->color
;
1455 nt_devmode
->duplex
=devmode
->duplex
;
1456 nt_devmode
->yresolution
=devmode
->yresolution
;
1457 nt_devmode
->ttoption
=devmode
->ttoption
;
1458 nt_devmode
->collate
=devmode
->collate
;
1460 nt_devmode
->logpixels
=devmode
->logpixels
;
1461 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1462 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1463 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1464 nt_devmode
->displayflags
=devmode
->displayflags
;
1465 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1466 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1467 nt_devmode
->icmintent
=devmode
->icmintent
;
1468 nt_devmode
->mediatype
=devmode
->mediatype
;
1469 nt_devmode
->dithertype
=devmode
->dithertype
;
1470 nt_devmode
->reserved1
=devmode
->reserved1
;
1471 nt_devmode
->reserved2
=devmode
->reserved2
;
1472 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1473 nt_devmode
->panningheight
=devmode
->panningheight
;
1476 * Only change private and driverextra if the incoming devmode
1477 * has a new one. JRA.
1480 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1481 SAFE_FREE(nt_devmode
->private);
1482 nt_devmode
->driverextra
=devmode
->driverextra
;
1483 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1485 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1488 *pp_nt_devmode
= nt_devmode
;
1493 /********************************************************************
1494 * _spoolss_enddocprinter_internal.
1495 ********************************************************************/
1497 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1499 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1503 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1507 if (!get_printer_snum(p
, handle
, &snum
))
1510 Printer
->document_started
=False
;
1511 print_job_end(snum
, Printer
->jobid
,True
);
1512 /* error codes unhandled so far ... */
1517 /********************************************************************
1518 * api_spoolss_closeprinter
1519 ********************************************************************/
1521 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1523 POLICY_HND
*handle
= &q_u
->handle
;
1525 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1527 if (Printer
&& Printer
->document_started
)
1528 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1530 if (!close_printer_handle(p
, handle
))
1533 /* clear the returned printer handle. Observed behavior
1534 from Win2k server. Don't think this really matters.
1535 Previous code just copied the value of the closed
1538 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1543 /********************************************************************
1544 * api_spoolss_deleteprinter
1546 ********************************************************************/
1548 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1550 POLICY_HND
*handle
= &q_u
->handle
;
1551 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1554 if (Printer
&& Printer
->document_started
)
1555 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1557 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1559 result
= delete_printer_handle(p
, handle
);
1561 update_c_setprinter(False
);
1566 /*******************************************************************
1567 * static function to lookup the version id corresponding to an
1568 * long architecture string
1569 ******************************************************************/
1571 static int get_version_id (char * arch
)
1574 struct table_node archi_table
[]= {
1576 {"Windows 4.0", "WIN40", 0 },
1577 {"Windows NT x86", "W32X86", 2 },
1578 {"Windows NT R4000", "W32MIPS", 2 },
1579 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1580 {"Windows NT PowerPC", "W32PPC", 2 },
1584 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1586 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1587 return (archi_table
[i
].version
);
1593 /********************************************************************
1594 * _spoolss_deleteprinterdriver
1595 ********************************************************************/
1597 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1601 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1603 struct current_user user
;
1605 get_current_user(&user
, p
);
1607 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1608 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1610 /* check that we have a valid driver name first */
1611 if ((version
=get_version_id(arch
)) == -1) {
1612 /* this is what NT returns */
1613 return WERR_INVALID_ENVIRONMENT
;
1616 /* if they said "Windows NT x86", then try for version 2 & 3 */
1619 version
= DRIVER_ANY_VERSION
;
1623 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1624 return WERR_UNKNOWN_PRINTER_DRIVER
;
1626 if (printer_driver_in_use(info
.info_3
))
1627 return WERR_PRINTER_DRIVER_IN_USE
;
1629 return delete_printer_driver(info
.info_3
, &user
, DRIVER_ANY_VERSION
, False
);
1632 /********************************************************************
1633 * spoolss_deleteprinterdriverex
1634 ********************************************************************/
1636 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
1640 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1642 uint32 flags
= q_u
->delete_flags
;
1644 struct current_user user
;
1646 get_current_user(&user
, p
);
1648 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1649 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1651 /* check that we have a valid driver name first */
1652 if ((version
=get_version_id(arch
)) == -1) {
1653 /* this is what NT returns */
1654 return WERR_INVALID_ENVIRONMENT
;
1657 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
1658 version
= q_u
->version
;
1659 else if ( version
== 2 )
1660 /* if they said "Windows NT x86", then try for version 2 & 3 */
1661 version
= DRIVER_ANY_VERSION
;
1665 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1666 return WERR_UNKNOWN_PRINTER_DRIVER
;
1668 if ( printer_driver_in_use(info
.info_3
) )
1669 return WERR_PRINTER_DRIVER_IN_USE
;
1672 * we have a couple of cases to consider.
1673 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
1674 * then the delete should fail if **any** files overlap with
1676 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
1677 * non-overlapping files
1678 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
1679 * is set, the do not delete any files
1680 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
1683 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
1687 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
1689 if ( printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) )
1690 /* no idea of the correct error here */
1691 return WERR_ACCESS_DENIED
;
1694 return delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
1698 /********************************************************************
1699 GetPrinterData on a printer server Handle.
1700 ********************************************************************/
1702 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1706 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1708 if (!strcmp(value
, "W3SvcInstalled")) {
1710 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
1716 if (!strcmp(value
, "BeepEnabled")) {
1718 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1720 SIVAL(*data
, 0, 0x00);
1725 if (!strcmp(value
, "EventLog")) {
1727 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1729 /* formally was 0x1b */
1730 SIVAL(*data
, 0, 0x0);
1735 if (!strcmp(value
, "NetPopup")) {
1737 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1739 SIVAL(*data
, 0, 0x00);
1744 if (!strcmp(value
, "MajorVersion")) {
1746 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1748 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1757 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1760 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
1762 *needed
= 2*(strlen(string
)+1);
1763 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1765 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1767 /* it's done by hand ready to go on the wire */
1768 for (i
=0; i
<strlen(string
); i
++) {
1769 (*data
)[2*i
]=string
[i
];
1770 (*data
)[2*i
+1]='\0';
1775 if (!strcmp(value
, "Architecture")) {
1776 pstring string
="Windows NT x86";
1778 *needed
= 2*(strlen(string
)+1);
1779 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1781 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1782 for (i
=0; i
<strlen(string
); i
++) {
1783 (*data
)[2*i
]=string
[i
];
1784 (*data
)[2*i
+1]='\0';
1792 /********************************************************************
1793 GetPrinterData on a printer Handle.
1794 ********************************************************************/
1796 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1797 fstring value
, uint32
*type
,
1798 uint8
**data
, uint32
*needed
, uint32 in_size
)
1800 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1802 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1803 REGISTRY_VALUE
*val
;
1806 DEBUG(5,("getprinterdata_printer\n"));
1809 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1813 if ( !get_printer_snum(p
, handle
, &snum
) )
1816 if ( !W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) )
1819 if ( !(val
= get_printer_data( printer
->info_2
, SPOOL_PRINTERDATA_KEY
, value
)) )
1821 free_a_printer(&printer
, 2);
1825 *type
= regval_type( val
);
1828 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1832 if ( (*data
= (uint8
*)talloc(ctx
, in_size
* sizeof(uint8
))) == NULL
)
1835 memset( *data
, 0, in_size
*sizeof(uint8
) );
1837 /* copy the min(in_size, len) */
1839 size
= regval_size( val
);
1840 memcpy( *data
, regval_data_p(val
), (size
> in_size
) ? in_size
: size
*sizeof(uint8
) );
1847 DEBUG(5,("getprinterdata_printer:copy done\n"));
1850 free_a_printer(&printer
, 2);
1854 /********************************************************************
1855 * spoolss_getprinterdata
1856 ********************************************************************/
1858 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1860 POLICY_HND
*handle
= &q_u
->handle
;
1861 UNISTR2
*valuename
= &q_u
->valuename
;
1862 uint32 in_size
= q_u
->size
;
1863 uint32
*type
= &r_u
->type
;
1864 uint32
*out_size
= &r_u
->size
;
1865 uint8
**data
= &r_u
->data
;
1866 uint32
*needed
= &r_u
->needed
;
1870 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1873 * Reminder: when it's a string, the length is in BYTES
1874 * even if UNICODE is negociated.
1879 *out_size
= in_size
;
1881 /* in case of problem, return some default values */
1886 DEBUG(4,("_spoolss_getprinterdata\n"));
1889 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1891 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1895 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1897 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1898 found
= getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1900 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1904 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1906 /* reply this param doesn't exist */
1909 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1915 /* error depends on handle type */
1917 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1918 return WERR_INVALID_PARAM
;
1920 return WERR_BADFILE
;
1923 if (*needed
> *out_size
)
1924 return WERR_MORE_DATA
;
1929 /*********************************************************
1930 Connect to the client machine.
1931 **********************************************************/
1933 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, char *remote_machine
)
1935 extern pstring global_myname
;
1937 ZERO_STRUCTP(the_cli
);
1938 if(cli_initialise(the_cli
) == NULL
) {
1939 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1943 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
1944 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
1945 cli_shutdown(the_cli
);
1949 if (ismyip(the_cli
->dest_ip
)) {
1950 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
1951 cli_shutdown(the_cli
);
1955 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
1956 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1957 cli_shutdown(the_cli
);
1961 if (!attempt_netbios_session_request(the_cli
, global_myname
, remote_machine
, &the_cli
->dest_ip
)) {
1962 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1967 the_cli
->protocol
= PROTOCOL_NT1
;
1969 if (!cli_negprot(the_cli
)) {
1970 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1971 cli_shutdown(the_cli
);
1975 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
1976 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
1977 cli_shutdown(the_cli
);
1982 * Do an anonymous session setup.
1985 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
1986 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1987 cli_shutdown(the_cli
);
1991 if (!(the_cli
->sec_mode
& 1)) {
1992 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
1993 cli_shutdown(the_cli
);
1997 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
1998 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1999 cli_shutdown(the_cli
);
2004 * Ok - we have an anonymous connection to the IPC$ share.
2005 * Now start the NT Domain stuff :-).
2008 if(cli_nt_session_open(the_cli
, PIPE_SPOOLSS
) == False
) {
2009 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
)));
2010 cli_nt_session_close(the_cli
);
2011 cli_ulogoff(the_cli
);
2012 cli_shutdown(the_cli
);
2019 /***************************************************************************
2020 Connect to the client.
2021 ****************************************************************************/
2023 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
2028 * If it's the first connection, contact the client
2029 * and connect to the IPC$ share anonumously
2031 if (smb_connections
==0) {
2032 fstring unix_printer
;
2034 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2036 if(!spoolss_connect_to_client(¬ify_cli
, unix_printer
))
2039 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message
);
2044 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2047 if (!W_ERROR_IS_OK(result
))
2048 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2049 dos_errstr(result
)));
2051 return (W_ERROR_IS_OK(result
));
2054 /********************************************************************
2056 * ReplyFindFirstPrinterChangeNotifyEx
2058 * before replying OK: status=0 a rpc call is made to the workstation
2059 * asking ReplyOpenPrinter
2061 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2062 * called from api_spoolss_rffpcnex
2063 ********************************************************************/
2065 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2067 POLICY_HND
*handle
= &q_u
->handle
;
2068 uint32 flags
= q_u
->flags
;
2069 uint32 options
= q_u
->options
;
2070 UNISTR2
*localmachine
= &q_u
->localmachine
;
2071 uint32 printerlocal
= q_u
->printerlocal
;
2072 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2074 /* store the notify value in the printer struct */
2076 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2079 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2083 Printer
->notify
.flags
=flags
;
2084 Printer
->notify
.options
=options
;
2085 Printer
->notify
.printerlocal
=printerlocal
;
2087 if (Printer
->notify
.option
)
2088 free_spool_notify_option(&Printer
->notify
.option
);
2090 Printer
->notify
.option
=dup_spool_notify_option(option
);
2092 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2093 sizeof(Printer
->notify
.localmachine
)-1);
2095 /* Connect to the client machine and send a ReplyOpenPrinter */
2097 if(!srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
2098 Printer
->notify
.printerlocal
, 1,
2099 &Printer
->notify
.client_hnd
))
2100 return WERR_SERVER_UNAVAILABLE
;
2102 Printer
->notify
.client_connected
=True
;
2107 /*******************************************************************
2108 * fill a notify_info_data with the servername
2109 ********************************************************************/
2111 void spoolss_notify_server_name(int snum
,
2112 SPOOL_NOTIFY_INFO_DATA
*data
,
2113 print_queue_struct
*queue
,
2114 NT_PRINTER_INFO_LEVEL
*printer
,
2115 TALLOC_CTX
*mem_ctx
)
2117 pstring temp_name
, temp
;
2120 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2122 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2124 data
->notify_data
.data
.length
= len
;
2125 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2127 if (!data
->notify_data
.data
.string
) {
2128 data
->notify_data
.data
.length
= 0;
2132 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2135 /*******************************************************************
2136 * fill a notify_info_data with the printername (not including the servername).
2137 ********************************************************************/
2139 void spoolss_notify_printer_name(int snum
,
2140 SPOOL_NOTIFY_INFO_DATA
*data
,
2141 print_queue_struct
*queue
,
2142 NT_PRINTER_INFO_LEVEL
*printer
,
2143 TALLOC_CTX
*mem_ctx
)
2148 /* the notify name should not contain the \\server\ part */
2149 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2152 p
= printer
->info_2
->printername
;
2157 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2159 data
->notify_data
.data
.length
= len
;
2160 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2162 if (!data
->notify_data
.data
.string
) {
2163 data
->notify_data
.data
.length
= 0;
2167 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2170 /*******************************************************************
2171 * fill a notify_info_data with the servicename
2172 ********************************************************************/
2174 void spoolss_notify_share_name(int snum
,
2175 SPOOL_NOTIFY_INFO_DATA
*data
,
2176 print_queue_struct
*queue
,
2177 NT_PRINTER_INFO_LEVEL
*printer
,
2178 TALLOC_CTX
*mem_ctx
)
2183 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2185 data
->notify_data
.data
.length
= len
;
2186 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2188 if (!data
->notify_data
.data
.string
) {
2189 data
->notify_data
.data
.length
= 0;
2193 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2196 /*******************************************************************
2197 * fill a notify_info_data with the port name
2198 ********************************************************************/
2200 void spoolss_notify_port_name(int snum
,
2201 SPOOL_NOTIFY_INFO_DATA
*data
,
2202 print_queue_struct
*queue
,
2203 NT_PRINTER_INFO_LEVEL
*printer
,
2204 TALLOC_CTX
*mem_ctx
)
2209 /* even if it's strange, that's consistant in all the code */
2211 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2213 data
->notify_data
.data
.length
= len
;
2214 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2216 if (!data
->notify_data
.data
.string
) {
2217 data
->notify_data
.data
.length
= 0;
2221 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2224 /*******************************************************************
2225 * fill a notify_info_data with the printername
2226 * but it doesn't exist, have to see what to do
2227 ********************************************************************/
2229 void spoolss_notify_driver_name(int snum
,
2230 SPOOL_NOTIFY_INFO_DATA
*data
,
2231 print_queue_struct
*queue
,
2232 NT_PRINTER_INFO_LEVEL
*printer
,
2233 TALLOC_CTX
*mem_ctx
)
2238 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2240 data
->notify_data
.data
.length
= len
;
2241 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2243 if (!data
->notify_data
.data
.string
) {
2244 data
->notify_data
.data
.length
= 0;
2248 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2251 /*******************************************************************
2252 * fill a notify_info_data with the comment
2253 ********************************************************************/
2255 void spoolss_notify_comment(int snum
,
2256 SPOOL_NOTIFY_INFO_DATA
*data
,
2257 print_queue_struct
*queue
,
2258 NT_PRINTER_INFO_LEVEL
*printer
,
2259 TALLOC_CTX
*mem_ctx
)
2264 if (*printer
->info_2
->comment
== '\0')
2265 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2267 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2269 data
->notify_data
.data
.length
= len
;
2270 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2272 if (!data
->notify_data
.data
.string
) {
2273 data
->notify_data
.data
.length
= 0;
2277 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2280 /*******************************************************************
2281 * fill a notify_info_data with the comment
2282 * location = "Room 1, floor 2, building 3"
2283 ********************************************************************/
2285 void spoolss_notify_location(int snum
,
2286 SPOOL_NOTIFY_INFO_DATA
*data
,
2287 print_queue_struct
*queue
,
2288 NT_PRINTER_INFO_LEVEL
*printer
,
2289 TALLOC_CTX
*mem_ctx
)
2294 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2296 data
->notify_data
.data
.length
= len
;
2297 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2299 if (!data
->notify_data
.data
.string
) {
2300 data
->notify_data
.data
.length
= 0;
2304 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2307 /*******************************************************************
2308 * fill a notify_info_data with the device mode
2309 * jfm:xxxx don't to it for know but that's a real problem !!!
2310 ********************************************************************/
2312 static void spoolss_notify_devmode(int snum
,
2313 SPOOL_NOTIFY_INFO_DATA
*data
,
2314 print_queue_struct
*queue
,
2315 NT_PRINTER_INFO_LEVEL
*printer
,
2316 TALLOC_CTX
*mem_ctx
)
2320 /*******************************************************************
2321 * fill a notify_info_data with the separator file name
2322 ********************************************************************/
2324 void spoolss_notify_sepfile(int snum
,
2325 SPOOL_NOTIFY_INFO_DATA
*data
,
2326 print_queue_struct
*queue
,
2327 NT_PRINTER_INFO_LEVEL
*printer
,
2328 TALLOC_CTX
*mem_ctx
)
2333 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2335 data
->notify_data
.data
.length
= len
;
2336 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2338 if (!data
->notify_data
.data
.string
) {
2339 data
->notify_data
.data
.length
= 0;
2343 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2346 /*******************************************************************
2347 * fill a notify_info_data with the print processor
2348 * jfm:xxxx return always winprint to indicate we don't do anything to it
2349 ********************************************************************/
2351 void spoolss_notify_print_processor(int snum
,
2352 SPOOL_NOTIFY_INFO_DATA
*data
,
2353 print_queue_struct
*queue
,
2354 NT_PRINTER_INFO_LEVEL
*printer
,
2355 TALLOC_CTX
*mem_ctx
)
2360 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2362 data
->notify_data
.data
.length
= len
;
2363 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2365 if (!data
->notify_data
.data
.string
) {
2366 data
->notify_data
.data
.length
= 0;
2370 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2373 /*******************************************************************
2374 * fill a notify_info_data with the print processor options
2375 * jfm:xxxx send an empty string
2376 ********************************************************************/
2378 void spoolss_notify_parameters(int snum
,
2379 SPOOL_NOTIFY_INFO_DATA
*data
,
2380 print_queue_struct
*queue
,
2381 NT_PRINTER_INFO_LEVEL
*printer
,
2382 TALLOC_CTX
*mem_ctx
)
2387 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2389 data
->notify_data
.data
.length
= len
;
2390 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2392 if (!data
->notify_data
.data
.string
) {
2393 data
->notify_data
.data
.length
= 0;
2397 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2400 /*******************************************************************
2401 * fill a notify_info_data with the data type
2402 * jfm:xxxx always send RAW as data type
2403 ********************************************************************/
2405 void spoolss_notify_datatype(int snum
,
2406 SPOOL_NOTIFY_INFO_DATA
*data
,
2407 print_queue_struct
*queue
,
2408 NT_PRINTER_INFO_LEVEL
*printer
,
2409 TALLOC_CTX
*mem_ctx
)
2414 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2416 data
->notify_data
.data
.length
= len
;
2417 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2419 if (!data
->notify_data
.data
.string
) {
2420 data
->notify_data
.data
.length
= 0;
2424 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2427 /*******************************************************************
2428 * fill a notify_info_data with the security descriptor
2429 * jfm:xxxx send an null pointer to say no security desc
2430 * have to implement security before !
2431 ********************************************************************/
2433 static void spoolss_notify_security_desc(int snum
,
2434 SPOOL_NOTIFY_INFO_DATA
*data
,
2435 print_queue_struct
*queue
,
2436 NT_PRINTER_INFO_LEVEL
*printer
,
2437 TALLOC_CTX
*mem_ctx
)
2439 data
->notify_data
.data
.length
=0;
2440 data
->notify_data
.data
.string
= NULL
;
2443 /*******************************************************************
2444 * fill a notify_info_data with the attributes
2445 * jfm:xxxx a samba printer is always shared
2446 ********************************************************************/
2448 void spoolss_notify_attributes(int snum
,
2449 SPOOL_NOTIFY_INFO_DATA
*data
,
2450 print_queue_struct
*queue
,
2451 NT_PRINTER_INFO_LEVEL
*printer
,
2452 TALLOC_CTX
*mem_ctx
)
2454 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2455 data
->notify_data
.value
[1] = 0;
2458 /*******************************************************************
2459 * fill a notify_info_data with the priority
2460 ********************************************************************/
2462 static void spoolss_notify_priority(int snum
,
2463 SPOOL_NOTIFY_INFO_DATA
*data
,
2464 print_queue_struct
*queue
,
2465 NT_PRINTER_INFO_LEVEL
*printer
,
2466 TALLOC_CTX
*mem_ctx
)
2468 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2469 data
->notify_data
.value
[1] = 0;
2472 /*******************************************************************
2473 * fill a notify_info_data with the default priority
2474 ********************************************************************/
2476 static void spoolss_notify_default_priority(int snum
,
2477 SPOOL_NOTIFY_INFO_DATA
*data
,
2478 print_queue_struct
*queue
,
2479 NT_PRINTER_INFO_LEVEL
*printer
,
2480 TALLOC_CTX
*mem_ctx
)
2482 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2483 data
->notify_data
.value
[1] = 0;
2486 /*******************************************************************
2487 * fill a notify_info_data with the start time
2488 ********************************************************************/
2490 static void spoolss_notify_start_time(int snum
,
2491 SPOOL_NOTIFY_INFO_DATA
*data
,
2492 print_queue_struct
*queue
,
2493 NT_PRINTER_INFO_LEVEL
*printer
,
2494 TALLOC_CTX
*mem_ctx
)
2496 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2497 data
->notify_data
.value
[1] = 0;
2500 /*******************************************************************
2501 * fill a notify_info_data with the until time
2502 ********************************************************************/
2504 static void spoolss_notify_until_time(int snum
,
2505 SPOOL_NOTIFY_INFO_DATA
*data
,
2506 print_queue_struct
*queue
,
2507 NT_PRINTER_INFO_LEVEL
*printer
,
2508 TALLOC_CTX
*mem_ctx
)
2510 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2511 data
->notify_data
.value
[1] = 0;
2514 /*******************************************************************
2515 * fill a notify_info_data with the status
2516 ********************************************************************/
2518 static void spoolss_notify_status(int snum
,
2519 SPOOL_NOTIFY_INFO_DATA
*data
,
2520 print_queue_struct
*queue
,
2521 NT_PRINTER_INFO_LEVEL
*printer
,
2522 TALLOC_CTX
*mem_ctx
)
2524 print_status_struct status
;
2526 print_queue_length(snum
, &status
);
2527 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2528 data
->notify_data
.value
[1] = 0;
2531 /*******************************************************************
2532 * fill a notify_info_data with the number of jobs queued
2533 ********************************************************************/
2535 void spoolss_notify_cjobs(int snum
,
2536 SPOOL_NOTIFY_INFO_DATA
*data
,
2537 print_queue_struct
*queue
,
2538 NT_PRINTER_INFO_LEVEL
*printer
,
2539 TALLOC_CTX
*mem_ctx
)
2541 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
2542 data
->notify_data
.value
[1] = 0;
2545 /*******************************************************************
2546 * fill a notify_info_data with the average ppm
2547 ********************************************************************/
2549 static void spoolss_notify_average_ppm(int snum
,
2550 SPOOL_NOTIFY_INFO_DATA
*data
,
2551 print_queue_struct
*queue
,
2552 NT_PRINTER_INFO_LEVEL
*printer
,
2553 TALLOC_CTX
*mem_ctx
)
2555 /* always respond 8 pages per minutes */
2556 /* a little hard ! */
2557 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
2558 data
->notify_data
.value
[1] = 0;
2561 /*******************************************************************
2562 * fill a notify_info_data with username
2563 ********************************************************************/
2565 static void spoolss_notify_username(int snum
,
2566 SPOOL_NOTIFY_INFO_DATA
*data
,
2567 print_queue_struct
*queue
,
2568 NT_PRINTER_INFO_LEVEL
*printer
,
2569 TALLOC_CTX
*mem_ctx
)
2574 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
2576 data
->notify_data
.data
.length
= len
;
2577 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2579 if (!data
->notify_data
.data
.string
) {
2580 data
->notify_data
.data
.length
= 0;
2584 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2587 /*******************************************************************
2588 * fill a notify_info_data with job status
2589 ********************************************************************/
2591 static void spoolss_notify_job_status(int snum
,
2592 SPOOL_NOTIFY_INFO_DATA
*data
,
2593 print_queue_struct
*queue
,
2594 NT_PRINTER_INFO_LEVEL
*printer
,
2595 TALLOC_CTX
*mem_ctx
)
2597 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
2598 data
->notify_data
.value
[1] = 0;
2601 /*******************************************************************
2602 * fill a notify_info_data with job name
2603 ********************************************************************/
2605 static void spoolss_notify_job_name(int snum
,
2606 SPOOL_NOTIFY_INFO_DATA
*data
,
2607 print_queue_struct
*queue
,
2608 NT_PRINTER_INFO_LEVEL
*printer
,
2609 TALLOC_CTX
*mem_ctx
)
2614 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
2616 data
->notify_data
.data
.length
= len
;
2617 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2619 if (!data
->notify_data
.data
.string
) {
2620 data
->notify_data
.data
.length
= 0;
2624 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2627 /*******************************************************************
2628 * fill a notify_info_data with job status
2629 ********************************************************************/
2631 static void spoolss_notify_job_status_string(int snum
,
2632 SPOOL_NOTIFY_INFO_DATA
*data
,
2633 print_queue_struct
*queue
,
2634 NT_PRINTER_INFO_LEVEL
*printer
,
2635 TALLOC_CTX
*mem_ctx
)
2638 * Now we're returning job status codes we just return a "" here. JRA.
2645 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2648 switch (queue
->status
) {
2653 p
= ""; /* NT provides the paused string */
2662 #endif /* NO LONGER NEEDED. */
2664 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
2666 data
->notify_data
.data
.length
= len
;
2667 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2669 if (!data
->notify_data
.data
.string
) {
2670 data
->notify_data
.data
.length
= 0;
2674 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2677 /*******************************************************************
2678 * fill a notify_info_data with job time
2679 ********************************************************************/
2681 static void spoolss_notify_job_time(int snum
,
2682 SPOOL_NOTIFY_INFO_DATA
*data
,
2683 print_queue_struct
*queue
,
2684 NT_PRINTER_INFO_LEVEL
*printer
,
2685 TALLOC_CTX
*mem_ctx
)
2687 data
->notify_data
.value
[0]=0x0;
2688 data
->notify_data
.value
[1]=0;
2691 /*******************************************************************
2692 * fill a notify_info_data with job size
2693 ********************************************************************/
2695 static void spoolss_notify_job_size(int snum
,
2696 SPOOL_NOTIFY_INFO_DATA
*data
,
2697 print_queue_struct
*queue
,
2698 NT_PRINTER_INFO_LEVEL
*printer
,
2699 TALLOC_CTX
*mem_ctx
)
2701 data
->notify_data
.value
[0]=queue
->size
;
2702 data
->notify_data
.value
[1]=0;
2705 /*******************************************************************
2706 * fill a notify_info_data with page info
2707 ********************************************************************/
2708 static void spoolss_notify_total_pages(int snum
,
2709 SPOOL_NOTIFY_INFO_DATA
*data
,
2710 print_queue_struct
*queue
,
2711 NT_PRINTER_INFO_LEVEL
*printer
,
2712 TALLOC_CTX
*mem_ctx
)
2714 data
->notify_data
.value
[0]=queue
->page_count
;
2715 data
->notify_data
.value
[1]=0;
2718 /*******************************************************************
2719 * fill a notify_info_data with pages printed info.
2720 ********************************************************************/
2721 static void spoolss_notify_pages_printed(int snum
,
2722 SPOOL_NOTIFY_INFO_DATA
*data
,
2723 print_queue_struct
*queue
,
2724 NT_PRINTER_INFO_LEVEL
*printer
,
2725 TALLOC_CTX
*mem_ctx
)
2727 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
2728 data
->notify_data
.value
[1]=0;
2731 /*******************************************************************
2732 Fill a notify_info_data with job position.
2733 ********************************************************************/
2735 static void spoolss_notify_job_position(int snum
,
2736 SPOOL_NOTIFY_INFO_DATA
*data
,
2737 print_queue_struct
*queue
,
2738 NT_PRINTER_INFO_LEVEL
*printer
,
2739 TALLOC_CTX
*mem_ctx
)
2741 data
->notify_data
.value
[0]=queue
->job
;
2742 data
->notify_data
.value
[1]=0;
2745 /*******************************************************************
2746 Fill a notify_info_data with submitted time.
2747 ********************************************************************/
2749 static void spoolss_notify_submitted_time(int snum
,
2750 SPOOL_NOTIFY_INFO_DATA
*data
,
2751 print_queue_struct
*queue
,
2752 NT_PRINTER_INFO_LEVEL
*printer
,
2753 TALLOC_CTX
*mem_ctx
)
2760 t
=gmtime(&queue
->time
);
2762 len
= sizeof(SYSTEMTIME
);
2764 data
->notify_data
.data
.length
= len
;
2765 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2767 if (!data
->notify_data
.data
.string
) {
2768 data
->notify_data
.data
.length
= 0;
2772 make_systemtime(&st
, t
);
2775 * Systemtime must be linearized as a set of UINT16's.
2776 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2779 p
= (char *)data
->notify_data
.data
.string
;
2780 SSVAL(p
, 0, st
.year
);
2781 SSVAL(p
, 2, st
.month
);
2782 SSVAL(p
, 4, st
.dayofweek
);
2783 SSVAL(p
, 6, st
.day
);
2784 SSVAL(p
, 8, st
.hour
);
2785 SSVAL(p
, 10, st
.minute
);
2786 SSVAL(p
, 12, st
.second
);
2787 SSVAL(p
, 14, st
.milliseconds
);
2790 struct s_notify_info_data_table
2796 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2797 print_queue_struct
*queue
,
2798 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2801 /* A table describing the various print notification constants and
2802 whether the notification data is a pointer to a variable sized
2803 buffer, a one value uint32 or a two value uint32. */
2805 struct s_notify_info_data_table notify_info_data_table
[] =
2807 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
2808 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
2809 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
2810 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
2811 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
2812 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
2813 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
2814 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
2815 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
2816 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
2817 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
2818 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
2819 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
2820 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
2821 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
2822 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
2823 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
2824 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
2825 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
2826 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
2827 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
2828 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
2829 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
2830 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
2831 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
2832 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
2833 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
2834 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
2835 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
2836 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
2837 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
2838 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
2839 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
2840 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
2841 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
2842 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
2843 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
2844 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
2845 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
2846 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
2847 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
2848 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
2849 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
2850 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
2851 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
2852 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
2853 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
2854 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
2855 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
2858 /*******************************************************************
2859 Return the size of info_data structure.
2860 ********************************************************************/
2862 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2866 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
2868 if ( (notify_info_data_table
[i
].type
== type
)
2869 && (notify_info_data_table
[i
].field
== field
) )
2871 switch(notify_info_data_table
[i
].size
)
2873 case NOTIFY_ONE_VALUE
:
2874 case NOTIFY_TWO_VALUE
:
2879 /* The only pointer notify data I have seen on
2880 the wire is the submitted time and this has
2881 the notify size set to 4. -tpot */
2883 case NOTIFY_POINTER
:
2886 case NOTIFY_SECDESC
:
2892 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
2897 /*******************************************************************
2898 Return the type of notify_info_data.
2899 ********************************************************************/
2901 static int type_of_notify_info_data(uint16 type
, uint16 field
)
2905 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
2906 if (notify_info_data_table
[i
].type
== type
&&
2907 notify_info_data_table
[i
].field
== field
)
2908 return notify_info_data_table
[i
].size
;
2914 /****************************************************************************
2915 ****************************************************************************/
2917 static int search_notify(uint16 type
, uint16 field
, int *value
)
2921 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
2922 if (notify_info_data_table
[i
].type
== type
&&
2923 notify_info_data_table
[i
].field
== field
&&
2924 notify_info_data_table
[i
].fn
!= NULL
) {
2933 /****************************************************************************
2934 ****************************************************************************/
2936 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2938 info_data
->type
= type
;
2939 info_data
->field
= field
;
2940 info_data
->reserved
= 0;
2942 info_data
->size
= size_of_notify_info_data(type
, field
);
2943 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2950 /*******************************************************************
2952 * fill a notify_info struct with info asked
2954 ********************************************************************/
2956 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2957 snum
, SPOOL_NOTIFY_OPTION_TYPE
2958 *option_type
, uint32 id
,
2959 TALLOC_CTX
*mem_ctx
)
2965 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2966 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2967 print_queue_struct
*queue
=NULL
;
2969 type
=option_type
->type
;
2971 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2972 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2973 option_type
->count
, lp_servicename(snum
)));
2975 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2978 for(field_num
=0; field_num
<option_type
->count
; field_num
++)
2980 field
= option_type
->fields
[field_num
];
2982 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2984 if (!search_notify(type
, field
, &j
) )
2987 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
)
2989 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2995 current_data
= &info
->data
[info
->count
];
2997 construct_info_data(current_data
, type
, field
, id
);
2999 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3000 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3002 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3008 free_a_printer(&printer
, 2);
3012 /*******************************************************************
3014 * fill a notify_info struct with info asked
3016 ********************************************************************/
3018 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3019 SPOOL_NOTIFY_INFO
*info
,
3020 NT_PRINTER_INFO_LEVEL
*printer
,
3021 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3022 *option_type
, uint32 id
,
3023 TALLOC_CTX
*mem_ctx
)
3029 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3031 DEBUG(4,("construct_notify_jobs_info\n"));
3033 type
= option_type
->type
;
3035 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3036 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3037 option_type
->count
));
3039 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3040 field
= option_type
->fields
[field_num
];
3042 if (!search_notify(type
, field
, &j
) )
3045 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3046 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3049 else info
->data
= tid
;
3051 current_data
=&(info
->data
[info
->count
]);
3053 construct_info_data(current_data
, type
, field
, id
);
3054 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3063 * JFM: The enumeration is not that simple, it's even non obvious.
3065 * let's take an example: I want to monitor the PRINTER SERVER for
3066 * the printer's name and the number of jobs currently queued.
3067 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3068 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3070 * I have 3 printers on the back of my server.
3072 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3075 * 1 printer 1 name 1
3076 * 2 printer 1 cjob 1
3077 * 3 printer 2 name 2
3078 * 4 printer 2 cjob 2
3079 * 5 printer 3 name 3
3080 * 6 printer 3 name 3
3082 * that's the print server case, the printer case is even worse.
3085 /*******************************************************************
3087 * enumerate all printers on the printserver
3088 * fill a notify_info struct with info asked
3090 ********************************************************************/
3092 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3093 SPOOL_NOTIFY_INFO
*info
,
3094 TALLOC_CTX
*mem_ctx
)
3097 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3098 int n_services
=lp_numservices();
3101 SPOOL_NOTIFY_OPTION
*option
;
3102 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3104 DEBUG(4,("printserver_notify_info\n"));
3109 option
=Printer
->notify
.option
;
3115 for (i
=0; i
<option
->count
; i
++) {
3116 option_type
=&(option
->ctr
.type
[i
]);
3118 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3121 for (snum
=0; snum
<n_services
; snum
++)
3123 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3124 construct_notify_printer_info ( info
, snum
, option_type
, snum
, mem_ctx
);
3130 * Debugging information, don't delete.
3133 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3134 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3135 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3137 for (i
=0; i
<info
->count
; i
++) {
3138 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3139 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3140 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3147 /*******************************************************************
3149 * fill a notify_info struct with info asked
3151 ********************************************************************/
3153 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3154 TALLOC_CTX
*mem_ctx
)
3157 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3160 SPOOL_NOTIFY_OPTION
*option
;
3161 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3163 print_queue_struct
*queue
=NULL
;
3164 print_status_struct status
;
3166 DEBUG(4,("printer_notify_info\n"));
3171 option
=Printer
->notify
.option
;
3177 get_printer_snum(p
, hnd
, &snum
);
3179 for (i
=0; i
<option
->count
; i
++) {
3180 option_type
=&option
->ctr
.type
[i
];
3182 switch ( option_type
->type
) {
3183 case PRINTER_NOTIFY_TYPE
:
3184 if(construct_notify_printer_info(info
, snum
,
3190 case JOB_NOTIFY_TYPE
: {
3191 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3193 count
= print_queue_status(snum
, &queue
, &status
);
3195 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3196 lp_servicename(snum
))))
3199 for (j
=0; j
<count
; j
++) {
3200 construct_notify_jobs_info(&queue
[j
], info
,
3207 free_a_printer(&printer
, 2);
3217 * Debugging information, don't delete.
3220 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3221 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3222 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3224 for (i=0; i<info->count; i++) {
3225 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3226 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3227 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3233 /********************************************************************
3235 ********************************************************************/
3237 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3239 POLICY_HND
*handle
= &q_u
->handle
;
3240 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3242 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3243 WERROR result
= WERR_BADFID
;
3245 /* we always have a NOTIFY_INFO struct */
3249 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3250 OUR_HANDLE(handle
)));
3254 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3257 * We are now using the change value, and
3258 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3259 * I don't have a global notification system, I'm sending back all the
3260 * informations even when _NOTHING_ has changed.
3263 /* We need to keep track of the change value to send back in
3264 RRPCN replies otherwise our updates are ignored. */
3266 if (Printer
->notify
.client_connected
) {
3267 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3268 Printer
->notify
.change
= q_u
->change
;
3271 /* just ignore the SPOOL_NOTIFY_OPTION */
3273 switch (Printer
->printer_type
) {
3274 case PRINTER_HANDLE_IS_PRINTSERVER
:
3275 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3278 case PRINTER_HANDLE_IS_PRINTER
:
3279 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3287 /********************************************************************
3288 * construct_printer_info_0
3289 * fill a printer_info_0 struct
3290 ********************************************************************/
3292 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3296 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3297 counter_printer_0
*session_counter
;
3298 uint32 global_counter
;
3301 print_status_struct status
;
3303 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3306 count
= print_queue_length(snum
, &status
);
3308 /* check if we already have a counter for this printer */
3309 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3311 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3312 if (session_counter
->snum
== snum
)
3316 /* it's the first time, add it to the list */
3317 if (session_counter
==NULL
) {
3318 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3319 free_a_printer(&ntprinter
, 2);
3322 ZERO_STRUCTP(session_counter
);
3323 session_counter
->snum
=snum
;
3324 session_counter
->counter
=0;
3325 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3329 session_counter
->counter
++;
3332 * the global_counter should be stored in a TDB as it's common to all the clients
3333 * and should be zeroed on samba startup
3335 global_counter
=session_counter
->counter
;
3337 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3339 init_unistr(&printer
->printername
, chaine
);
3341 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3342 init_unistr(&printer
->servername
, chaine
);
3344 printer
->cjobs
= count
;
3345 printer
->total_jobs
= 0;
3346 printer
->total_bytes
= 0;
3348 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3349 t
=gmtime(&setuptime
);
3351 printer
->year
= t
->tm_year
+1900;
3352 printer
->month
= t
->tm_mon
+1;
3353 printer
->dayofweek
= t
->tm_wday
;
3354 printer
->day
= t
->tm_mday
;
3355 printer
->hour
= t
->tm_hour
;
3356 printer
->minute
= t
->tm_min
;
3357 printer
->second
= t
->tm_sec
;
3358 printer
->milliseconds
= 0;
3360 printer
->global_counter
= global_counter
;
3361 printer
->total_pages
= 0;
3362 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3363 printer
->major_version
= 0x0004; /* NT 4 */
3364 printer
->build_version
= 0x0565; /* build 1381 */
3366 printer
->major_version
= 0x0005; /* NT 5 */
3367 printer
->build_version
= 0x0893; /* build 2195 */
3369 printer
->unknown7
= 0x1;
3370 printer
->unknown8
= 0x0;
3371 printer
->unknown9
= 0x0;
3372 printer
->session_counter
= session_counter
->counter
;
3373 printer
->unknown11
= 0x0;
3374 printer
->printer_errors
= 0x0; /* number of print failure */
3375 printer
->unknown13
= 0x0;
3376 printer
->unknown14
= 0x1;
3377 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3378 printer
->unknown16
= 0x0;
3379 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3380 printer
->unknown18
= 0x0;
3381 printer
->status
= nt_printq_status(status
.status
);
3382 printer
->unknown20
= 0x0;
3383 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3384 printer
->unknown22
= 0x0;
3385 printer
->unknown23
= 0x6; /* 6 ???*/
3386 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3387 printer
->unknown25
= 0;
3388 printer
->unknown26
= 0;
3389 printer
->unknown27
= 0;
3390 printer
->unknown28
= 0;
3391 printer
->unknown29
= 0;
3393 free_a_printer(&ntprinter
,2);
3397 /********************************************************************
3398 * construct_printer_info_1
3399 * fill a printer_info_1 struct
3400 ********************************************************************/
3401 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3405 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3407 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3410 printer
->flags
=flags
;
3412 if (*ntprinter
->info_2
->comment
== '\0') {
3413 init_unistr(&printer
->comment
, lp_comment(snum
));
3414 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3415 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3418 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3419 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3420 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3423 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3425 init_unistr(&printer
->description
, chaine
);
3426 init_unistr(&printer
->name
, chaine2
);
3428 free_a_printer(&ntprinter
,2);
3433 /****************************************************************************
3434 Free a DEVMODE struct.
3435 ****************************************************************************/
3437 static void free_dev_mode(DEVICEMODE
*dev
)
3442 SAFE_FREE(dev
->private);
3446 /****************************************************************************
3447 Create a DEVMODE struct. Returns malloced memory.
3448 ****************************************************************************/
3450 DEVICEMODE
*construct_dev_mode(int snum
)
3454 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3455 NT_DEVICEMODE
*ntdevmode
= NULL
;
3456 DEVICEMODE
*devmode
= NULL
;
3458 DEBUG(7,("construct_dev_mode\n"));
3460 DEBUGADD(8,("getting printer characteristics\n"));
3462 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3463 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3467 ZERO_STRUCTP(devmode
);
3469 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3472 if (printer
->info_2
->devmode
)
3473 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
3475 if (ntdevmode
== NULL
) {
3476 DEBUG(5, ("BONG! There was no device mode!\n"));
3480 DEBUGADD(8,("loading DEVICEMODE\n"));
3482 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
3483 init_unistr(&devmode
->devicename
, adevice
);
3485 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
3486 init_unistr(&devmode
->formname
, aform
);
3488 devmode
->specversion
= ntdevmode
->specversion
;
3489 devmode
->driverversion
= ntdevmode
->driverversion
;
3490 devmode
->size
= ntdevmode
->size
;
3491 devmode
->driverextra
= ntdevmode
->driverextra
;
3492 devmode
->fields
= ntdevmode
->fields
;
3494 devmode
->orientation
= ntdevmode
->orientation
;
3495 devmode
->papersize
= ntdevmode
->papersize
;
3496 devmode
->paperlength
= ntdevmode
->paperlength
;
3497 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3498 devmode
->scale
= ntdevmode
->scale
;
3499 devmode
->copies
= ntdevmode
->copies
;
3500 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3501 devmode
->printquality
= ntdevmode
->printquality
;
3502 devmode
->color
= ntdevmode
->color
;
3503 devmode
->duplex
= ntdevmode
->duplex
;
3504 devmode
->yresolution
= ntdevmode
->yresolution
;
3505 devmode
->ttoption
= ntdevmode
->ttoption
;
3506 devmode
->collate
= ntdevmode
->collate
;
3507 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3508 devmode
->icmintent
= ntdevmode
->icmintent
;
3509 devmode
->mediatype
= ntdevmode
->mediatype
;
3510 devmode
->dithertype
= ntdevmode
->dithertype
;
3512 if (ntdevmode
->private != NULL
) {
3513 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3517 free_nt_devicemode(&ntdevmode
);
3518 free_a_printer(&printer
,2);
3525 free_nt_devicemode(&ntdevmode
);
3527 free_a_printer(&printer
,2);
3528 free_dev_mode(devmode
);
3533 /********************************************************************
3534 * construct_printer_info_2
3535 * fill a printer_info_2 struct
3536 ********************************************************************/
3538 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
3541 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3543 print_status_struct status
;
3545 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3548 count
= print_queue_length(snum
, &status
);
3550 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3551 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3552 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
3553 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
3554 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
3556 if (*ntprinter
->info_2
->comment
== '\0')
3557 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
3559 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3561 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
3562 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
3563 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
3564 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
3565 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
3567 printer
->attributes
= ntprinter
->info_2
->attributes
;
3569 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
3570 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
3571 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
3572 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
3573 printer
->status
= nt_printq_status(status
.status
); /* status */
3574 printer
->cjobs
= count
; /* jobs */
3575 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
3577 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
3578 DEBUG(8, ("Returning NULL Devicemode!\n"));
3581 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3582 /* steal the printer info sec_desc structure. [badly done]. */
3583 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3584 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
3585 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
3586 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
3589 printer
->secdesc
= NULL
;
3592 free_a_printer(&ntprinter
, 2);
3596 /********************************************************************
3597 * construct_printer_info_3
3598 * fill a printer_info_3 struct
3599 ********************************************************************/
3601 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
3603 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3604 PRINTER_INFO_3
*printer
= NULL
;
3606 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3610 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
3611 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3615 ZERO_STRUCTP(printer
);
3617 printer
->flags
= 4; /* These are the components of the SD we are returning. */
3618 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3619 /* steal the printer info sec_desc structure. [badly done]. */
3620 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3624 * Set the flags for the components we are returning.
3627 if (printer
->secdesc
->owner_sid
)
3628 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
3630 if (printer
->secdesc
->grp_sid
)
3631 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
3633 if (printer
->secdesc
->dacl
)
3634 printer
->flags
|= DACL_SECURITY_INFORMATION
;
3636 if (printer
->secdesc
->sacl
)
3637 printer
->flags
|= SACL_SECURITY_INFORMATION
;
3640 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
3641 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
3642 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
3645 free_a_printer(&ntprinter
, 2);
3647 *pp_printer
= printer
;
3651 /********************************************************************
3652 * construct_printer_info_4
3653 * fill a printer_info_4 struct
3654 ********************************************************************/
3656 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
3658 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3660 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3663 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3664 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3665 printer
->attributes
= ntprinter
->info_2
->attributes
;
3667 free_a_printer(&ntprinter
, 2);
3671 /********************************************************************
3672 * construct_printer_info_5
3673 * fill a printer_info_5 struct
3674 ********************************************************************/
3676 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
3678 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3680 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3683 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3684 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
3685 printer
->attributes
= ntprinter
->info_2
->attributes
;
3686 printer
->device_not_selected_timeout
= 0x3a98;
3687 printer
->transmission_retry_timeout
= 0xafc8;
3689 free_a_printer(&ntprinter
, 2);
3693 /********************************************************************
3694 Spoolss_enumprinters.
3695 ********************************************************************/
3697 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3701 int n_services
=lp_numservices();
3702 PRINTER_INFO_1
*tp
, *printers
=NULL
;
3703 PRINTER_INFO_1 current_prt
;
3705 DEBUG(4,("enum_all_printers_info_1\n"));
3707 for (snum
=0; snum
<n_services
; snum
++) {
3708 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3709 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3711 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
3712 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
3713 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3714 SAFE_FREE(printers
);
3719 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
3721 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
3727 /* check the required size. */
3728 for (i
=0; i
<*returned
; i
++)
3729 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
3731 if (!alloc_buffer_size(buffer
, *needed
))
3732 return WERR_INSUFFICIENT_BUFFER
;
3734 /* fill the buffer with the structures */
3735 for (i
=0; i
<*returned
; i
++)
3736 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
3739 SAFE_FREE(printers
);
3741 if (*needed
> offered
) {
3743 return WERR_INSUFFICIENT_BUFFER
;
3749 /********************************************************************
3750 enum_all_printers_info_1_local.
3751 *********************************************************************/
3753 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3755 DEBUG(4,("enum_all_printers_info_1_local\n"));
3757 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3760 /********************************************************************
3761 enum_all_printers_info_1_name.
3762 *********************************************************************/
3764 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3768 DEBUG(4,("enum_all_printers_info_1_name\n"));
3770 if ((name
[0] == '\\') && (name
[1] == '\\'))
3773 if (is_myname_or_ipaddr(s
)) {
3774 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3777 return WERR_INVALID_NAME
;
3780 /********************************************************************
3781 enum_all_printers_info_1_remote.
3782 *********************************************************************/
3784 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3786 PRINTER_INFO_1
*printer
;
3787 fstring printername
;
3790 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3792 /* JFM: currently it's more a place holder than anything else.
3793 * In the spooler world there is a notion of server registration.
3794 * the print servers are registring (sp ?) on the PDC (in the same domain)
3796 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3799 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3804 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3805 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
3806 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3808 init_unistr(&printer
->description
, desc
);
3809 init_unistr(&printer
->name
, printername
);
3810 init_unistr(&printer
->comment
, comment
);
3811 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3813 /* check the required size. */
3814 *needed
+= spoolss_size_printer_info_1(printer
);
3816 if (!alloc_buffer_size(buffer
, *needed
)) {
3818 return WERR_INSUFFICIENT_BUFFER
;
3821 /* fill the buffer with the structures */
3822 smb_io_printer_info_1("", buffer
, printer
, 0);
3827 if (*needed
> offered
) {
3829 return WERR_INSUFFICIENT_BUFFER
;
3835 /********************************************************************
3836 enum_all_printers_info_1_network.
3837 *********************************************************************/
3839 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3843 DEBUG(4,("enum_all_printers_info_1_network\n"));
3845 /* If we respond to a enum_printers level 1 on our name with flags
3846 set to PRINTER_ENUM_REMOTE with a list of printers then these
3847 printers incorrectly appear in the APW browse list.
3848 Specifically the printers for the server appear at the workgroup
3849 level where all the other servers in the domain are
3850 listed. Windows responds to this call with a
3851 WERR_CAN_NOT_COMPLETE so we should do the same. */
3853 if (name
[0] == '\\' && name
[1] == '\\')
3856 if (is_myname_or_ipaddr(s
))
3857 return WERR_CAN_NOT_COMPLETE
;
3859 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3862 /********************************************************************
3863 * api_spoolss_enumprinters
3865 * called from api_spoolss_enumprinters (see this to understand)
3866 ********************************************************************/
3868 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3872 int n_services
=lp_numservices();
3873 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3874 PRINTER_INFO_2 current_prt
;
3876 for (snum
=0; snum
<n_services
; snum
++) {
3877 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3878 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3880 if (construct_printer_info_2(¤t_prt
, snum
)) {
3881 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3882 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3883 SAFE_FREE(printers
);
3888 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3889 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3895 /* check the required size. */
3896 for (i
=0; i
<*returned
; i
++)
3897 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3899 if (!alloc_buffer_size(buffer
, *needed
)) {
3900 for (i
=0; i
<*returned
; i
++) {
3901 free_devmode(printers
[i
].devmode
);
3903 SAFE_FREE(printers
);
3904 return WERR_INSUFFICIENT_BUFFER
;
3907 /* fill the buffer with the structures */
3908 for (i
=0; i
<*returned
; i
++)
3909 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3912 for (i
=0; i
<*returned
; i
++) {
3913 free_devmode(printers
[i
].devmode
);
3915 SAFE_FREE(printers
);
3917 if (*needed
> offered
) {
3919 return WERR_INSUFFICIENT_BUFFER
;
3925 /********************************************************************
3926 * handle enumeration of printers at level 1
3927 ********************************************************************/
3929 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3930 NEW_BUFFER
*buffer
, uint32 offered
,
3931 uint32
*needed
, uint32
*returned
)
3933 /* Not all the flags are equals */
3935 if (flags
& PRINTER_ENUM_LOCAL
)
3936 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3938 if (flags
& PRINTER_ENUM_NAME
)
3939 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3941 if (flags
& PRINTER_ENUM_REMOTE
)
3942 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3944 if (flags
& PRINTER_ENUM_NETWORK
)
3945 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
3947 return WERR_OK
; /* NT4sp5 does that */
3950 /********************************************************************
3951 * handle enumeration of printers at level 2
3952 ********************************************************************/
3954 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3955 NEW_BUFFER
*buffer
, uint32 offered
,
3956 uint32
*needed
, uint32
*returned
)
3958 char *s
= servername
;
3960 if (flags
& PRINTER_ENUM_LOCAL
) {
3961 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3964 if (flags
& PRINTER_ENUM_NAME
) {
3965 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3967 if (is_myname_or_ipaddr(s
))
3968 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3970 return WERR_INVALID_NAME
;
3973 if (flags
& PRINTER_ENUM_REMOTE
)
3974 return WERR_UNKNOWN_LEVEL
;
3979 /********************************************************************
3980 * handle enumeration of printers at level 5
3981 ********************************************************************/
3983 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3984 NEW_BUFFER
*buffer
, uint32 offered
,
3985 uint32
*needed
, uint32
*returned
)
3987 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3991 /********************************************************************
3992 * api_spoolss_enumprinters
3994 * called from api_spoolss_enumprinters (see this to understand)
3995 ********************************************************************/
3997 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3999 uint32 flags
= q_u
->flags
;
4000 UNISTR2
*servername
= &q_u
->servername
;
4001 uint32 level
= q_u
->level
;
4002 NEW_BUFFER
*buffer
= NULL
;
4003 uint32 offered
= q_u
->offered
;
4004 uint32
*needed
= &r_u
->needed
;
4005 uint32
*returned
= &r_u
->returned
;
4009 /* that's an [in out] buffer */
4010 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4011 buffer
= r_u
->buffer
;
4013 DEBUG(4,("_spoolss_enumprinters\n"));
4020 * flags==PRINTER_ENUM_NAME
4021 * if name=="" then enumerates all printers
4022 * if name!="" then enumerate the printer
4023 * flags==PRINTER_ENUM_REMOTE
4024 * name is NULL, enumerate printers
4025 * Level 2: name!="" enumerates printers, name can't be NULL
4026 * Level 3: doesn't exist
4027 * Level 4: does a local registry lookup
4028 * Level 5: same as Level 2
4031 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4036 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4038 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4040 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4045 return WERR_UNKNOWN_LEVEL
;
4048 /****************************************************************************
4049 ****************************************************************************/
4051 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4053 PRINTER_INFO_0
*printer
=NULL
;
4055 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4058 construct_printer_info_0(printer
, snum
);
4060 /* check the required size. */
4061 *needed
+= spoolss_size_printer_info_0(printer
);
4063 if (!alloc_buffer_size(buffer
, *needed
)) {
4065 return WERR_INSUFFICIENT_BUFFER
;
4068 /* fill the buffer with the structures */
4069 smb_io_printer_info_0("", buffer
, printer
, 0);
4074 if (*needed
> offered
) {
4075 return WERR_INSUFFICIENT_BUFFER
;
4081 /****************************************************************************
4082 ****************************************************************************/
4084 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4086 PRINTER_INFO_1
*printer
=NULL
;
4088 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4091 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
4093 /* check the required size. */
4094 *needed
+= spoolss_size_printer_info_1(printer
);
4096 if (!alloc_buffer_size(buffer
, *needed
)) {
4098 return WERR_INSUFFICIENT_BUFFER
;
4101 /* fill the buffer with the structures */
4102 smb_io_printer_info_1("", buffer
, printer
, 0);
4107 if (*needed
> offered
) {
4108 return WERR_INSUFFICIENT_BUFFER
;
4114 /****************************************************************************
4115 ****************************************************************************/
4117 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4119 PRINTER_INFO_2
*printer
=NULL
;
4121 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4124 construct_printer_info_2(printer
, snum
);
4126 /* check the required size. */
4127 *needed
+= spoolss_size_printer_info_2(printer
);
4129 if (!alloc_buffer_size(buffer
, *needed
)) {
4130 free_printer_info_2(printer
);
4131 return WERR_INSUFFICIENT_BUFFER
;
4134 /* fill the buffer with the structures */
4135 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4136 free_printer_info_2(printer
);
4141 free_printer_info_2(printer
);
4143 if (*needed
> offered
) {
4144 return WERR_INSUFFICIENT_BUFFER
;
4150 /****************************************************************************
4151 ****************************************************************************/
4153 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4155 PRINTER_INFO_3
*printer
=NULL
;
4157 if (!construct_printer_info_3(&printer
, snum
))
4160 /* check the required size. */
4161 *needed
+= spoolss_size_printer_info_3(printer
);
4163 if (!alloc_buffer_size(buffer
, *needed
)) {
4164 free_printer_info_3(printer
);
4165 return WERR_INSUFFICIENT_BUFFER
;
4168 /* fill the buffer with the structures */
4169 smb_io_printer_info_3("", buffer
, printer
, 0);
4172 free_printer_info_3(printer
);
4174 if (*needed
> offered
) {
4175 return WERR_INSUFFICIENT_BUFFER
;
4181 /****************************************************************************
4182 ****************************************************************************/
4184 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4186 PRINTER_INFO_4
*printer
=NULL
;
4188 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4191 if (!construct_printer_info_4(printer
, snum
))
4194 /* check the required size. */
4195 *needed
+= spoolss_size_printer_info_4(printer
);
4197 if (!alloc_buffer_size(buffer
, *needed
)) {
4198 free_printer_info_4(printer
);
4199 return WERR_INSUFFICIENT_BUFFER
;
4202 /* fill the buffer with the structures */
4203 smb_io_printer_info_4("", buffer
, printer
, 0);
4206 free_printer_info_4(printer
);
4208 if (*needed
> offered
) {
4209 return WERR_INSUFFICIENT_BUFFER
;
4215 /****************************************************************************
4216 ****************************************************************************/
4218 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4220 PRINTER_INFO_5
*printer
=NULL
;
4222 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4225 if (!construct_printer_info_5(printer
, snum
))
4228 /* check the required size. */
4229 *needed
+= spoolss_size_printer_info_5(printer
);
4231 if (!alloc_buffer_size(buffer
, *needed
)) {
4232 free_printer_info_5(printer
);
4233 return WERR_INSUFFICIENT_BUFFER
;
4236 /* fill the buffer with the structures */
4237 smb_io_printer_info_5("", buffer
, printer
, 0);
4240 free_printer_info_5(printer
);
4242 if (*needed
> offered
) {
4243 return WERR_INSUFFICIENT_BUFFER
;
4249 /****************************************************************************
4250 ****************************************************************************/
4252 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4254 POLICY_HND
*handle
= &q_u
->handle
;
4255 uint32 level
= q_u
->level
;
4256 NEW_BUFFER
*buffer
= NULL
;
4257 uint32 offered
= q_u
->offered
;
4258 uint32
*needed
= &r_u
->needed
;
4262 /* that's an [in out] buffer */
4263 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4264 buffer
= r_u
->buffer
;
4268 if (!get_printer_snum(p
, handle
, &snum
))
4273 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4275 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4277 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4279 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4281 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4283 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4285 return WERR_UNKNOWN_LEVEL
;
4288 /********************************************************************
4289 * fill a DRIVER_INFO_1 struct
4290 ********************************************************************/
4292 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4294 init_unistr( &info
->name
, driver
.info_3
->name
);
4297 /********************************************************************
4298 * construct_printer_driver_info_1
4299 ********************************************************************/
4301 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4303 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4304 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4306 ZERO_STRUCT(driver
);
4308 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4309 return WERR_INVALID_PRINTER_NAME
;
4311 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4312 return WERR_UNKNOWN_PRINTER_DRIVER
;
4314 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4316 free_a_printer(&printer
,2);
4321 /********************************************************************
4322 * construct_printer_driver_info_2
4323 * fill a printer_info_2 struct
4324 ********************************************************************/
4326 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4330 info
->version
=driver
.info_3
->cversion
;
4332 init_unistr( &info
->name
, driver
.info_3
->name
);
4333 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4336 if (strlen(driver
.info_3
->driverpath
)) {
4337 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4338 init_unistr( &info
->driverpath
, temp
);
4340 init_unistr( &info
->driverpath
, "" );
4342 if (strlen(driver
.info_3
->datafile
)) {
4343 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4344 init_unistr( &info
->datafile
, temp
);
4346 init_unistr( &info
->datafile
, "" );
4348 if (strlen(driver
.info_3
->configfile
)) {
4349 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4350 init_unistr( &info
->configfile
, temp
);
4352 init_unistr( &info
->configfile
, "" );
4355 /********************************************************************
4356 * construct_printer_driver_info_2
4357 * fill a printer_info_2 struct
4358 ********************************************************************/
4360 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4362 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4363 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4365 ZERO_STRUCT(printer
);
4366 ZERO_STRUCT(driver
);
4368 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4369 return WERR_INVALID_PRINTER_NAME
;
4371 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4372 return WERR_UNKNOWN_PRINTER_DRIVER
;
4374 fill_printer_driver_info_2(info
, driver
, servername
);
4376 free_a_printer(&printer
,2);
4381 /********************************************************************
4382 * copy a strings array and convert to UNICODE
4384 * convert an array of ascii string to a UNICODE string
4385 ********************************************************************/
4387 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
4395 DEBUG(6,("init_unistr_array\n"));
4400 if (char_array
== NULL
)
4404 if (!v
) v
= ""; /* hack to handle null lists */
4410 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4412 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4414 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4415 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4420 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
4425 (*uni_array
)[j
]=0x0000;
4428 DEBUGADD(6,("last one:done\n"));
4431 /********************************************************************
4432 * construct_printer_info_3
4433 * fill a printer_info_3 struct
4434 ********************************************************************/
4436 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4442 info
->version
=driver
.info_3
->cversion
;
4444 init_unistr( &info
->name
, driver
.info_3
->name
);
4445 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4447 if (strlen(driver
.info_3
->driverpath
)) {
4448 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4449 init_unistr( &info
->driverpath
, temp
);
4451 init_unistr( &info
->driverpath
, "" );
4453 if (strlen(driver
.info_3
->datafile
)) {
4454 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4455 init_unistr( &info
->datafile
, temp
);
4457 init_unistr( &info
->datafile
, "" );
4459 if (strlen(driver
.info_3
->configfile
)) {
4460 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4461 init_unistr( &info
->configfile
, temp
);
4463 init_unistr( &info
->configfile
, "" );
4465 if (strlen(driver
.info_3
->helpfile
)) {
4466 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4467 init_unistr( &info
->helpfile
, temp
);
4469 init_unistr( &info
->helpfile
, "" );
4471 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4472 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4474 info
->dependentfiles
=NULL
;
4475 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4478 /********************************************************************
4479 * construct_printer_info_3
4480 * fill a printer_info_3 struct
4481 ********************************************************************/
4483 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4485 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4486 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4488 ZERO_STRUCT(driver
);
4490 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4491 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4492 if (!W_ERROR_IS_OK(status
))
4493 return WERR_INVALID_PRINTER_NAME
;
4495 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4496 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4501 * I put this code in during testing. Helpful when commenting out the
4502 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4503 * as win2k always queries the driver using an infor level of 6.
4504 * I've left it in (but ifdef'd out) because I'll probably
4505 * use it in experimentation again in the future. --jerry 22/01/2002
4508 if (!W_ERROR_IS_OK(status
)) {
4510 * Is this a W2k client ?
4513 /* Yes - try again with a WinNT driver. */
4515 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4516 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4520 if (!W_ERROR_IS_OK(status
)) {
4521 free_a_printer(&printer
,2);
4522 return WERR_UNKNOWN_PRINTER_DRIVER
;
4530 fill_printer_driver_info_3(info
, driver
, servername
);
4532 free_a_printer(&printer
,2);
4537 /********************************************************************
4538 * construct_printer_info_6
4539 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4540 ********************************************************************/
4542 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4548 memset(&nullstr
, '\0', sizeof(fstring
));
4550 info
->version
=driver
.info_3
->cversion
;
4552 init_unistr( &info
->name
, driver
.info_3
->name
);
4553 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4555 if (strlen(driver
.info_3
->driverpath
)) {
4556 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4557 init_unistr( &info
->driverpath
, temp
);
4559 init_unistr( &info
->driverpath
, "" );
4561 if (strlen(driver
.info_3
->datafile
)) {
4562 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4563 init_unistr( &info
->datafile
, temp
);
4565 init_unistr( &info
->datafile
, "" );
4567 if (strlen(driver
.info_3
->configfile
)) {
4568 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4569 init_unistr( &info
->configfile
, temp
);
4571 init_unistr( &info
->configfile
, "" );
4573 if (strlen(driver
.info_3
->helpfile
)) {
4574 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4575 init_unistr( &info
->helpfile
, temp
);
4577 init_unistr( &info
->helpfile
, "" );
4579 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4580 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4582 info
->dependentfiles
= NULL
;
4583 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4585 info
->previousdrivernames
=NULL
;
4586 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
4588 info
->driver_date
.low
=0;
4589 info
->driver_date
.high
=0;
4592 info
->driver_version_low
=0;
4593 info
->driver_version_high
=0;
4595 init_unistr( &info
->mfgname
, "");
4596 init_unistr( &info
->oem_url
, "");
4597 init_unistr( &info
->hardware_id
, "");
4598 init_unistr( &info
->provider
, "");
4601 /********************************************************************
4602 * construct_printer_info_6
4603 * fill a printer_info_6 struct
4604 ********************************************************************/
4606 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
4607 fstring servername
, fstring architecture
, uint32 version
)
4609 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4610 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4613 ZERO_STRUCT(driver
);
4615 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4617 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4619 if (!W_ERROR_IS_OK(status
))
4620 return WERR_INVALID_PRINTER_NAME
;
4622 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4624 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4626 if (!W_ERROR_IS_OK(status
))
4629 * Is this a W2k client ?
4633 free_a_printer(&printer
,2);
4634 return WERR_UNKNOWN_PRINTER_DRIVER
;
4637 /* Yes - try again with a WinNT driver. */
4639 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4640 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4641 if (!W_ERROR_IS_OK(status
)) {
4642 free_a_printer(&printer
,2);
4643 return WERR_UNKNOWN_PRINTER_DRIVER
;
4647 fill_printer_driver_info_6(info
, driver
, servername
);
4649 free_a_printer(&printer
,2);
4654 /****************************************************************************
4655 ****************************************************************************/
4657 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
4659 SAFE_FREE(info
->dependentfiles
);
4662 /****************************************************************************
4663 ****************************************************************************/
4665 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
4667 SAFE_FREE(info
->dependentfiles
);
4671 /****************************************************************************
4672 ****************************************************************************/
4674 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4676 DRIVER_INFO_1
*info
=NULL
;
4679 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
4682 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
4683 if (!W_ERROR_IS_OK(status
)) {
4688 /* check the required size. */
4689 *needed
+= spoolss_size_printer_driver_info_1(info
);
4691 if (!alloc_buffer_size(buffer
, *needed
)) {
4693 return WERR_INSUFFICIENT_BUFFER
;
4696 /* fill the buffer with the structures */
4697 smb_io_printer_driver_info_1("", buffer
, info
, 0);
4702 if (*needed
> offered
)
4703 return WERR_INSUFFICIENT_BUFFER
;
4708 /****************************************************************************
4709 ****************************************************************************/
4711 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4713 DRIVER_INFO_2
*info
=NULL
;
4716 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
4719 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
4720 if (!W_ERROR_IS_OK(status
)) {
4725 /* check the required size. */
4726 *needed
+= spoolss_size_printer_driver_info_2(info
);
4728 if (!alloc_buffer_size(buffer
, *needed
)) {
4730 return WERR_INSUFFICIENT_BUFFER
;
4733 /* fill the buffer with the structures */
4734 smb_io_printer_driver_info_2("", buffer
, info
, 0);
4739 if (*needed
> offered
)
4740 return WERR_INSUFFICIENT_BUFFER
;
4745 /****************************************************************************
4746 ****************************************************************************/
4748 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4755 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
4756 if (!W_ERROR_IS_OK(status
)) {
4760 /* check the required size. */
4761 *needed
+= spoolss_size_printer_driver_info_3(&info
);
4763 if (!alloc_buffer_size(buffer
, *needed
)) {
4764 free_printer_driver_info_3(&info
);
4765 return WERR_INSUFFICIENT_BUFFER
;
4768 /* fill the buffer with the structures */
4769 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
4771 free_printer_driver_info_3(&info
);
4773 if (*needed
> offered
)
4774 return WERR_INSUFFICIENT_BUFFER
;
4779 /****************************************************************************
4780 ****************************************************************************/
4782 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4789 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
4790 if (!W_ERROR_IS_OK(status
)) {
4794 /* check the required size. */
4795 *needed
+= spoolss_size_printer_driver_info_6(&info
);
4797 if (!alloc_buffer_size(buffer
, *needed
)) {
4798 free_printer_driver_info_6(&info
);
4799 return WERR_INSUFFICIENT_BUFFER
;
4802 /* fill the buffer with the structures */
4803 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
4805 free_printer_driver_info_6(&info
);
4807 if (*needed
> offered
)
4808 return WERR_INSUFFICIENT_BUFFER
;
4813 /****************************************************************************
4814 ****************************************************************************/
4816 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
4818 POLICY_HND
*handle
= &q_u
->handle
;
4819 UNISTR2
*uni_arch
= &q_u
->architecture
;
4820 uint32 level
= q_u
->level
;
4821 uint32 clientmajorversion
= q_u
->clientmajorversion
;
4822 NEW_BUFFER
*buffer
= NULL
;
4823 uint32 offered
= q_u
->offered
;
4824 uint32
*needed
= &r_u
->needed
;
4825 uint32
*servermajorversion
= &r_u
->servermajorversion
;
4826 uint32
*serverminorversion
= &r_u
->serverminorversion
;
4829 fstring architecture
;
4832 /* that's an [in out] buffer */
4833 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4834 buffer
= r_u
->buffer
;
4836 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4839 *servermajorversion
= 0;
4840 *serverminorversion
= 0;
4842 pstrcpy(servername
, get_called_name());
4843 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
4845 if (!get_printer_snum(p
, handle
, &snum
))
4850 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4852 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4854 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4856 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4859 return WERR_UNKNOWN_LEVEL
;
4862 /****************************************************************************
4863 ****************************************************************************/
4865 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
4867 POLICY_HND
*handle
= &q_u
->handle
;
4869 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4872 DEBUG(3,("Error in startpageprinter printer handle\n"));
4876 Printer
->page_started
=True
;
4880 /****************************************************************************
4881 ****************************************************************************/
4883 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
4885 POLICY_HND
*handle
= &q_u
->handle
;
4888 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4891 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
4895 if (!get_printer_snum(p
, handle
, &snum
))
4898 Printer
->page_started
=False
;
4899 print_job_endpage(snum
, Printer
->jobid
);
4904 /********************************************************************
4905 * api_spoolss_getprinter
4906 * called from the spoolss dispatcher
4908 ********************************************************************/
4910 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
4912 POLICY_HND
*handle
= &q_u
->handle
;
4913 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
4914 uint32
*jobid
= &r_u
->jobid
;
4916 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
4920 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4921 struct current_user user
;
4924 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4928 get_current_user(&user
, p
);
4931 * a nice thing with NT is it doesn't listen to what you tell it.
4932 * when asked to send _only_ RAW datas, it tries to send datas
4935 * So I add checks like in NT Server ...
4937 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4938 * there's a bug in NT client-side code, so we'll fix it in the
4939 * server-side code. *nnnnnggggh!*
4942 if (info_1
->p_datatype
!= 0) {
4943 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
4944 if (strcmp(datatype
, "RAW") != 0) {
4946 return WERR_INVALID_DATATYPE
;
4950 /* get the share number of the printer */
4951 if (!get_printer_snum(p
, handle
, &snum
)) {
4955 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
4957 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4959 /* An error occured in print_job_start() so return an appropriate
4962 if (Printer
->jobid
== -1) {
4963 return map_werror_from_unix(errno
);
4966 Printer
->document_started
=True
;
4967 (*jobid
) = Printer
->jobid
;
4972 /********************************************************************
4973 * api_spoolss_getprinter
4974 * called from the spoolss dispatcher
4976 ********************************************************************/
4978 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4980 POLICY_HND
*handle
= &q_u
->handle
;
4982 return _spoolss_enddocprinter_internal(p
, handle
);
4985 /****************************************************************************
4986 ****************************************************************************/
4988 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4990 POLICY_HND
*handle
= &q_u
->handle
;
4991 uint32 buffer_size
= q_u
->buffer_size
;
4992 uint8
*buffer
= q_u
->buffer
;
4993 uint32
*buffer_written
= &q_u
->buffer_size2
;
4995 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4998 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
4999 r_u
->buffer_written
= q_u
->buffer_size2
;
5003 if (!get_printer_snum(p
, handle
, &snum
))
5006 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5008 r_u
->buffer_written
= q_u
->buffer_size2
;
5013 /********************************************************************
5014 * api_spoolss_getprinter
5015 * called from the spoolss dispatcher
5017 ********************************************************************/
5019 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5022 struct current_user user
;
5024 WERROR errcode
= WERR_BADFUNC
;
5025 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5027 get_current_user(&user
, p
);
5030 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5034 if (!get_printer_snum(p
, handle
, &snum
))
5038 case PRINTER_CONTROL_PAUSE
:
5039 if (print_queue_pause(&user
, snum
, &errcode
)) {
5043 case PRINTER_CONTROL_RESUME
:
5044 case PRINTER_CONTROL_UNPAUSE
:
5045 if (print_queue_resume(&user
, snum
, &errcode
)) {
5049 case PRINTER_CONTROL_PURGE
:
5050 if (print_queue_purge(&user
, snum
, &errcode
)) {
5055 return WERR_UNKNOWN_LEVEL
;
5061 /********************************************************************
5062 * api_spoolss_abortprinter
5063 ********************************************************************/
5065 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5067 POLICY_HND
*handle
= &q_u
->handle
;
5069 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
5072 /********************************************************************
5073 * called by spoolss_api_setprinter
5074 * when updating a printer description
5075 ********************************************************************/
5077 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5078 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5079 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5081 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5082 struct current_user user
;
5086 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5088 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5089 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5090 OUR_HANDLE(handle
)));
5092 result
= WERR_BADFID
;
5096 /* NT seems to like setting the security descriptor even though
5097 nothing may have actually changed. This causes annoying
5098 dialog boxes when the user doesn't have permission to change
5099 the security descriptor. */
5101 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
5103 if (DEBUGLEVEL
>= 10) {
5107 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5108 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5109 PRINTERNAME(snum
), the_acl
->num_aces
));
5111 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5114 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5116 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5117 the_acl
->ace
[i
].info
.mask
));
5120 the_acl
= secdesc_ctr
->sec
->dacl
;
5123 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5124 PRINTERNAME(snum
), the_acl
->num_aces
));
5126 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5129 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5131 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5132 the_acl
->ace
[i
].info
.mask
));
5135 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5139 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5141 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5146 /* Work out which user is performing the operation */
5148 get_current_user(&user
, p
);
5150 /* Check the user has permissions to change the security
5151 descriptor. By experimentation with two NT machines, the user
5152 requires Full Access to the printer to change security
5155 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5156 result
= WERR_ACCESS_DENIED
;
5160 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5167 /********************************************************************
5168 Do Samba sanity checks on a printer info struct.
5169 this has changed purpose: it now "canonicalises" printer
5170 info from a client rather than just checking it is correct
5171 ********************************************************************/
5173 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5175 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5176 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5178 /* we force some elements to "correct" values */
5179 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5180 fstrcpy(info
->sharename
, lp_servicename(snum
));
5181 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5182 get_called_name(), info
->sharename
);
5183 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
5188 /****************************************************************************
5189 ****************************************************************************/
5191 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5193 extern userdom_struct current_user_info
;
5194 char *cmd
= lp_addprinter_cmd();
5197 pstring driverlocation
;
5201 fstring remote_machine
= "%m";
5203 /* build driver path... only 9X architecture is needed for legacy reasons */
5204 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
5206 /* change \ to \\ for the shell */
5207 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
5208 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5210 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5211 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5212 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5213 printer
->info_2
->location
, driverlocation
, remote_machine
);
5215 DEBUG(10,("Running [%s]\n", command
));
5216 ret
= smbrun(command
, &fd
);
5217 DEBUGADD(10,("returned [%d]\n", ret
));
5226 /* Get lines and convert them back to dos-codepage */
5227 qlines
= fd_lines_load(fd
, &numlines
);
5228 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5232 /* Set the portname to what the script says the portname should be. */
5233 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5234 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5236 /* Send SIGHUP to process group... is there a better way? */
5241 file_lines_free(qlines
);
5245 /********************************************************************
5246 * Called by spoolss_api_setprinter
5247 * when updating a printer description.
5248 ********************************************************************/
5250 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5251 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5252 DEVICEMODE
*devmode
)
5255 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5256 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5259 DEBUG(8,("update_printer\n"));
5264 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5265 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5266 result
= WERR_UNKNOWN_LEVEL
;
5271 result
= WERR_BADFID
;
5275 if (!get_printer_snum(p
, handle
, &snum
)) {
5276 result
= WERR_BADFID
;
5280 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5281 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5282 result
= WERR_BADFID
;
5286 DEBUGADD(8,("Converting info_2 struct\n"));
5289 * convert_printer_info converts the incoming
5290 * info from the client and overwrites the info
5291 * just read from the tdb in the pointer 'printer'.
5294 if (!convert_printer_info(info
, printer
, level
)) {
5295 result
= WERR_NOMEM
;
5300 /* we have a valid devmode
5301 convert it and link it*/
5303 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5304 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5305 &printer
->info_2
->devmode
)) {
5306 result
= WERR_NOMEM
;
5311 /* Do sanity check on the requested changes for Samba */
5313 if (!check_printer_ok(printer
->info_2
, snum
)) {
5314 result
= WERR_INVALID_PARAM
;
5321 * Another one of those historical misunderstandings...
5322 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5323 * I'm leaving it here as a reminder. --jerry
5326 if (nt_printer_info_level_equal(printer
, old_printer
)) {
5327 DEBUG(3, ("update_printer: printer info has not changed\n"));
5334 /* Check calling user has permission to update printer description */
5336 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5337 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5338 result
= WERR_ACCESS_DENIED
;
5342 /* Call addprinter hook */
5344 if (*lp_addprinter_cmd()) {
5345 if ( !add_printer_hook(printer
) ) {
5346 result
= WERR_ACCESS_DENIED
;
5352 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5353 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5354 * requires Win32 client code (see other notes elsewhere in the code).
5356 if (printer
->info_2
->devmode
&&
5357 printer
->info_2
->devmode
->displayfrequency
== MAGIC_DISPLAY_FREQUENCY
)
5360 DEBUG(10,("update_printer: Save printer driver init data\n"));
5361 printer
->info_2
->devmode
->displayfrequency
= 0;
5363 if (update_driver_init(*printer
, 2)!=0) {
5364 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5365 result
= WERR_ACCESS_DENIED
;
5369 /* we need to reset all driver init data for all printers
5370 bound to this driver */
5372 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
5378 * When a *new* driver is bound to a printer, the drivername is used to
5379 * lookup previously saved driver initialization info, which is then
5380 * bound to the printer, simulating what happens in the Windows arch.
5382 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5384 if (!set_driver_init(printer
, 2))
5386 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5387 printer
->info_2
->drivername
));
5390 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5391 printer
->info_2
->drivername
));
5393 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5397 /* Update printer info */
5398 result
= mod_a_printer(*printer
, 2);
5400 /* flag which changes actually occured. This is a small subset of
5401 all the possible changes */
5403 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5404 notify_printer_comment(snum
, printer
->info_2
->comment
);
5406 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5407 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5409 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5410 notify_printer_port(snum
, printer
->info_2
->portname
);
5412 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5413 notify_printer_location(snum
, printer
->info_2
->location
);
5416 free_a_printer(&printer
, 2);
5417 free_a_printer(&old_printer
, 2);
5423 /****************************************************************************
5424 ****************************************************************************/
5426 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5428 POLICY_HND
*handle
= &q_u
->handle
;
5429 uint32 level
= q_u
->level
;
5430 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5431 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5432 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5433 uint32 command
= q_u
->command
;
5435 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5438 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5442 /* check the level */
5445 return control_printer(handle
, command
, p
);
5447 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
5449 return update_printer_sec(handle
, level
, info
, p
,
5452 return WERR_UNKNOWN_LEVEL
;
5456 /****************************************************************************
5457 ****************************************************************************/
5459 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
5461 POLICY_HND
*handle
= &q_u
->handle
;
5463 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5466 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5470 if (Printer
->notify
.client_connected
==True
)
5471 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
5473 Printer
->notify
.flags
=0;
5474 Printer
->notify
.options
=0;
5475 Printer
->notify
.localmachine
[0]='\0';
5476 Printer
->notify
.printerlocal
=0;
5477 if (Printer
->notify
.option
)
5478 free_spool_notify_option(&Printer
->notify
.option
);
5479 Printer
->notify
.client_connected
=False
;
5484 /****************************************************************************
5485 ****************************************************************************/
5487 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
5489 /* that's an [in out] buffer (despite appearences to the contrary) */
5490 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5493 return WERR_INVALID_PARAM
; /* this is what a NT server
5494 returns for AddJob. AddJob
5495 must fail on non-local
5499 /****************************************************************************
5500 ****************************************************************************/
5502 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
5503 int position
, int snum
)
5509 t
=gmtime(&queue
->time
);
5510 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5512 job_info
->jobid
=queue
->job
;
5513 init_unistr(&job_info
->printername
, lp_servicename(snum
));
5514 init_unistr(&job_info
->machinename
, temp_name
);
5515 init_unistr(&job_info
->username
, queue
->fs_user
);
5516 init_unistr(&job_info
->document
, queue
->fs_file
);
5517 init_unistr(&job_info
->datatype
, "RAW");
5518 init_unistr(&job_info
->text_status
, "");
5519 job_info
->status
=nt_printj_status(queue
->status
);
5520 job_info
->priority
=queue
->priority
;
5521 job_info
->position
=position
;
5522 job_info
->totalpages
=queue
->page_count
;
5523 job_info
->pagesprinted
=0;
5525 make_systemtime(&job_info
->submitted
, t
);
5528 /****************************************************************************
5529 ****************************************************************************/
5531 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
5532 int position
, int snum
,
5533 NT_PRINTER_INFO_LEVEL
*ntprinter
,
5534 DEVICEMODE
*devmode
)
5540 t
=gmtime(&queue
->time
);
5541 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5543 job_info
->jobid
=queue
->job
;
5545 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
5547 init_unistr(&job_info
->printername
, chaine
);
5549 init_unistr(&job_info
->machinename
, temp_name
);
5550 init_unistr(&job_info
->username
, queue
->fs_user
);
5551 init_unistr(&job_info
->document
, queue
->fs_file
);
5552 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
5553 init_unistr(&job_info
->datatype
, "RAW");
5554 init_unistr(&job_info
->printprocessor
, "winprint");
5555 init_unistr(&job_info
->parameters
, "");
5556 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
5557 init_unistr(&job_info
->text_status
, "");
5559 /* and here the security descriptor */
5561 job_info
->status
=nt_printj_status(queue
->status
);
5562 job_info
->priority
=queue
->priority
;
5563 job_info
->position
=position
;
5564 job_info
->starttime
=0;
5565 job_info
->untiltime
=0;
5566 job_info
->totalpages
=queue
->page_count
;
5567 job_info
->size
=queue
->size
;
5568 make_systemtime(&(job_info
->submitted
), t
);
5569 job_info
->timeelapsed
=0;
5570 job_info
->pagesprinted
=0;
5572 job_info
->devmode
= devmode
;
5577 /****************************************************************************
5578 Enumjobs at level 1.
5579 ****************************************************************************/
5581 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
5582 NEW_BUFFER
*buffer
, uint32 offered
,
5583 uint32
*needed
, uint32
*returned
)
5588 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
5595 for (i
=0; i
<*returned
; i
++)
5596 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
5600 /* check the required size. */
5601 for (i
=0; i
<*returned
; i
++)
5602 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
5604 if (!alloc_buffer_size(buffer
, *needed
)) {
5606 return WERR_INSUFFICIENT_BUFFER
;
5609 /* fill the buffer with the structures */
5610 for (i
=0; i
<*returned
; i
++)
5611 smb_io_job_info_1("", buffer
, &info
[i
], 0);
5616 if (*needed
> offered
) {
5618 return WERR_INSUFFICIENT_BUFFER
;
5624 /****************************************************************************
5625 Enumjobs at level 2.
5626 ****************************************************************************/
5628 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
5629 NEW_BUFFER
*buffer
, uint32 offered
,
5630 uint32
*needed
, uint32
*returned
)
5632 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
5633 JOB_INFO_2
*info
= NULL
;
5636 DEVICEMODE
*devmode
= NULL
;
5638 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
5641 result
= WERR_NOMEM
;
5645 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
5646 if (!W_ERROR_IS_OK(result
)) {
5651 if (!(devmode
= construct_dev_mode(snum
))) {
5653 result
= WERR_NOMEM
;
5657 for (i
=0; i
<*returned
; i
++)
5658 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
5661 free_a_printer(&ntprinter
, 2);
5664 /* check the required size. */
5665 for (i
=0; i
<*returned
; i
++)
5666 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
5668 if (*needed
> offered
) {
5670 result
= WERR_INSUFFICIENT_BUFFER
;
5674 if (!alloc_buffer_size(buffer
, *needed
)) {
5676 result
= WERR_INSUFFICIENT_BUFFER
;
5680 /* fill the buffer with the structures */
5681 for (i
=0; i
<*returned
; i
++)
5682 smb_io_job_info_2("", buffer
, &info
[i
], 0);
5687 free_a_printer(&ntprinter
, 2);
5688 free_devmode(devmode
);
5696 /****************************************************************************
5698 ****************************************************************************/
5700 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
5702 POLICY_HND
*handle
= &q_u
->handle
;
5703 uint32 level
= q_u
->level
;
5704 NEW_BUFFER
*buffer
= NULL
;
5705 uint32 offered
= q_u
->offered
;
5706 uint32
*needed
= &r_u
->needed
;
5707 uint32
*returned
= &r_u
->returned
;
5710 print_status_struct prt_status
;
5711 print_queue_struct
*queue
=NULL
;
5713 /* that's an [in out] buffer */
5714 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5715 buffer
= r_u
->buffer
;
5717 DEBUG(4,("_spoolss_enumjobs\n"));
5722 if (!get_printer_snum(p
, handle
, &snum
))
5725 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
5726 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
5728 if (*returned
== 0) {
5735 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
5737 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
5741 return WERR_UNKNOWN_LEVEL
;
5745 /****************************************************************************
5746 ****************************************************************************/
5748 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
5753 /****************************************************************************
5754 ****************************************************************************/
5756 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
5758 POLICY_HND
*handle
= &q_u
->handle
;
5759 uint32 jobid
= q_u
->jobid
;
5760 uint32 command
= q_u
->command
;
5762 struct current_user user
;
5764 WERROR errcode
= WERR_BADFUNC
;
5766 if (!get_printer_snum(p
, handle
, &snum
)) {
5770 if (!print_job_exists(snum
, jobid
)) {
5771 return WERR_INVALID_PRINTER_NAME
;
5774 get_current_user(&user
, p
);
5777 case JOB_CONTROL_CANCEL
:
5778 case JOB_CONTROL_DELETE
:
5779 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
5783 case JOB_CONTROL_PAUSE
:
5784 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
5788 case JOB_CONTROL_RESTART
:
5789 case JOB_CONTROL_RESUME
:
5790 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
5795 return WERR_UNKNOWN_LEVEL
;
5801 /****************************************************************************
5802 Enumerates all printer drivers at level 1.
5803 ****************************************************************************/
5805 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5810 fstring
*list
= NULL
;
5812 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5813 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5817 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
5819 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5820 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5826 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5827 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5828 SAFE_FREE(driver_info_1
);
5832 else driver_info_1
= tdi1
;
5835 for (i
=0; i
<ndrivers
; i
++) {
5837 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5838 ZERO_STRUCT(driver
);
5839 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5840 architecture
, version
);
5841 if (!W_ERROR_IS_OK(status
)) {
5845 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5846 free_a_printer_driver(driver
, 3);
5849 *returned
+=ndrivers
;
5853 /* check the required size. */
5854 for (i
=0; i
<*returned
; i
++) {
5855 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5856 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5859 if (!alloc_buffer_size(buffer
, *needed
)) {
5860 SAFE_FREE(driver_info_1
);
5861 return WERR_INSUFFICIENT_BUFFER
;
5864 /* fill the buffer with the driver structures */
5865 for (i
=0; i
<*returned
; i
++) {
5866 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5867 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5870 SAFE_FREE(driver_info_1
);
5872 if (*needed
> offered
) {
5874 return WERR_INSUFFICIENT_BUFFER
;
5880 /****************************************************************************
5881 Enumerates all printer drivers at level 2.
5882 ****************************************************************************/
5884 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5889 fstring
*list
= NULL
;
5891 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5892 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
5896 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
5898 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5899 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5905 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
5906 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5907 SAFE_FREE(driver_info_2
);
5911 else driver_info_2
= tdi2
;
5914 for (i
=0; i
<ndrivers
; i
++) {
5917 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5918 ZERO_STRUCT(driver
);
5919 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5920 architecture
, version
);
5921 if (!W_ERROR_IS_OK(status
)) {
5925 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
5926 free_a_printer_driver(driver
, 3);
5929 *returned
+=ndrivers
;
5933 /* check the required size. */
5934 for (i
=0; i
<*returned
; i
++) {
5935 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5936 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
5939 if (!alloc_buffer_size(buffer
, *needed
)) {
5940 SAFE_FREE(driver_info_2
);
5941 return WERR_INSUFFICIENT_BUFFER
;
5944 /* fill the buffer with the form structures */
5945 for (i
=0; i
<*returned
; i
++) {
5946 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5947 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
5950 SAFE_FREE(driver_info_2
);
5952 if (*needed
> offered
) {
5954 return WERR_INSUFFICIENT_BUFFER
;
5960 /****************************************************************************
5961 Enumerates all printer drivers at level 3.
5962 ****************************************************************************/
5964 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5969 fstring
*list
= NULL
;
5971 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5972 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
5976 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
5978 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5979 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5985 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
5986 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5987 SAFE_FREE(driver_info_3
);
5991 else driver_info_3
= tdi3
;
5994 for (i
=0; i
<ndrivers
; i
++) {
5997 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5998 ZERO_STRUCT(driver
);
5999 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6000 architecture
, version
);
6001 if (!W_ERROR_IS_OK(status
)) {
6005 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6006 free_a_printer_driver(driver
, 3);
6009 *returned
+=ndrivers
;
6013 /* check the required size. */
6014 for (i
=0; i
<*returned
; i
++) {
6015 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6016 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6019 if (!alloc_buffer_size(buffer
, *needed
)) {
6020 SAFE_FREE(driver_info_3
);
6021 return WERR_INSUFFICIENT_BUFFER
;
6024 /* fill the buffer with the driver structures */
6025 for (i
=0; i
<*returned
; i
++) {
6026 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6027 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6030 for (i
=0; i
<*returned
; i
++)
6031 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6033 SAFE_FREE(driver_info_3
);
6035 if (*needed
> offered
) {
6037 return WERR_INSUFFICIENT_BUFFER
;
6043 /****************************************************************************
6044 Enumerates all printer drivers.
6045 ****************************************************************************/
6047 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6049 UNISTR2
*environment
= &q_u
->environment
;
6050 uint32 level
= q_u
->level
;
6051 NEW_BUFFER
*buffer
= NULL
;
6052 uint32 offered
= q_u
->offered
;
6053 uint32
*needed
= &r_u
->needed
;
6054 uint32
*returned
= &r_u
->returned
;
6056 fstring
*list
= NULL
;
6058 fstring architecture
;
6060 /* that's an [in out] buffer */
6061 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6062 buffer
= r_u
->buffer
;
6064 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6065 fstrcpy(servername
, get_called_name());
6069 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6073 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6075 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6077 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6081 return WERR_UNKNOWN_LEVEL
;
6085 /****************************************************************************
6086 ****************************************************************************/
6088 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6090 form
->flag
=list
->flag
;
6091 init_unistr(&form
->name
, list
->name
);
6092 form
->width
=list
->width
;
6093 form
->length
=list
->length
;
6094 form
->left
=list
->left
;
6095 form
->top
=list
->top
;
6096 form
->right
=list
->right
;
6097 form
->bottom
=list
->bottom
;
6100 /****************************************************************************
6101 ****************************************************************************/
6103 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6105 uint32 level
= q_u
->level
;
6106 NEW_BUFFER
*buffer
= NULL
;
6107 uint32 offered
= q_u
->offered
;
6108 uint32
*needed
= &r_u
->needed
;
6109 uint32
*numofforms
= &r_u
->numofforms
;
6110 uint32 numbuiltinforms
;
6112 nt_forms_struct
*list
=NULL
;
6113 nt_forms_struct
*builtinlist
=NULL
;
6118 /* that's an [in out] buffer */
6119 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6120 buffer
= r_u
->buffer
;
6122 DEBUG(4,("_spoolss_enumforms\n"));
6123 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6124 DEBUGADD(5,("Info level [%d]\n", level
));
6126 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6127 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6128 *numofforms
= get_ntforms(&list
);
6129 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6130 *numofforms
+= numbuiltinforms
;
6132 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6136 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6141 /* construct the list of form structures */
6142 for (i
=0; i
<numbuiltinforms
; i
++) {
6143 DEBUGADD(6,("Filling form number [%d]\n",i
));
6144 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6147 SAFE_FREE(builtinlist
);
6149 for (; i
<*numofforms
; i
++) {
6150 DEBUGADD(6,("Filling form number [%d]\n",i
));
6151 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6156 /* check the required size. */
6157 for (i
=0; i
<numbuiltinforms
; i
++) {
6158 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6159 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6161 for (; i
<*numofforms
; i
++) {
6162 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6163 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6166 *needed
=buffer_size
;
6168 if (!alloc_buffer_size(buffer
, buffer_size
)){
6170 return WERR_INSUFFICIENT_BUFFER
;
6173 /* fill the buffer with the form structures */
6174 for (i
=0; i
<numbuiltinforms
; i
++) {
6175 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6176 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6178 for (; i
<*numofforms
; i
++) {
6179 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6180 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6185 if (*needed
> offered
) {
6187 return WERR_INSUFFICIENT_BUFFER
;
6194 SAFE_FREE(builtinlist
);
6195 return WERR_UNKNOWN_LEVEL
;
6200 /****************************************************************************
6201 ****************************************************************************/
6203 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6205 uint32 level
= q_u
->level
;
6206 UNISTR2
*uni_formname
= &q_u
->formname
;
6207 NEW_BUFFER
*buffer
= NULL
;
6208 uint32 offered
= q_u
->offered
;
6209 uint32
*needed
= &r_u
->needed
;
6211 nt_forms_struct
*list
=NULL
;
6212 nt_forms_struct builtin_form
;
6217 int numofforms
=0, i
=0;
6219 /* that's an [in out] buffer */
6220 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6221 buffer
= r_u
->buffer
;
6223 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6225 DEBUG(4,("_spoolss_getform\n"));
6226 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6227 DEBUGADD(5,("Info level [%d]\n", level
));
6229 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6230 if (!foundBuiltin
) {
6231 numofforms
= get_ntforms(&list
);
6232 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6234 if (numofforms
== 0)
6241 fill_form_1(&form_1
, &builtin_form
);
6244 /* Check if the requested name is in the list of form structures */
6245 for (i
=0; i
<numofforms
; i
++) {
6247 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6249 if (strequal(form_name
, list
[i
].name
)) {
6250 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6251 fill_form_1(&form_1
, &list
[i
]);
6257 if (i
== numofforms
) {
6261 /* check the required size. */
6263 *needed
=spoolss_size_form_1(&form_1
);
6265 if (!alloc_buffer_size(buffer
, buffer_size
)){
6266 return WERR_INSUFFICIENT_BUFFER
;
6269 if (*needed
> offered
) {
6270 return WERR_INSUFFICIENT_BUFFER
;
6273 /* fill the buffer with the form structures */
6274 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6275 smb_io_form_1("", buffer
, &form_1
, 0);
6281 return WERR_UNKNOWN_LEVEL
;
6285 /****************************************************************************
6286 ****************************************************************************/
6288 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
6290 init_unistr(&port
->port_name
, name
);
6293 /****************************************************************************
6294 ****************************************************************************/
6296 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
6298 init_unistr(&port
->port_name
, name
);
6299 init_unistr(&port
->monitor_name
, "Local Monitor");
6300 init_unistr(&port
->description
, "Local Port");
6301 #define PORT_TYPE_WRITE 1
6302 port
->port_type
=PORT_TYPE_WRITE
;
6306 /****************************************************************************
6308 ****************************************************************************/
6310 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6312 PORT_INFO_1
*ports
=NULL
;
6315 if (*lp_enumports_cmd()) {
6316 char *cmd
= lp_enumports_cmd();
6323 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6325 DEBUG(10,("Running [%s]\n", command
));
6326 ret
= smbrun(command
, &fd
);
6327 DEBUG(10,("Returned [%d]\n", ret
));
6331 /* Is this the best error to return here? */
6332 return WERR_ACCESS_DENIED
;
6336 qlines
= fd_lines_load(fd
, &numlines
);
6337 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6341 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6342 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6343 dos_errstr(WERR_NOMEM
)));
6344 file_lines_free(qlines
);
6348 for (i
=0; i
<numlines
; i
++) {
6349 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6350 fill_port_1(&ports
[i
], qlines
[i
]);
6353 file_lines_free(qlines
);
6356 *returned
= numlines
;
6359 *returned
= 1; /* Sole Samba port returned. */
6361 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6364 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6366 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6369 /* check the required size. */
6370 for (i
=0; i
<*returned
; i
++) {
6371 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6372 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6375 if (!alloc_buffer_size(buffer
, *needed
)) {
6377 return WERR_INSUFFICIENT_BUFFER
;
6380 /* fill the buffer with the ports structures */
6381 for (i
=0; i
<*returned
; i
++) {
6382 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6383 smb_io_port_1("", buffer
, &ports
[i
], 0);
6388 if (*needed
> offered
) {
6390 return WERR_INSUFFICIENT_BUFFER
;
6396 /****************************************************************************
6398 ****************************************************************************/
6400 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6402 PORT_INFO_2
*ports
=NULL
;
6405 if (*lp_enumports_cmd()) {
6406 char *cmd
= lp_enumports_cmd();
6415 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6416 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6418 path
= lp_lockdir();
6420 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6421 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6424 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6425 ret
= smbrun(command
, &fd
);
6426 DEBUGADD(10,("returned [%d]\n", ret
));
6430 /* Is this the best error to return here? */
6431 return WERR_ACCESS_DENIED
;
6435 qlines
= fd_lines_load(fd
, &numlines
);
6436 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6440 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
6441 file_lines_free(qlines
);
6445 for (i
=0; i
<numlines
; i
++) {
6446 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6447 fill_port_2(&(ports
[i
]), qlines
[i
]);
6450 file_lines_free(qlines
);
6453 *returned
= numlines
;
6459 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
6462 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6464 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6467 /* check the required size. */
6468 for (i
=0; i
<*returned
; i
++) {
6469 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6470 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
6473 if (!alloc_buffer_size(buffer
, *needed
)) {
6475 return WERR_INSUFFICIENT_BUFFER
;
6478 /* fill the buffer with the ports structures */
6479 for (i
=0; i
<*returned
; i
++) {
6480 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6481 smb_io_port_2("", buffer
, &ports
[i
], 0);
6486 if (*needed
> offered
) {
6488 return WERR_INSUFFICIENT_BUFFER
;
6494 /****************************************************************************
6496 ****************************************************************************/
6498 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
6500 uint32 level
= q_u
->level
;
6501 NEW_BUFFER
*buffer
= NULL
;
6502 uint32 offered
= q_u
->offered
;
6503 uint32
*needed
= &r_u
->needed
;
6504 uint32
*returned
= &r_u
->returned
;
6506 /* that's an [in out] buffer */
6507 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6508 buffer
= r_u
->buffer
;
6510 DEBUG(4,("_spoolss_enumports\n"));
6517 return enumports_level_1(buffer
, offered
, needed
, returned
);
6519 return enumports_level_2(buffer
, offered
, needed
, returned
);
6521 return WERR_UNKNOWN_LEVEL
;
6525 /****************************************************************************
6526 ****************************************************************************/
6528 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
6529 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6530 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
6531 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
6534 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6537 WERROR err
= WERR_OK
;
6539 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
6540 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6544 ZERO_STRUCTP(printer
);
6546 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6547 if (!convert_printer_info(info
, printer
, 2)) {
6548 free_a_printer(&printer
, 2);
6552 /* check to see if the printer already exists */
6554 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
6555 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6556 printer
->info_2
->sharename
));
6557 free_a_printer(&printer
, 2);
6558 return WERR_PRINTER_ALREADY_EXISTS
;
6561 if (*lp_addprinter_cmd() )
6562 if ( !add_printer_hook(printer
) ) {
6563 free_a_printer(&printer
,2);
6564 return WERR_ACCESS_DENIED
;
6567 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
6568 printer
->info_2
->sharename
);
6570 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
6571 free_a_printer(&printer
,2);
6572 return WERR_ACCESS_DENIED
;
6575 /* you must be a printer admin to add a new printer */
6576 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6577 free_a_printer(&printer
,2);
6578 return WERR_ACCESS_DENIED
;
6582 * Do sanity check on the requested changes for Samba.
6585 if (!check_printer_ok(printer
->info_2
, snum
)) {
6586 free_a_printer(&printer
,2);
6587 return WERR_INVALID_PARAM
;
6591 * When a printer is created, the drivername bound to the printer is used
6592 * to lookup previously saved driver initialization info, which is then
6593 * bound to the new printer, simulating what happens in the Windows arch.
6597 set_driver_init(printer
, 2);
6599 /* A valid devmode was included, convert and link it
6601 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6603 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6604 &printer
->info_2
->devmode
))
6608 set_driver_init(printer
, 2);
6610 /* write the ASCII on disk */
6611 err
= mod_a_printer(*printer
, 2);
6612 if (!W_ERROR_IS_OK(err
)) {
6613 free_a_printer(&printer
,2);
6617 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
6618 /* Handle open failed - remove addition. */
6619 del_a_printer(printer
->info_2
->sharename
);
6620 free_a_printer(&printer
,2);
6621 return WERR_ACCESS_DENIED
;
6624 update_c_setprinter(False
);
6625 free_a_printer(&printer
,2);
6630 /****************************************************************************
6631 ****************************************************************************/
6633 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
6635 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
6636 uint32 level
= q_u
->level
;
6637 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6638 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
6639 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
6640 uint32 user_switch
= q_u
->user_switch
;
6641 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
6642 POLICY_HND
*handle
= &r_u
->handle
;
6646 /* we don't handle yet */
6647 /* but I know what to do ... */
6648 return WERR_UNKNOWN_LEVEL
;
6650 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
6652 user_switch
, user
, handle
);
6654 return WERR_UNKNOWN_LEVEL
;
6658 /****************************************************************************
6659 ****************************************************************************/
6661 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
6663 uint32 level
= q_u
->level
;
6664 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
6665 WERROR err
= WERR_OK
;
6666 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6667 struct current_user user
;
6668 fstring driver_name
;
6671 ZERO_STRUCT(driver
);
6673 get_current_user(&user
, p
);
6675 if (!convert_printer_driver_info(info
, &driver
, level
)) {
6680 DEBUG(5,("Cleaning driver's information\n"));
6681 err
= clean_up_driver_struct(driver
, level
, &user
);
6682 if (!W_ERROR_IS_OK(err
))
6685 DEBUG(5,("Moving driver to final destination\n"));
6686 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
6687 if (W_ERROR_IS_OK(err
))
6688 err
= WERR_ACCESS_DENIED
;
6692 if (add_a_printer_driver(driver
, level
)!=0) {
6693 err
= WERR_ACCESS_DENIED
;
6697 /* BEGIN_ADMIN_LOG */
6700 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6701 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
6702 fstrcpy(driver_name
, driver
.info_3
->name
);
6705 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6706 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
6707 fstrcpy(driver_name
, driver
.info_6
->name
);
6713 * I think this is where he DrvUpgradePrinter() hook would be
6714 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6715 * server. Right now, we just need to send ourselves a message
6716 * to update each printer bound to this driver. --jerry
6719 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
6720 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6725 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6726 * decide if the driver init data should be deleted. The rules are:
6727 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6728 * 2) delete init data only if there is no 2k/Xp driver
6729 * 3) always delete init data
6730 * The generalized rule is always use init data from the highest order driver.
6731 * It is necessary to follow the driver install by an initialization step to
6732 * finish off this process.
6735 version
= driver
.info_3
->cversion
;
6736 else if (level
== 6)
6737 version
= driver
.info_6
->version
;
6742 * 9x printer driver - never delete init data
6745 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6750 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6751 * there is no 2k/Xp driver init data for this driver name.
6755 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
6757 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
6759 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6761 if (!del_driver_init(driver_name
))
6762 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
6765 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6767 free_a_printer_driver(driver1
,3);
6768 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6775 * 2k or Xp printer driver - always delete init data
6778 if (!del_driver_init(driver_name
))
6779 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
6783 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
6789 free_a_printer_driver(driver
, level
);
6793 /********************************************************************
6794 * spoolss_addprinterdriverex
6795 ********************************************************************/
6797 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
6799 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
6800 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
6803 * we only support the semantics of AddPrinterDriver()
6804 * i.e. only copy files that are newer than existing ones
6807 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
6808 return WERR_ACCESS_DENIED
;
6810 ZERO_STRUCT(q_u_local
);
6811 ZERO_STRUCT(r_u_local
);
6813 /* just pass the information off to _spoolss_addprinterdriver() */
6814 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
6815 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
6816 q_u_local
.level
= q_u
->level
;
6817 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
6819 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
6822 /****************************************************************************
6823 ****************************************************************************/
6825 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
6827 init_unistr(&info
->name
, name
);
6830 /****************************************************************************
6831 ****************************************************************************/
6833 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6837 pstring short_archi
;
6838 DRIVER_DIRECTORY_1
*info
=NULL
;
6840 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
6842 if (get_short_archi(short_archi
, long_archi
)==False
)
6843 return WERR_INVALID_ENVIRONMENT
;
6845 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
6848 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
6850 DEBUG(4,("printer driver directory: [%s]\n", path
));
6852 fill_driverdir_1(info
, path
);
6854 *needed
+= spoolss_size_driverdir_info_1(info
);
6856 if (!alloc_buffer_size(buffer
, *needed
)) {
6858 return WERR_INSUFFICIENT_BUFFER
;
6861 smb_io_driverdir_1("", buffer
, info
, 0);
6865 if (*needed
> offered
)
6866 return WERR_INSUFFICIENT_BUFFER
;
6871 /****************************************************************************
6872 ****************************************************************************/
6874 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
6876 UNISTR2
*name
= &q_u
->name
;
6877 UNISTR2
*uni_environment
= &q_u
->environment
;
6878 uint32 level
= q_u
->level
;
6879 NEW_BUFFER
*buffer
= NULL
;
6880 uint32 offered
= q_u
->offered
;
6881 uint32
*needed
= &r_u
->needed
;
6883 /* that's an [in out] buffer */
6884 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6885 buffer
= r_u
->buffer
;
6887 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6893 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
6895 return WERR_UNKNOWN_LEVEL
;
6899 /****************************************************************************
6900 ****************************************************************************/
6902 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
6904 POLICY_HND
*handle
= &q_u
->handle
;
6905 uint32 idx
= q_u
->index
;
6906 uint32 in_value_len
= q_u
->valuesize
;
6907 uint32 in_data_len
= q_u
->datasize
;
6908 uint32
*out_max_value_len
= &r_u
->valuesize
;
6909 uint16
**out_value
= &r_u
->value
;
6910 uint32
*out_value_len
= &r_u
->realvaluesize
;
6911 uint32
*out_type
= &r_u
->type
;
6912 uint32
*out_max_data_len
= &r_u
->datasize
;
6913 uint8
**data_out
= &r_u
->data
;
6914 uint32
*out_data_len
= &r_u
->realdatasize
;
6916 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6919 uint32 biggest_valuesize
;
6920 uint32 biggest_datasize
;
6922 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6925 REGISTRY_VALUE
*val
;
6926 NT_PRINTER_DATA
*p_data
;
6927 int i
, key_index
, num_values
;
6930 ZERO_STRUCT( printer
);
6934 *out_max_data_len
= 0;
6938 DEBUG(5,("spoolss_enumprinterdata\n"));
6941 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6945 if (!get_printer_snum(p
,handle
, &snum
))
6948 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6949 if (!W_ERROR_IS_OK(result
))
6952 p_data
= &printer
->info_2
->data
;
6953 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
6958 * The NT machine wants to know the biggest size of value and data
6960 * cf: MSDN EnumPrinterData remark section
6963 if ( !in_value_len
&& !in_data_len
)
6965 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6968 biggest_valuesize
= 0;
6969 biggest_datasize
= 0;
6971 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
6973 for ( i
=0; i
<num_values
; i
++ )
6975 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
6977 name_length
= strlen(val
->valuename
);
6978 if ( strlen(val
->valuename
) > biggest_valuesize
)
6979 biggest_valuesize
= name_length
;
6981 if ( val
->size
> biggest_datasize
)
6982 biggest_datasize
= val
->size
;
6984 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
6988 /* the value is an UNICODE string but real_value_size is the length
6989 in bytes including the trailing 0 */
6991 *out_value_len
= 2 * (1+biggest_valuesize
);
6992 *out_data_len
= biggest_datasize
;
6994 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7000 * the value len is wrong in NT sp3
7001 * that's the number of bytes not the number of unicode chars
7004 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7009 /* out_value should default to "" or else NT4 has
7010 problems unmarshalling the response */
7012 *out_max_value_len
= (in_value_len
/sizeof(uint16
));
7014 if ( (*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7016 result
= WERR_NOMEM
;
7020 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7022 /* the data is counted in bytes */
7024 *out_max_data_len
= in_data_len
;
7025 *out_data_len
= in_data_len
;
7027 /* only allocate when given a non-zero data_len */
7029 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7031 result
= WERR_NOMEM
;
7035 result
= WERR_NO_MORE_ITEMS
;
7041 * - counted in bytes in the request
7042 * - counted in UNICODE chars in the max reply
7043 * - counted in bytes in the real size
7045 * take a pause *before* coding not *during* coding
7049 *out_max_value_len
= ( in_value_len
/ sizeof(uint16
) );
7050 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7052 result
= WERR_NOMEM
;
7056 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7060 *out_type
= regval_type( val
);
7062 /* data - counted in bytes */
7064 *out_max_data_len
= in_data_len
;
7065 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7067 result
= WERR_NOMEM
;
7070 data_len
= (size_t)regval_size(val
);
7071 memcpy( *data_out
, regval_data_p(val
), data_len
);
7072 *out_data_len
= data_len
;
7076 free_a_printer(&printer
, 2);
7080 /****************************************************************************
7081 ****************************************************************************/
7083 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7085 POLICY_HND
*handle
= &q_u
->handle
;
7086 UNISTR2
*value
= &q_u
->value
;
7087 uint32 type
= q_u
->type
;
7088 uint8
*data
= q_u
->data
;
7089 uint32 real_len
= q_u
->real_len
;
7091 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7093 WERROR status
= WERR_OK
;
7094 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7097 DEBUG(5,("spoolss_setprinterdata\n"));
7100 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7104 if (!get_printer_snum(p
,handle
, &snum
))
7108 * Access check : NT returns "access denied" if you make a
7109 * SetPrinterData call without the necessary privildge.
7110 * we were originally returning OK if nothing changed
7111 * which made Win2k issue **a lot** of SetPrinterData
7112 * when connecting to a printer --jerry
7115 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7116 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7117 status
= WERR_ACCESS_DENIED
;
7121 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7122 if (!W_ERROR_IS_OK(status
))
7125 /* save the registry data */
7127 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7128 delete_printer_data( printer
->info_2
, SPOOL_PRINTERDATA_KEY
, valuename
);
7129 add_printer_data( printer
->info_2
, SPOOL_PRINTERDATA_KEY
, valuename
, type
, data
, real_len
);
7131 /* write the **entire** printer out to disk.... :-( */
7133 status
= mod_a_printer(*printer
, 2);
7136 free_a_printer(&printer
, 2);
7141 /****************************************************************************
7142 ****************************************************************************/
7144 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7146 POLICY_HND
*handle
= &q_u
->handle
;
7147 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7150 DEBUG(5,("_spoolss_resetprinter\n"));
7153 * All we do is to check to see if the handle and queue is valid.
7154 * This call really doesn't mean anything to us because we only
7155 * support RAW printing. --jerry
7159 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7163 if (!get_printer_snum(p
,handle
, &snum
))
7167 /* blindly return success */
7172 /****************************************************************************
7173 ****************************************************************************/
7175 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7177 POLICY_HND
*handle
= &q_u
->handle
;
7178 UNISTR2
*value
= &q_u
->valuename
;
7180 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7182 WERROR status
= WERR_OK
;
7183 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7186 DEBUG(5,("spoolss_deleteprinterdata\n"));
7189 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7193 if (!get_printer_snum(p
, handle
, &snum
))
7196 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7197 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7198 return WERR_ACCESS_DENIED
;
7201 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7202 if (!W_ERROR_IS_OK(status
))
7205 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
7207 status
= delete_printer_data( printer
->info_2
, SPOOL_PRINTERDATA_KEY
, valuename
);
7208 if ( NT_STATUS_IS_OK(status
) )
7209 status
= mod_a_printer(*printer
, 2);
7211 free_a_printer(&printer
, 2);
7216 /****************************************************************************
7217 ****************************************************************************/
7219 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7221 POLICY_HND
*handle
= &q_u
->handle
;
7222 FORM
*form
= &q_u
->form
;
7223 nt_forms_struct tmpForm
;
7225 WERROR status
= WERR_OK
;
7226 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7229 nt_forms_struct
*list
=NULL
;
7230 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7232 DEBUG(5,("spoolss_addform\n"));
7235 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7239 if (!get_printer_snum(p
,handle
, &snum
))
7242 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7243 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7244 status
= WERR_ACCESS_DENIED
;
7248 /* can't add if builtin */
7249 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7250 return WERR_ALREADY_EXISTS
;
7253 count
=get_ntforms(&list
);
7254 if(!add_a_form(&list
, form
, &count
))
7256 write_ntforms(&list
, count
);
7259 * ChangeID must always be set
7262 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7263 if (!W_ERROR_IS_OK(status
))
7266 status
= mod_a_printer(*printer
, 2);
7267 if (!W_ERROR_IS_OK(status
))
7271 free_a_printer(&printer
, 2);
7277 /****************************************************************************
7278 ****************************************************************************/
7280 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7282 POLICY_HND
*handle
= &q_u
->handle
;
7283 UNISTR2
*form_name
= &q_u
->name
;
7284 nt_forms_struct tmpForm
;
7286 WERROR ret
= WERR_OK
;
7287 nt_forms_struct
*list
=NULL
;
7288 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7290 WERROR status
= WERR_OK
;
7291 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7293 DEBUG(5,("spoolss_deleteform\n"));
7296 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7300 if (!get_printer_snum(p
, handle
, &snum
))
7303 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7304 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7305 return WERR_ACCESS_DENIED
;
7308 /* can't delete if builtin */
7309 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7310 return WERR_INVALID_PARAM
;
7313 count
= get_ntforms(&list
);
7314 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
7315 return WERR_INVALID_PARAM
;
7318 * ChangeID must always be set
7321 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7322 if (!W_ERROR_IS_OK(status
))
7325 status
= mod_a_printer(*printer
, 2);
7326 if (!W_ERROR_IS_OK(status
))
7330 free_a_printer(&printer
, 2);
7336 /****************************************************************************
7337 ****************************************************************************/
7339 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7341 POLICY_HND
*handle
= &q_u
->handle
;
7342 FORM
*form
= &q_u
->form
;
7343 nt_forms_struct tmpForm
;
7345 WERROR status
= WERR_OK
;
7346 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7349 nt_forms_struct
*list
=NULL
;
7350 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7352 DEBUG(5,("spoolss_setform\n"));
7355 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7359 if (!get_printer_snum(p
, handle
, &snum
))
7362 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7363 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7364 return WERR_ACCESS_DENIED
;
7367 /* can't set if builtin */
7368 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7369 return WERR_INVALID_PARAM
;
7372 count
=get_ntforms(&list
);
7373 update_a_form(&list
, form
, count
);
7374 write_ntforms(&list
, count
);
7377 * ChangeID must always be set
7380 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7381 if (!W_ERROR_IS_OK(status
))
7384 status
= mod_a_printer(*printer
, 2);
7385 if (!W_ERROR_IS_OK(status
))
7389 free_a_printer(&printer
, 2);
7395 /****************************************************************************
7396 enumprintprocessors level 1.
7397 ****************************************************************************/
7399 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7401 PRINTPROCESSOR_1
*info_1
=NULL
;
7403 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
7408 init_unistr(&info_1
->name
, "winprint");
7410 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
7412 if (!alloc_buffer_size(buffer
, *needed
))
7413 return WERR_INSUFFICIENT_BUFFER
;
7415 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
7419 if (*needed
> offered
) {
7421 return WERR_INSUFFICIENT_BUFFER
;
7427 /****************************************************************************
7428 ****************************************************************************/
7430 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
7432 uint32 level
= q_u
->level
;
7433 NEW_BUFFER
*buffer
= NULL
;
7434 uint32 offered
= q_u
->offered
;
7435 uint32
*needed
= &r_u
->needed
;
7436 uint32
*returned
= &r_u
->returned
;
7438 /* that's an [in out] buffer */
7439 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7440 buffer
= r_u
->buffer
;
7442 DEBUG(5,("spoolss_enumprintprocessors\n"));
7445 * Enumerate the print processors ...
7447 * Just reply with "winprint", to keep NT happy
7448 * and I can use my nice printer checker.
7456 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
7458 return WERR_UNKNOWN_LEVEL
;
7462 /****************************************************************************
7463 enumprintprocdatatypes level 1.
7464 ****************************************************************************/
7466 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7468 PRINTPROCDATATYPE_1
*info_1
=NULL
;
7470 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
7475 init_unistr(&info_1
->name
, "RAW");
7477 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
7479 if (!alloc_buffer_size(buffer
, *needed
))
7480 return WERR_INSUFFICIENT_BUFFER
;
7482 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
7486 if (*needed
> offered
) {
7488 return WERR_INSUFFICIENT_BUFFER
;
7494 /****************************************************************************
7495 ****************************************************************************/
7497 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
7499 uint32 level
= q_u
->level
;
7500 NEW_BUFFER
*buffer
= NULL
;
7501 uint32 offered
= q_u
->offered
;
7502 uint32
*needed
= &r_u
->needed
;
7503 uint32
*returned
= &r_u
->returned
;
7505 /* that's an [in out] buffer */
7506 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7507 buffer
= r_u
->buffer
;
7509 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7516 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
7518 return WERR_UNKNOWN_LEVEL
;
7522 /****************************************************************************
7523 enumprintmonitors level 1.
7524 ****************************************************************************/
7526 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7528 PRINTMONITOR_1
*info_1
=NULL
;
7530 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
7535 init_unistr(&info_1
->name
, "Local Port");
7537 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
7539 if (!alloc_buffer_size(buffer
, *needed
))
7540 return WERR_INSUFFICIENT_BUFFER
;
7542 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
7546 if (*needed
> offered
) {
7548 return WERR_INSUFFICIENT_BUFFER
;
7554 /****************************************************************************
7555 enumprintmonitors level 2.
7556 ****************************************************************************/
7558 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7560 PRINTMONITOR_2
*info_2
=NULL
;
7562 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
7567 init_unistr(&info_2
->name
, "Local Port");
7568 init_unistr(&info_2
->environment
, "Windows NT X86");
7569 init_unistr(&info_2
->dll_name
, "localmon.dll");
7571 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
7573 if (!alloc_buffer_size(buffer
, *needed
))
7574 return WERR_INSUFFICIENT_BUFFER
;
7576 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
7580 if (*needed
> offered
) {
7582 return WERR_INSUFFICIENT_BUFFER
;
7588 /****************************************************************************
7589 ****************************************************************************/
7591 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
7593 uint32 level
= q_u
->level
;
7594 NEW_BUFFER
*buffer
= NULL
;
7595 uint32 offered
= q_u
->offered
;
7596 uint32
*needed
= &r_u
->needed
;
7597 uint32
*returned
= &r_u
->returned
;
7599 /* that's an [in out] buffer */
7600 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7601 buffer
= r_u
->buffer
;
7603 DEBUG(5,("spoolss_enumprintmonitors\n"));
7606 * Enumerate the print monitors ...
7608 * Just reply with "Local Port", to keep NT happy
7609 * and I can use my nice printer checker.
7617 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
7619 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
7621 return WERR_UNKNOWN_LEVEL
;
7625 /****************************************************************************
7626 ****************************************************************************/
7628 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7632 JOB_INFO_1
*info_1
=NULL
;
7634 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
7636 if (info_1
== NULL
) {
7641 for (i
=0; i
<count
&& found
==False
; i
++) {
7642 if (queue
[i
].job
==(int)jobid
)
7649 /* NT treats not found as bad param... yet another bad choice */
7650 return WERR_INVALID_PARAM
;
7653 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
7657 *needed
+= spoolss_size_job_info_1(info_1
);
7659 if (!alloc_buffer_size(buffer
, *needed
)) {
7661 return WERR_INSUFFICIENT_BUFFER
;
7664 smb_io_job_info_1("", buffer
, info_1
, 0);
7668 if (*needed
> offered
)
7669 return WERR_INSUFFICIENT_BUFFER
;
7674 /****************************************************************************
7675 ****************************************************************************/
7677 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7682 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
7684 DEVICEMODE
*devmode
= NULL
;
7686 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
7688 ZERO_STRUCTP(info_2
);
7690 if (info_2
== NULL
) {
7695 for (i
=0; i
<count
&& found
==False
; i
++) {
7696 if (queue
[i
].job
==(int)jobid
)
7701 /* NT treats not found as bad param... yet another bad
7703 ret
= WERR_INVALID_PARAM
;
7707 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
7708 if (!W_ERROR_IS_OK(ret
))
7710 if (construct_dev_mode(snum
) == NULL
) {
7715 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
7717 *needed
+= spoolss_size_job_info_2(info_2
);
7719 if (!alloc_buffer_size(buffer
, *needed
)) {
7720 ret
= WERR_INSUFFICIENT_BUFFER
;
7724 smb_io_job_info_2("", buffer
, info_2
, 0);
7726 if (*needed
> offered
) {
7727 ret
= WERR_INSUFFICIENT_BUFFER
;
7734 /* Cleanup allocated memory */
7737 free_job_info_2(info_2
); /* Also frees devmode */
7739 free_a_printer(&ntprinter
, 2);
7744 /****************************************************************************
7745 ****************************************************************************/
7747 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
7749 POLICY_HND
*handle
= &q_u
->handle
;
7750 uint32 jobid
= q_u
->jobid
;
7751 uint32 level
= q_u
->level
;
7752 NEW_BUFFER
*buffer
= NULL
;
7753 uint32 offered
= q_u
->offered
;
7754 uint32
*needed
= &r_u
->needed
;
7758 print_queue_struct
*queue
=NULL
;
7759 print_status_struct prt_status
;
7761 /* that's an [in out] buffer */
7762 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7763 buffer
= r_u
->buffer
;
7765 DEBUG(5,("spoolss_getjob\n"));
7769 if (!get_printer_snum(p
, handle
, &snum
))
7772 count
= print_queue_status(snum
, &queue
, &prt_status
);
7774 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7775 count
, prt_status
.status
, prt_status
.message
));
7779 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7781 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7784 return WERR_UNKNOWN_LEVEL
;
7788 /********************************************************************
7789 * spoolss_getprinterdataex
7790 ********************************************************************/
7792 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
7794 POLICY_HND
*handle
= &q_u
->handle
;
7795 uint32 in_size
= q_u
->size
;
7796 uint32
*type
= &r_u
->type
;
7797 uint32
*out_size
= &r_u
->size
;
7798 uint8
**data
= &r_u
->data
;
7799 uint32
*needed
= &r_u
->needed
;
7802 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7805 DEBUG(4,("_spoolss_getprinterdataex\n"));
7807 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
7808 unistr2_to_ascii(value
, &q_u
->valuename
, sizeof(value
) - 1);
7810 /* in case of problem, return some default values */
7817 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
7819 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7824 /* Is the handle to a printer or to the server? */
7826 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
7828 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7829 return WERR_INVALID_PARAM
;
7834 * From MSDN documentation of GetPrinterDataEx: pass request
7835 * to GetPrinterData if key is "PrinterDriverData". This is
7836 * the only key we really support. Other keys to implement:
7843 if (strcmp(key
, SPOOL_PRINTERDATA_KEY
) != 0)
7844 return WERR_BADFILE
;
7846 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7847 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
7848 type
, data
, needed
, in_size
);
7853 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
7855 /* reply this param doesn't exist */
7857 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
7863 return WERR_INVALID_PARAM
;
7866 if (*needed
> *out_size
)
7867 return WERR_MORE_DATA
;
7872 /********************************************************************
7873 * spoolss_setprinterdata
7874 ********************************************************************/
7876 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
7878 SPOOL_Q_SETPRINTERDATA q_u_local
;
7879 SPOOL_R_SETPRINTERDATA r_u_local
;
7882 DEBUG(4,("_spoolss_setprinterdataex\n"));
7884 /* From MSDN documentation of SetPrinterDataEx: pass request to
7885 SetPrinterData if key is "PrinterDriverData" */
7887 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7889 if (strcmp(key
, SPOOL_PRINTERDATA_KEY
) != 0)
7890 return WERR_INVALID_PARAM
;
7892 ZERO_STRUCT(q_u_local
);
7893 ZERO_STRUCT(r_u_local
);
7895 /* make a copy to call _spoolss_setprinterdata() */
7897 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
7898 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
7899 q_u_local
.type
= q_u
->type
;
7900 q_u_local
.max_len
= q_u
->max_len
;
7901 q_u_local
.data
= q_u
->data
;
7902 q_u_local
.real_len
= q_u
->real_len
;
7903 q_u_local
.numeric_data
= q_u
->numeric_data
;
7905 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
7909 /********************************************************************
7910 * spoolss_deleteprinterdataex
7911 ********************************************************************/
7913 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
7915 SPOOL_Q_DELETEPRINTERDATA q_u_local
;
7916 SPOOL_R_DELETEPRINTERDATA r_u_local
;
7919 /* From MSDN documentation of SetPrinterDataEx: pass request to
7920 SetPrinterData if key is "PrinterDriverData" */
7922 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
7924 if (strcmp(key
, SPOOL_PRINTERDATA_KEY
) != 0)
7925 return WERR_INVALID_PARAM
;
7927 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
7928 copy_unistr2(&q_u_local
.valuename
, &q_u
->valuename
);
7930 return _spoolss_deleteprinterdata( p
, &q_u_local
, &r_u_local
);
7936 /********************************************************************
7937 * spoolss_enumprinterkey
7938 ********************************************************************/
7941 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
7944 uint16
*enumkeys
= NULL
;
7947 int printerkey_len
= strlen(SPOOL_PRINTERDATA_KEY
)+1;
7949 DEBUG(4,("_spoolss_enumprinterkey\n"));
7951 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
7954 * we only support enumating all keys (key == "")
7955 * Of course, the only key we support is the "PrinterDriverData"
7959 if ( !strlen( key
) )
7961 r_u
->needed
= printerkey_len
*2;
7963 if ( q_u
->size
< r_u
->needed
)
7964 return WERR_MORE_DATA
;
7966 if ( !(enumkeys
= talloc( p
->mem_ctx
, printerkey_len
*2 )) ) {
7967 DEBUG(0,("_spoolss_enumprinterkey: talloc() failed for [%d] bytes!\n",
7972 ptr
= SPOOL_PRINTERDATA_KEY
;
7973 for ( i
=0; i
<(printerkey_len
-1); i
++ )
7975 enumkeys
[i
] = (uint16
)(*ptr
);
7983 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
))
7984 return WERR_BADFILE
;
7989 /* The "PrinterDriverData" key should have no subkeys */
7990 if ( strcmp(key
, SPOOL_PRINTERDATA_KEY
) == 0 )
7992 uint16 dummy_key
= 0;
7996 if (q_u
->size
< r_u
->needed
)
7997 return WERR_MORE_DATA
;
7999 if ( !make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, &dummy_key
) )
8000 return WERR_BADFILE
;
8006 /* The return value for an unknown key is documented in MSDN
8007 EnumPrinterKey description */
8009 return WERR_BADFILE
;
8012 /********************************************************************
8013 * spoolss_deleteprinterkey
8014 ********************************************************************/
8016 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8018 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8022 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
8026 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8028 if (strcmp(key
, SPOOL_PRINTERDATA_KEY
) != 0)
8029 return WERR_INVALID_PARAM
;
8032 * this is what 2k returns when you try to delete the "PrinterDriverData"
8036 return WERR_ACCESS_DENIED
;
8040 /********************************************************************
8041 * spoolss_enumprinterdataex
8042 ********************************************************************/
8044 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8046 POLICY_HND
*handle
= &q_u
->handle
;
8047 uint32 in_size
= q_u
->size
;
8050 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8051 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8052 NT_PRINTER_DATA
*p_data
;
8054 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8059 REGISTRY_VALUE
*val
;
8064 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8067 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8072 /* first get the printer off of disk */
8074 if (!get_printer_snum(p
,handle
, &snum
))
8077 ZERO_STRUCT(printer
);
8078 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8079 if (!W_ERROR_IS_OK(result
))
8082 /* now look for a match on the key name */
8084 p_data
= &printer
->info_2
->data
;
8086 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8087 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
8089 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8090 result
= WERR_INVALID_PARAM
;
8097 /* allocate the memory for the array of pointers -- if necessary */
8099 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
8102 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8104 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
8105 num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
8106 result
= WERR_NOMEM
;
8110 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
8114 * loop through all params and build the array to pass
8115 * back to the client
8118 for ( i
=0; i
<num_entries
; i
++ )
8120 /* lookup the registry value */
8122 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
8123 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
8127 value_name
= regval_name( val
);
8128 init_unistr( &enum_values
[i
].valuename
, value_name
);
8129 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
8130 enum_values
[i
].type
= regval_type( val
);
8132 data_len
= regval_size( val
);
8134 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
8136 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
8138 result
= WERR_NOMEM
;
8142 enum_values
[i
].data_len
= data_len
;
8144 /* keep track of the size of the array in bytes */
8146 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
8149 /* housekeeping information in the reply */
8151 r_u
->needed
= needed
;
8152 r_u
->returned
= num_entries
;
8154 if (needed
> in_size
) {
8155 result
= WERR_MORE_DATA
;
8159 /* copy data into the reply */
8161 r_u
->ctr
.size
= r_u
->needed
;
8162 r_u
->ctr
.size_of_array
= r_u
->returned
;
8163 r_u
->ctr
.values
= enum_values
;
8168 free_a_printer(&printer
, 2);
8173 /****************************************************************************
8174 ****************************************************************************/
8176 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8178 init_unistr(&info
->name
, name
);
8181 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8182 UNISTR2
*environment
,
8189 pstring short_archi
;
8190 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8192 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
8194 if (get_short_archi(short_archi
, long_archi
)==False
)
8195 return WERR_INVALID_ENVIRONMENT
;
8197 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8200 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8202 fill_printprocessordirectory_1(info
, path
);
8204 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8206 if (!alloc_buffer_size(buffer
, *needed
)) {
8208 return WERR_INSUFFICIENT_BUFFER
;
8211 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8215 if (*needed
> offered
)
8216 return WERR_INSUFFICIENT_BUFFER
;
8221 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8223 uint32 level
= q_u
->level
;
8224 NEW_BUFFER
*buffer
= NULL
;
8225 uint32 offered
= q_u
->offered
;
8226 uint32
*needed
= &r_u
->needed
;
8229 /* that's an [in out] buffer */
8230 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8231 buffer
= r_u
->buffer
;
8233 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8239 result
= getprintprocessordirectory_level_1
8240 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
8242 result
= WERR_UNKNOWN_LEVEL
;
8250 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
8251 SPOOL_R_REPLYOPENPRINTER
*r_u
)
8253 DEBUG(5,("_spoolss_replyopenprinter\n"));
8255 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
8260 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
8261 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
8263 DEBUG(5,("_spoolss_replycloseprinter\n"));