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-2001,
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 int 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 cli
;
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(&cli
, 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(&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", NULL
},
672 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL
},
673 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL
},
674 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL
},
675 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL
},
676 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL
},
677 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL
},
678 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
679 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL
},
680 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL
},
681 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
682 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL
},
683 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
684 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL
},
685 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL
},
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 for (p
= printers_list
; p
; p
= p
->next
) {
730 SPOOL_NOTIFY_INFO_DATA
*data
;
734 /* Is there notification on this handle? */
736 if (!p
->notify
.client_connected
)
739 /* For this printer? Print servers always receive
742 if (p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
&&
743 !strequal(msg
->printer
, p
->dev
.handlename
))
746 /* Are we monitoring this event? */
748 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
751 /* OK - send the event to the client */
753 data
= talloc(mem_ctx
, sizeof(SPOOL_NOTIFY_INFO_DATA
));
757 /* Convert unix jobid to smb jobid */
761 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
763 id
= sysjob_to_jobid(msg
->id
);
766 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
771 construct_info_data(data
, msg
->type
, msg
->field
, id
);
774 case PRINTER_NOTIFY_TYPE
:
775 if (printer_notify_table
[msg
->field
].fn
)
776 printer_notify_table
[msg
->field
].fn(
781 case JOB_NOTIFY_TYPE
:
782 if (job_notify_table
[msg
->field
].fn
)
783 job_notify_table
[msg
->field
].fn(
789 DEBUG(5, ("Unknown notification type %d\n",
794 if (!p
->notify
.flags
)
796 &cli
, mem_ctx
, &p
->notify
.client_hnd
,
797 data_len
, data
, p
->notify
.change
, 0);
799 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
801 get_a_printer(&printer
, 2, msg
->printer
);
804 DEBUG(5, ("unable to load info2 for %s\n",
809 /* XXX: This needs to be updated for
810 PRINTER_CHANGE_SET_PRINTER_DRIVER. */
812 cli_spoolss_routerreplyprinter(
813 &cli
, mem_ctx
, &p
->notify
.client_hnd
,
814 0, printer
->info_2
->changeid
);
816 free_a_printer(&printer
, 2);
823 /* Receive a notify2 message */
825 static void receive_notify2_message(int msg_type
, pid_t src
, void *buf
,
828 struct spoolss_notify_msg msg
;
830 TALLOC_CTX
*mem_ctx
= talloc_init();
836 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
839 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddd",
840 &msg
.type
, &msg
.field
, &msg
.id
, &msg
.len
, &msg
.flags
);
843 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
844 &msg
.notify
.value
[0], &msg
.notify
.value
[1]);
846 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
847 &msg
.len
, &msg
.notify
.data
);
849 DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
850 msg
.type
, msg
.field
, msg
.flags
));
853 DEBUG(3, ("value1 = %d, value2 = %d\n", msg
.notify
.value
[0],
854 msg
.notify
.value
[1]));
856 dump_data(3, msg
.notify
.data
, msg
.len
);
858 /* Process message */
860 process_notify2_message(&msg
, mem_ctx
);
865 free(msg
.notify
.data
);
867 talloc_destroy(mem_ctx
);
870 /***************************************************************************
871 Server wrapper for cli_spoolss_routerreplyprinter() since the client
872 function can only send a single change notification at a time.
874 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
876 **************************************************************************/
878 static WERROR
srv_spoolss_routerreplyprinter (struct cli_state
*reply_cli
, TALLOC_CTX
*mem_ctx
,
879 POLICY_HND
*pol
, PRINTER_MESSAGE_INFO
*info
,
880 NT_PRINTER_INFO_LEVEL
*printer
)
883 uint32 condition
= 0x0;
885 if (info
->flags
& PRINTER_MESSAGE_DRIVER
)
886 condition
= PRINTER_CHANGE_SET_PRINTER_DRIVER
;
888 result
= cli_spoolss_routerreplyprinter(reply_cli
, mem_ctx
, pol
, condition
,
889 printer
->info_2
->changeid
);
894 /********************************************************************
895 Send a message to ourself about new driver being installed
896 so we can upgrade the information for each printer bound to this
898 ********************************************************************/
900 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
902 int len
= strlen(drivername
);
907 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
910 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
915 /**********************************************************************
916 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
917 over all printers, upgrading ones as neessary
918 **********************************************************************/
920 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
924 int n_services
= lp_numservices();
926 len
= MIN(len
,sizeof(drivername
)-1);
927 strncpy(drivername
, buf
, len
);
929 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
931 /* Iterate the printer list */
933 for (snum
=0; snum
<n_services
; snum
++)
935 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
938 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
940 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
941 if (!W_ERROR_IS_OK(result
))
944 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
946 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
948 /* all we care about currently is the change_id */
950 result
= mod_a_printer(*printer
, 2);
951 if (!W_ERROR_IS_OK(result
)) {
952 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
953 dos_errstr(result
)));
957 free_a_printer(&printer
, 2);
964 /********************************************************************
965 Copy routines used by convert_to_openprinterex()
966 *******************************************************************/
968 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
976 DEBUG (8,("dup_devmode\n"));
978 /* bulk copy first */
980 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
984 /* dup the pointer members separately */
986 len
= unistrlen(devmode
->devicename
.buffer
);
988 d
->devicename
.buffer
= talloc(ctx
, len
*2);
989 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
994 len
= unistrlen(devmode
->formname
.buffer
);
996 d
->devicename
.buffer
= talloc(ctx
, len
*2);
997 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1001 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1006 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1008 if (!new_ctr
|| !ctr
)
1011 DEBUG(8,("copy_devmode_ctr\n"));
1013 new_ctr
->size
= ctr
->size
;
1014 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1016 if(ctr
->devmode_ptr
)
1017 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1020 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1022 if (!new_def
|| !def
)
1025 DEBUG(8,("copy_printer_defaults\n"));
1027 new_def
->datatype_ptr
= def
->datatype_ptr
;
1029 if (def
->datatype_ptr
)
1030 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1032 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1034 new_def
->access_required
= def
->access_required
;
1037 /********************************************************************
1038 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1039 * SPOOL_Q_OPEN_PRINTER_EX structure
1040 ********************************************************************/
1042 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1044 if (!q_u_ex
|| !q_u
)
1047 DEBUG(8,("convert_to_openprinterex\n"));
1049 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1051 if (q_u
->printername_ptr
)
1052 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1054 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1057 /********************************************************************
1058 * spoolss_open_printer
1060 * called from the spoolss dispatcher
1061 ********************************************************************/
1063 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1065 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1066 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1071 ZERO_STRUCT(q_u_ex
);
1072 ZERO_STRUCT(r_u_ex
);
1074 /* convert the OpenPrinter() call to OpenPrinterEx() */
1076 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1078 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1080 /* convert back to OpenPrinter() */
1082 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1087 /********************************************************************
1088 * spoolss_open_printer
1090 * called from the spoolss dispatcher
1091 ********************************************************************/
1093 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1095 UNISTR2
*printername
= NULL
;
1096 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1097 /* uint32 user_switch = q_u->user_switch; - notused */
1098 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
1099 POLICY_HND
*handle
= &r_u
->handle
;
1103 struct current_user user
;
1104 Printer_entry
*Printer
=NULL
;
1106 if (q_u
->printername_ptr
!= 0)
1107 printername
= &q_u
->printername
;
1109 if (printername
== NULL
)
1110 return WERR_INVALID_PRINTER_NAME
;
1112 /* some sanity check because you can open a printer or a print server */
1113 /* aka: \\server\printer or \\server */
1114 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1116 DEBUGADD(3,("checking name: %s\n",name
));
1118 if (!open_printer_hnd(p
, handle
, name
, 0))
1119 return WERR_INVALID_PRINTER_NAME
;
1121 Printer
=find_printer_index_by_hnd(p
, handle
);
1123 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1124 Can't find printer handle we created for printer %s\n", name
));
1125 close_printer_handle(p
,handle
);
1126 return WERR_INVALID_PRINTER_NAME
;
1130 First case: the user is opening the print server:
1132 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1133 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1135 Then both Win2k and WinNT clients try an OpenPrinterEx with
1136 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1137 or if the user is listed in the smb.conf printer admin parameter.
1139 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1140 client view printer folder, but does not show the MSAPW.
1142 Note: this test needs code to check access rights here too. Jeremy
1143 could you look at this?
1146 Second case: the user is opening a printer:
1147 NT doesn't let us connect to a printer if the connecting user
1148 doesn't have print permission.
1152 get_current_user(&user
, p
);
1154 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
1156 /* Printserver handles use global struct... */
1160 /* Map standard access rights to object specific access
1163 se_map_standard(&printer_default
->access_required
,
1164 &printserver_std_mapping
);
1166 /* Deny any object specific bits that don't apply to print
1167 servers (i.e printer and job specific bits) */
1169 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1171 if (printer_default
->access_required
&
1172 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1173 DEBUG(3, ("access DENIED for non-printserver bits"));
1174 close_printer_handle(p
, handle
);
1175 return WERR_ACCESS_DENIED
;
1178 /* Allow admin access */
1180 if (printer_default
->access_required
&
1181 SERVER_ACCESS_ADMINISTER
) {
1183 if (!lp_ms_add_printer_wizard()) {
1184 close_printer_handle(p
, handle
);
1185 return WERR_ACCESS_DENIED
;
1188 if (user
.uid
== 0 ||
1189 user_in_list(uidtoname(user
.uid
),
1190 lp_printer_admin(snum
)))
1193 close_printer_handle(p
, handle
);
1194 return WERR_ACCESS_DENIED
;
1197 /* We fall through to return WERR_OK */
1202 /* NT doesn't let us connect to a printer if the connecting user
1203 doesn't have print permission. */
1205 if (!get_printer_snum(p
, handle
, &snum
))
1208 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1210 /* map an empty access mask to the minimum access mask */
1211 if (printer_default
->access_required
== 0x0)
1212 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1215 * If we are not serving the printer driver for this printer,
1216 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1217 * will keep NT clients happy --jerry
1220 if (lp_use_client_driver(snum
)
1221 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1223 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1226 /* check smb.conf parameters and the the sec_desc */
1228 if (!user_ok(uidtoname(user
.uid
), snum
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1229 DEBUG(3, ("access DENIED for printer open\n"));
1230 close_printer_handle(p
, handle
);
1231 return WERR_ACCESS_DENIED
;
1234 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1235 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1236 close_printer_handle(p
, handle
);
1237 return WERR_ACCESS_DENIED
;
1240 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1241 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1243 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1245 DEBUG(4,("Setting printer access=%x\n", printer_default
->access_required
));
1246 Printer
->access_granted
= printer_default
->access_required
;
1249 * If we have a default device pointer in the
1250 * printer_default struct, then we need to get
1251 * the printer info from the tdb and if there is
1252 * no default devicemode there then we do a *SET*
1253 * here ! This is insanity.... JRA.
1257 * If the openprinterex rpc call contains a devmode,
1258 * it's a per-user one. This per-user devmode is derivated
1259 * from the global devmode. Openprinterex() contains a per-user
1260 * devmode for when you do EMF printing and spooling.
1261 * In the EMF case, the NT workstation is only doing half the job
1262 * of rendering the page. The other half is done by running the printer
1263 * driver on the server.
1264 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1265 * The EMF file only contains what is to be printed on the page.
1266 * So in order for the server to know how to print, the NT client sends
1267 * a devicemode attached to the openprinterex call.
1268 * But this devicemode is short lived, it's only valid for the current print job.
1270 * If Samba would have supported EMF spooling, this devicemode would
1271 * have been attached to the handle, to sent it to the driver to correctly
1272 * rasterize the EMF file.
1274 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1275 * we just act as a pass-thru between windows and the printer.
1277 * In order to know that Samba supports only RAW spooling, NT has to call
1278 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1279 * and until NT sends a RAW job, we refuse it.
1281 * But to call getprinter() or startdoc(), you first need a valid handle,
1282 * and to get an handle you have to call openprintex(). Hence why you have
1283 * a devicemode in the openprinterex() call.
1286 * Differences between NT4 and NT 2000.
1289 * On NT4, you only have a global devicemode. This global devicemode can be changed
1290 * by the administrator (or by a user with enough privs). Everytime a user
1291 * wants to print, the devicemode is resetted to the default. In Word, everytime
1292 * you print, the printer's characteristics are always reset to the global devicemode.
1296 * In W2K, there is the notion of per-user devicemode. The first time you use
1297 * a printer, a per-user devicemode is build from the global devicemode.
1298 * If you change your per-user devicemode, it is saved in the registry, under the
1299 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1300 * printer preferences available.
1302 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1303 * on the General Tab of the printer properties windows.
1305 * To change the global devicemode: it's the "Printing Defaults..." button
1306 * on the Advanced Tab of the printer properties window.
1314 if (printer_default
->devmode_cont
.devmode
!= NULL
) {
1315 result
= printer_write_default_dev( snum
, printer_default
);
1317 close_printer_handle(p
, handle
);
1327 /****************************************************************************
1328 ****************************************************************************/
1330 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1331 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1337 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1346 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1347 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1353 printer
->info_3
=NULL
;
1354 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1358 printer
->info_6
=NULL
;
1359 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1369 BOOL
convert_devicemode(char *printername
, const DEVICEMODE
*devmode
,
1370 NT_DEVICEMODE
**pp_nt_devmode
)
1372 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1375 * Ensure nt_devmode is a valid pointer
1376 * as we will be overwriting it.
1379 if (nt_devmode
== NULL
) {
1380 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1381 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1385 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1386 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1388 nt_devmode
->specversion
=devmode
->specversion
;
1389 nt_devmode
->driverversion
=devmode
->driverversion
;
1390 nt_devmode
->size
=devmode
->size
;
1391 nt_devmode
->fields
=devmode
->fields
;
1392 nt_devmode
->orientation
=devmode
->orientation
;
1393 nt_devmode
->papersize
=devmode
->papersize
;
1394 nt_devmode
->paperlength
=devmode
->paperlength
;
1395 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1396 nt_devmode
->scale
=devmode
->scale
;
1397 nt_devmode
->copies
=devmode
->copies
;
1398 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1399 nt_devmode
->printquality
=devmode
->printquality
;
1400 nt_devmode
->color
=devmode
->color
;
1401 nt_devmode
->duplex
=devmode
->duplex
;
1402 nt_devmode
->yresolution
=devmode
->yresolution
;
1403 nt_devmode
->ttoption
=devmode
->ttoption
;
1404 nt_devmode
->collate
=devmode
->collate
;
1406 nt_devmode
->logpixels
=devmode
->logpixels
;
1407 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1408 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1409 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1410 nt_devmode
->displayflags
=devmode
->displayflags
;
1411 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1412 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1413 nt_devmode
->icmintent
=devmode
->icmintent
;
1414 nt_devmode
->mediatype
=devmode
->mediatype
;
1415 nt_devmode
->dithertype
=devmode
->dithertype
;
1416 nt_devmode
->reserved1
=devmode
->reserved1
;
1417 nt_devmode
->reserved2
=devmode
->reserved2
;
1418 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1419 nt_devmode
->panningheight
=devmode
->panningheight
;
1422 * Only change private and driverextra if the incoming devmode
1423 * has a new one. JRA.
1426 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1427 SAFE_FREE(nt_devmode
->private);
1428 nt_devmode
->driverextra
=devmode
->driverextra
;
1429 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1431 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1434 *pp_nt_devmode
= nt_devmode
;
1439 /********************************************************************
1440 * _spoolss_enddocprinter_internal.
1441 ********************************************************************/
1443 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1445 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1448 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1452 Printer
->document_started
=False
;
1453 print_job_end(Printer
->jobid
,True
);
1454 /* error codes unhandled so far ... */
1459 /********************************************************************
1460 * api_spoolss_closeprinter
1461 ********************************************************************/
1463 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1465 POLICY_HND
*handle
= &q_u
->handle
;
1467 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1469 if (Printer
&& Printer
->document_started
)
1470 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1472 if (!close_printer_handle(p
, handle
))
1475 /* clear the returned printer handle. Observed behavior
1476 from Win2k server. Don't think this really matters.
1477 Previous code just copied the value of the closed
1480 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1485 /********************************************************************
1486 * api_spoolss_deleteprinter
1488 ********************************************************************/
1490 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1492 POLICY_HND
*handle
= &q_u
->handle
;
1493 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1496 if (Printer
&& Printer
->document_started
)
1497 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1499 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1501 result
= delete_printer_handle(p
, handle
);
1503 update_c_setprinter(False
);
1508 /*******************************************************************
1509 * static function to lookup the version id corresponding to an
1510 * long architecture string
1511 ******************************************************************/
1513 static int get_version_id (char * arch
)
1516 struct table_node archi_table
[]= {
1518 {"Windows 4.0", "WIN40", 0 },
1519 {"Windows NT x86", "W32X86", 2 },
1520 {"Windows NT R4000", "W32MIPS", 2 },
1521 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1522 {"Windows NT PowerPC", "W32PPC", 2 },
1526 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1528 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1529 return (archi_table
[i
].version
);
1535 /********************************************************************
1536 * _spoolss_deleteprinterdriver
1538 * We currently delete the driver for the architecture only.
1539 * This can leave the driver for other archtectures. However,
1540 * since every printer associates a "Windows NT x86" driver name
1541 * and we cannot delete that one while it is in use, **and** since
1542 * it is impossible to assign a driver to a Samba printer without
1543 * having the "Windows NT x86" driver installed,...
1545 * ....we should not get into trouble here.
1548 ********************************************************************/
1550 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1554 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1557 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1558 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1560 /* check that we have a valid driver name first */
1561 if ((version
=get_version_id(arch
)) == -1) {
1562 /* this is what NT returns */
1563 return WERR_INVALID_ENVIRONMENT
;
1567 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1568 return WERR_UNKNOWN_PRINTER_DRIVER
;
1571 if (printer_driver_in_use(arch
, driver
))
1572 return WERR_PRINTER_DRIVER_IN_USE
;
1574 return delete_printer_driver(info
.info_3
);
1577 /********************************************************************
1578 * spoolss_deleteprinterdriverex
1579 ********************************************************************/
1581 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
1585 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1588 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1589 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1591 /* check that we have a valid driver name first */
1592 if ((version
=get_version_id(arch
)) == -1) {
1593 /* this is what NT returns */
1594 return WERR_INVALID_ENVIRONMENT
;
1597 if (q_u
->delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
1598 version
= q_u
->version
;
1601 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1602 return WERR_UNKNOWN_PRINTER_DRIVER
;
1605 if (printer_driver_in_use(arch
, driver
))
1606 return WERR_PRINTER_DRIVER_IN_USE
;
1608 return delete_printer_driver(info
.info_3
);
1612 /********************************************************************
1613 GetPrinterData on a printer server Handle.
1614 ********************************************************************/
1616 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1620 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1622 if (!strcmp(value
, "W3SvcInstalled")) {
1624 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
1630 if (!strcmp(value
, "BeepEnabled")) {
1632 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1634 SIVAL(*data
, 0, 0x00);
1639 if (!strcmp(value
, "EventLog")) {
1641 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1643 /* formally was 0x1b */
1644 SIVAL(*data
, 0, 0x0);
1649 if (!strcmp(value
, "NetPopup")) {
1651 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1653 SIVAL(*data
, 0, 0x00);
1658 if (!strcmp(value
, "MajorVersion")) {
1660 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1662 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1671 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1674 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
1676 *needed
= 2*(strlen(string
)+1);
1677 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1679 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1681 /* it's done by hand ready to go on the wire */
1682 for (i
=0; i
<strlen(string
); i
++) {
1683 (*data
)[2*i
]=string
[i
];
1684 (*data
)[2*i
+1]='\0';
1689 if (!strcmp(value
, "Architecture")) {
1690 pstring string
="Windows NT x86";
1692 *needed
= 2*(strlen(string
)+1);
1693 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1695 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1696 for (i
=0; i
<strlen(string
); i
++) {
1697 (*data
)[2*i
]=string
[i
];
1698 (*data
)[2*i
+1]='\0';
1706 /********************************************************************
1707 GetPrinterData on a printer Handle.
1708 ********************************************************************/
1710 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1711 fstring value
, uint32
*type
,
1712 uint8
**data
, uint32
*needed
, uint32 in_size
)
1714 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1718 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1720 DEBUG(5,("getprinterdata_printer\n"));
1723 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1727 if(!get_printer_snum(p
, handle
, &snum
))
1730 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
1733 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
1734 free_a_printer(&printer
, 2);
1738 free_a_printer(&printer
, 2);
1740 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1743 if((*data
= (uint8
*)talloc(ctx
, in_size
*sizeof(uint8
) )) == NULL
) {
1747 memset(*data
, 0, in_size
*sizeof(uint8
));
1748 /* copy the min(in_size, len) */
1749 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
1756 DEBUG(5,("getprinterdata_printer:copy done\n"));
1763 /********************************************************************
1764 * spoolss_getprinterdata
1765 ********************************************************************/
1767 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1769 POLICY_HND
*handle
= &q_u
->handle
;
1770 UNISTR2
*valuename
= &q_u
->valuename
;
1771 uint32 in_size
= q_u
->size
;
1772 uint32
*type
= &r_u
->type
;
1773 uint32
*out_size
= &r_u
->size
;
1774 uint8
**data
= &r_u
->data
;
1775 uint32
*needed
= &r_u
->needed
;
1779 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1782 * Reminder: when it's a string, the length is in BYTES
1783 * even if UNICODE is negociated.
1790 /* in case of problem, return some default values */
1794 DEBUG(4,("_spoolss_getprinterdata\n"));
1797 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1799 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1803 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1805 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1806 found
=getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1808 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1811 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1812 /* reply this param doesn't exist */
1814 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1820 /* error depends on handle type */
1822 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1823 return WERR_INVALID_PARAM
;
1825 return WERR_BADFILE
;
1828 if (*needed
> *out_size
)
1829 return WERR_MORE_DATA
;
1834 /*********************************************************
1835 Connect to the client machine.
1836 **********************************************************/
1838 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
, char *remote_machine
)
1840 extern pstring global_myname
;
1842 ZERO_STRUCTP(the_cli
);
1843 if(cli_initialise(the_cli
) == NULL
) {
1844 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
1848 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
1849 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine
));
1850 cli_shutdown(the_cli
);
1854 if (ismyip(the_cli
->dest_ip
)) {
1855 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
1856 cli_shutdown(the_cli
);
1860 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
1861 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1862 cli_shutdown(the_cli
);
1866 if (!attempt_netbios_session_request(the_cli
, global_myname
, remote_machine
, &the_cli
->dest_ip
)) {
1867 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
1872 the_cli
->protocol
= PROTOCOL_NT1
;
1874 if (!cli_negprot(the_cli
)) {
1875 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1876 cli_shutdown(the_cli
);
1880 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
1881 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
1882 cli_shutdown(the_cli
);
1887 * Do an anonymous session setup.
1890 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
1891 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1892 cli_shutdown(the_cli
);
1896 if (!(the_cli
->sec_mode
& 1)) {
1897 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
1898 cli_shutdown(the_cli
);
1902 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
1903 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
1904 cli_shutdown(the_cli
);
1909 * Ok - we have an anonymous connection to the IPC$ share.
1910 * Now start the NT Domain stuff :-).
1913 if(cli_nt_session_open(the_cli
, PIPE_SPOOLSS
) == False
) {
1914 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
)));
1915 cli_nt_session_close(the_cli
);
1916 cli_ulogoff(the_cli
);
1917 cli_shutdown(the_cli
);
1924 /***************************************************************************
1925 Connect to the client.
1926 ****************************************************************************/
1928 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1933 * If it's the first connection, contact the client
1934 * and connect to the IPC$ share anonumously
1936 if (smb_connections
==0) {
1937 fstring unix_printer
;
1939 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
1941 if(!spoolss_connect_to_client(&cli
, unix_printer
))
1944 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message
);
1949 result
= cli_spoolss_reply_open_printer(&cli
, cli
.mem_ctx
, printer
, localprinter
,
1952 if (!W_ERROR_IS_OK(result
))
1953 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1954 dos_errstr(result
)));
1956 return (W_ERROR_IS_OK(result
));
1959 /********************************************************************
1961 * ReplyFindFirstPrinterChangeNotifyEx
1963 * before replying OK: status=0 a rpc call is made to the workstation
1964 * asking ReplyOpenPrinter
1966 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1967 * called from api_spoolss_rffpcnex
1968 ********************************************************************/
1970 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
1972 POLICY_HND
*handle
= &q_u
->handle
;
1973 uint32 flags
= q_u
->flags
;
1974 uint32 options
= q_u
->options
;
1975 UNISTR2
*localmachine
= &q_u
->localmachine
;
1976 uint32 printerlocal
= q_u
->printerlocal
;
1977 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
1979 /* store the notify value in the printer struct */
1981 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1984 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1988 Printer
->notify
.flags
=flags
;
1989 Printer
->notify
.options
=options
;
1990 Printer
->notify
.printerlocal
=printerlocal
;
1992 if (Printer
->notify
.option
)
1993 free_spool_notify_option(&Printer
->notify
.option
);
1995 Printer
->notify
.option
=dup_spool_notify_option(option
);
1997 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
1998 sizeof(Printer
->notify
.localmachine
)-1);
2000 /* Connect to the client machine and send a ReplyOpenPrinter */
2002 if(!srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
2003 Printer
->notify
.printerlocal
, 1,
2004 &Printer
->notify
.client_hnd
))
2005 return WERR_SERVER_UNAVAILABLE
;
2007 Printer
->notify
.client_connected
=True
;
2012 /*******************************************************************
2013 * fill a notify_info_data with the servername
2014 ********************************************************************/
2016 void spoolss_notify_server_name(int snum
,
2017 SPOOL_NOTIFY_INFO_DATA
*data
,
2018 print_queue_struct
*queue
,
2019 NT_PRINTER_INFO_LEVEL
*printer
,
2020 TALLOC_CTX
*mem_ctx
)
2022 pstring temp_name
, temp
;
2025 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
2027 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2029 data
->notify_data
.data
.length
= len
;
2030 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2032 if (!data
->notify_data
.data
.string
) {
2033 data
->notify_data
.data
.length
= 0;
2037 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2040 /*******************************************************************
2041 * fill a notify_info_data with the printername (not including the servername).
2042 ********************************************************************/
2044 void spoolss_notify_printer_name(int snum
,
2045 SPOOL_NOTIFY_INFO_DATA
*data
,
2046 print_queue_struct
*queue
,
2047 NT_PRINTER_INFO_LEVEL
*printer
,
2048 TALLOC_CTX
*mem_ctx
)
2053 /* the notify name should not contain the \\server\ part */
2054 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2057 p
= printer
->info_2
->printername
;
2062 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2064 data
->notify_data
.data
.length
= len
;
2065 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2067 if (!data
->notify_data
.data
.string
) {
2068 data
->notify_data
.data
.length
= 0;
2072 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2075 /*******************************************************************
2076 * fill a notify_info_data with the servicename
2077 ********************************************************************/
2079 void spoolss_notify_share_name(int snum
,
2080 SPOOL_NOTIFY_INFO_DATA
*data
,
2081 print_queue_struct
*queue
,
2082 NT_PRINTER_INFO_LEVEL
*printer
,
2083 TALLOC_CTX
*mem_ctx
)
2088 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2090 data
->notify_data
.data
.length
= len
;
2091 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2093 if (!data
->notify_data
.data
.string
) {
2094 data
->notify_data
.data
.length
= 0;
2098 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2101 /*******************************************************************
2102 * fill a notify_info_data with the port name
2103 ********************************************************************/
2105 void spoolss_notify_port_name(int snum
,
2106 SPOOL_NOTIFY_INFO_DATA
*data
,
2107 print_queue_struct
*queue
,
2108 NT_PRINTER_INFO_LEVEL
*printer
,
2109 TALLOC_CTX
*mem_ctx
)
2114 /* even if it's strange, that's consistant in all the code */
2116 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2118 data
->notify_data
.data
.length
= len
;
2119 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2121 if (!data
->notify_data
.data
.string
) {
2122 data
->notify_data
.data
.length
= 0;
2126 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2129 /*******************************************************************
2130 * fill a notify_info_data with the printername
2131 * but it doesn't exist, have to see what to do
2132 ********************************************************************/
2134 void spoolss_notify_driver_name(int snum
,
2135 SPOOL_NOTIFY_INFO_DATA
*data
,
2136 print_queue_struct
*queue
,
2137 NT_PRINTER_INFO_LEVEL
*printer
,
2138 TALLOC_CTX
*mem_ctx
)
2143 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2145 data
->notify_data
.data
.length
= len
;
2146 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2148 if (!data
->notify_data
.data
.string
) {
2149 data
->notify_data
.data
.length
= 0;
2153 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2156 /*******************************************************************
2157 * fill a notify_info_data with the comment
2158 ********************************************************************/
2160 void spoolss_notify_comment(int snum
,
2161 SPOOL_NOTIFY_INFO_DATA
*data
,
2162 print_queue_struct
*queue
,
2163 NT_PRINTER_INFO_LEVEL
*printer
,
2164 TALLOC_CTX
*mem_ctx
)
2169 if (*printer
->info_2
->comment
== '\0')
2170 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2172 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2174 data
->notify_data
.data
.length
= len
;
2175 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2177 if (!data
->notify_data
.data
.string
) {
2178 data
->notify_data
.data
.length
= 0;
2182 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2185 /*******************************************************************
2186 * fill a notify_info_data with the comment
2187 * location = "Room 1, floor 2, building 3"
2188 ********************************************************************/
2190 void spoolss_notify_location(int snum
,
2191 SPOOL_NOTIFY_INFO_DATA
*data
,
2192 print_queue_struct
*queue
,
2193 NT_PRINTER_INFO_LEVEL
*printer
,
2194 TALLOC_CTX
*mem_ctx
)
2199 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2201 data
->notify_data
.data
.length
= len
;
2202 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2204 if (!data
->notify_data
.data
.string
) {
2205 data
->notify_data
.data
.length
= 0;
2209 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2212 /*******************************************************************
2213 * fill a notify_info_data with the device mode
2214 * jfm:xxxx don't to it for know but that's a real problem !!!
2215 ********************************************************************/
2217 static void spoolss_notify_devmode(int snum
,
2218 SPOOL_NOTIFY_INFO_DATA
*data
,
2219 print_queue_struct
*queue
,
2220 NT_PRINTER_INFO_LEVEL
*printer
,
2221 TALLOC_CTX
*mem_ctx
)
2225 /*******************************************************************
2226 * fill a notify_info_data with the separator file name
2227 ********************************************************************/
2229 void spoolss_notify_sepfile(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
->sepfile
, 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 print processor
2253 * jfm:xxxx return always winprint to indicate we don't do anything to it
2254 ********************************************************************/
2256 void spoolss_notify_print_processor(int snum
,
2257 SPOOL_NOTIFY_INFO_DATA
*data
,
2258 print_queue_struct
*queue
,
2259 NT_PRINTER_INFO_LEVEL
*printer
,
2260 TALLOC_CTX
*mem_ctx
)
2265 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2267 data
->notify_data
.data
.length
= len
;
2268 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2270 if (!data
->notify_data
.data
.string
) {
2271 data
->notify_data
.data
.length
= 0;
2275 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2278 /*******************************************************************
2279 * fill a notify_info_data with the print processor options
2280 * jfm:xxxx send an empty string
2281 ********************************************************************/
2283 void spoolss_notify_parameters(int snum
,
2284 SPOOL_NOTIFY_INFO_DATA
*data
,
2285 print_queue_struct
*queue
,
2286 NT_PRINTER_INFO_LEVEL
*printer
,
2287 TALLOC_CTX
*mem_ctx
)
2292 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2294 data
->notify_data
.data
.length
= len
;
2295 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2297 if (!data
->notify_data
.data
.string
) {
2298 data
->notify_data
.data
.length
= 0;
2302 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2305 /*******************************************************************
2306 * fill a notify_info_data with the data type
2307 * jfm:xxxx always send RAW as data type
2308 ********************************************************************/
2310 void spoolss_notify_datatype(int snum
,
2311 SPOOL_NOTIFY_INFO_DATA
*data
,
2312 print_queue_struct
*queue
,
2313 NT_PRINTER_INFO_LEVEL
*printer
,
2314 TALLOC_CTX
*mem_ctx
)
2319 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2321 data
->notify_data
.data
.length
= len
;
2322 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2324 if (!data
->notify_data
.data
.string
) {
2325 data
->notify_data
.data
.length
= 0;
2329 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2332 /*******************************************************************
2333 * fill a notify_info_data with the security descriptor
2334 * jfm:xxxx send an null pointer to say no security desc
2335 * have to implement security before !
2336 ********************************************************************/
2338 static void spoolss_notify_security_desc(int snum
,
2339 SPOOL_NOTIFY_INFO_DATA
*data
,
2340 print_queue_struct
*queue
,
2341 NT_PRINTER_INFO_LEVEL
*printer
,
2342 TALLOC_CTX
*mem_ctx
)
2344 data
->notify_data
.data
.length
=0;
2345 data
->notify_data
.data
.string
= NULL
;
2348 /*******************************************************************
2349 * fill a notify_info_data with the attributes
2350 * jfm:xxxx a samba printer is always shared
2351 ********************************************************************/
2353 void spoolss_notify_attributes(int snum
,
2354 SPOOL_NOTIFY_INFO_DATA
*data
,
2355 print_queue_struct
*queue
,
2356 NT_PRINTER_INFO_LEVEL
*printer
,
2357 TALLOC_CTX
*mem_ctx
)
2359 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2360 data
->notify_data
.value
[1] = 0;
2363 /*******************************************************************
2364 * fill a notify_info_data with the priority
2365 ********************************************************************/
2367 static void spoolss_notify_priority(int snum
,
2368 SPOOL_NOTIFY_INFO_DATA
*data
,
2369 print_queue_struct
*queue
,
2370 NT_PRINTER_INFO_LEVEL
*printer
,
2371 TALLOC_CTX
*mem_ctx
)
2373 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2374 data
->notify_data
.value
[1] = 0;
2377 /*******************************************************************
2378 * fill a notify_info_data with the default priority
2379 ********************************************************************/
2381 static void spoolss_notify_default_priority(int snum
,
2382 SPOOL_NOTIFY_INFO_DATA
*data
,
2383 print_queue_struct
*queue
,
2384 NT_PRINTER_INFO_LEVEL
*printer
,
2385 TALLOC_CTX
*mem_ctx
)
2387 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2388 data
->notify_data
.value
[1] = 0;
2391 /*******************************************************************
2392 * fill a notify_info_data with the start time
2393 ********************************************************************/
2395 static void spoolss_notify_start_time(int snum
,
2396 SPOOL_NOTIFY_INFO_DATA
*data
,
2397 print_queue_struct
*queue
,
2398 NT_PRINTER_INFO_LEVEL
*printer
,
2399 TALLOC_CTX
*mem_ctx
)
2401 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2402 data
->notify_data
.value
[1] = 0;
2405 /*******************************************************************
2406 * fill a notify_info_data with the until time
2407 ********************************************************************/
2409 static void spoolss_notify_until_time(int snum
,
2410 SPOOL_NOTIFY_INFO_DATA
*data
,
2411 print_queue_struct
*queue
,
2412 NT_PRINTER_INFO_LEVEL
*printer
,
2413 TALLOC_CTX
*mem_ctx
)
2415 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2416 data
->notify_data
.value
[1] = 0;
2419 /*******************************************************************
2420 * fill a notify_info_data with the status
2421 ********************************************************************/
2423 static void spoolss_notify_status(int snum
,
2424 SPOOL_NOTIFY_INFO_DATA
*data
,
2425 print_queue_struct
*queue
,
2426 NT_PRINTER_INFO_LEVEL
*printer
,
2427 TALLOC_CTX
*mem_ctx
)
2429 print_status_struct status
;
2431 print_queue_length(snum
, &status
);
2432 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2433 data
->notify_data
.value
[1] = 0;
2436 /*******************************************************************
2437 * fill a notify_info_data with the number of jobs queued
2438 ********************************************************************/
2440 void spoolss_notify_cjobs(int snum
,
2441 SPOOL_NOTIFY_INFO_DATA
*data
,
2442 print_queue_struct
*queue
,
2443 NT_PRINTER_INFO_LEVEL
*printer
,
2444 TALLOC_CTX
*mem_ctx
)
2446 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
2447 data
->notify_data
.value
[1] = 0;
2450 /*******************************************************************
2451 * fill a notify_info_data with the average ppm
2452 ********************************************************************/
2454 static void spoolss_notify_average_ppm(int snum
,
2455 SPOOL_NOTIFY_INFO_DATA
*data
,
2456 print_queue_struct
*queue
,
2457 NT_PRINTER_INFO_LEVEL
*printer
,
2458 TALLOC_CTX
*mem_ctx
)
2460 /* always respond 8 pages per minutes */
2461 /* a little hard ! */
2462 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
2463 data
->notify_data
.value
[1] = 0;
2466 /*******************************************************************
2467 * fill a notify_info_data with username
2468 ********************************************************************/
2470 static void spoolss_notify_username(int snum
,
2471 SPOOL_NOTIFY_INFO_DATA
*data
,
2472 print_queue_struct
*queue
,
2473 NT_PRINTER_INFO_LEVEL
*printer
,
2474 TALLOC_CTX
*mem_ctx
)
2479 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
2481 data
->notify_data
.data
.length
= len
;
2482 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2484 if (!data
->notify_data
.data
.string
) {
2485 data
->notify_data
.data
.length
= 0;
2489 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2492 /*******************************************************************
2493 * fill a notify_info_data with job status
2494 ********************************************************************/
2496 static void spoolss_notify_job_status(int snum
,
2497 SPOOL_NOTIFY_INFO_DATA
*data
,
2498 print_queue_struct
*queue
,
2499 NT_PRINTER_INFO_LEVEL
*printer
,
2500 TALLOC_CTX
*mem_ctx
)
2502 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
2503 data
->notify_data
.value
[1] = 0;
2506 /*******************************************************************
2507 * fill a notify_info_data with job name
2508 ********************************************************************/
2510 static void spoolss_notify_job_name(int snum
,
2511 SPOOL_NOTIFY_INFO_DATA
*data
,
2512 print_queue_struct
*queue
,
2513 NT_PRINTER_INFO_LEVEL
*printer
,
2514 TALLOC_CTX
*mem_ctx
)
2519 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
2521 data
->notify_data
.data
.length
= len
;
2522 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2524 if (!data
->notify_data
.data
.string
) {
2525 data
->notify_data
.data
.length
= 0;
2529 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2532 /*******************************************************************
2533 * fill a notify_info_data with job status
2534 ********************************************************************/
2536 static void spoolss_notify_job_status_string(int snum
,
2537 SPOOL_NOTIFY_INFO_DATA
*data
,
2538 print_queue_struct
*queue
,
2539 NT_PRINTER_INFO_LEVEL
*printer
,
2540 TALLOC_CTX
*mem_ctx
)
2543 * Now we're returning job status codes we just return a "" here. JRA.
2550 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2553 switch (queue
->status
) {
2558 p
= ""; /* NT provides the paused string */
2567 #endif /* NO LONGER NEEDED. */
2569 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
2571 data
->notify_data
.data
.length
= len
;
2572 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2574 if (!data
->notify_data
.data
.string
) {
2575 data
->notify_data
.data
.length
= 0;
2579 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2582 /*******************************************************************
2583 * fill a notify_info_data with job time
2584 ********************************************************************/
2586 static void spoolss_notify_job_time(int snum
,
2587 SPOOL_NOTIFY_INFO_DATA
*data
,
2588 print_queue_struct
*queue
,
2589 NT_PRINTER_INFO_LEVEL
*printer
,
2590 TALLOC_CTX
*mem_ctx
)
2592 data
->notify_data
.value
[0]=0x0;
2593 data
->notify_data
.value
[1]=0;
2596 /*******************************************************************
2597 * fill a notify_info_data with job size
2598 ********************************************************************/
2600 static void spoolss_notify_job_size(int snum
,
2601 SPOOL_NOTIFY_INFO_DATA
*data
,
2602 print_queue_struct
*queue
,
2603 NT_PRINTER_INFO_LEVEL
*printer
,
2604 TALLOC_CTX
*mem_ctx
)
2606 data
->notify_data
.value
[0]=queue
->size
;
2607 data
->notify_data
.value
[1]=0;
2610 /*******************************************************************
2611 * fill a notify_info_data with page info
2612 ********************************************************************/
2613 static void spoolss_notify_total_pages(int snum
,
2614 SPOOL_NOTIFY_INFO_DATA
*data
,
2615 print_queue_struct
*queue
,
2616 NT_PRINTER_INFO_LEVEL
*printer
,
2617 TALLOC_CTX
*mem_ctx
)
2619 data
->notify_data
.value
[0]=queue
->page_count
;
2620 data
->notify_data
.value
[1]=0;
2623 /*******************************************************************
2624 * fill a notify_info_data with pages printed info.
2625 ********************************************************************/
2626 static void spoolss_notify_pages_printed(int snum
,
2627 SPOOL_NOTIFY_INFO_DATA
*data
,
2628 print_queue_struct
*queue
,
2629 NT_PRINTER_INFO_LEVEL
*printer
,
2630 TALLOC_CTX
*mem_ctx
)
2632 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
2633 data
->notify_data
.value
[1]=0;
2636 /*******************************************************************
2637 Fill a notify_info_data with job position.
2638 ********************************************************************/
2640 static void spoolss_notify_job_position(int snum
,
2641 SPOOL_NOTIFY_INFO_DATA
*data
,
2642 print_queue_struct
*queue
,
2643 NT_PRINTER_INFO_LEVEL
*printer
,
2644 TALLOC_CTX
*mem_ctx
)
2646 data
->notify_data
.value
[0]=queue
->job
;
2647 data
->notify_data
.value
[1]=0;
2650 /*******************************************************************
2651 Fill a notify_info_data with submitted time.
2652 ********************************************************************/
2654 static void spoolss_notify_submitted_time(int snum
,
2655 SPOOL_NOTIFY_INFO_DATA
*data
,
2656 print_queue_struct
*queue
,
2657 NT_PRINTER_INFO_LEVEL
*printer
,
2658 TALLOC_CTX
*mem_ctx
)
2665 t
=gmtime(&queue
->time
);
2667 len
= sizeof(SYSTEMTIME
);
2669 data
->notify_data
.data
.length
= len
;
2670 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2672 if (!data
->notify_data
.data
.string
) {
2673 data
->notify_data
.data
.length
= 0;
2677 make_systemtime(&st
, t
);
2680 * Systemtime must be linearized as a set of UINT16's.
2681 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2684 p
= (char *)data
->notify_data
.data
.string
;
2685 SSVAL(p
, 0, st
.year
);
2686 SSVAL(p
, 2, st
.month
);
2687 SSVAL(p
, 4, st
.dayofweek
);
2688 SSVAL(p
, 6, st
.day
);
2689 SSVAL(p
, 8, st
.hour
);
2690 SSVAL(p
, 10, st
.minute
);
2691 SSVAL(p
, 12, st
.second
);
2692 SSVAL(p
, 14, st
.milliseconds
);
2695 struct s_notify_info_data_table
2701 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2702 print_queue_struct
*queue
,
2703 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2706 /* A table describing the various print notification constants and
2707 whether the notification data is a pointer to a variable sized
2708 buffer, a one value uint32 or a two value uint32. */
2710 struct s_notify_info_data_table notify_info_data_table
[] =
2712 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
2713 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
2714 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
2715 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
2716 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
2717 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
2718 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
2719 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
2720 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
2721 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
2722 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
2723 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
2724 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, spoolss_notify_security_desc
},
2725 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
2726 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
2727 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
2728 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
2729 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
2730 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
2731 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
2732 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
2733 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
2734 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
2735 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
2736 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
2737 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
2738 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
2739 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
2740 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
2741 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
2742 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
2743 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
2744 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
2745 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
2746 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
2747 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
2748 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
2749 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
2750 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
2751 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
2752 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
2753 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
2754 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
2755 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
2756 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
2757 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
2758 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
2759 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
2760 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
2763 /*******************************************************************
2764 Return the size of info_data structure.
2765 ********************************************************************/
2767 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2771 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
2772 if (notify_info_data_table
[i
].type
== type
&&
2773 notify_info_data_table
[i
].field
== field
) {
2774 switch(notify_info_data_table
[i
].size
) {
2775 case NOTIFY_ONE_VALUE
:
2776 case NOTIFY_TWO_VALUE
:
2781 /* The only pointer notify data I have seen on
2782 the wire is the submitted time and this has
2783 the notify size set to 4. -tpot */
2785 case NOTIFY_POINTER
:
2791 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
2796 /*******************************************************************
2797 Return the type of notify_info_data.
2798 ********************************************************************/
2800 static int type_of_notify_info_data(uint16 type
, uint16 field
)
2804 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
2805 if (notify_info_data_table
[i
].type
== type
&&
2806 notify_info_data_table
[i
].field
== field
)
2807 return notify_info_data_table
[i
].size
;
2813 /****************************************************************************
2814 ****************************************************************************/
2816 static int search_notify(uint16 type
, uint16 field
, int *value
)
2820 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
2821 if (notify_info_data_table
[i
].type
== type
&&
2822 notify_info_data_table
[i
].field
== field
&&
2823 notify_info_data_table
[i
].fn
!= NULL
) {
2832 /****************************************************************************
2833 ****************************************************************************/
2835 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2837 info_data
->type
= type
;
2838 info_data
->field
= field
;
2839 info_data
->reserved
= 0;
2841 if (type
== JOB_NOTIFY_TYPE
)
2846 info_data
->size
= size_of_notify_info_data(type
, field
);
2847 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2851 /*******************************************************************
2853 * fill a notify_info struct with info asked
2855 ********************************************************************/
2857 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2858 snum
, SPOOL_NOTIFY_OPTION_TYPE
2859 *option_type
, uint32 id
,
2860 TALLOC_CTX
*mem_ctx
)
2866 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2867 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2868 print_queue_struct
*queue
=NULL
;
2870 type
=option_type
->type
;
2872 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2873 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2874 option_type
->count
, lp_servicename(snum
)));
2876 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2879 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2880 field
= option_type
->fields
[field_num
];
2881 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2883 if (!search_notify(type
, field
, &j
) )
2886 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2887 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2890 else info
->data
= tid
;
2892 current_data
=&info
->data
[info
->count
];
2894 construct_info_data(current_data
, type
, field
, id
);
2896 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2897 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
2899 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2905 free_a_printer(&printer
, 2);
2909 /*******************************************************************
2911 * fill a notify_info struct with info asked
2913 ********************************************************************/
2915 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
2916 SPOOL_NOTIFY_INFO
*info
,
2917 NT_PRINTER_INFO_LEVEL
*printer
,
2918 int snum
, SPOOL_NOTIFY_OPTION_TYPE
2919 *option_type
, uint32 id
,
2920 TALLOC_CTX
*mem_ctx
)
2926 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2928 DEBUG(4,("construct_notify_jobs_info\n"));
2930 type
= option_type
->type
;
2932 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2933 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2934 option_type
->count
));
2936 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2937 field
= option_type
->fields
[field_num
];
2939 if (!search_notify(type
, field
, &j
) )
2942 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2943 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2946 else info
->data
= tid
;
2948 current_data
=&(info
->data
[info
->count
]);
2950 construct_info_data(current_data
, type
, field
, id
);
2951 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2960 * JFM: The enumeration is not that simple, it's even non obvious.
2962 * let's take an example: I want to monitor the PRINTER SERVER for
2963 * the printer's name and the number of jobs currently queued.
2964 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2965 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2967 * I have 3 printers on the back of my server.
2969 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2972 * 1 printer 1 name 1
2973 * 2 printer 1 cjob 1
2974 * 3 printer 2 name 2
2975 * 4 printer 2 cjob 2
2976 * 5 printer 3 name 3
2977 * 6 printer 3 name 3
2979 * that's the print server case, the printer case is even worse.
2982 /*******************************************************************
2984 * enumerate all printers on the printserver
2985 * fill a notify_info struct with info asked
2987 ********************************************************************/
2989 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
2990 SPOOL_NOTIFY_INFO
*info
,
2991 TALLOC_CTX
*mem_ctx
)
2994 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2995 int n_services
=lp_numservices();
2998 SPOOL_NOTIFY_OPTION
*option
;
2999 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3001 DEBUG(4,("printserver_notify_info\n"));
3006 option
=Printer
->notify
.option
;
3012 for (i
=0; i
<option
->count
; i
++) {
3013 option_type
=&(option
->ctr
.type
[i
]);
3015 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3018 for (snum
=0; snum
<n_services
; snum
++)
3019 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3020 if (construct_notify_printer_info
3021 (info
, snum
, option_type
, id
, mem_ctx
))
3026 * Debugging information, don't delete.
3029 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3030 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3031 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3033 for (i=0; i<info->count; i++) {
3034 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3035 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3036 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3043 /*******************************************************************
3045 * fill a notify_info struct with info asked
3047 ********************************************************************/
3049 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3050 TALLOC_CTX
*mem_ctx
)
3053 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3056 SPOOL_NOTIFY_OPTION
*option
;
3057 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3059 print_queue_struct
*queue
=NULL
;
3060 print_status_struct status
;
3062 DEBUG(4,("printer_notify_info\n"));
3067 option
=Printer
->notify
.option
;
3073 get_printer_snum(p
, hnd
, &snum
);
3075 for (i
=0; i
<option
->count
; i
++) {
3076 option_type
=&option
->ctr
.type
[i
];
3078 switch ( option_type
->type
) {
3079 case PRINTER_NOTIFY_TYPE
:
3080 if(construct_notify_printer_info(info
, snum
,
3086 case JOB_NOTIFY_TYPE
: {
3087 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3089 count
= print_queue_status(snum
, &queue
, &status
);
3091 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
3092 lp_servicename(snum
))))
3095 for (j
=0; j
<count
; j
++) {
3096 construct_notify_jobs_info(&queue
[j
], info
,
3103 free_a_printer(&printer
, 2);
3113 * Debugging information, don't delete.
3116 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3117 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3118 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3120 for (i=0; i<info->count; i++) {
3121 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3122 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3123 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3129 /********************************************************************
3131 ********************************************************************/
3133 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3135 POLICY_HND
*handle
= &q_u
->handle
;
3136 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
3137 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3139 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3140 WERROR result
= WERR_BADFID
;
3142 /* we always have a NOTIFY_INFO struct */
3146 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3147 OUR_HANDLE(handle
)));
3151 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3154 * We are now using the change value, and
3155 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3156 * I don't have a global notification system, I'm sending back all the
3157 * informations even when _NOTHING_ has changed.
3160 /* We need to keep track of the change value to send back in
3161 RRPCN replies otherwise our updates are ignored. */
3163 if (Printer
->notify
.client_connected
)
3164 Printer
->notify
.change
= q_u
->change
;
3166 /* just ignore the SPOOL_NOTIFY_OPTION */
3168 switch (Printer
->printer_type
) {
3169 case PRINTER_HANDLE_IS_PRINTSERVER
:
3170 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3173 case PRINTER_HANDLE_IS_PRINTER
:
3174 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3182 /********************************************************************
3183 * construct_printer_info_0
3184 * fill a printer_info_0 struct
3185 ********************************************************************/
3187 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3191 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3192 counter_printer_0
*session_counter
;
3193 uint32 global_counter
;
3196 print_status_struct status
;
3198 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3201 count
= print_queue_length(snum
, &status
);
3203 /* check if we already have a counter for this printer */
3204 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3206 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3207 if (session_counter
->snum
== snum
)
3211 /* it's the first time, add it to the list */
3212 if (session_counter
==NULL
) {
3213 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3214 free_a_printer(&ntprinter
, 2);
3217 ZERO_STRUCTP(session_counter
);
3218 session_counter
->snum
=snum
;
3219 session_counter
->counter
=0;
3220 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3224 session_counter
->counter
++;
3227 * the global_counter should be stored in a TDB as it's common to all the clients
3228 * and should be zeroed on samba startup
3230 global_counter
=session_counter
->counter
;
3232 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3234 init_unistr(&printer
->printername
, chaine
);
3236 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3237 init_unistr(&printer
->servername
, chaine
);
3239 printer
->cjobs
= count
;
3240 printer
->total_jobs
= 0;
3241 printer
->total_bytes
= 0;
3243 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3244 t
=gmtime(&setuptime
);
3246 printer
->year
= t
->tm_year
+1900;
3247 printer
->month
= t
->tm_mon
+1;
3248 printer
->dayofweek
= t
->tm_wday
;
3249 printer
->day
= t
->tm_mday
;
3250 printer
->hour
= t
->tm_hour
;
3251 printer
->minute
= t
->tm_min
;
3252 printer
->second
= t
->tm_sec
;
3253 printer
->milliseconds
= 0;
3255 printer
->global_counter
= global_counter
;
3256 printer
->total_pages
= 0;
3257 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3258 printer
->major_version
= 0x0004; /* NT 4 */
3259 printer
->build_version
= 0x0565; /* build 1381 */
3261 printer
->major_version
= 0x0005; /* NT 5 */
3262 printer
->build_version
= 0x0893; /* build 2195 */
3264 printer
->unknown7
= 0x1;
3265 printer
->unknown8
= 0x0;
3266 printer
->unknown9
= 0x0;
3267 printer
->session_counter
= session_counter
->counter
;
3268 printer
->unknown11
= 0x0;
3269 printer
->printer_errors
= 0x0; /* number of print failure */
3270 printer
->unknown13
= 0x0;
3271 printer
->unknown14
= 0x1;
3272 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3273 printer
->unknown16
= 0x0;
3274 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3275 printer
->unknown18
= 0x0;
3276 printer
->status
= nt_printq_status(status
.status
);
3277 printer
->unknown20
= 0x0;
3278 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3279 printer
->unknown22
= 0x0;
3280 printer
->unknown23
= 0x6; /* 6 ???*/
3281 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3282 printer
->unknown25
= 0;
3283 printer
->unknown26
= 0;
3284 printer
->unknown27
= 0;
3285 printer
->unknown28
= 0;
3286 printer
->unknown29
= 0;
3288 free_a_printer(&ntprinter
,2);
3292 /********************************************************************
3293 * construct_printer_info_1
3294 * fill a printer_info_1 struct
3295 ********************************************************************/
3296 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3300 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3302 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3305 printer
->flags
=flags
;
3307 if (*ntprinter
->info_2
->comment
== '\0') {
3308 init_unistr(&printer
->comment
, lp_comment(snum
));
3309 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3310 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3313 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3314 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3315 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3318 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3320 init_unistr(&printer
->description
, chaine
);
3321 init_unistr(&printer
->name
, chaine2
);
3323 free_a_printer(&ntprinter
,2);
3328 /****************************************************************************
3329 Free a DEVMODE struct.
3330 ****************************************************************************/
3332 static void free_dev_mode(DEVICEMODE
*dev
)
3337 SAFE_FREE(dev
->private);
3341 /****************************************************************************
3342 Create a DEVMODE struct. Returns malloced memory.
3343 ****************************************************************************/
3345 static DEVICEMODE
*construct_dev_mode(int snum
)
3349 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3350 NT_DEVICEMODE
*ntdevmode
= NULL
;
3351 DEVICEMODE
*devmode
= NULL
;
3353 DEBUG(7,("construct_dev_mode\n"));
3355 DEBUGADD(8,("getting printer characteristics\n"));
3357 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3358 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3362 ZERO_STRUCTP(devmode
);
3364 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3367 if (printer
->info_2
->devmode
)
3368 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
3370 if (ntdevmode
== NULL
) {
3371 DEBUG(5, ("BONG! There was no device mode!\n"));
3375 DEBUGADD(8,("loading DEVICEMODE\n"));
3377 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
3378 init_unistr(&devmode
->devicename
, adevice
);
3380 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
3381 init_unistr(&devmode
->formname
, aform
);
3383 devmode
->specversion
= ntdevmode
->specversion
;
3384 devmode
->driverversion
= ntdevmode
->driverversion
;
3385 devmode
->size
= ntdevmode
->size
;
3386 devmode
->driverextra
= ntdevmode
->driverextra
;
3387 devmode
->fields
= ntdevmode
->fields
;
3389 devmode
->orientation
= ntdevmode
->orientation
;
3390 devmode
->papersize
= ntdevmode
->papersize
;
3391 devmode
->paperlength
= ntdevmode
->paperlength
;
3392 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3393 devmode
->scale
= ntdevmode
->scale
;
3394 devmode
->copies
= ntdevmode
->copies
;
3395 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3396 devmode
->printquality
= ntdevmode
->printquality
;
3397 devmode
->color
= ntdevmode
->color
;
3398 devmode
->duplex
= ntdevmode
->duplex
;
3399 devmode
->yresolution
= ntdevmode
->yresolution
;
3400 devmode
->ttoption
= ntdevmode
->ttoption
;
3401 devmode
->collate
= ntdevmode
->collate
;
3402 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3403 devmode
->icmintent
= ntdevmode
->icmintent
;
3404 devmode
->mediatype
= ntdevmode
->mediatype
;
3405 devmode
->dithertype
= ntdevmode
->dithertype
;
3407 if (ntdevmode
->private != NULL
) {
3408 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3412 free_nt_devicemode(&ntdevmode
);
3413 free_a_printer(&printer
,2);
3420 free_nt_devicemode(&ntdevmode
);
3422 free_a_printer(&printer
,2);
3423 free_dev_mode(devmode
);
3428 /********************************************************************
3429 * construct_printer_info_2
3430 * fill a printer_info_2 struct
3431 ********************************************************************/
3433 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
3436 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3438 print_status_struct status
;
3440 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3443 count
= print_queue_length(snum
, &status
);
3445 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3446 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3447 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
3448 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
3449 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
3451 if (*ntprinter
->info_2
->comment
== '\0')
3452 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
3454 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3456 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
3457 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
3458 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
3459 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
3460 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
3462 printer
->attributes
= ntprinter
->info_2
->attributes
;
3464 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
3465 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
3466 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
3467 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
3468 printer
->status
= nt_printq_status(status
.status
); /* status */
3469 printer
->cjobs
= count
; /* jobs */
3470 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
3472 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
3473 DEBUG(8, ("Returning NULL Devicemode!\n"));
3476 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3477 /* steal the printer info sec_desc structure. [badly done]. */
3478 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3479 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
3480 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
3481 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
3484 printer
->secdesc
= NULL
;
3487 free_a_printer(&ntprinter
, 2);
3491 /********************************************************************
3492 * construct_printer_info_3
3493 * fill a printer_info_3 struct
3494 ********************************************************************/
3496 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
3498 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3499 PRINTER_INFO_3
*printer
= NULL
;
3501 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3505 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
3506 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3510 ZERO_STRUCTP(printer
);
3512 printer
->flags
= 4; /* These are the components of the SD we are returning. */
3513 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3514 /* steal the printer info sec_desc structure. [badly done]. */
3515 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3519 * Set the flags for the components we are returning.
3522 if (printer
->secdesc
->owner_sid
)
3523 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
3525 if (printer
->secdesc
->grp_sid
)
3526 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
3528 if (printer
->secdesc
->dacl
)
3529 printer
->flags
|= DACL_SECURITY_INFORMATION
;
3531 if (printer
->secdesc
->sacl
)
3532 printer
->flags
|= SACL_SECURITY_INFORMATION
;
3535 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
3536 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
3537 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
3540 free_a_printer(&ntprinter
, 2);
3542 *pp_printer
= printer
;
3546 /********************************************************************
3547 * construct_printer_info_4
3548 * fill a printer_info_4 struct
3549 ********************************************************************/
3551 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
3553 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3555 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3558 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3559 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3560 printer
->attributes
= ntprinter
->info_2
->attributes
;
3562 free_a_printer(&ntprinter
, 2);
3566 /********************************************************************
3567 * construct_printer_info_5
3568 * fill a printer_info_5 struct
3569 ********************************************************************/
3571 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
3573 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3575 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3578 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3579 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
3580 printer
->attributes
= ntprinter
->info_2
->attributes
;
3581 printer
->device_not_selected_timeout
= 0x3a98;
3582 printer
->transmission_retry_timeout
= 0xafc8;
3584 free_a_printer(&ntprinter
, 2);
3588 /********************************************************************
3589 Spoolss_enumprinters.
3590 ********************************************************************/
3592 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3596 int n_services
=lp_numservices();
3597 PRINTER_INFO_1
*tp
, *printers
=NULL
;
3598 PRINTER_INFO_1 current_prt
;
3600 DEBUG(4,("enum_all_printers_info_1\n"));
3602 for (snum
=0; snum
<n_services
; snum
++) {
3603 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3604 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3606 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
3607 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
3608 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3609 SAFE_FREE(printers
);
3614 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
3616 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
3622 /* check the required size. */
3623 for (i
=0; i
<*returned
; i
++)
3624 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
3626 if (!alloc_buffer_size(buffer
, *needed
))
3627 return WERR_INSUFFICIENT_BUFFER
;
3629 /* fill the buffer with the structures */
3630 for (i
=0; i
<*returned
; i
++)
3631 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
3634 SAFE_FREE(printers
);
3636 if (*needed
> offered
) {
3638 return WERR_INSUFFICIENT_BUFFER
;
3644 /********************************************************************
3645 enum_all_printers_info_1_local.
3646 *********************************************************************/
3648 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3650 DEBUG(4,("enum_all_printers_info_1_local\n"));
3652 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3655 /********************************************************************
3656 enum_all_printers_info_1_name.
3657 *********************************************************************/
3659 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3663 DEBUG(4,("enum_all_printers_info_1_name\n"));
3665 if ((name
[0] == '\\') && (name
[1] == '\\'))
3668 if (is_myname_or_ipaddr(s
)) {
3669 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3672 return WERR_INVALID_NAME
;
3675 /********************************************************************
3676 enum_all_printers_info_1_remote.
3677 *********************************************************************/
3679 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3681 PRINTER_INFO_1
*printer
;
3682 fstring printername
;
3685 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3687 /* JFM: currently it's more a place holder than anything else.
3688 * In the spooler world there is a notion of server registration.
3689 * the print servers are registring (sp ?) on the PDC (in the same domain)
3691 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3694 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3699 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3700 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
3701 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3703 init_unistr(&printer
->description
, desc
);
3704 init_unistr(&printer
->name
, printername
);
3705 init_unistr(&printer
->comment
, comment
);
3706 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3708 /* check the required size. */
3709 *needed
+= spoolss_size_printer_info_1(printer
);
3711 if (!alloc_buffer_size(buffer
, *needed
)) {
3713 return WERR_INSUFFICIENT_BUFFER
;
3716 /* fill the buffer with the structures */
3717 smb_io_printer_info_1("", buffer
, printer
, 0);
3722 if (*needed
> offered
) {
3724 return WERR_INSUFFICIENT_BUFFER
;
3730 /********************************************************************
3731 enum_all_printers_info_1_network.
3732 *********************************************************************/
3734 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3738 DEBUG(4,("enum_all_printers_info_1_network\n"));
3740 /* If we respond to a enum_printers level 1 on our name with flags
3741 set to PRINTER_ENUM_REMOTE with a list of printers then these
3742 printers incorrectly appear in the APW browse list.
3743 Specifically the printers for the server appear at the workgroup
3744 level where all the other servers in the domain are
3745 listed. Windows responds to this call with a
3746 WERR_CAN_NOT_COMPLETE so we should do the same. */
3748 if (name
[0] == '\\' && name
[1] == '\\')
3751 if (is_myname_or_ipaddr(s
))
3752 return WERR_CAN_NOT_COMPLETE
;
3754 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3757 /********************************************************************
3758 * api_spoolss_enumprinters
3760 * called from api_spoolss_enumprinters (see this to understand)
3761 ********************************************************************/
3763 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3767 int n_services
=lp_numservices();
3768 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3769 PRINTER_INFO_2 current_prt
;
3771 for (snum
=0; snum
<n_services
; snum
++) {
3772 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3773 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3775 if (construct_printer_info_2(¤t_prt
, snum
)) {
3776 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3777 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3778 SAFE_FREE(printers
);
3783 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3784 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3790 /* check the required size. */
3791 for (i
=0; i
<*returned
; i
++)
3792 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3794 if (!alloc_buffer_size(buffer
, *needed
)) {
3795 for (i
=0; i
<*returned
; i
++) {
3796 free_devmode(printers
[i
].devmode
);
3798 SAFE_FREE(printers
);
3799 return WERR_INSUFFICIENT_BUFFER
;
3802 /* fill the buffer with the structures */
3803 for (i
=0; i
<*returned
; i
++)
3804 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3807 for (i
=0; i
<*returned
; i
++) {
3808 free_devmode(printers
[i
].devmode
);
3810 SAFE_FREE(printers
);
3812 if (*needed
> offered
) {
3814 return WERR_INSUFFICIENT_BUFFER
;
3820 /********************************************************************
3821 * handle enumeration of printers at level 1
3822 ********************************************************************/
3824 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3825 NEW_BUFFER
*buffer
, uint32 offered
,
3826 uint32
*needed
, uint32
*returned
)
3828 /* Not all the flags are equals */
3830 if (flags
& PRINTER_ENUM_LOCAL
)
3831 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3833 if (flags
& PRINTER_ENUM_NAME
)
3834 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3836 if (flags
& PRINTER_ENUM_REMOTE
)
3837 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3839 if (flags
& PRINTER_ENUM_NETWORK
)
3840 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
3842 return WERR_OK
; /* NT4sp5 does that */
3845 /********************************************************************
3846 * handle enumeration of printers at level 2
3847 ********************************************************************/
3849 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3850 NEW_BUFFER
*buffer
, uint32 offered
,
3851 uint32
*needed
, uint32
*returned
)
3853 char *s
= servername
;
3855 if (flags
& PRINTER_ENUM_LOCAL
) {
3856 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3859 if (flags
& PRINTER_ENUM_NAME
) {
3860 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3862 if (is_myname_or_ipaddr(s
))
3863 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3865 return WERR_INVALID_NAME
;
3868 if (flags
& PRINTER_ENUM_REMOTE
)
3869 return WERR_UNKNOWN_LEVEL
;
3874 /********************************************************************
3875 * handle enumeration of printers at level 5
3876 ********************************************************************/
3878 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3879 NEW_BUFFER
*buffer
, uint32 offered
,
3880 uint32
*needed
, uint32
*returned
)
3882 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3886 /********************************************************************
3887 * api_spoolss_enumprinters
3889 * called from api_spoolss_enumprinters (see this to understand)
3890 ********************************************************************/
3892 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3894 uint32 flags
= q_u
->flags
;
3895 UNISTR2
*servername
= &q_u
->servername
;
3896 uint32 level
= q_u
->level
;
3897 NEW_BUFFER
*buffer
= NULL
;
3898 uint32 offered
= q_u
->offered
;
3899 uint32
*needed
= &r_u
->needed
;
3900 uint32
*returned
= &r_u
->returned
;
3904 /* that's an [in out] buffer */
3905 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3906 buffer
= r_u
->buffer
;
3908 DEBUG(4,("_spoolss_enumprinters\n"));
3915 * flags==PRINTER_ENUM_NAME
3916 * if name=="" then enumerates all printers
3917 * if name!="" then enumerate the printer
3918 * flags==PRINTER_ENUM_REMOTE
3919 * name is NULL, enumerate printers
3920 * Level 2: name!="" enumerates printers, name can't be NULL
3921 * Level 3: doesn't exist
3922 * Level 4: does a local registry lookup
3923 * Level 5: same as Level 2
3926 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
3931 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
3933 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
3935 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
3940 return WERR_UNKNOWN_LEVEL
;
3943 /****************************************************************************
3944 ****************************************************************************/
3946 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3948 PRINTER_INFO_0
*printer
=NULL
;
3950 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
3953 construct_printer_info_0(printer
, snum
);
3955 /* check the required size. */
3956 *needed
+= spoolss_size_printer_info_0(printer
);
3958 if (!alloc_buffer_size(buffer
, *needed
)) {
3960 return WERR_INSUFFICIENT_BUFFER
;
3963 /* fill the buffer with the structures */
3964 smb_io_printer_info_0("", buffer
, printer
, 0);
3969 if (*needed
> offered
) {
3970 return WERR_INSUFFICIENT_BUFFER
;
3976 /****************************************************************************
3977 ****************************************************************************/
3979 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3981 PRINTER_INFO_1
*printer
=NULL
;
3983 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3986 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
3988 /* check the required size. */
3989 *needed
+= spoolss_size_printer_info_1(printer
);
3991 if (!alloc_buffer_size(buffer
, *needed
)) {
3993 return WERR_INSUFFICIENT_BUFFER
;
3996 /* fill the buffer with the structures */
3997 smb_io_printer_info_1("", buffer
, printer
, 0);
4002 if (*needed
> offered
) {
4003 return WERR_INSUFFICIENT_BUFFER
;
4009 /****************************************************************************
4010 ****************************************************************************/
4012 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4014 PRINTER_INFO_2
*printer
=NULL
;
4016 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4019 construct_printer_info_2(printer
, snum
);
4021 /* check the required size. */
4022 *needed
+= spoolss_size_printer_info_2(printer
);
4024 if (!alloc_buffer_size(buffer
, *needed
)) {
4025 free_printer_info_2(printer
);
4026 return WERR_INSUFFICIENT_BUFFER
;
4029 /* fill the buffer with the structures */
4030 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4031 free_printer_info_2(printer
);
4036 free_printer_info_2(printer
);
4038 if (*needed
> offered
) {
4039 return WERR_INSUFFICIENT_BUFFER
;
4045 /****************************************************************************
4046 ****************************************************************************/
4048 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4050 PRINTER_INFO_3
*printer
=NULL
;
4052 if (!construct_printer_info_3(&printer
, snum
))
4055 /* check the required size. */
4056 *needed
+= spoolss_size_printer_info_3(printer
);
4058 if (!alloc_buffer_size(buffer
, *needed
)) {
4059 free_printer_info_3(printer
);
4060 return WERR_INSUFFICIENT_BUFFER
;
4063 /* fill the buffer with the structures */
4064 smb_io_printer_info_3("", buffer
, printer
, 0);
4067 free_printer_info_3(printer
);
4069 if (*needed
> offered
) {
4070 return WERR_INSUFFICIENT_BUFFER
;
4076 /****************************************************************************
4077 ****************************************************************************/
4079 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4081 PRINTER_INFO_4
*printer
=NULL
;
4083 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4086 if (!construct_printer_info_4(printer
, snum
))
4089 /* check the required size. */
4090 *needed
+= spoolss_size_printer_info_4(printer
);
4092 if (!alloc_buffer_size(buffer
, *needed
)) {
4093 free_printer_info_4(printer
);
4094 return WERR_INSUFFICIENT_BUFFER
;
4097 /* fill the buffer with the structures */
4098 smb_io_printer_info_4("", buffer
, printer
, 0);
4101 free_printer_info_4(printer
);
4103 if (*needed
> offered
) {
4104 return WERR_INSUFFICIENT_BUFFER
;
4110 /****************************************************************************
4111 ****************************************************************************/
4113 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4115 PRINTER_INFO_5
*printer
=NULL
;
4117 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4120 if (!construct_printer_info_5(printer
, snum
))
4123 /* check the required size. */
4124 *needed
+= spoolss_size_printer_info_5(printer
);
4126 if (!alloc_buffer_size(buffer
, *needed
)) {
4127 free_printer_info_5(printer
);
4128 return WERR_INSUFFICIENT_BUFFER
;
4131 /* fill the buffer with the structures */
4132 smb_io_printer_info_5("", buffer
, printer
, 0);
4135 free_printer_info_5(printer
);
4137 if (*needed
> offered
) {
4138 return WERR_INSUFFICIENT_BUFFER
;
4144 /****************************************************************************
4145 ****************************************************************************/
4147 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4149 POLICY_HND
*handle
= &q_u
->handle
;
4150 uint32 level
= q_u
->level
;
4151 NEW_BUFFER
*buffer
= NULL
;
4152 uint32 offered
= q_u
->offered
;
4153 uint32
*needed
= &r_u
->needed
;
4157 /* that's an [in out] buffer */
4158 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4159 buffer
= r_u
->buffer
;
4163 if (!get_printer_snum(p
, handle
, &snum
))
4168 return getprinter_level_0(snum
, buffer
, offered
, needed
);
4170 return getprinter_level_1(snum
, buffer
, offered
, needed
);
4172 return getprinter_level_2(snum
, buffer
, offered
, needed
);
4174 return getprinter_level_3(snum
, buffer
, offered
, needed
);
4176 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4178 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4180 return WERR_UNKNOWN_LEVEL
;
4183 /********************************************************************
4184 * fill a DRIVER_INFO_1 struct
4185 ********************************************************************/
4187 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4189 init_unistr( &info
->name
, driver
.info_3
->name
);
4192 /********************************************************************
4193 * construct_printer_driver_info_1
4194 ********************************************************************/
4196 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4198 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4199 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4201 ZERO_STRUCT(driver
);
4203 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4204 return WERR_INVALID_PRINTER_NAME
;
4206 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4207 return WERR_UNKNOWN_PRINTER_DRIVER
;
4209 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4211 free_a_printer(&printer
,2);
4216 /********************************************************************
4217 * construct_printer_driver_info_2
4218 * fill a printer_info_2 struct
4219 ********************************************************************/
4221 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4225 info
->version
=driver
.info_3
->cversion
;
4227 init_unistr( &info
->name
, driver
.info_3
->name
);
4228 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4231 if (strlen(driver
.info_3
->driverpath
)) {
4232 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4233 init_unistr( &info
->driverpath
, temp
);
4235 init_unistr( &info
->driverpath
, "" );
4237 if (strlen(driver
.info_3
->datafile
)) {
4238 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4239 init_unistr( &info
->datafile
, temp
);
4241 init_unistr( &info
->datafile
, "" );
4243 if (strlen(driver
.info_3
->configfile
)) {
4244 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4245 init_unistr( &info
->configfile
, temp
);
4247 init_unistr( &info
->configfile
, "" );
4250 /********************************************************************
4251 * construct_printer_driver_info_2
4252 * fill a printer_info_2 struct
4253 ********************************************************************/
4255 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4257 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4258 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4260 ZERO_STRUCT(printer
);
4261 ZERO_STRUCT(driver
);
4263 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4264 return WERR_INVALID_PRINTER_NAME
;
4266 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4267 return WERR_UNKNOWN_PRINTER_DRIVER
;
4269 fill_printer_driver_info_2(info
, driver
, servername
);
4271 free_a_printer(&printer
,2);
4276 /********************************************************************
4277 * copy a strings array and convert to UNICODE
4279 * convert an array of ascii string to a UNICODE string
4280 ********************************************************************/
4282 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
4290 DEBUG(6,("init_unistr_array\n"));
4294 if (char_array
== NULL
)
4298 if (!v
) v
= ""; /* hack to handle null lists */
4300 if (strlen(v
) == 0) break;
4301 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4302 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4303 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4304 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4308 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, 0)/ sizeof(uint16
));
4313 (*uni_array
)[j
]=0x0000;
4316 DEBUGADD(6,("last one:done\n"));
4319 /********************************************************************
4320 * construct_printer_info_3
4321 * fill a printer_info_3 struct
4322 ********************************************************************/
4324 static void fill_printer_driver_info_3(DRIVER_INFO_3
*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
);
4335 if (strlen(driver
.info_3
->driverpath
)) {
4336 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4337 init_unistr( &info
->driverpath
, temp
);
4339 init_unistr( &info
->driverpath
, "" );
4341 if (strlen(driver
.info_3
->datafile
)) {
4342 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4343 init_unistr( &info
->datafile
, temp
);
4345 init_unistr( &info
->datafile
, "" );
4347 if (strlen(driver
.info_3
->configfile
)) {
4348 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4349 init_unistr( &info
->configfile
, temp
);
4351 init_unistr( &info
->configfile
, "" );
4353 if (strlen(driver
.info_3
->helpfile
)) {
4354 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4355 init_unistr( &info
->helpfile
, temp
);
4357 init_unistr( &info
->helpfile
, "" );
4359 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4360 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4362 info
->dependentfiles
=NULL
;
4363 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4366 /********************************************************************
4367 * construct_printer_info_3
4368 * fill a printer_info_3 struct
4369 ********************************************************************/
4371 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4373 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4374 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4376 ZERO_STRUCT(driver
);
4378 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4379 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4380 if (!W_ERROR_IS_OK(status
))
4381 return WERR_INVALID_PRINTER_NAME
;
4383 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4384 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4389 * I put this code in during testing. Helpful when commenting out the
4390 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4391 * as win2k always queries the driver using an infor level of 6.
4392 * I've left it in (but ifdef'd out) because I'll probably
4393 * use it in experimentation again in the future. --jerry 22/01/2002
4396 if (!W_ERROR_IS_OK(status
)) {
4398 * Is this a W2k client ?
4401 /* Yes - try again with a WinNT driver. */
4403 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4404 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4408 if (!W_ERROR_IS_OK(status
)) {
4409 free_a_printer(&printer
,2);
4410 return WERR_UNKNOWN_PRINTER_DRIVER
;
4418 fill_printer_driver_info_3(info
, driver
, servername
);
4420 free_a_printer(&printer
,2);
4425 /********************************************************************
4426 * construct_printer_info_6
4427 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4428 ********************************************************************/
4430 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4436 memset(&nullstr
, '\0', sizeof(fstring
));
4438 info
->version
=driver
.info_3
->cversion
;
4440 init_unistr( &info
->name
, driver
.info_3
->name
);
4441 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4443 if (strlen(driver
.info_3
->driverpath
)) {
4444 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4445 init_unistr( &info
->driverpath
, temp
);
4447 init_unistr( &info
->driverpath
, "" );
4449 if (strlen(driver
.info_3
->datafile
)) {
4450 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4451 init_unistr( &info
->datafile
, temp
);
4453 init_unistr( &info
->datafile
, "" );
4455 if (strlen(driver
.info_3
->configfile
)) {
4456 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4457 init_unistr( &info
->configfile
, temp
);
4459 init_unistr( &info
->configfile
, "" );
4461 if (strlen(driver
.info_3
->helpfile
)) {
4462 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4463 init_unistr( &info
->helpfile
, temp
);
4465 init_unistr( &info
->helpfile
, "" );
4467 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4468 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4470 info
->dependentfiles
=NULL
;
4471 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4473 info
->previousdrivernames
=NULL
;
4474 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
4476 info
->driver_date
.low
=0;
4477 info
->driver_date
.high
=0;
4480 info
->driver_version_low
=0;
4481 info
->driver_version_high
=0;
4483 init_unistr( &info
->mfgname
, "");
4484 init_unistr( &info
->oem_url
, "");
4485 init_unistr( &info
->hardware_id
, "");
4486 init_unistr( &info
->provider
, "");
4489 /********************************************************************
4490 * construct_printer_info_6
4491 * fill a printer_info_6 struct
4492 ********************************************************************/
4494 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4496 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4497 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4499 ZERO_STRUCT(driver
);
4501 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4502 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4503 if (!W_ERROR_IS_OK(status
))
4504 return WERR_INVALID_PRINTER_NAME
;
4506 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4507 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4508 if (!W_ERROR_IS_OK(status
)) {
4510 * Is this a W2k client ?
4514 free_a_printer(&printer
,2);
4515 return WERR_UNKNOWN_PRINTER_DRIVER
;
4518 /* Yes - try again with a WinNT driver. */
4520 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4521 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4522 if (!W_ERROR_IS_OK(status
)) {
4523 free_a_printer(&printer
,2);
4524 return WERR_UNKNOWN_PRINTER_DRIVER
;
4528 fill_printer_driver_info_6(info
, driver
, servername
);
4530 free_a_printer(&printer
,2);
4535 /****************************************************************************
4536 ****************************************************************************/
4538 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
4540 SAFE_FREE(info
->dependentfiles
);
4543 /****************************************************************************
4544 ****************************************************************************/
4546 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
4548 SAFE_FREE(info
->dependentfiles
);
4552 /****************************************************************************
4553 ****************************************************************************/
4555 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4557 DRIVER_INFO_1
*info
=NULL
;
4560 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
4563 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
4564 if (!W_ERROR_IS_OK(status
)) {
4569 /* check the required size. */
4570 *needed
+= spoolss_size_printer_driver_info_1(info
);
4572 if (!alloc_buffer_size(buffer
, *needed
)) {
4574 return WERR_INSUFFICIENT_BUFFER
;
4577 /* fill the buffer with the structures */
4578 smb_io_printer_driver_info_1("", buffer
, info
, 0);
4583 if (*needed
> offered
)
4584 return WERR_INSUFFICIENT_BUFFER
;
4589 /****************************************************************************
4590 ****************************************************************************/
4592 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4594 DRIVER_INFO_2
*info
=NULL
;
4597 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
4600 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
4601 if (!W_ERROR_IS_OK(status
)) {
4606 /* check the required size. */
4607 *needed
+= spoolss_size_printer_driver_info_2(info
);
4609 if (!alloc_buffer_size(buffer
, *needed
)) {
4611 return WERR_INSUFFICIENT_BUFFER
;
4614 /* fill the buffer with the structures */
4615 smb_io_printer_driver_info_2("", buffer
, info
, 0);
4620 if (*needed
> offered
)
4621 return WERR_INSUFFICIENT_BUFFER
;
4626 /****************************************************************************
4627 ****************************************************************************/
4629 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4636 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
4637 if (!W_ERROR_IS_OK(status
)) {
4641 /* check the required size. */
4642 *needed
+= spoolss_size_printer_driver_info_3(&info
);
4644 if (!alloc_buffer_size(buffer
, *needed
)) {
4645 free_printer_driver_info_3(&info
);
4646 return WERR_INSUFFICIENT_BUFFER
;
4649 /* fill the buffer with the structures */
4650 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
4652 free_printer_driver_info_3(&info
);
4654 if (*needed
> offered
)
4655 return WERR_INSUFFICIENT_BUFFER
;
4660 /****************************************************************************
4661 ****************************************************************************/
4663 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4670 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
4671 if (!W_ERROR_IS_OK(status
)) {
4675 /* check the required size. */
4676 *needed
+= spoolss_size_printer_driver_info_6(&info
);
4678 if (!alloc_buffer_size(buffer
, *needed
)) {
4679 free_printer_driver_info_6(&info
);
4680 return WERR_INSUFFICIENT_BUFFER
;
4683 /* fill the buffer with the structures */
4684 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
4686 free_printer_driver_info_6(&info
);
4688 if (*needed
> offered
)
4689 return WERR_INSUFFICIENT_BUFFER
;
4694 /****************************************************************************
4695 ****************************************************************************/
4697 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
4699 POLICY_HND
*handle
= &q_u
->handle
;
4700 UNISTR2
*uni_arch
= &q_u
->architecture
;
4701 uint32 level
= q_u
->level
;
4702 uint32 clientmajorversion
= q_u
->clientmajorversion
;
4703 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4704 NEW_BUFFER
*buffer
= NULL
;
4705 uint32 offered
= q_u
->offered
;
4706 uint32
*needed
= &r_u
->needed
;
4707 uint32
*servermajorversion
= &r_u
->servermajorversion
;
4708 uint32
*serverminorversion
= &r_u
->serverminorversion
;
4711 fstring architecture
;
4714 /* that's an [in out] buffer */
4715 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4716 buffer
= r_u
->buffer
;
4718 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4721 *servermajorversion
=0;
4722 *serverminorversion
=0;
4724 pstrcpy(servername
, get_called_name());
4725 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
4727 if (!get_printer_snum(p
, handle
, &snum
))
4732 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4734 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4736 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4738 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4741 return WERR_UNKNOWN_LEVEL
;
4744 /****************************************************************************
4745 ****************************************************************************/
4747 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
4749 POLICY_HND
*handle
= &q_u
->handle
;
4751 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4754 DEBUG(3,("Error in startpageprinter printer handle\n"));
4758 Printer
->page_started
=True
;
4762 /****************************************************************************
4763 ****************************************************************************/
4765 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
4767 POLICY_HND
*handle
= &q_u
->handle
;
4769 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4772 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
4776 Printer
->page_started
=False
;
4777 print_job_endpage(Printer
->jobid
);
4782 /********************************************************************
4783 * api_spoolss_getprinter
4784 * called from the spoolss dispatcher
4786 ********************************************************************/
4788 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
4790 POLICY_HND
*handle
= &q_u
->handle
;
4791 /* uint32 level = q_u->doc_info_container.level; - notused. */
4792 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
4793 uint32
*jobid
= &r_u
->jobid
;
4795 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
4799 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4800 struct current_user user
;
4803 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4807 get_current_user(&user
, p
);
4810 * a nice thing with NT is it doesn't listen to what you tell it.
4811 * when asked to send _only_ RAW datas, it tries to send datas
4814 * So I add checks like in NT Server ...
4816 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4817 * there's a bug in NT client-side code, so we'll fix it in the
4818 * server-side code. *nnnnnggggh!*
4821 if (info_1
->p_datatype
!= 0) {
4822 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
4823 if (strcmp(datatype
, "RAW") != 0) {
4825 return WERR_INVALID_DATATYPE
;
4829 /* get the share number of the printer */
4830 if (!get_printer_snum(p
, handle
, &snum
)) {
4834 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
4836 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4838 /* An error occured in print_job_start() so return an appropriate
4841 if (Printer
->jobid
== -1) {
4842 return map_werror_from_unix(errno
);
4845 Printer
->document_started
=True
;
4846 (*jobid
) = Printer
->jobid
;
4851 /********************************************************************
4852 * api_spoolss_getprinter
4853 * called from the spoolss dispatcher
4855 ********************************************************************/
4857 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4859 POLICY_HND
*handle
= &q_u
->handle
;
4861 return _spoolss_enddocprinter_internal(p
, handle
);
4864 /****************************************************************************
4865 ****************************************************************************/
4867 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4869 POLICY_HND
*handle
= &q_u
->handle
;
4870 uint32 buffer_size
= q_u
->buffer_size
;
4871 uint8
*buffer
= q_u
->buffer
;
4872 uint32
*buffer_written
= &q_u
->buffer_size2
;
4874 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4877 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
4878 r_u
->buffer_written
= q_u
->buffer_size2
;
4882 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
, buffer_size
);
4885 r_u
->buffer_written
= q_u
->buffer_size2
;
4890 /********************************************************************
4891 * api_spoolss_getprinter
4892 * called from the spoolss dispatcher
4894 ********************************************************************/
4896 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
4899 struct current_user user
;
4901 WERROR errcode
= WERR_BADFUNC
;
4902 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4904 get_current_user(&user
, p
);
4907 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4911 if (!get_printer_snum(p
, handle
, &snum
))
4915 case PRINTER_CONTROL_PAUSE
:
4916 if (print_queue_pause(&user
, snum
, &errcode
)) {
4920 case PRINTER_CONTROL_RESUME
:
4921 case PRINTER_CONTROL_UNPAUSE
:
4922 if (print_queue_resume(&user
, snum
, &errcode
)) {
4926 case PRINTER_CONTROL_PURGE
:
4927 if (print_queue_purge(&user
, snum
, &errcode
)) {
4932 return WERR_UNKNOWN_LEVEL
;
4938 /********************************************************************
4939 * api_spoolss_abortprinter
4940 ********************************************************************/
4942 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
4944 POLICY_HND
*handle
= &q_u
->handle
;
4946 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
4949 /********************************************************************
4950 * called by spoolss_api_setprinter
4951 * when updating a printer description
4952 ********************************************************************/
4954 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
4955 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4956 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
4958 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
4959 struct current_user user
;
4963 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4965 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
4966 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4967 OUR_HANDLE(handle
)));
4969 result
= WERR_BADFID
;
4973 /* NT seems to like setting the security descriptor even though
4974 nothing may have actually changed. This causes annoying
4975 dialog boxes when the user doesn't have permission to change
4976 the security descriptor. */
4978 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
4980 if (DEBUGLEVEL
>= 10) {
4984 the_acl
= old_secdesc_ctr
->sec
->dacl
;
4985 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4986 PRINTERNAME(snum
), the_acl
->num_aces
));
4988 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4991 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4993 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4994 the_acl
->ace
[i
].info
.mask
));
4997 the_acl
= secdesc_ctr
->sec
->dacl
;
5000 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5001 PRINTERNAME(snum
), the_acl
->num_aces
));
5003 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5006 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5008 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5009 the_acl
->ace
[i
].info
.mask
));
5012 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5016 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5018 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5023 /* Work out which user is performing the operation */
5025 get_current_user(&user
, p
);
5027 /* Check the user has permissions to change the security
5028 descriptor. By experimentation with two NT machines, the user
5029 requires Full Access to the printer to change security
5032 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5033 result
= WERR_ACCESS_DENIED
;
5037 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
5044 /********************************************************************
5045 Do Samba sanity checks on a printer info struct.
5046 this has changed purpose: it now "canonicalises" printer
5047 info from a client rather than just checking it is correct
5048 ********************************************************************/
5050 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5052 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
5053 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5055 /* we force some elements to "correct" values */
5056 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
5057 fstrcpy(info
->sharename
, lp_servicename(snum
));
5058 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5059 get_called_name(), info
->sharename
);
5060 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
5065 /****************************************************************************
5066 ****************************************************************************/
5068 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5070 extern userdom_struct current_user_info
;
5071 char *cmd
= lp_addprinter_cmd();
5074 pstring driverlocation
;
5078 fstring remote_machine
= "%m";
5080 /* build driver path... only 9X architecture is needed for legacy reasons */
5081 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
5083 /* change \ to \\ for the shell */
5084 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
5085 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
5087 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5088 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5089 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5090 printer
->info_2
->location
, driverlocation
, remote_machine
);
5092 DEBUG(10,("Running [%s]\n", command
));
5093 ret
= smbrun(command
, &fd
);
5094 DEBUGADD(10,("returned [%d]\n", ret
));
5103 /* Get lines and convert them back to dos-codepage */
5104 qlines
= fd_lines_load(fd
, &numlines
);
5105 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5109 /* Set the portname to what the script says the portname should be. */
5110 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5111 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5113 /* Send SIGHUP to process group... is there a better way? */
5118 file_lines_free(qlines
);
5124 /* Return true if two devicemodes are equal */
5126 #define DEVMODE_CHECK_INT(field) \
5127 if (d1->field != d2->field) { \
5128 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
5129 d1->field, d2->field)); \
5133 /************************************************************************
5134 Handy, but currently unused functions
5135 ***********************************************************************/
5137 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
5139 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
5142 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
5143 return False
; /* if either is exclusively NULL are not equal */
5146 if (!strequal(d1
->devicename
, d2
->devicename
)) {
5147 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1
->devicename
, d2
->devicename
));
5151 if (!strequal(d1
->formname
, d2
->formname
)) {
5152 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1
->formname
, d2
->formname
));
5156 DEVMODE_CHECK_INT(specversion
);
5157 DEVMODE_CHECK_INT(driverversion
);
5158 DEVMODE_CHECK_INT(driverextra
);
5159 DEVMODE_CHECK_INT(orientation
);
5160 DEVMODE_CHECK_INT(papersize
);
5161 DEVMODE_CHECK_INT(paperlength
);
5162 DEVMODE_CHECK_INT(paperwidth
);
5163 DEVMODE_CHECK_INT(scale
);
5164 DEVMODE_CHECK_INT(copies
);
5165 DEVMODE_CHECK_INT(defaultsource
);
5166 DEVMODE_CHECK_INT(printquality
);
5167 DEVMODE_CHECK_INT(color
);
5168 DEVMODE_CHECK_INT(duplex
);
5169 DEVMODE_CHECK_INT(yresolution
);
5170 DEVMODE_CHECK_INT(ttoption
);
5171 DEVMODE_CHECK_INT(collate
);
5172 DEVMODE_CHECK_INT(logpixels
);
5174 DEVMODE_CHECK_INT(fields
);
5175 DEVMODE_CHECK_INT(bitsperpel
);
5176 DEVMODE_CHECK_INT(pelswidth
);
5177 DEVMODE_CHECK_INT(pelsheight
);
5178 DEVMODE_CHECK_INT(displayflags
);
5179 DEVMODE_CHECK_INT(displayfrequency
);
5180 DEVMODE_CHECK_INT(icmmethod
);
5181 DEVMODE_CHECK_INT(icmintent
);
5182 DEVMODE_CHECK_INT(mediatype
);
5183 DEVMODE_CHECK_INT(dithertype
);
5184 DEVMODE_CHECK_INT(reserved1
);
5185 DEVMODE_CHECK_INT(reserved2
);
5186 DEVMODE_CHECK_INT(panningwidth
);
5187 DEVMODE_CHECK_INT(panningheight
);
5189 /* compare the private data if it exists */
5190 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
5193 DEVMODE_CHECK_INT(driverextra
);
5195 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
5196 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5201 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5205 /* Return true if two NT_PRINTER_PARAM structures are equal */
5207 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
5208 NT_PRINTER_PARAM
*p2
)
5210 if (!p1
&& !p2
) goto equal
;
5212 if ((!p1
&& p2
) || (p1
&& !p2
)) {
5213 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5217 /* Compare lists of printer parameters */
5221 NT_PRINTER_PARAM
*q
= p1
;
5223 /* Find the parameter in the second structure */
5227 if (strequal(p1
->value
, q
->value
)) {
5229 if (p1
->type
!= q
->type
) {
5230 DEBUG(10, ("nt_printer_param_equal():"
5231 "types for %s differ (%d != %d)\n",
5232 p1
->value
, p1
->type
,
5237 if (p1
->data_len
!= q
->data_len
) {
5238 DEBUG(10, ("nt_printer_param_equal():"
5239 "len for %s differs (%d != %d)\n",
5240 p1
->value
, p1
->data_len
,
5245 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
5248 DEBUG(10, ("nt_printer_param_equal():"
5249 "data for %s differs\n", p1
->value
));
5259 DEBUG(10, ("nt_printer_param_equal(): param %s "
5260 "does not exist\n", p1
->value
));
5269 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5273 /********************************************************************
5274 * Called by update_printer when trying to work out whether to
5275 * actually update printer info.
5276 ********************************************************************/
5278 #define PI_CHECK_INT(field) \
5279 if (pi1->field != pi2->field) { \
5280 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5281 pi1->field, pi2->field)); \
5285 #define PI_CHECK_STR(field) \
5286 if (!strequal(pi1->field, pi2->field)) { \
5287 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5288 pi1->field, pi2->field)); \
5292 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
5293 NT_PRINTER_INFO_LEVEL
*p2
)
5295 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
5297 /* Trivial conditions */
5299 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
5303 if ((!p1
&& p2
) || (p1
&& !p2
) ||
5304 (!p1
->info_2
&& p2
->info_2
) ||
5305 (p1
->info_2
&& !p2
->info_2
)) {
5306 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5311 /* Compare two nt_printer_info_level structures. Don't compare
5312 status or cjobs as they seem to have something to do with the
5318 /* Don't check the attributes as we stomp on the value in
5319 check_printer_ok() anyway. */
5322 PI_CHECK_INT(attributes
);
5325 PI_CHECK_INT(priority
);
5326 PI_CHECK_INT(default_priority
);
5327 PI_CHECK_INT(starttime
);
5328 PI_CHECK_INT(untiltime
);
5329 PI_CHECK_INT(averageppm
);
5331 /* Yuck - don't check the printername or servername as the
5332 mod_a_printer() code plays games with them. You can't
5333 change the printername or the sharename through this interface
5336 PI_CHECK_STR(sharename
);
5337 PI_CHECK_STR(portname
);
5338 PI_CHECK_STR(drivername
);
5339 PI_CHECK_STR(comment
);
5340 PI_CHECK_STR(location
);
5342 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
5346 PI_CHECK_STR(sepfile
);
5347 PI_CHECK_STR(printprocessor
);
5348 PI_CHECK_STR(datatype
);
5349 PI_CHECK_STR(parameters
);
5351 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
5355 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
5359 PI_CHECK_INT(changeid
);
5360 PI_CHECK_INT(c_setprinter
);
5361 PI_CHECK_INT(setuptime
);
5364 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5370 /********************************************************************
5371 * Called by spoolss_api_setprinter
5372 * when updating a printer description.
5373 ********************************************************************/
5375 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5376 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5377 DEVICEMODE
*devmode
)
5380 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5381 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5384 DEBUG(8,("update_printer\n"));
5389 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5390 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5391 result
= WERR_UNKNOWN_LEVEL
;
5396 result
= WERR_BADFID
;
5400 if (!get_printer_snum(p
, handle
, &snum
)) {
5401 result
= WERR_BADFID
;
5405 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5406 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5407 result
= WERR_BADFID
;
5411 DEBUGADD(8,("Converting info_2 struct\n"));
5414 * convert_printer_info converts the incoming
5415 * info from the client and overwrites the info
5416 * just read from the tdb in the pointer 'printer'.
5419 if (!convert_printer_info(info
, printer
, level
)) {
5420 result
= WERR_NOMEM
;
5425 /* we have a valid devmode
5426 convert it and link it*/
5428 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5429 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5430 &printer
->info_2
->devmode
)) {
5431 result
= WERR_NOMEM
;
5436 /* Do sanity check on the requested changes for Samba */
5438 if (!check_printer_ok(printer
->info_2
, snum
)) {
5439 result
= WERR_INVALID_PARAM
;
5446 * Another one of those historical misunderstandings...
5447 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5448 * I'm leaving it here as a reminder. --jerry
5451 if (nt_printer_info_level_equal(printer
, old_printer
)) {
5452 DEBUG(3, ("update_printer: printer info has not changed\n"));
5459 /* Check calling user has permission to update printer description */
5461 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5462 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5463 result
= WERR_ACCESS_DENIED
;
5467 /* Call addprinter hook */
5469 if (*lp_addprinter_cmd()) {
5470 if ( !add_printer_hook(printer
) ) {
5471 result
= WERR_ACCESS_DENIED
;
5477 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5478 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5479 * requires Win32 client code (see other notes elsewhere in the code).
5481 if (printer
->info_2
->devmode
&&
5482 printer
->info_2
->devmode
->displayfrequency
== MAGIC_DISPLAY_FREQUENCY
) {
5484 DEBUG(10,("update_printer: Save printer driver init data\n"));
5485 printer
->info_2
->devmode
->displayfrequency
= 0;
5487 if (update_driver_init(*printer
, 2)!=0) {
5488 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5489 result
= WERR_ACCESS_DENIED
;
5494 * When a *new* driver is bound to a printer, the drivername is used to
5495 * lookup previously saved driver initialization info, which is then
5496 * bound to the printer, simulating what happens in the Windows arch.
5498 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)){
5499 if (!set_driver_init(printer
, 2)) {
5500 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5501 printer
->info_2
->drivername
));
5503 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5507 /* Update printer info */
5508 result
= mod_a_printer(*printer
, 2);
5510 /* flag which changes actually occured. This is a small subset of
5511 all the possible changes */
5513 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5514 notify_printer_comment(snum
, printer
->info_2
->comment
);
5516 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5517 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5519 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5520 notify_printer_port(snum
, printer
->info_2
->portname
);
5522 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5523 notify_printer_location(snum
, printer
->info_2
->location
);
5526 free_a_printer(&printer
, 2);
5527 free_a_printer(&old_printer
, 2);
5533 /****************************************************************************
5534 ****************************************************************************/
5536 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5538 POLICY_HND
*handle
= &q_u
->handle
;
5539 uint32 level
= q_u
->level
;
5540 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5541 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5542 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5543 uint32 command
= q_u
->command
;
5545 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5548 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5552 /* check the level */
5555 return control_printer(handle
, command
, p
);
5557 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
5559 return update_printer_sec(handle
, level
, info
, p
,
5562 return WERR_UNKNOWN_LEVEL
;
5566 /****************************************************************************
5567 ****************************************************************************/
5569 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
5571 POLICY_HND
*handle
= &q_u
->handle
;
5573 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5576 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5580 if (Printer
->notify
.client_connected
==True
)
5581 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
5583 Printer
->notify
.flags
=0;
5584 Printer
->notify
.options
=0;
5585 Printer
->notify
.localmachine
[0]='\0';
5586 Printer
->notify
.printerlocal
=0;
5587 if (Printer
->notify
.option
)
5588 free_spool_notify_option(&Printer
->notify
.option
);
5589 Printer
->notify
.client_connected
=False
;
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
5599 /* that's an [in out] buffer (despite appearences to the contrary) */
5600 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5603 return WERR_INVALID_PARAM
; /* this is what a NT server
5604 returns for AddJob. AddJob
5605 must fail on non-local
5609 /****************************************************************************
5610 ****************************************************************************/
5612 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
5613 int position
, int snum
)
5619 t
=gmtime(&queue
->time
);
5620 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5622 job_info
->jobid
=queue
->job
;
5623 init_unistr(&job_info
->printername
, lp_servicename(snum
));
5624 init_unistr(&job_info
->machinename
, temp_name
);
5625 init_unistr(&job_info
->username
, queue
->fs_user
);
5626 init_unistr(&job_info
->document
, queue
->fs_file
);
5627 init_unistr(&job_info
->datatype
, "RAW");
5628 init_unistr(&job_info
->text_status
, "");
5629 job_info
->status
=nt_printj_status(queue
->status
);
5630 job_info
->priority
=queue
->priority
;
5631 job_info
->position
=position
;
5632 job_info
->totalpages
=queue
->page_count
;
5633 job_info
->pagesprinted
=0;
5635 make_systemtime(&job_info
->submitted
, t
);
5638 /****************************************************************************
5639 ****************************************************************************/
5641 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
5642 int position
, int snum
,
5643 NT_PRINTER_INFO_LEVEL
*ntprinter
,
5644 DEVICEMODE
*devmode
)
5650 t
=gmtime(&queue
->time
);
5651 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5653 job_info
->jobid
=queue
->job
;
5655 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
5657 init_unistr(&job_info
->printername
, chaine
);
5659 init_unistr(&job_info
->machinename
, temp_name
);
5660 init_unistr(&job_info
->username
, queue
->fs_user
);
5661 init_unistr(&job_info
->document
, queue
->fs_file
);
5662 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
5663 init_unistr(&job_info
->datatype
, "RAW");
5664 init_unistr(&job_info
->printprocessor
, "winprint");
5665 init_unistr(&job_info
->parameters
, "");
5666 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
5667 init_unistr(&job_info
->text_status
, "");
5669 /* and here the security descriptor */
5671 job_info
->status
=nt_printj_status(queue
->status
);
5672 job_info
->priority
=queue
->priority
;
5673 job_info
->position
=position
;
5674 job_info
->starttime
=0;
5675 job_info
->untiltime
=0;
5676 job_info
->totalpages
=queue
->page_count
;
5677 job_info
->size
=queue
->size
;
5678 make_systemtime(&(job_info
->submitted
), t
);
5679 job_info
->timeelapsed
=0;
5680 job_info
->pagesprinted
=0;
5682 job_info
->devmode
= devmode
;
5687 /****************************************************************************
5688 Enumjobs at level 1.
5689 ****************************************************************************/
5691 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
5692 NEW_BUFFER
*buffer
, uint32 offered
,
5693 uint32
*needed
, uint32
*returned
)
5698 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
5705 for (i
=0; i
<*returned
; i
++)
5706 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
5710 /* check the required size. */
5711 for (i
=0; i
<*returned
; i
++)
5712 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
5714 if (!alloc_buffer_size(buffer
, *needed
)) {
5716 return WERR_INSUFFICIENT_BUFFER
;
5719 /* fill the buffer with the structures */
5720 for (i
=0; i
<*returned
; i
++)
5721 smb_io_job_info_1("", buffer
, &info
[i
], 0);
5726 if (*needed
> offered
) {
5728 return WERR_INSUFFICIENT_BUFFER
;
5734 /****************************************************************************
5735 Enumjobs at level 2.
5736 ****************************************************************************/
5738 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
5739 NEW_BUFFER
*buffer
, uint32 offered
,
5740 uint32
*needed
, uint32
*returned
)
5742 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
5743 JOB_INFO_2
*info
= NULL
;
5746 DEVICEMODE
*devmode
= NULL
;
5748 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
5751 result
= WERR_NOMEM
;
5755 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
5756 if (!W_ERROR_IS_OK(result
)) {
5761 if (!(devmode
= construct_dev_mode(snum
))) {
5763 result
= WERR_NOMEM
;
5767 for (i
=0; i
<*returned
; i
++)
5768 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
5771 free_a_printer(&ntprinter
, 2);
5774 /* check the required size. */
5775 for (i
=0; i
<*returned
; i
++)
5776 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
5778 if (*needed
> offered
) {
5780 result
= WERR_INSUFFICIENT_BUFFER
;
5784 if (!alloc_buffer_size(buffer
, *needed
)) {
5786 result
= WERR_INSUFFICIENT_BUFFER
;
5790 /* fill the buffer with the structures */
5791 for (i
=0; i
<*returned
; i
++)
5792 smb_io_job_info_2("", buffer
, &info
[i
], 0);
5797 free_a_printer(&ntprinter
, 2);
5798 free_devmode(devmode
);
5806 /****************************************************************************
5808 ****************************************************************************/
5810 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
5812 POLICY_HND
*handle
= &q_u
->handle
;
5813 /* uint32 firstjob = q_u->firstjob; - notused. */
5814 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5815 uint32 level
= q_u
->level
;
5816 NEW_BUFFER
*buffer
= NULL
;
5817 uint32 offered
= q_u
->offered
;
5818 uint32
*needed
= &r_u
->needed
;
5819 uint32
*returned
= &r_u
->returned
;
5822 print_status_struct prt_status
;
5823 print_queue_struct
*queue
=NULL
;
5825 /* that's an [in out] buffer */
5826 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5827 buffer
= r_u
->buffer
;
5829 DEBUG(4,("_spoolss_enumjobs\n"));
5834 if (!get_printer_snum(p
, handle
, &snum
))
5837 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
5838 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
5840 if (*returned
== 0) {
5847 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
5849 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
5853 return WERR_UNKNOWN_LEVEL
;
5857 /****************************************************************************
5858 ****************************************************************************/
5860 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
5865 /****************************************************************************
5866 ****************************************************************************/
5868 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
5870 POLICY_HND
*handle
= &q_u
->handle
;
5871 uint32 jobid
= q_u
->jobid
;
5872 /* uint32 level = q_u->level; - notused. */
5873 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5874 uint32 command
= q_u
->command
;
5876 struct current_user user
;
5878 WERROR errcode
= WERR_BADFUNC
;
5880 if (!get_printer_snum(p
, handle
, &snum
)) {
5884 if (!print_job_exists(jobid
)) {
5885 return WERR_INVALID_PRINTER_NAME
;
5888 get_current_user(&user
, p
);
5891 case JOB_CONTROL_CANCEL
:
5892 case JOB_CONTROL_DELETE
:
5893 if (print_job_delete(&user
, jobid
, &errcode
)) {
5897 case JOB_CONTROL_PAUSE
:
5898 if (print_job_pause(&user
, jobid
, &errcode
)) {
5902 case JOB_CONTROL_RESTART
:
5903 case JOB_CONTROL_RESUME
:
5904 if (print_job_resume(&user
, jobid
, &errcode
)) {
5909 return WERR_UNKNOWN_LEVEL
;
5915 /****************************************************************************
5916 Enumerates all printer drivers at level 1.
5917 ****************************************************************************/
5919 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5924 fstring
*list
= NULL
;
5926 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5927 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5931 #define MAX_VERSION 4
5933 for (version
=0; version
<MAX_VERSION
; version
++) {
5935 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5936 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5942 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5943 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5944 SAFE_FREE(driver_info_1
);
5948 else driver_info_1
= tdi1
;
5951 for (i
=0; i
<ndrivers
; i
++) {
5953 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5954 ZERO_STRUCT(driver
);
5955 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5956 architecture
, version
);
5957 if (!W_ERROR_IS_OK(status
)) {
5961 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5962 free_a_printer_driver(driver
, 3);
5965 *returned
+=ndrivers
;
5969 /* check the required size. */
5970 for (i
=0; i
<*returned
; i
++) {
5971 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5972 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5975 if (!alloc_buffer_size(buffer
, *needed
)) {
5976 SAFE_FREE(driver_info_1
);
5977 return WERR_INSUFFICIENT_BUFFER
;
5980 /* fill the buffer with the driver structures */
5981 for (i
=0; i
<*returned
; i
++) {
5982 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5983 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5986 SAFE_FREE(driver_info_1
);
5988 if (*needed
> offered
) {
5990 return WERR_INSUFFICIENT_BUFFER
;
5996 /****************************************************************************
5997 Enumerates all printer drivers at level 2.
5998 ****************************************************************************/
6000 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6005 fstring
*list
= NULL
;
6007 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6008 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6012 #define MAX_VERSION 4
6014 for (version
=0; version
<MAX_VERSION
; version
++) {
6016 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6017 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6023 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6024 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6025 SAFE_FREE(driver_info_2
);
6029 else driver_info_2
= tdi2
;
6032 for (i
=0; i
<ndrivers
; i
++) {
6035 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6036 ZERO_STRUCT(driver
);
6037 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6038 architecture
, version
);
6039 if (!W_ERROR_IS_OK(status
)) {
6043 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6044 free_a_printer_driver(driver
, 3);
6047 *returned
+=ndrivers
;
6051 /* check the required size. */
6052 for (i
=0; i
<*returned
; i
++) {
6053 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6054 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6057 if (!alloc_buffer_size(buffer
, *needed
)) {
6058 SAFE_FREE(driver_info_2
);
6059 return WERR_INSUFFICIENT_BUFFER
;
6062 /* fill the buffer with the form structures */
6063 for (i
=0; i
<*returned
; i
++) {
6064 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6065 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6068 SAFE_FREE(driver_info_2
);
6070 if (*needed
> offered
) {
6072 return WERR_INSUFFICIENT_BUFFER
;
6078 /****************************************************************************
6079 Enumerates all printer drivers at level 3.
6080 ****************************************************************************/
6082 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6087 fstring
*list
= NULL
;
6089 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6090 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6094 #define MAX_VERSION 4
6096 for (version
=0; version
<MAX_VERSION
; version
++) {
6098 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6099 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6105 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6106 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6107 SAFE_FREE(driver_info_3
);
6111 else driver_info_3
= tdi3
;
6114 for (i
=0; i
<ndrivers
; i
++) {
6117 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6118 ZERO_STRUCT(driver
);
6119 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6120 architecture
, version
);
6121 if (!W_ERROR_IS_OK(status
)) {
6125 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6126 free_a_printer_driver(driver
, 3);
6129 *returned
+=ndrivers
;
6133 /* check the required size. */
6134 for (i
=0; i
<*returned
; i
++) {
6135 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6136 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6139 if (!alloc_buffer_size(buffer
, *needed
)) {
6140 SAFE_FREE(driver_info_3
);
6141 return WERR_INSUFFICIENT_BUFFER
;
6144 /* fill the buffer with the driver structures */
6145 for (i
=0; i
<*returned
; i
++) {
6146 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6147 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6150 for (i
=0; i
<*returned
; i
++)
6151 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6153 SAFE_FREE(driver_info_3
);
6155 if (*needed
> offered
) {
6157 return WERR_INSUFFICIENT_BUFFER
;
6163 /****************************************************************************
6164 Enumerates all printer drivers.
6165 ****************************************************************************/
6167 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6169 /* UNISTR2 *name = &q_u->name; - notused. */
6170 UNISTR2
*environment
= &q_u
->environment
;
6171 uint32 level
= q_u
->level
;
6172 NEW_BUFFER
*buffer
= NULL
;
6173 uint32 offered
= q_u
->offered
;
6174 uint32
*needed
= &r_u
->needed
;
6175 uint32
*returned
= &r_u
->returned
;
6177 fstring
*list
= NULL
;
6179 fstring architecture
;
6181 /* that's an [in out] buffer */
6182 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6183 buffer
= r_u
->buffer
;
6185 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6186 fstrcpy(servername
, get_called_name());
6190 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
6194 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6196 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6198 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6202 return WERR_UNKNOWN_LEVEL
;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6211 form
->flag
=list
->flag
;
6212 init_unistr(&form
->name
, list
->name
);
6213 form
->width
=list
->width
;
6214 form
->length
=list
->length
;
6215 form
->left
=list
->left
;
6216 form
->top
=list
->top
;
6217 form
->right
=list
->right
;
6218 form
->bottom
=list
->bottom
;
6221 /****************************************************************************
6222 ****************************************************************************/
6224 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6226 /* POLICY_HND *handle = &q_u->handle; - notused. */
6227 uint32 level
= q_u
->level
;
6228 NEW_BUFFER
*buffer
= NULL
;
6229 uint32 offered
= q_u
->offered
;
6230 uint32
*needed
= &r_u
->needed
;
6231 uint32
*numofforms
= &r_u
->numofforms
;
6232 uint32 numbuiltinforms
;
6234 nt_forms_struct
*list
=NULL
;
6235 nt_forms_struct
*builtinlist
=NULL
;
6240 /* that's an [in out] buffer */
6241 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6242 buffer
= r_u
->buffer
;
6244 DEBUG(4,("_spoolss_enumforms\n"));
6245 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6246 DEBUGADD(5,("Info level [%d]\n", level
));
6248 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6249 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6250 *numofforms
= get_ntforms(&list
);
6251 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6252 *numofforms
+= numbuiltinforms
;
6254 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6258 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6263 /* construct the list of form structures */
6264 for (i
=0; i
<numbuiltinforms
; i
++) {
6265 DEBUGADD(6,("Filling form number [%d]\n",i
));
6266 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6269 SAFE_FREE(builtinlist
);
6271 for (; i
<*numofforms
; i
++) {
6272 DEBUGADD(6,("Filling form number [%d]\n",i
));
6273 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6278 /* check the required size. */
6279 for (i
=0; i
<numbuiltinforms
; i
++) {
6280 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6281 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6283 for (; i
<*numofforms
; i
++) {
6284 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6285 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6288 *needed
=buffer_size
;
6290 if (!alloc_buffer_size(buffer
, buffer_size
)){
6292 return WERR_INSUFFICIENT_BUFFER
;
6295 /* fill the buffer with the form structures */
6296 for (i
=0; i
<numbuiltinforms
; i
++) {
6297 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6298 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6300 for (; i
<*numofforms
; i
++) {
6301 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6302 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6307 if (*needed
> offered
) {
6309 return WERR_INSUFFICIENT_BUFFER
;
6316 SAFE_FREE(builtinlist
);
6317 return WERR_UNKNOWN_LEVEL
;
6322 /****************************************************************************
6323 ****************************************************************************/
6325 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6327 /* POLICY_HND *handle = &q_u->handle; - notused. */
6328 uint32 level
= q_u
->level
;
6329 UNISTR2
*uni_formname
= &q_u
->formname
;
6330 NEW_BUFFER
*buffer
= NULL
;
6331 uint32 offered
= q_u
->offered
;
6332 uint32
*needed
= &r_u
->needed
;
6334 nt_forms_struct
*list
=NULL
;
6335 nt_forms_struct builtin_form
;
6340 int numofforms
=0, i
=0;
6342 /* that's an [in out] buffer */
6343 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6344 buffer
= r_u
->buffer
;
6346 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6348 DEBUG(4,("_spoolss_getform\n"));
6349 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6350 DEBUGADD(5,("Info level [%d]\n", level
));
6352 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6353 if (!foundBuiltin
) {
6354 numofforms
= get_ntforms(&list
);
6355 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6357 if (numofforms
== 0)
6364 fill_form_1(&form_1
, &builtin_form
);
6367 /* Check if the requested name is in the list of form structures */
6368 for (i
=0; i
<numofforms
; i
++) {
6370 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6372 if (strequal(form_name
, list
[i
].name
)) {
6373 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6374 fill_form_1(&form_1
, &list
[i
]);
6380 if (i
== numofforms
) {
6384 /* check the required size. */
6386 *needed
=spoolss_size_form_1(&form_1
);
6388 if (!alloc_buffer_size(buffer
, buffer_size
)){
6389 return WERR_INSUFFICIENT_BUFFER
;
6392 if (*needed
> offered
) {
6393 return WERR_INSUFFICIENT_BUFFER
;
6396 /* fill the buffer with the form structures */
6397 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6398 smb_io_form_1("", buffer
, &form_1
, 0);
6404 return WERR_UNKNOWN_LEVEL
;
6408 /****************************************************************************
6409 ****************************************************************************/
6411 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
6413 init_unistr(&port
->port_name
, name
);
6416 /****************************************************************************
6417 ****************************************************************************/
6419 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
6421 init_unistr(&port
->port_name
, name
);
6422 init_unistr(&port
->monitor_name
, "Local Monitor");
6423 init_unistr(&port
->description
, "Local Port");
6424 #define PORT_TYPE_WRITE 1
6425 port
->port_type
=PORT_TYPE_WRITE
;
6429 /****************************************************************************
6431 ****************************************************************************/
6433 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6435 PORT_INFO_1
*ports
=NULL
;
6438 if (*lp_enumports_cmd()) {
6439 char *cmd
= lp_enumports_cmd();
6446 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6448 DEBUG(10,("Running [%s]\n", command
));
6449 ret
= smbrun(command
, &fd
);
6450 DEBUG(10,("Returned [%d]\n", ret
));
6454 /* Is this the best error to return here? */
6455 return WERR_ACCESS_DENIED
;
6459 qlines
= fd_lines_load(fd
, &numlines
);
6460 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6464 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6465 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6466 dos_errstr(WERR_NOMEM
)));
6467 file_lines_free(qlines
);
6471 for (i
=0; i
<numlines
; i
++) {
6472 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6473 fill_port_1(&ports
[i
], qlines
[i
]);
6476 file_lines_free(qlines
);
6479 *returned
= numlines
;
6482 *returned
= 1; /* Sole Samba port returned. */
6484 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6487 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6489 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6492 /* check the required size. */
6493 for (i
=0; i
<*returned
; i
++) {
6494 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6495 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6498 if (!alloc_buffer_size(buffer
, *needed
)) {
6500 return WERR_INSUFFICIENT_BUFFER
;
6503 /* fill the buffer with the ports structures */
6504 for (i
=0; i
<*returned
; i
++) {
6505 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6506 smb_io_port_1("", buffer
, &ports
[i
], 0);
6511 if (*needed
> offered
) {
6513 return WERR_INSUFFICIENT_BUFFER
;
6519 /****************************************************************************
6521 ****************************************************************************/
6523 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6525 PORT_INFO_2
*ports
=NULL
;
6528 if (*lp_enumports_cmd()) {
6529 char *cmd
= lp_enumports_cmd();
6538 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6539 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6541 path
= lp_lockdir();
6543 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6544 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6547 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6548 ret
= smbrun(command
, &fd
);
6549 DEBUGADD(10,("returned [%d]\n", ret
));
6553 /* Is this the best error to return here? */
6554 return WERR_ACCESS_DENIED
;
6558 qlines
= fd_lines_load(fd
, &numlines
);
6559 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6563 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
6564 file_lines_free(qlines
);
6568 for (i
=0; i
<numlines
; i
++) {
6569 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6570 fill_port_2(&(ports
[i
]), qlines
[i
]);
6573 file_lines_free(qlines
);
6576 *returned
= numlines
;
6582 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
6585 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6587 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6590 /* check the required size. */
6591 for (i
=0; i
<*returned
; i
++) {
6592 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6593 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
6596 if (!alloc_buffer_size(buffer
, *needed
)) {
6598 return WERR_INSUFFICIENT_BUFFER
;
6601 /* fill the buffer with the ports structures */
6602 for (i
=0; i
<*returned
; i
++) {
6603 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6604 smb_io_port_2("", buffer
, &ports
[i
], 0);
6609 if (*needed
> offered
) {
6611 return WERR_INSUFFICIENT_BUFFER
;
6617 /****************************************************************************
6619 ****************************************************************************/
6621 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
6623 /* UNISTR2 *name = &q_u->name; - notused. */
6624 uint32 level
= q_u
->level
;
6625 NEW_BUFFER
*buffer
= NULL
;
6626 uint32 offered
= q_u
->offered
;
6627 uint32
*needed
= &r_u
->needed
;
6628 uint32
*returned
= &r_u
->returned
;
6630 /* that's an [in out] buffer */
6631 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6632 buffer
= r_u
->buffer
;
6634 DEBUG(4,("_spoolss_enumports\n"));
6641 return enumports_level_1(buffer
, offered
, needed
, returned
);
6643 return enumports_level_2(buffer
, offered
, needed
, returned
);
6645 return WERR_UNKNOWN_LEVEL
;
6649 /****************************************************************************
6650 ****************************************************************************/
6652 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
6653 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6654 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
6655 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
6658 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6661 WERROR err
= WERR_OK
;
6663 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
6664 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6668 ZERO_STRUCTP(printer
);
6670 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6671 if (!convert_printer_info(info
, printer
, 2)) {
6672 free_a_printer(&printer
, 2);
6676 /* check to see if the printer already exists */
6678 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
6679 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6680 printer
->info_2
->sharename
));
6681 free_a_printer(&printer
, 2);
6682 return WERR_PRINTER_ALREADY_EXISTS
;
6685 if (*lp_addprinter_cmd() )
6686 if ( !add_printer_hook(printer
) ) {
6687 free_a_printer(&printer
,2);
6688 return WERR_ACCESS_DENIED
;
6691 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
6692 printer
->info_2
->sharename
);
6694 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
6695 free_a_printer(&printer
,2);
6696 return WERR_ACCESS_DENIED
;
6699 /* you must be a printer admin to add a new printer */
6700 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6701 free_a_printer(&printer
,2);
6702 return WERR_ACCESS_DENIED
;
6706 * Do sanity check on the requested changes for Samba.
6709 if (!check_printer_ok(printer
->info_2
, snum
)) {
6710 free_a_printer(&printer
,2);
6711 return WERR_INVALID_PARAM
;
6715 * When a printer is created, the drivername bound to the printer is used
6716 * to lookup previously saved driver initialization info, which is then
6717 * bound to the new printer, simulating what happens in the Windows arch.
6721 set_driver_init(printer
, 2);
6723 /* A valid devmode was included, convert and link it
6725 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6727 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6728 &printer
->info_2
->devmode
))
6732 set_driver_init(printer
, 2);
6734 /* write the ASCII on disk */
6735 err
= mod_a_printer(*printer
, 2);
6736 if (!W_ERROR_IS_OK(err
)) {
6737 free_a_printer(&printer
,2);
6741 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
6742 /* Handle open failed - remove addition. */
6743 del_a_printer(printer
->info_2
->sharename
);
6744 free_a_printer(&printer
,2);
6745 return WERR_ACCESS_DENIED
;
6748 update_c_setprinter(False
);
6749 free_a_printer(&printer
,2);
6754 /****************************************************************************
6755 ****************************************************************************/
6757 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
6759 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
6760 uint32 level
= q_u
->level
;
6761 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6762 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
6763 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
6764 uint32 user_switch
= q_u
->user_switch
;
6765 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
6766 POLICY_HND
*handle
= &r_u
->handle
;
6770 /* we don't handle yet */
6771 /* but I know what to do ... */
6772 return WERR_UNKNOWN_LEVEL
;
6774 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
6776 user_switch
, user
, handle
);
6778 return WERR_UNKNOWN_LEVEL
;
6782 /****************************************************************************
6783 ****************************************************************************/
6785 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
6787 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6788 uint32 level
= q_u
->level
;
6789 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
6790 WERROR err
= WERR_OK
;
6791 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6792 struct current_user user
;
6793 fstring driver_name
;
6796 ZERO_STRUCT(driver
);
6798 get_current_user(&user
, p
);
6800 if (!convert_printer_driver_info(info
, &driver
, level
)) {
6805 DEBUG(5,("Cleaning driver's information\n"));
6806 err
= clean_up_driver_struct(driver
, level
, &user
);
6807 if (!W_ERROR_IS_OK(err
))
6810 DEBUG(5,("Moving driver to final destination\n"));
6811 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
6812 if (W_ERROR_IS_OK(err
))
6813 err
= WERR_ACCESS_DENIED
;
6817 if (add_a_printer_driver(driver
, level
)!=0) {
6818 err
= WERR_ACCESS_DENIED
;
6822 /* BEGIN_ADMIN_LOG */
6825 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6826 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
6827 fstrcpy(driver_name
, driver
.info_3
->name
);
6830 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6831 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
6832 fstrcpy(driver_name
, driver
.info_6
->name
);
6838 * I think this is where he DrvUpgradePrinter() hook would be
6839 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6840 * server. Right now, we just need to send ourselves a message
6841 * to update each printer bound to this driver. --jerry
6844 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
6845 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6850 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6851 * decide if the driver init data should be deleted. The rules are:
6852 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6853 * 2) delete init data only if there is no 2k/Xp driver
6854 * 3) always delete init data
6855 * The generalized rule is always use init data from the highest order driver.
6856 * It is necessary to follow the driver install by an initialization step to
6857 * finish off this process.
6860 version
= driver
.info_3
->cversion
;
6861 else if (level
== 6)
6862 version
= driver
.info_6
->version
;
6867 * 9x printer driver - never delete init data
6870 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6875 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6876 * there is no 2k/Xp driver init data for this driver name.
6880 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
6882 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
6884 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6886 if (!del_driver_init(driver_name
))
6887 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
6890 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6892 free_a_printer_driver(driver1
,3);
6893 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6900 * 2k or Xp printer driver - always delete init data
6903 if (!del_driver_init(driver_name
))
6904 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
6908 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
6914 free_a_printer_driver(driver
, level
);
6918 /********************************************************************
6919 * spoolss_addprinterdriverex
6920 ********************************************************************/
6922 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
6924 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
6925 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
6928 * we only support the semantics of AddPrinterDriver()
6929 * i.e. only copy files that are newer than existing ones
6932 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
6933 return WERR_ACCESS_DENIED
;
6935 /* just pass the information off to _spoolss_addprinterdriver() */
6936 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
6937 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
6938 q_u_local
.level
= q_u
->level
;
6939 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
6941 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
6944 /****************************************************************************
6945 ****************************************************************************/
6947 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
6949 init_unistr(&info
->name
, name
);
6952 /****************************************************************************
6953 ****************************************************************************/
6955 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6959 pstring short_archi
;
6960 DRIVER_DIRECTORY_1
*info
=NULL
;
6962 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
6964 if (get_short_archi(short_archi
, long_archi
)==False
)
6965 return WERR_INVALID_ENVIRONMENT
;
6967 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
6970 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
6972 DEBUG(4,("printer driver directory: [%s]\n", path
));
6974 fill_driverdir_1(info
, path
);
6976 *needed
+= spoolss_size_driverdir_info_1(info
);
6978 if (!alloc_buffer_size(buffer
, *needed
)) {
6980 return WERR_INSUFFICIENT_BUFFER
;
6983 smb_io_driverdir_1("", buffer
, info
, 0);
6987 if (*needed
> offered
)
6988 return WERR_INSUFFICIENT_BUFFER
;
6993 /****************************************************************************
6994 ****************************************************************************/
6996 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
6998 UNISTR2
*name
= &q_u
->name
;
6999 UNISTR2
*uni_environment
= &q_u
->environment
;
7000 uint32 level
= q_u
->level
;
7001 NEW_BUFFER
*buffer
= NULL
;
7002 uint32 offered
= q_u
->offered
;
7003 uint32
*needed
= &r_u
->needed
;
7005 /* that's an [in out] buffer */
7006 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7007 buffer
= r_u
->buffer
;
7009 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7015 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7017 return WERR_UNKNOWN_LEVEL
;
7021 /****************************************************************************
7022 ****************************************************************************/
7024 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7026 POLICY_HND
*handle
= &q_u
->handle
;
7027 uint32 idx
= q_u
->index
;
7028 uint32 in_value_len
= q_u
->valuesize
;
7029 uint32 in_data_len
= q_u
->datasize
;
7030 uint32
*out_max_value_len
= &r_u
->valuesize
;
7031 uint16
**out_value
= &r_u
->value
;
7032 uint32
*out_value_len
= &r_u
->realvaluesize
;
7033 uint32
*out_type
= &r_u
->type
;
7034 uint32
*out_max_data_len
= &r_u
->datasize
;
7035 uint8
**data_out
= &r_u
->data
;
7036 uint32
*out_data_len
= &r_u
->realdatasize
;
7038 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7043 uint32 biggest_valuesize
;
7044 uint32 biggest_datasize
;
7046 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7052 ZERO_STRUCT(printer
);
7056 *out_max_data_len
=0;
7060 DEBUG(5,("spoolss_enumprinterdata\n"));
7063 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7067 if (!get_printer_snum(p
,handle
, &snum
))
7070 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7071 if (!W_ERROR_IS_OK(result
))
7075 * The NT machine wants to know the biggest size of value and data
7077 * cf: MSDN EnumPrinterData remark section
7079 if ( (in_value_len
==0) && (in_data_len
==0) ) {
7080 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7085 biggest_valuesize
=0;
7088 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
7089 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
7090 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
7092 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
7098 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
7099 *out_value_len
=2*(1+biggest_valuesize
);
7100 *out_data_len
=biggest_datasize
;
7102 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7104 free_a_printer(&printer
, 2);
7109 * the value len is wrong in NT sp3
7110 * that's the number of bytes not the number of unicode chars
7113 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
7116 free_a_printer(&printer
, 2);
7118 /* out_value should default to "" or else NT4 has
7119 problems unmarshalling the response */
7121 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7122 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7125 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7127 /* the data is counted in bytes */
7128 *out_max_data_len
= in_data_len
;
7129 *out_data_len
= in_data_len
;
7130 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7133 return WERR_NO_MORE_ITEMS
;
7136 free_a_printer(&printer
, 2);
7140 * - counted in bytes in the request
7141 * - counted in UNICODE chars in the max reply
7142 * - counted in bytes in the real size
7144 * take a pause *before* coding not *during* coding
7147 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7148 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
,in_value_len
*sizeof(uint8
))) == NULL
) {
7153 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
,value
, in_value_len
, 0);
7157 /* the data is counted in bytes */
7158 *out_max_data_len
=in_data_len
;
7159 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) {
7164 memcpy(*data_out
, data
, (size_t)data_len
);
7165 *out_data_len
=data_len
;
7172 /****************************************************************************
7173 ****************************************************************************/
7175 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7177 POLICY_HND
*handle
= &q_u
->handle
;
7178 UNISTR2
*value
= &q_u
->value
;
7179 uint32 type
= q_u
->type
;
7180 uint8
*data
= q_u
->data
;
7181 uint32 real_len
= q_u
->real_len
;
7183 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7184 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
7186 WERROR status
= WERR_OK
;
7187 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7189 DEBUG(5,("spoolss_setprinterdata\n"));
7192 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7196 if (!get_printer_snum(p
,handle
, &snum
))
7199 ZERO_STRUCT(old_param
);
7202 * Access check : NT returns "access denied" if you make a
7203 * SetPrinterData call without the necessary privildge.
7204 * we were originally returning OK if nothing changed
7205 * which made Win2k issue **a lot** of SetPrinterData
7206 * when connecting to a printer --jerry
7209 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7210 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7211 status
= WERR_ACCESS_DENIED
;
7215 /* Check if we are making any changes or not. Return true if
7216 nothing is actually changing. This is not needed anymore but
7217 has been left in as an optimization to keep from from
7218 writing to disk as often --jerry */
7220 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7221 if (!W_ERROR_IS_OK(status
))
7224 convert_specific_param(¶m
, value
, type
, data
, real_len
);
7226 unlink_specific_param_if_exist(printer
->info_2
, param
);
7229 * When client side code sets a magic printer data key, detect it and save
7230 * the current printer data and the magic key's data (its the DEVMODE) for
7231 * future printer/driver initializations.
7233 if (param
->type
==3 && !strcmp( param
->value
, PHANTOM_DEVMODE_KEY
)) {
7235 * Set devmode and printer initialization info
7237 status
= save_driver_init(printer
, 2, param
);
7240 add_a_specific_param(printer
->info_2
, ¶m
);
7241 status
= mod_a_printer(*printer
, 2);
7245 free_a_printer(&printer
, 2);
7247 free_nt_printer_param(¶m
);
7248 SAFE_FREE(old_param
.data
);
7253 /****************************************************************************
7254 ****************************************************************************/
7256 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7258 POLICY_HND
*handle
= &q_u
->handle
;
7259 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7262 DEBUG(5,("_spoolss_resetprinter\n"));
7265 * All we do is to check to see if the handle and queue is valid.
7266 * This call really doesn't mean anything to us because we only
7267 * support RAW printing. --jerry
7271 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7275 if (!get_printer_snum(p
,handle
, &snum
))
7279 /* blindly return success */
7284 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7286 POLICY_HND
*handle
= &q_u
->handle
;
7287 UNISTR2
*value
= &q_u
->valuename
;
7289 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7290 NT_PRINTER_PARAM param
;
7292 WERROR status
= WERR_OK
;
7293 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7295 DEBUG(5,("spoolss_deleteprinterdata\n"));
7298 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7302 if (!get_printer_snum(p
, handle
, &snum
))
7305 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7306 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7307 return WERR_ACCESS_DENIED
;
7310 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7311 if (!W_ERROR_IS_OK(status
))
7314 ZERO_STRUCTP(¶m
);
7315 unistr2_to_ascii(param
.value
, value
, sizeof(param
.value
)-1);
7317 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
7318 status
= WERR_INVALID_PARAM
;
7320 status
= mod_a_printer(*printer
, 2);
7322 free_a_printer(&printer
, 2);
7326 /****************************************************************************
7327 ****************************************************************************/
7329 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7331 POLICY_HND
*handle
= &q_u
->handle
;
7332 /* uint32 level = q_u->level; - notused. */
7333 FORM
*form
= &q_u
->form
;
7334 nt_forms_struct tmpForm
;
7336 WERROR status
= WERR_OK
;
7337 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7340 nt_forms_struct
*list
=NULL
;
7341 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7343 DEBUG(5,("spoolss_addform\n"));
7346 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7350 if (!get_printer_snum(p
,handle
, &snum
))
7353 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7354 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7355 status
= WERR_ACCESS_DENIED
;
7359 /* can't add if builtin */
7360 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7361 return WERR_ALREADY_EXISTS
;
7364 count
=get_ntforms(&list
);
7365 if(!add_a_form(&list
, form
, &count
))
7367 write_ntforms(&list
, count
);
7370 * ChangeID must always be set
7373 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7374 if (!W_ERROR_IS_OK(status
))
7377 status
= mod_a_printer(*printer
, 2);
7378 if (!W_ERROR_IS_OK(status
))
7382 free_a_printer(&printer
, 2);
7388 /****************************************************************************
7389 ****************************************************************************/
7391 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7393 POLICY_HND
*handle
= &q_u
->handle
;
7394 UNISTR2
*form_name
= &q_u
->name
;
7395 nt_forms_struct tmpForm
;
7397 WERROR ret
= WERR_OK
;
7398 nt_forms_struct
*list
=NULL
;
7399 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7401 WERROR status
= WERR_OK
;
7402 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7404 DEBUG(5,("spoolss_deleteform\n"));
7407 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7411 if (!get_printer_snum(p
, handle
, &snum
))
7414 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7415 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
7416 return WERR_ACCESS_DENIED
;
7419 /* can't delete if builtin */
7420 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7421 return WERR_INVALID_PARAM
;
7424 count
= get_ntforms(&list
);
7425 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
7426 return WERR_INVALID_PARAM
;
7429 * ChangeID must always be set
7432 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7433 if (!W_ERROR_IS_OK(status
))
7436 status
= mod_a_printer(*printer
, 2);
7437 if (!W_ERROR_IS_OK(status
))
7441 free_a_printer(&printer
, 2);
7447 /****************************************************************************
7448 ****************************************************************************/
7450 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7452 POLICY_HND
*handle
= &q_u
->handle
;
7453 FORM
*form
= &q_u
->form
;
7454 nt_forms_struct tmpForm
;
7456 WERROR status
= WERR_OK
;
7457 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7460 nt_forms_struct
*list
=NULL
;
7461 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7463 DEBUG(5,("spoolss_setform\n"));
7466 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7470 if (!get_printer_snum(p
, handle
, &snum
))
7473 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7474 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7475 return WERR_ACCESS_DENIED
;
7478 /* can't set if builtin */
7479 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7480 return WERR_INVALID_PARAM
;
7483 count
=get_ntforms(&list
);
7484 update_a_form(&list
, form
, count
);
7485 write_ntforms(&list
, count
);
7488 * ChangeID must always be set
7491 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7492 if (!W_ERROR_IS_OK(status
))
7495 status
= mod_a_printer(*printer
, 2);
7496 if (!W_ERROR_IS_OK(status
))
7500 free_a_printer(&printer
, 2);
7506 /****************************************************************************
7507 enumprintprocessors level 1.
7508 ****************************************************************************/
7510 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7512 PRINTPROCESSOR_1
*info_1
=NULL
;
7514 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
7519 init_unistr(&info_1
->name
, "winprint");
7521 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
7523 if (!alloc_buffer_size(buffer
, *needed
))
7524 return WERR_INSUFFICIENT_BUFFER
;
7526 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
7530 if (*needed
> offered
) {
7532 return WERR_INSUFFICIENT_BUFFER
;
7538 /****************************************************************************
7539 ****************************************************************************/
7541 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
7543 uint32 level
= q_u
->level
;
7544 NEW_BUFFER
*buffer
= NULL
;
7545 uint32 offered
= q_u
->offered
;
7546 uint32
*needed
= &r_u
->needed
;
7547 uint32
*returned
= &r_u
->returned
;
7549 /* that's an [in out] buffer */
7550 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7551 buffer
= r_u
->buffer
;
7553 DEBUG(5,("spoolss_enumprintprocessors\n"));
7556 * Enumerate the print processors ...
7558 * Just reply with "winprint", to keep NT happy
7559 * and I can use my nice printer checker.
7567 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
7569 return WERR_UNKNOWN_LEVEL
;
7573 /****************************************************************************
7574 enumprintprocdatatypes level 1.
7575 ****************************************************************************/
7577 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7579 PRINTPROCDATATYPE_1
*info_1
=NULL
;
7581 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
7586 init_unistr(&info_1
->name
, "RAW");
7588 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
7590 if (!alloc_buffer_size(buffer
, *needed
))
7591 return WERR_INSUFFICIENT_BUFFER
;
7593 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
7597 if (*needed
> offered
) {
7599 return WERR_INSUFFICIENT_BUFFER
;
7605 /****************************************************************************
7606 ****************************************************************************/
7608 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
7610 uint32 level
= q_u
->level
;
7611 NEW_BUFFER
*buffer
= NULL
;
7612 uint32 offered
= q_u
->offered
;
7613 uint32
*needed
= &r_u
->needed
;
7614 uint32
*returned
= &r_u
->returned
;
7616 /* that's an [in out] buffer */
7617 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7618 buffer
= r_u
->buffer
;
7620 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7627 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
7629 return WERR_UNKNOWN_LEVEL
;
7633 /****************************************************************************
7634 enumprintmonitors level 1.
7635 ****************************************************************************/
7637 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7639 PRINTMONITOR_1
*info_1
=NULL
;
7641 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
7646 init_unistr(&info_1
->name
, "Local Port");
7648 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
7650 if (!alloc_buffer_size(buffer
, *needed
))
7651 return WERR_INSUFFICIENT_BUFFER
;
7653 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
7657 if (*needed
> offered
) {
7659 return WERR_INSUFFICIENT_BUFFER
;
7665 /****************************************************************************
7666 enumprintmonitors level 2.
7667 ****************************************************************************/
7669 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7671 PRINTMONITOR_2
*info_2
=NULL
;
7673 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
7678 init_unistr(&info_2
->name
, "Local Port");
7679 init_unistr(&info_2
->environment
, "Windows NT X86");
7680 init_unistr(&info_2
->dll_name
, "localmon.dll");
7682 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
7684 if (!alloc_buffer_size(buffer
, *needed
))
7685 return WERR_INSUFFICIENT_BUFFER
;
7687 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
7691 if (*needed
> offered
) {
7693 return WERR_INSUFFICIENT_BUFFER
;
7699 /****************************************************************************
7700 ****************************************************************************/
7702 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
7704 uint32 level
= q_u
->level
;
7705 NEW_BUFFER
*buffer
= NULL
;
7706 uint32 offered
= q_u
->offered
;
7707 uint32
*needed
= &r_u
->needed
;
7708 uint32
*returned
= &r_u
->returned
;
7710 /* that's an [in out] buffer */
7711 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7712 buffer
= r_u
->buffer
;
7714 DEBUG(5,("spoolss_enumprintmonitors\n"));
7717 * Enumerate the print monitors ...
7719 * Just reply with "Local Port", to keep NT happy
7720 * and I can use my nice printer checker.
7728 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
7730 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
7732 return WERR_UNKNOWN_LEVEL
;
7736 /****************************************************************************
7737 ****************************************************************************/
7739 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7743 JOB_INFO_1
*info_1
=NULL
;
7745 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
7747 if (info_1
== NULL
) {
7752 for (i
=0; i
<count
&& found
==False
; i
++) {
7753 if (queue
[i
].job
==(int)jobid
)
7760 /* NT treats not found as bad param... yet another bad choice */
7761 return WERR_INVALID_PARAM
;
7764 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
7768 *needed
+= spoolss_size_job_info_1(info_1
);
7770 if (!alloc_buffer_size(buffer
, *needed
)) {
7772 return WERR_INSUFFICIENT_BUFFER
;
7775 smb_io_job_info_1("", buffer
, info_1
, 0);
7779 if (*needed
> offered
)
7780 return WERR_INSUFFICIENT_BUFFER
;
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7793 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
7795 DEVICEMODE
*devmode
= NULL
;
7797 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
7799 ZERO_STRUCTP(info_2
);
7801 if (info_2
== NULL
) {
7806 for (i
=0; i
<count
&& found
==False
; i
++) {
7807 if (queue
[i
].job
==(int)jobid
)
7812 /* NT treats not found as bad param... yet another bad
7814 ret
= WERR_INVALID_PARAM
;
7818 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
7819 if (!W_ERROR_IS_OK(ret
))
7821 if (construct_dev_mode(snum
) == NULL
) {
7826 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
7828 *needed
+= spoolss_size_job_info_2(info_2
);
7830 if (!alloc_buffer_size(buffer
, *needed
)) {
7831 ret
= WERR_INSUFFICIENT_BUFFER
;
7835 smb_io_job_info_2("", buffer
, info_2
, 0);
7837 if (*needed
> offered
) {
7838 ret
= WERR_INSUFFICIENT_BUFFER
;
7845 /* Cleanup allocated memory */
7848 free_job_info_2(info_2
); /* Also frees devmode */
7850 free_a_printer(&ntprinter
, 2);
7855 /****************************************************************************
7856 ****************************************************************************/
7858 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
7860 POLICY_HND
*handle
= &q_u
->handle
;
7861 uint32 jobid
= q_u
->jobid
;
7862 uint32 level
= q_u
->level
;
7863 NEW_BUFFER
*buffer
= NULL
;
7864 uint32 offered
= q_u
->offered
;
7865 uint32
*needed
= &r_u
->needed
;
7869 print_queue_struct
*queue
=NULL
;
7870 print_status_struct prt_status
;
7872 /* that's an [in out] buffer */
7873 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7874 buffer
= r_u
->buffer
;
7876 DEBUG(5,("spoolss_getjob\n"));
7880 if (!get_printer_snum(p
, handle
, &snum
))
7883 count
= print_queue_status(snum
, &queue
, &prt_status
);
7885 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7886 count
, prt_status
.status
, prt_status
.message
));
7890 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7892 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7895 return WERR_UNKNOWN_LEVEL
;
7899 /********************************************************************
7900 * spoolss_getprinterdataex
7901 ********************************************************************/
7903 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
7905 POLICY_HND
*handle
= &q_u
->handle
;
7906 uint32 in_size
= q_u
->size
;
7907 uint32
*type
= &r_u
->type
;
7908 uint32
*out_size
= &r_u
->size
;
7909 uint8
**data
= &r_u
->data
;
7910 uint32
*needed
= &r_u
->needed
;
7913 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7916 DEBUG(4,("_spoolss_getprinterdataex\n"));
7918 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
7919 unistr2_to_ascii(value
, &q_u
->valuename
, sizeof(value
) - 1);
7921 /* in case of problem, return some default values */
7928 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
7930 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7935 /* Is the handle to a printer or to the server? */
7937 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
7939 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7940 return WERR_INVALID_PARAM
;
7945 * From MSDN documentation of GetPrinterDataEx: pass request
7946 * to GetPrinterData if key is "PrinterDriverData". This is
7947 * the only key we really support. Other keys to implement:
7953 if (strcmp(key
, "PrinterDriverData") != 0)
7954 return WERR_BADFILE
;
7956 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7957 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
7958 type
, data
, needed
, in_size
);
7963 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
7965 /* reply this param doesn't exist */
7967 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
7973 return WERR_INVALID_PARAM
;
7976 if (*needed
> *out_size
)
7977 return WERR_MORE_DATA
;
7982 /********************************************************************
7983 * spoolss_setprinterdata
7984 ********************************************************************/
7986 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
7988 SPOOL_Q_SETPRINTERDATA q_u_local
;
7989 SPOOL_R_SETPRINTERDATA r_u_local
;
7992 DEBUG(4,("_spoolss_setprinterdataex\n"));
7994 /* From MSDN documentation of SetPrinterDataEx: pass request to
7995 SetPrinterData if key is "PrinterDriverData" */
7997 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7999 if (strcmp(key
, "PrinterDriverData") != 0)
8000 return WERR_INVALID_PARAM
;
8002 ZERO_STRUCT(q_u_local
);
8003 ZERO_STRUCT(r_u_local
);
8005 /* make a copy to call _spoolss_setprinterdata() */
8007 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
8008 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
8009 q_u_local
.type
= q_u
->type
;
8010 q_u_local
.max_len
= q_u
->max_len
;
8011 q_u_local
.data
= q_u
->data
;
8012 q_u_local
.real_len
= q_u
->real_len
;
8013 q_u_local
.numeric_data
= q_u
->numeric_data
;
8015 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
8019 /********************************************************************
8020 * spoolss_deleteprinterdataex
8021 ********************************************************************/
8023 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8025 SPOOL_Q_DELETEPRINTERDATA q_u_local
;
8026 SPOOL_R_DELETEPRINTERDATA r_u_local
;
8029 /* From MSDN documentation of SetPrinterDataEx: pass request to
8030 SetPrinterData if key is "PrinterDriverData" */
8032 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8034 if (strcmp(key
, "PrinterDriverData") != 0)
8035 return WERR_INVALID_PARAM
;
8037 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
8038 copy_unistr2(&q_u_local
.valuename
, &q_u
->valuename
);
8040 return _spoolss_deleteprinterdata( p
, &q_u_local
, &r_u_local
);
8046 /********************************************************************
8047 * spoolss_enumprinterkey
8048 ********************************************************************/
8050 /* constants for EnumPrinterKey() */
8051 #define ENUMERATED_KEY_SIZE 19
8053 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8056 uint16 enumkeys
[ENUMERATED_KEY_SIZE
+1];
8059 char *PrinterKey
= "PrinterDriverData";
8061 DEBUG(4,("_spoolss_enumprinterkey\n"));
8063 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8066 * we only support enumating all keys (key == "")
8067 * Of course, the only key we support is the "PrinterDriverData"
8070 if (strlen(key
) == 0)
8072 r_u
->needed
= ENUMERATED_KEY_SIZE
*2;
8073 if (q_u
->size
< r_u
->needed
)
8074 return WERR_MORE_DATA
;
8077 for (i
=0; i
<ENUMERATED_KEY_SIZE
-2; i
++)
8079 enumkeys
[i
] = (uint16
)(*ptr
);
8083 /* tag of with 2 '\0's */
8084 enumkeys
[i
++] = '\0';
8087 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, ENUMERATED_KEY_SIZE
, enumkeys
))
8088 return WERR_BADFILE
;
8093 /* The "PrinterDriverData" key should have no subkeys */
8094 if (strcmp(key
, PrinterKey
) == 0)
8097 if (q_u
->size
< r_u
->needed
)
8098 return WERR_MORE_DATA
;
8100 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, enumkeys
))
8101 return WERR_BADFILE
;
8107 /* The return value for an unknown key is documented in MSDN
8108 EnumPrinterKey description */
8109 return WERR_BADFILE
;
8112 /********************************************************************
8113 * spoolss_deleteprinterkey
8114 ********************************************************************/
8116 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
8118 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
8122 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
8126 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
8128 if (strcmp(key
, "PrinterDriverData") != 0)
8129 return WERR_INVALID_PARAM
;
8132 * this is what 2k returns when you try to delete the "PrinterDriverData"
8136 return WERR_ACCESS_DENIED
;
8140 /********************************************************************
8141 * spoolss_enumprinterdataex
8142 ********************************************************************/
8144 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
8146 POLICY_HND
*handle
= &q_u
->handle
;
8147 uint32 in_size
= q_u
->size
;
8150 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8151 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
8153 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8162 DEBUG(4,("_spoolss_enumprinterdataex\n"));
8165 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
8171 * The only key we support is "PrinterDriverData". This should return
8172 > an array of all the key/value pairs returned by EnumPrinterDataSee
8173 * _spoolss_getprinterdataex() for details --jerry
8176 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
8177 if (strcmp(key
, "PrinterDriverData") != 0)
8179 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
8180 return WERR_INVALID_PARAM
;
8184 if (!get_printer_snum(p
,handle
, &snum
))
8187 ZERO_STRUCT(printer
);
8188 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
8189 if (!W_ERROR_IS_OK(result
))
8194 * loop through all params and build the array to pass
8195 * back to the client
8202 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
))
8204 PRINTER_ENUM_VALUES
*ptr
;
8207 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries
, value
));
8209 if ((ptr
=talloc_realloc(p
->mem_ctx
, enum_values
, (num_entries
+1) * sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8211 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8212 result
= WERR_NOMEM
;
8218 init_unistr(&enum_values
[num_entries
].valuename
, value
);
8219 enum_values
[num_entries
].value_len
= (strlen(value
)+1) * 2;
8220 enum_values
[num_entries
].type
= type
;
8222 if (!(enum_values
[num_entries
].data
=talloc_zero(p
->mem_ctx
, data_len
+add_len
))) {
8223 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
8224 result
= WERR_NOMEM
;
8227 memcpy(enum_values
[num_entries
].data
, data
, data_len
);
8228 enum_values
[num_entries
].data_len
= data_len
+ add_len
;
8230 /* keep track of the size of the array in bytes */
8232 needed
+= spoolss_size_printer_enum_values(&enum_values
[num_entries
]);
8238 r_u
->needed
= needed
;
8239 r_u
->returned
= num_entries
;
8241 if (needed
> in_size
) {
8242 result
= WERR_MORE_DATA
;
8246 /* copy data into the reply */
8248 r_u
->ctr
.size
= r_u
->needed
;
8249 r_u
->ctr
.size_of_array
= r_u
->returned
;
8250 r_u
->ctr
.values
= enum_values
;
8255 free_a_printer(&printer
, 2);
8260 /****************************************************************************
8261 ****************************************************************************/
8263 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8265 init_unistr(&info
->name
, name
);
8268 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8269 UNISTR2
*environment
,
8276 pstring short_archi
;
8277 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8279 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
8281 if (get_short_archi(short_archi
, long_archi
)==False
)
8282 return WERR_INVALID_ENVIRONMENT
;
8284 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8287 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8289 fill_printprocessordirectory_1(info
, path
);
8291 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8293 if (!alloc_buffer_size(buffer
, *needed
)) {
8295 return WERR_INSUFFICIENT_BUFFER
;
8298 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8302 if (*needed
> offered
)
8303 return WERR_INSUFFICIENT_BUFFER
;
8308 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8310 uint32 level
= q_u
->level
;
8311 NEW_BUFFER
*buffer
= NULL
;
8312 uint32 offered
= q_u
->offered
;
8313 uint32
*needed
= &r_u
->needed
;
8316 /* that's an [in out] buffer */
8317 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8318 buffer
= r_u
->buffer
;
8320 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8326 result
= getprintprocessordirectory_level_1
8327 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
8329 result
= WERR_UNKNOWN_LEVEL
;