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. */
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer
{
52 struct _Printer
*prev
, *next
;
53 BOOL document_started
;
55 int jobid
; /* jobid in printing backend */
59 fstring printerservername
;
62 uint32 access_granted
;
68 SPOOL_NOTIFY_OPTION
*option
;
69 POLICY_HND client_hnd
;
70 uint32 client_connected
;
78 static Printer_entry
*printers_list
;
80 typedef struct _counter_printer_0
{
88 static ubi_dlList counter_list
;
90 static struct cli_state cli
;
91 static uint32 smb_connections
=0;
94 /* in printing/nt_printing.c */
96 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
98 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
99 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v
)
108 return JOB_STATUS_PAUSED
;
110 return JOB_STATUS_SPOOLING
;
112 return JOB_STATUS_PRINTING
;
114 return JOB_STATUS_ERROR
;
116 return JOB_STATUS_DELETING
;
118 return JOB_STATUS_OFFLINE
;
120 return JOB_STATUS_PAPEROUT
;
122 return JOB_STATUS_PRINTED
;
124 return JOB_STATUS_DELETED
;
126 return JOB_STATUS_BLOCKED
;
127 case LPQ_USER_INTERVENTION
:
128 return JOB_STATUS_USER_INTERVENTION
;
133 static int nt_printq_status(int v
)
137 return PRINTER_STATUS_PAUSED
;
146 /****************************************************************************
147 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
148 ****************************************************************************/
150 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
155 SAFE_FREE((*pp
)->ctr
.type
);
159 /***************************************************************************
160 Disconnect from the client
161 ****************************************************************************/
163 static void srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
167 /* weird if the test succeds !!! */
168 if (smb_connections
==0) {
169 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
173 result
= cli_spoolss_reply_close_printer(&cli
, cli
.mem_ctx
, handle
);
175 if (!W_ERROR_IS_OK(result
))
176 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
177 dos_errstr(result
)));
179 /* if it's the last connection, deconnect the IPC$ share */
180 if (smb_connections
==1) {
181 if(!spoolss_disconnect_from_client(&cli
))
184 message_deregister(MSG_PRINTER_NOTIFY
);
190 /****************************************************************************
191 Functions to free a printer entry datastruct.
192 ****************************************************************************/
194 static void free_printer_entry(void *ptr
)
196 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
198 if (Printer
->notify
.client_connected
==True
)
199 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
201 Printer
->notify
.flags
=0;
202 Printer
->notify
.options
=0;
203 Printer
->notify
.localmachine
[0]='\0';
204 Printer
->notify
.printerlocal
=0;
205 free_spool_notify_option(&Printer
->notify
.option
);
206 Printer
->notify
.option
=NULL
;
207 Printer
->notify
.client_connected
=False
;
209 /* Remove from the internal list. */
210 DLIST_REMOVE(printers_list
, Printer
);
215 /****************************************************************************
216 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
217 ****************************************************************************/
219 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
221 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
226 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
233 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
235 if (!new_sp
->ctr
.type
) {
244 /****************************************************************************
245 find printer index by handle
246 ****************************************************************************/
248 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
250 Printer_entry
*find_printer
= NULL
;
252 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
253 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
260 /****************************************************************************
261 Close printer index by handle.
262 ****************************************************************************/
264 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
266 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
269 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
273 close_policy_hnd(p
, hnd
);
278 /****************************************************************************
279 Delete a printer given a handle.
280 ****************************************************************************/
282 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
284 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
287 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
291 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
292 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
296 /* Check calling user has permission to delete printer. Note that
297 since we set the snum parameter to -1 only administrators can
298 delete the printer. This stops people with the Full Control
299 permission from deleting the printer. */
301 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
302 DEBUG(3, ("printer delete denied by security descriptor\n"));
303 return WERR_ACCESS_DENIED
;
306 if (*lp_deleteprinter_cmd()) {
308 char *cmd
= lp_deleteprinter_cmd();
313 /* Printer->dev.handlename equals portname equals sharename */
314 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
315 Printer
->dev
.handlename
);
317 DEBUG(10,("Running [%s]\n", command
));
318 ret
= smbrun(command
, NULL
);
320 return WERR_BADFID
; /* What to return here? */
322 DEBUGADD(10,("returned [%d]\n", ret
));
324 /* Send SIGHUP to process group... is there a better way? */
327 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) >= 0 ) {
331 return WERR_ACCESS_DENIED
;
337 /****************************************************************************
338 Return the snum of a printer corresponding to an handle.
339 ****************************************************************************/
341 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
343 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
346 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
350 switch (Printer
->printer_type
) {
351 case PRINTER_HANDLE_IS_PRINTER
:
352 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
353 *number
= print_queue_snum(Printer
->dev
.handlename
);
354 return (*number
!= -1);
355 case PRINTER_HANDLE_IS_PRINTSERVER
:
362 /****************************************************************************
363 Set printer handle type.
364 Check if it's \\server or \\server\printer
365 ****************************************************************************/
367 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
369 DEBUG(3,("Setting printer type=%s\n", handlename
));
371 if ( strlen(handlename
) < 3 ) {
372 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
376 /* it's a print server */
377 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
378 DEBUGADD(4,("Printer is a print server\n"));
379 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
383 DEBUGADD(4,("Printer is a printer\n"));
384 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
390 /****************************************************************************
391 Set printer handle name.
392 ****************************************************************************/
394 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
397 int n_services
=lp_numservices();
402 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
404 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
405 ZERO_STRUCT(Printer
->dev
.printerservername
);
406 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
410 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
413 if (*handlename
=='\\') {
414 aprinter
=strchr_m(handlename
+2, '\\');
421 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
424 * The original code allowed smbd to store a printer name that
425 * was different from the share name. This is not possible
426 * anymore, so I've simplified this loop greatly. Here
427 * we are just verifying that the printer name is a valid
428 * printer service defined in smb.conf
429 * --jerry [Fri Feb 15 11:17:46 CST 2002]
432 for (snum
=0; snum
<n_services
; snum
++) {
434 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
437 fstrcpy(sname
, lp_servicename(snum
));
439 DEBUGADD(5,("share:%s\n",sname
));
441 if (! StrCaseCmp(sname
, aprinter
)) {
450 DEBUGADD(4,("Printer not found\n"));
454 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
456 ZERO_STRUCT(Printer
->dev
.handlename
);
457 fstrcpy(Printer
->dev
.handlename
, sname
);
462 /****************************************************************************
463 Find first available printer slot. creates a printer handle for you.
464 ****************************************************************************/
466 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
468 Printer_entry
*new_printer
;
470 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
472 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
475 ZERO_STRUCTP(new_printer
);
477 new_printer
->notify
.option
=NULL
;
479 /* Add to the internal list. */
480 DLIST_ADD(printers_list
, new_printer
);
482 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
483 SAFE_FREE(new_printer
);
487 if (!set_printer_hnd_printertype(new_printer
, name
)) {
488 close_printer_handle(p
, hnd
);
492 if (!set_printer_hnd_name(new_printer
, name
)) {
493 close_printer_handle(p
, hnd
);
497 new_printer
->access_granted
= access_granted
;
499 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
504 /****************************************************************************
505 Allocate more memory for a BUFFER.
506 ****************************************************************************/
508 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
516 /* damn, I'm doing the reverse operation of prs_grow() :) */
517 if (buffer_size
< prs_data_size(ps
))
520 extra_space
= buffer_size
- prs_data_size(ps
);
523 * save the offset and move to the end of the buffer
524 * prs_grow() checks the extra_space against the offset
526 old_offset
=prs_offset(ps
);
527 prs_set_offset(ps
, prs_data_size(ps
));
529 if (!prs_grow(ps
, extra_space
))
532 prs_set_offset(ps
, old_offset
);
534 buffer
->string_at_end
=prs_data_size(ps
);
538 /***************************************************************************
539 Always give preference Printer_entry.notify.option over
540 Printer_entry.notify.flags. Return True if we should send notification
541 events using SPOOLSS_RRPCN. False means that we should use
542 SPOOLSS_ROUTERREPLYPRINTER.
543 **************************************************************************/
544 static BOOL
valid_notify_options(Printer_entry
*printer
)
546 if (printer
->notify
.option
== NULL
)
552 /***************************************************************************
553 Simple check to see if the client motify handle is set to watch for events
554 represented by 'flags'
556 FIXME!!!! only a stub right now --jerry
557 **************************************************************************/
559 static BOOL
is_client_monitoring_event(Printer_entry
*p
, uint32 flags
)
565 /***************************************************************************
566 Server wrapper for cli_spoolss_routerreplyprinter() since the client
567 function can only send a single change notification at a time.
569 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
571 **************************************************************************/
573 static WERROR
srv_spoolss_routerreplyprinter (struct cli_state
*reply_cli
, TALLOC_CTX
*mem_ctx
,
574 POLICY_HND
*pol
, PRINTER_MESSAGE_INFO
*info
,
575 NT_PRINTER_INFO_LEVEL
*printer
)
578 uint32 condition
= 0x0;
580 if (info
->flags
& PRINTER_MESSAGE_DRIVER
)
581 condition
= PRINTER_CHANGE_SET_PRINTER_DRIVER
;
583 result
= cli_spoolss_routerreplyprinter(reply_cli
, mem_ctx
, pol
, condition
,
584 printer
->info_2
->changeid
);
589 /***********************************************************************
590 Wrapper around the decision of which RPC use to in the change
592 **********************************************************************/
594 static WERROR
srv_spoolss_send_event_to_client(Printer_entry
* Printer
,
595 struct cli_state
*send_cli
, PRINTER_MESSAGE_INFO
*msg
,
596 NT_PRINTER_INFO_LEVEL
*info
)
600 if (valid_notify_options(Printer
)) {
601 /* This is a single call that can send information about multiple changes */
602 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
603 msg
->flags
|= PRINTER_MESSAGE_ATTRIBUTES
;
605 result
= cli_spoolss_reply_rrpcn(send_cli
, send_cli
->mem_ctx
, &Printer
->notify
.client_hnd
,
609 /* This requires that the server send an individual event notification for each change */
610 result
= srv_spoolss_routerreplyprinter(send_cli
, send_cli
->mem_ctx
, &Printer
->notify
.client_hnd
,
618 /***********************************************************************
619 Send a change notication message on all handles which have a call
621 **********************************************************************/
623 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO
*msg
)
625 Printer_entry
*find_printer
;
627 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
630 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
634 for(find_printer
= printers_list
; find_printer
; find_printer
= find_printer
->next
) {
637 * If the entry has a connected client we send the message. There should
638 * only be one of these normally when dealing with the NT/2k spooler.
639 * However, iterate over all to make sure we deal with user applications
640 * in addition to spooler service.
642 * While we are only maintaining a single connection to the client,
643 * the FindFirstPrinterChangeNotification() call is made on a printer
644 * handle, so "client_connected" represents the whether or not the
645 * client asked for change notication on this handle.
650 if (find_printer
->notify
.client_connected
==True
) {
652 /* does the client care about what changed? */
654 if (msg
->flags
&& !is_client_monitoring_event(find_printer
, msg
->flags
)) {
655 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
656 find_printer
->client
.machine
));
660 if (find_printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
661 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer
->dev
.printerservername
));
663 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer
->dev
.handlename
));
666 * if handle is a printer, only send if the printer_name matches.
667 * ...else if handle is a printerserver, send to all
670 if (*msg
->printer_name
&& (find_printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
671 && !strequal(msg
->printer_name
, find_printer
->dev
.handlename
))
673 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
674 msg
->printer_name
, find_printer
->dev
.handlename
));
679 /* lookup the printer if we have a name if we don't already have a
680 valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
681 will always have a non-empty msg.printer_name */
683 if (!printer
|| !printer
->info_2
|| strcmp(msg
->printer_name
, printer
->info_2
->printername
))
687 free_a_printer(&printer
, 2);
691 result
= get_a_printer(&printer
, 2, msg
->printer_name
);
692 if (!W_ERROR_IS_OK(result
))
696 /* issue the client call */
698 result
= srv_spoolss_send_event_to_client(find_printer
, &cli
, msg
, printer
);
700 if (!W_ERROR_IS_OK(result
)) {
701 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
702 dos_errstr(result
)));
709 /***************************************************************************
710 Receive the notify message and decode the message. Do not send
711 notification if we sent this originally as that would result in
713 ****************************************************************************/
715 static void srv_spoolss_receive_message(int msg_type
, pid_t src
, void *buf
, size_t len
)
717 PRINTER_MESSAGE_INFO msg
;
719 if (len
< sizeof(msg
)) {
720 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len
));
724 memcpy(&msg
, buf
, sizeof(PRINTER_MESSAGE_INFO
));
726 DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
727 msg
.printer_name
, (unsigned int)msg
.low
, (unsigned int)msg
.high
, msg
.flags
));
729 /* Iterate the printer list */
731 send_spoolss_event_notification(&msg
);
735 /***************************************************************************
737 ****************************************************************************/
739 static BOOL
srv_spoolss_sendnotify(char* printer_name
, uint32 high
, uint32 low
, uint32 flags
)
741 char msg
[sizeof(PRINTER_MESSAGE_INFO
)];
742 PRINTER_MESSAGE_INFO info
;
749 fstrcpy(info
.printer_name
, printer_name
);
751 memcpy(msg
, &info
, sizeof(PRINTER_MESSAGE_INFO
));
753 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
754 low
, high
, printer_name
, flags
));
756 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY
, msg
, sizeof(PRINTER_MESSAGE_INFO
),
762 /********************************************************************
763 Copy routines used by convert_to_openprinterex()
764 *******************************************************************/
766 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
774 DEBUG (8,("dup_devmode\n"));
776 /* bulk copy first */
778 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
782 /* dup the pointer members separately */
784 len
= unistrlen(devmode
->devicename
.buffer
);
786 d
->devicename
.buffer
= talloc(ctx
, len
*2);
787 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
792 len
= unistrlen(devmode
->formname
.buffer
);
794 d
->devicename
.buffer
= talloc(ctx
, len
*2);
795 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
799 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
804 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
806 if (!new_ctr
|| !ctr
)
809 DEBUG(8,("copy_devmode_ctr\n"));
811 new_ctr
->size
= ctr
->size
;
812 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
815 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
818 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
820 if (!new_def
|| !def
)
823 DEBUG(8,("copy_printer_defaults\n"));
825 new_def
->datatype_ptr
= def
->datatype_ptr
;
827 if (def
->datatype_ptr
)
828 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
830 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
832 new_def
->access_required
= def
->access_required
;
835 /********************************************************************
836 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
837 * SPOOL_Q_OPEN_PRINTER_EX structure
838 ********************************************************************/
840 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
845 DEBUG(8,("convert_to_openprinterex\n"));
847 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
849 if (q_u
->printername_ptr
)
850 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
852 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
855 /********************************************************************
856 * spoolss_open_printer
858 * called from the spoolss dispatcher
859 ********************************************************************/
861 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
863 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
864 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
872 /* convert the OpenPrinter() call to OpenPrinterEx() */
874 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
876 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
878 /* convert back to OpenPrinter() */
880 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
885 /********************************************************************
886 * spoolss_open_printer
888 * called from the spoolss dispatcher
889 ********************************************************************/
891 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
893 UNISTR2
*printername
= NULL
;
894 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
895 /* uint32 user_switch = q_u->user_switch; - notused */
896 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
897 POLICY_HND
*handle
= &r_u
->handle
;
901 struct current_user user
;
902 Printer_entry
*Printer
=NULL
;
904 if (q_u
->printername_ptr
!= 0)
905 printername
= &q_u
->printername
;
907 if (printername
== NULL
)
908 return WERR_INVALID_PRINTER_NAME
;
910 /* some sanity check because you can open a printer or a print server */
911 /* aka: \\server\printer or \\server */
912 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
914 DEBUGADD(3,("checking name: %s\n",name
));
916 if (!open_printer_hnd(p
, handle
, name
, 0))
917 return WERR_INVALID_PRINTER_NAME
;
919 Printer
=find_printer_index_by_hnd(p
, handle
);
921 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
922 Can't find printer handle we created for printer %s\n", name
));
923 close_printer_handle(p
,handle
);
924 return WERR_INVALID_PRINTER_NAME
;
928 if (printer_default->datatype_ptr != NULL)
930 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
931 set_printer_hnd_datatype(handle, datatype);
934 set_printer_hnd_datatype(handle, "");
938 First case: the user is opening the print server:
940 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
941 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
943 Then both Win2k and WinNT clients try an OpenPrinterEx with
944 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
945 or if the user is listed in the smb.conf printer admin parameter.
947 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
948 client view printer folder, but does not show the MSAPW.
950 Note: this test needs code to check access rights here too. Jeremy
951 could you look at this?
954 Second case: the user is opening a printer:
955 NT doesn't let us connect to a printer if the connecting user
956 doesn't have print permission.
960 get_current_user(&user
, p
);
962 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
964 /* Printserver handles use global struct... */
968 /* Map standard access rights to object specific access
971 se_map_standard(&printer_default
->access_required
,
972 &printserver_std_mapping
);
974 /* Deny any object specific bits that don't apply to print
975 servers (i.e printer and job specific bits) */
977 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
979 if (printer_default
->access_required
&
980 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
981 DEBUG(3, ("access DENIED for non-printserver bits"));
982 close_printer_handle(p
, handle
);
983 return WERR_ACCESS_DENIED
;
986 /* Allow admin access */
988 if (printer_default
->access_required
&
989 SERVER_ACCESS_ADMINISTER
) {
991 if (!lp_ms_add_printer_wizard()) {
992 close_printer_handle(p
, handle
);
993 return WERR_ACCESS_DENIED
;
997 user_in_list(uidtoname(user
.uid
),
998 lp_printer_admin(snum
)))
1001 close_printer_handle(p
, handle
);
1002 return WERR_ACCESS_DENIED
;
1005 /* We fall through to return WERR_OK */
1010 /* NT doesn't let us connect to a printer if the connecting user
1011 doesn't have print permission. */
1013 if (!get_printer_snum(p
, handle
, &snum
))
1016 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1018 /* map an empty access mask to the minimum access mask */
1019 if (printer_default
->access_required
== 0x0)
1020 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1023 * If we are not serving the printer driver for this printer,
1024 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1025 * will keep NT clients happy --jerry
1028 if (lp_use_client_driver(snum
)
1029 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1031 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1034 if (!print_access_check(&user
, snum
, printer_default
->access_required
)) {
1035 DEBUG(3, ("access DENIED for printer open\n"));
1036 close_printer_handle(p
, handle
);
1037 return WERR_ACCESS_DENIED
;
1040 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1041 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1042 close_printer_handle(p
, handle
);
1043 return WERR_ACCESS_DENIED
;
1046 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1047 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1049 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1051 DEBUG(4,("Setting printer access=%x\n", printer_default
->access_required
));
1052 Printer
->access_granted
= printer_default
->access_required
;
1055 * If we have a default device pointer in the
1056 * printer_default struct, then we need to get
1057 * the printer info from the tdb and if there is
1058 * no default devicemode there then we do a *SET*
1059 * here ! This is insanity.... JRA.
1063 * If the openprinterex rpc call contains a devmode,
1064 * it's a per-user one. This per-user devmode is derivated
1065 * from the global devmode. Openprinterex() contains a per-user
1066 * devmode for when you do EMF printing and spooling.
1067 * In the EMF case, the NT workstation is only doing half the job
1068 * of rendering the page. The other half is done by running the printer
1069 * driver on the server.
1070 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1071 * The EMF file only contains what is to be printed on the page.
1072 * So in order for the server to know how to print, the NT client sends
1073 * a devicemode attached to the openprinterex call.
1074 * But this devicemode is short lived, it's only valid for the current print job.
1076 * If Samba would have supported EMF spooling, this devicemode would
1077 * have been attached to the handle, to sent it to the driver to correctly
1078 * rasterize the EMF file.
1080 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1081 * we just act as a pass-thru between windows and the printer.
1083 * In order to know that Samba supports only RAW spooling, NT has to call
1084 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1085 * and until NT sends a RAW job, we refuse it.
1087 * But to call getprinter() or startdoc(), you first need a valid handle,
1088 * and to get an handle you have to call openprintex(). Hence why you have
1089 * a devicemode in the openprinterex() call.
1092 * Differences between NT4 and NT 2000.
1095 * On NT4, you only have a global devicemode. This global devicemode can be changed
1096 * by the administrator (or by a user with enough privs). Everytime a user
1097 * wants to print, the devicemode is resetted to the default. In Word, everytime
1098 * you print, the printer's characteristics are always reset to the global devicemode.
1102 * In W2K, there is the notion of per-user devicemode. The first time you use
1103 * a printer, a per-user devicemode is build from the global devicemode.
1104 * If you change your per-user devicemode, it is saved in the registry, under the
1105 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1106 * printer preferences available.
1108 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1109 * on the General Tab of the printer properties windows.
1111 * To change the global devicemode: it's the "Printing Defaults..." button
1112 * on the Advanced Tab of the printer properties window.
1120 if (printer_default
->devmode_cont
.devmode
!= NULL
) {
1121 result
= printer_write_default_dev( snum
, printer_default
);
1123 close_printer_handle(p
, handle
);
1133 /****************************************************************************
1134 ****************************************************************************/
1136 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1137 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1143 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1152 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1153 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1159 printer
->info_3
=NULL
;
1160 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1164 printer
->info_6
=NULL
;
1165 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1175 BOOL
convert_devicemode(char *printername
, const DEVICEMODE
*devmode
,
1176 NT_DEVICEMODE
**pp_nt_devmode
)
1178 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1181 * Ensure nt_devmode is a valid pointer
1182 * as we will be overwriting it.
1185 if (nt_devmode
== NULL
) {
1186 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1187 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1191 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1192 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1194 nt_devmode
->specversion
=devmode
->specversion
;
1195 nt_devmode
->driverversion
=devmode
->driverversion
;
1196 nt_devmode
->size
=devmode
->size
;
1197 nt_devmode
->fields
=devmode
->fields
;
1198 nt_devmode
->orientation
=devmode
->orientation
;
1199 nt_devmode
->papersize
=devmode
->papersize
;
1200 nt_devmode
->paperlength
=devmode
->paperlength
;
1201 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1202 nt_devmode
->scale
=devmode
->scale
;
1203 nt_devmode
->copies
=devmode
->copies
;
1204 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1205 nt_devmode
->printquality
=devmode
->printquality
;
1206 nt_devmode
->color
=devmode
->color
;
1207 nt_devmode
->duplex
=devmode
->duplex
;
1208 nt_devmode
->yresolution
=devmode
->yresolution
;
1209 nt_devmode
->ttoption
=devmode
->ttoption
;
1210 nt_devmode
->collate
=devmode
->collate
;
1212 nt_devmode
->logpixels
=devmode
->logpixels
;
1213 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1214 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1215 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1216 nt_devmode
->displayflags
=devmode
->displayflags
;
1217 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1218 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1219 nt_devmode
->icmintent
=devmode
->icmintent
;
1220 nt_devmode
->mediatype
=devmode
->mediatype
;
1221 nt_devmode
->dithertype
=devmode
->dithertype
;
1222 nt_devmode
->reserved1
=devmode
->reserved1
;
1223 nt_devmode
->reserved2
=devmode
->reserved2
;
1224 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1225 nt_devmode
->panningheight
=devmode
->panningheight
;
1228 * Only change private and driverextra if the incoming devmode
1229 * has a new one. JRA.
1232 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1233 SAFE_FREE(nt_devmode
->private);
1234 nt_devmode
->driverextra
=devmode
->driverextra
;
1235 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1237 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1240 *pp_nt_devmode
= nt_devmode
;
1245 /********************************************************************
1246 * _spoolss_enddocprinter_internal.
1247 ********************************************************************/
1249 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1251 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1254 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1258 Printer
->document_started
=False
;
1259 print_job_end(Printer
->jobid
,True
);
1260 /* error codes unhandled so far ... */
1265 /********************************************************************
1266 * api_spoolss_closeprinter
1267 ********************************************************************/
1269 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1271 POLICY_HND
*handle
= &q_u
->handle
;
1273 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1275 if (Printer
&& Printer
->document_started
)
1276 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1278 if (!close_printer_handle(p
, handle
))
1281 /* clear the returned printer handle. Observed behavior
1282 from Win2k server. Don't think this really matters.
1283 Previous code just copied the value of the closed
1286 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1291 /********************************************************************
1292 * api_spoolss_deleteprinter
1294 ********************************************************************/
1296 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1298 POLICY_HND
*handle
= &q_u
->handle
;
1299 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1302 if (Printer
&& Printer
->document_started
)
1303 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1305 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1307 result
= delete_printer_handle(p
, handle
);
1309 update_c_setprinter(False
);
1311 if (W_ERROR_IS_OK(result
)) {
1312 srv_spoolss_sendnotify(Printer
->dev
.handlename
, 0, PRINTER_CHANGE_DELETE_PRINTER
, 0x0);
1318 /*******************************************************************
1319 * static function to lookup the version id corresponding to an
1320 * long architecture string
1321 ******************************************************************/
1323 static int get_version_id (char * arch
)
1326 struct table_node archi_table
[]= {
1328 {"Windows 4.0", "WIN40", 0 },
1329 {"Windows NT x86", "W32X86", 2 },
1330 {"Windows NT R4000", "W32MIPS", 2 },
1331 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1332 {"Windows NT PowerPC", "W32PPC", 2 },
1336 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1338 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1339 return (archi_table
[i
].version
);
1345 /********************************************************************
1346 * _spoolss_deleteprinterdriver
1348 * We currently delete the driver for the architecture only.
1349 * This can leave the driver for other archtectures. However,
1350 * since every printer associates a "Windows NT x86" driver name
1351 * and we cannot delete that one while it is in use, **and** since
1352 * it is impossible to assign a driver to a Samba printer without
1353 * having the "Windows NT x86" driver installed,...
1355 * ....we should not get into trouble here.
1358 ********************************************************************/
1360 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
,
1361 SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1365 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1368 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1369 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1371 /* check that we have a valid driver name first */
1372 if ((version
=get_version_id(arch
)) == -1) {
1373 /* this is what NT returns */
1374 return WERR_INVALID_ENVIRONMENT
;
1378 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1379 return WERR_UNKNOWN_PRINTER_DRIVER
;
1383 if (printer_driver_in_use(arch
, driver
))
1385 return WERR_PRINTER_DRIVER_IN_USE
;
1388 return delete_printer_driver(info
.info_3
);
1391 /********************************************************************
1392 GetPrinterData on a printer server Handle.
1393 ********************************************************************/
1395 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1399 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1401 if (!strcmp(value
, "W3SvcInstalled")) {
1403 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
1409 if (!strcmp(value
, "BeepEnabled")) {
1411 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1413 SIVAL(*data
, 0, 0x00);
1418 if (!strcmp(value
, "EventLog")) {
1420 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1422 /* formally was 0x1b */
1423 SIVAL(*data
, 0, 0x0);
1428 if (!strcmp(value
, "NetPopup")) {
1430 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1432 SIVAL(*data
, 0, 0x00);
1437 if (!strcmp(value
, "MajorVersion")) {
1439 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1446 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1449 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
1451 *needed
= 2*(strlen(string
)+1);
1452 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1454 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1456 /* it's done by hand ready to go on the wire */
1457 for (i
=0; i
<strlen(string
); i
++) {
1458 (*data
)[2*i
]=string
[i
];
1459 (*data
)[2*i
+1]='\0';
1464 if (!strcmp(value
, "Architecture")) {
1465 pstring string
="Windows NT x86";
1467 *needed
= 2*(strlen(string
)+1);
1468 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1470 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1471 for (i
=0; i
<strlen(string
); i
++) {
1472 (*data
)[2*i
]=string
[i
];
1473 (*data
)[2*i
+1]='\0';
1481 /********************************************************************
1482 GetPrinterData on a printer Handle.
1483 ********************************************************************/
1485 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1486 fstring value
, uint32
*type
,
1487 uint8
**data
, uint32
*needed
, uint32 in_size
)
1489 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1493 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1495 DEBUG(5,("getprinterdata_printer\n"));
1498 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1502 if(!get_printer_snum(p
, handle
, &snum
))
1505 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
1508 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
1509 free_a_printer(&printer
, 2);
1513 free_a_printer(&printer
, 2);
1515 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1518 if((*data
= (uint8
*)talloc(ctx
, in_size
*sizeof(uint8
) )) == NULL
) {
1522 memset(*data
, 0, in_size
*sizeof(uint8
));
1523 /* copy the min(in_size, len) */
1524 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
1531 DEBUG(5,("getprinterdata_printer:copy done\n"));
1538 /********************************************************************
1539 * spoolss_getprinterdata
1540 ********************************************************************/
1542 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1544 POLICY_HND
*handle
= &q_u
->handle
;
1545 UNISTR2
*valuename
= &q_u
->valuename
;
1546 uint32 in_size
= q_u
->size
;
1547 uint32
*type
= &r_u
->type
;
1548 uint32
*out_size
= &r_u
->size
;
1549 uint8
**data
= &r_u
->data
;
1550 uint32
*needed
= &r_u
->needed
;
1554 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1557 * Reminder: when it's a string, the length is in BYTES
1558 * even if UNICODE is negociated.
1565 /* in case of problem, return some default values */
1569 DEBUG(4,("_spoolss_getprinterdata\n"));
1572 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1574 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1578 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1580 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1581 found
=getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1583 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1586 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1587 /* reply this param doesn't exist */
1589 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1595 /* error depends on handle type */
1597 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1598 return WERR_INVALID_PARAM
;
1600 return WERR_BADFILE
;
1603 if (*needed
> *out_size
)
1604 return WERR_MORE_DATA
;
1609 /***************************************************************************
1610 Connect to the client.
1611 ****************************************************************************/
1613 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1618 * If it's the first connection, contact the client
1619 * and connect to the IPC$ share anonumously
1621 if (smb_connections
==0) {
1622 fstring unix_printer
;
1624 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
1626 if(!spoolss_connect_to_client(&cli
, unix_printer
))
1629 message_register(MSG_PRINTER_NOTIFY
, srv_spoolss_receive_message
);
1635 result
= cli_spoolss_reply_open_printer(&cli
, cli
.mem_ctx
, printer
, localprinter
,
1638 if (!W_ERROR_IS_OK(result
))
1639 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1640 dos_errstr(result
)));
1642 return (W_ERROR_IS_OK(result
));
1645 /********************************************************************
1647 * ReplyFindFirstPrinterChangeNotifyEx
1649 * jfmxxxx: before replying OK: status=0
1650 * should do a rpc call to the workstation asking ReplyOpenPrinter
1651 * have to code it, later.
1653 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1654 * called from api_spoolss_rffpcnex
1655 ********************************************************************/
1657 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
1659 POLICY_HND
*handle
= &q_u
->handle
;
1660 uint32 flags
= q_u
->flags
;
1661 uint32 options
= q_u
->options
;
1662 UNISTR2
*localmachine
= &q_u
->localmachine
;
1663 uint32 printerlocal
= q_u
->printerlocal
;
1664 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
1666 /* store the notify value in the printer struct */
1668 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1671 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1675 Printer
->notify
.flags
=flags
;
1676 Printer
->notify
.options
=options
;
1677 Printer
->notify
.printerlocal
=printerlocal
;
1679 if (Printer
->notify
.option
)
1680 free_spool_notify_option(&Printer
->notify
.option
);
1682 Printer
->notify
.option
=dup_spool_notify_option(option
);
1684 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
, sizeof(Printer
->notify
.localmachine
)-1);
1686 /* connect to the client machine and send a ReplyOpenPrinter */
1687 if(srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
1688 Printer
->notify
.printerlocal
, 1,
1689 &Printer
->notify
.client_hnd
))
1691 Printer
->notify
.client_connected
=True
;
1697 /*******************************************************************
1698 * fill a notify_info_data with the servername
1699 ********************************************************************/
1701 void spoolss_notify_server_name(int snum
,
1702 SPOOL_NOTIFY_INFO_DATA
*data
,
1703 print_queue_struct
*queue
,
1704 NT_PRINTER_INFO_LEVEL
*printer
,
1705 TALLOC_CTX
*mem_ctx
)
1707 pstring temp_name
, temp
;
1710 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
1712 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
1714 data
->notify_data
.data
.length
= len
/ 2 - 1;
1715 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1717 if (!data
->notify_data
.data
.string
) {
1718 data
->notify_data
.data
.length
= 0;
1722 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1725 /*******************************************************************
1726 * fill a notify_info_data with the printername (not including the servername).
1727 ********************************************************************/
1729 void spoolss_notify_printer_name(int snum
,
1730 SPOOL_NOTIFY_INFO_DATA
*data
,
1731 print_queue_struct
*queue
,
1732 NT_PRINTER_INFO_LEVEL
*printer
,
1733 TALLOC_CTX
*mem_ctx
)
1738 /* the notify name should not contain the \\server\ part */
1739 char *p
= strrchr(printer
->info_2
->printername
, '\\');
1742 p
= printer
->info_2
->printername
;
1747 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
1749 data
->notify_data
.data
.length
= len
/ 2 - 1;
1750 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1752 if (!data
->notify_data
.data
.string
) {
1753 data
->notify_data
.data
.length
= 0;
1757 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1760 /*******************************************************************
1761 * fill a notify_info_data with the servicename
1762 ********************************************************************/
1764 void spoolss_notify_share_name(int snum
,
1765 SPOOL_NOTIFY_INFO_DATA
*data
,
1766 print_queue_struct
*queue
,
1767 NT_PRINTER_INFO_LEVEL
*printer
,
1768 TALLOC_CTX
*mem_ctx
)
1773 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
1775 data
->notify_data
.data
.length
= len
/ 2 - 1;
1776 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1778 if (!data
->notify_data
.data
.string
) {
1779 data
->notify_data
.data
.length
= 0;
1783 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1786 /*******************************************************************
1787 * fill a notify_info_data with the port name
1788 ********************************************************************/
1790 void spoolss_notify_port_name(int snum
,
1791 SPOOL_NOTIFY_INFO_DATA
*data
,
1792 print_queue_struct
*queue
,
1793 NT_PRINTER_INFO_LEVEL
*printer
,
1794 TALLOC_CTX
*mem_ctx
)
1799 /* even if it's strange, that's consistant in all the code */
1801 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
1803 data
->notify_data
.data
.length
= len
/ 2 - 1;
1804 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1806 if (!data
->notify_data
.data
.string
) {
1807 data
->notify_data
.data
.length
= 0;
1811 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1814 /*******************************************************************
1815 * fill a notify_info_data with the printername
1816 * but it doesn't exist, have to see what to do
1817 ********************************************************************/
1819 void spoolss_notify_driver_name(int snum
,
1820 SPOOL_NOTIFY_INFO_DATA
*data
,
1821 print_queue_struct
*queue
,
1822 NT_PRINTER_INFO_LEVEL
*printer
,
1823 TALLOC_CTX
*mem_ctx
)
1828 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
1829 data
->notify_data
.data
.length
= len
/ 2 - 1;
1830 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1832 if (!data
->notify_data
.data
.string
) {
1833 data
->notify_data
.data
.length
= 0;
1837 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1840 /*******************************************************************
1841 * fill a notify_info_data with the comment
1842 ********************************************************************/
1844 void spoolss_notify_comment(int snum
,
1845 SPOOL_NOTIFY_INFO_DATA
*data
,
1846 print_queue_struct
*queue
,
1847 NT_PRINTER_INFO_LEVEL
*printer
,
1848 TALLOC_CTX
*mem_ctx
)
1853 if (*printer
->info_2
->comment
== '\0')
1854 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
1856 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
1858 data
->notify_data
.data
.length
= len
/ 2 - 1;
1859 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1861 if (!data
->notify_data
.data
.string
) {
1862 data
->notify_data
.data
.length
= 0;
1866 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1869 /*******************************************************************
1870 * fill a notify_info_data with the comment
1871 * location = "Room 1, floor 2, building 3"
1872 ********************************************************************/
1874 void spoolss_notify_location(int snum
,
1875 SPOOL_NOTIFY_INFO_DATA
*data
,
1876 print_queue_struct
*queue
,
1877 NT_PRINTER_INFO_LEVEL
*printer
,
1878 TALLOC_CTX
*mem_ctx
)
1883 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
1885 data
->notify_data
.data
.length
= len
/ 2 - 1;
1886 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1888 if (!data
->notify_data
.data
.string
) {
1889 data
->notify_data
.data
.length
= 0;
1893 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1896 /*******************************************************************
1897 * fill a notify_info_data with the device mode
1898 * jfm:xxxx don't to it for know but that's a real problem !!!
1899 ********************************************************************/
1901 static void spoolss_notify_devmode(int snum
,
1902 SPOOL_NOTIFY_INFO_DATA
*data
,
1903 print_queue_struct
*queue
,
1904 NT_PRINTER_INFO_LEVEL
*printer
,
1905 TALLOC_CTX
*mem_ctx
)
1909 /*******************************************************************
1910 * fill a notify_info_data with the separator file name
1911 ********************************************************************/
1913 void spoolss_notify_sepfile(int snum
,
1914 SPOOL_NOTIFY_INFO_DATA
*data
,
1915 print_queue_struct
*queue
,
1916 NT_PRINTER_INFO_LEVEL
*printer
,
1917 TALLOC_CTX
*mem_ctx
)
1922 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
1924 data
->notify_data
.data
.length
= len
/ 2 - 1;
1925 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1927 if (!data
->notify_data
.data
.string
) {
1928 data
->notify_data
.data
.length
= 0;
1932 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1935 /*******************************************************************
1936 * fill a notify_info_data with the print processor
1937 * jfm:xxxx return always winprint to indicate we don't do anything to it
1938 ********************************************************************/
1940 void spoolss_notify_print_processor(int snum
,
1941 SPOOL_NOTIFY_INFO_DATA
*data
,
1942 print_queue_struct
*queue
,
1943 NT_PRINTER_INFO_LEVEL
*printer
,
1944 TALLOC_CTX
*mem_ctx
)
1949 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
1951 data
->notify_data
.data
.length
= len
/ 2 - 1;
1952 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1954 if (!data
->notify_data
.data
.string
) {
1955 data
->notify_data
.data
.length
= 0;
1959 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1962 /*******************************************************************
1963 * fill a notify_info_data with the print processor options
1964 * jfm:xxxx send an empty string
1965 ********************************************************************/
1967 void spoolss_notify_parameters(int snum
,
1968 SPOOL_NOTIFY_INFO_DATA
*data
,
1969 print_queue_struct
*queue
,
1970 NT_PRINTER_INFO_LEVEL
*printer
,
1971 TALLOC_CTX
*mem_ctx
)
1976 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
1978 data
->notify_data
.data
.length
= len
/ 2 - 1;
1979 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1981 if (!data
->notify_data
.data
.string
) {
1982 data
->notify_data
.data
.length
= 0;
1986 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1989 /*******************************************************************
1990 * fill a notify_info_data with the data type
1991 * jfm:xxxx always send RAW as data type
1992 ********************************************************************/
1994 void spoolss_notify_datatype(int snum
,
1995 SPOOL_NOTIFY_INFO_DATA
*data
,
1996 print_queue_struct
*queue
,
1997 NT_PRINTER_INFO_LEVEL
*printer
,
1998 TALLOC_CTX
*mem_ctx
)
2003 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2005 data
->notify_data
.data
.length
= len
/ 2 - 1;
2006 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2008 if (!data
->notify_data
.data
.string
) {
2009 data
->notify_data
.data
.length
= 0;
2013 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2016 /*******************************************************************
2017 * fill a notify_info_data with the security descriptor
2018 * jfm:xxxx send an null pointer to say no security desc
2019 * have to implement security before !
2020 ********************************************************************/
2022 static void spoolss_notify_security_desc(int snum
,
2023 SPOOL_NOTIFY_INFO_DATA
*data
,
2024 print_queue_struct
*queue
,
2025 NT_PRINTER_INFO_LEVEL
*printer
,
2026 TALLOC_CTX
*mem_ctx
)
2028 data
->notify_data
.data
.length
=0;
2029 data
->notify_data
.data
.string
= NULL
;
2032 /*******************************************************************
2033 * fill a notify_info_data with the attributes
2034 * jfm:xxxx a samba printer is always shared
2035 ********************************************************************/
2037 void spoolss_notify_attributes(int snum
,
2038 SPOOL_NOTIFY_INFO_DATA
*data
,
2039 print_queue_struct
*queue
,
2040 NT_PRINTER_INFO_LEVEL
*printer
,
2041 TALLOC_CTX
*mem_ctx
)
2043 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2044 data
->notify_data
.value
[1] = 0;
2047 /*******************************************************************
2048 * fill a notify_info_data with the priority
2049 ********************************************************************/
2051 static void spoolss_notify_priority(int snum
,
2052 SPOOL_NOTIFY_INFO_DATA
*data
,
2053 print_queue_struct
*queue
,
2054 NT_PRINTER_INFO_LEVEL
*printer
,
2055 TALLOC_CTX
*mem_ctx
)
2057 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2058 data
->notify_data
.value
[1] = 0;
2061 /*******************************************************************
2062 * fill a notify_info_data with the default priority
2063 ********************************************************************/
2065 static void spoolss_notify_default_priority(int snum
,
2066 SPOOL_NOTIFY_INFO_DATA
*data
,
2067 print_queue_struct
*queue
,
2068 NT_PRINTER_INFO_LEVEL
*printer
,
2069 TALLOC_CTX
*mem_ctx
)
2071 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2072 data
->notify_data
.value
[1] = 0;
2075 /*******************************************************************
2076 * fill a notify_info_data with the start time
2077 ********************************************************************/
2079 static void spoolss_notify_start_time(int snum
,
2080 SPOOL_NOTIFY_INFO_DATA
*data
,
2081 print_queue_struct
*queue
,
2082 NT_PRINTER_INFO_LEVEL
*printer
,
2083 TALLOC_CTX
*mem_ctx
)
2085 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2086 data
->notify_data
.value
[1] = 0;
2089 /*******************************************************************
2090 * fill a notify_info_data with the until time
2091 ********************************************************************/
2093 static void spoolss_notify_until_time(int snum
,
2094 SPOOL_NOTIFY_INFO_DATA
*data
,
2095 print_queue_struct
*queue
,
2096 NT_PRINTER_INFO_LEVEL
*printer
,
2097 TALLOC_CTX
*mem_ctx
)
2099 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2100 data
->notify_data
.value
[1] = 0;
2103 /*******************************************************************
2104 * fill a notify_info_data with the status
2105 ********************************************************************/
2107 static void spoolss_notify_status(int snum
,
2108 SPOOL_NOTIFY_INFO_DATA
*data
,
2109 print_queue_struct
*queue
,
2110 NT_PRINTER_INFO_LEVEL
*printer
,
2111 TALLOC_CTX
*mem_ctx
)
2113 print_status_struct status
;
2115 print_queue_length(snum
, &status
);
2116 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2117 data
->notify_data
.value
[1] = 0;
2120 /*******************************************************************
2121 * fill a notify_info_data with the number of jobs queued
2122 ********************************************************************/
2124 void spoolss_notify_cjobs(int snum
,
2125 SPOOL_NOTIFY_INFO_DATA
*data
,
2126 print_queue_struct
*queue
,
2127 NT_PRINTER_INFO_LEVEL
*printer
,
2128 TALLOC_CTX
*mem_ctx
)
2130 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
2131 data
->notify_data
.value
[1] = 0;
2134 /*******************************************************************
2135 * fill a notify_info_data with the average ppm
2136 ********************************************************************/
2138 static void spoolss_notify_average_ppm(int snum
,
2139 SPOOL_NOTIFY_INFO_DATA
*data
,
2140 print_queue_struct
*queue
,
2141 NT_PRINTER_INFO_LEVEL
*printer
,
2142 TALLOC_CTX
*mem_ctx
)
2144 /* always respond 8 pages per minutes */
2145 /* a little hard ! */
2146 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
2147 data
->notify_data
.value
[1] = 0;
2150 /*******************************************************************
2151 * fill a notify_info_data with username
2152 ********************************************************************/
2154 static void spoolss_notify_username(int snum
,
2155 SPOOL_NOTIFY_INFO_DATA
*data
,
2156 print_queue_struct
*queue
,
2157 NT_PRINTER_INFO_LEVEL
*printer
,
2158 TALLOC_CTX
*mem_ctx
)
2163 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
2165 data
->notify_data
.data
.length
= len
/ 2 - 1;
2166 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2168 if (!data
->notify_data
.data
.string
) {
2169 data
->notify_data
.data
.length
= 0;
2173 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2176 /*******************************************************************
2177 * fill a notify_info_data with job status
2178 ********************************************************************/
2180 static void spoolss_notify_job_status(int snum
,
2181 SPOOL_NOTIFY_INFO_DATA
*data
,
2182 print_queue_struct
*queue
,
2183 NT_PRINTER_INFO_LEVEL
*printer
,
2184 TALLOC_CTX
*mem_ctx
)
2186 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
2187 data
->notify_data
.value
[1] = 0;
2190 /*******************************************************************
2191 * fill a notify_info_data with job name
2192 ********************************************************************/
2194 static void spoolss_notify_job_name(int snum
,
2195 SPOOL_NOTIFY_INFO_DATA
*data
,
2196 print_queue_struct
*queue
,
2197 NT_PRINTER_INFO_LEVEL
*printer
,
2198 TALLOC_CTX
*mem_ctx
)
2203 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
2205 data
->notify_data
.data
.length
= len
/ 2 - 1;
2206 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2208 if (!data
->notify_data
.data
.string
) {
2209 data
->notify_data
.data
.length
= 0;
2213 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2216 /*******************************************************************
2217 * fill a notify_info_data with job status
2218 ********************************************************************/
2220 static void spoolss_notify_job_status_string(int snum
,
2221 SPOOL_NOTIFY_INFO_DATA
*data
,
2222 print_queue_struct
*queue
,
2223 NT_PRINTER_INFO_LEVEL
*printer
,
2224 TALLOC_CTX
*mem_ctx
)
2227 * Now we're returning job status codes we just return a "" here. JRA.
2234 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2237 switch (queue
->status
) {
2242 p
= ""; /* NT provides the paused string */
2251 #endif /* NO LONGER NEEDED. */
2253 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
2255 data
->notify_data
.data
.length
= len
/ 2 - 1;
2256 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2258 if (!data
->notify_data
.data
.string
) {
2259 data
->notify_data
.data
.length
= 0;
2263 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2266 /*******************************************************************
2267 * fill a notify_info_data with job time
2268 ********************************************************************/
2270 static void spoolss_notify_job_time(int snum
,
2271 SPOOL_NOTIFY_INFO_DATA
*data
,
2272 print_queue_struct
*queue
,
2273 NT_PRINTER_INFO_LEVEL
*printer
,
2274 TALLOC_CTX
*mem_ctx
)
2276 data
->notify_data
.value
[0]=0x0;
2277 data
->notify_data
.value
[1]=0;
2280 /*******************************************************************
2281 * fill a notify_info_data with job size
2282 ********************************************************************/
2284 static void spoolss_notify_job_size(int snum
,
2285 SPOOL_NOTIFY_INFO_DATA
*data
,
2286 print_queue_struct
*queue
,
2287 NT_PRINTER_INFO_LEVEL
*printer
,
2288 TALLOC_CTX
*mem_ctx
)
2290 data
->notify_data
.value
[0]=queue
->size
;
2291 data
->notify_data
.value
[1]=0;
2294 /*******************************************************************
2295 * fill a notify_info_data with page info
2296 ********************************************************************/
2297 static void spoolss_notify_total_pages(int snum
,
2298 SPOOL_NOTIFY_INFO_DATA
*data
,
2299 print_queue_struct
*queue
,
2300 NT_PRINTER_INFO_LEVEL
*printer
,
2301 TALLOC_CTX
*mem_ctx
)
2303 data
->notify_data
.value
[0]=queue
->page_count
;
2304 data
->notify_data
.value
[1]=0;
2307 /*******************************************************************
2308 * fill a notify_info_data with pages printed info.
2309 ********************************************************************/
2310 static void spoolss_notify_pages_printed(int snum
,
2311 SPOOL_NOTIFY_INFO_DATA
*data
,
2312 print_queue_struct
*queue
,
2313 NT_PRINTER_INFO_LEVEL
*printer
,
2314 TALLOC_CTX
*mem_ctx
)
2316 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
2317 data
->notify_data
.value
[1]=0;
2320 /*******************************************************************
2321 Fill a notify_info_data with job position.
2322 ********************************************************************/
2324 static void spoolss_notify_job_position(int snum
,
2325 SPOOL_NOTIFY_INFO_DATA
*data
,
2326 print_queue_struct
*queue
,
2327 NT_PRINTER_INFO_LEVEL
*printer
,
2328 TALLOC_CTX
*mem_ctx
)
2330 data
->notify_data
.value
[0]=queue
->job
;
2331 data
->notify_data
.value
[1]=0;
2334 /*******************************************************************
2335 Fill a notify_info_data with submitted time.
2336 ********************************************************************/
2338 static void spoolss_notify_submitted_time(int snum
,
2339 SPOOL_NOTIFY_INFO_DATA
*data
,
2340 print_queue_struct
*queue
,
2341 NT_PRINTER_INFO_LEVEL
*printer
,
2342 TALLOC_CTX
*mem_ctx
)
2349 t
=gmtime(&queue
->time
);
2351 len
= sizeof(SYSTEMTIME
);
2353 data
->notify_data
.data
.length
= len
;
2354 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2356 if (!data
->notify_data
.data
.string
) {
2357 data
->notify_data
.data
.length
= 0;
2361 make_systemtime(&st
, t
);
2364 * Systemtime must be linearized as a set of UINT16's.
2365 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2368 p
= (char *)data
->notify_data
.data
.string
;
2369 SSVAL(p
, 0, st
.year
);
2370 SSVAL(p
, 2, st
.month
);
2371 SSVAL(p
, 4, st
.dayofweek
);
2372 SSVAL(p
, 6, st
.day
);
2373 SSVAL(p
, 8, st
.hour
);
2374 SSVAL(p
, 10, st
.minute
);
2375 SSVAL(p
, 12, st
.second
);
2376 SSVAL(p
, 14, st
.milliseconds
);
2381 struct s_notify_info_data_table
2387 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2388 print_queue_struct
*queue
,
2389 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2392 struct s_notify_info_data_table notify_info_data_table
[] =
2394 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", POINTER
, spoolss_notify_server_name
},
2395 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2396 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", POINTER
, spoolss_notify_share_name
},
2397 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2398 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2399 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", POINTER
, spoolss_notify_comment
},
2400 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", POINTER
, spoolss_notify_location
},
2401 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2402 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", POINTER
, spoolss_notify_sepfile
},
2403 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2404 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2405 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2406 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, spoolss_notify_security_desc
},
2407 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE
, spoolss_notify_attributes
},
2408 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2409 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE
, spoolss_notify_default_priority
},
2410 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2411 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2412 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_status
},
2413 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", POINTER
, NULL
},
2414 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", ONE_VALUE
, spoolss_notify_cjobs
},
2415 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE
, spoolss_notify_average_ppm
},
2416 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER
, NULL
},
2417 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER
, NULL
},
2418 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER
, NULL
},
2419 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER
, NULL
},
2420 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2421 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", POINTER
, spoolss_notify_server_name
},
2422 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2423 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", POINTER
, spoolss_notify_username
},
2424 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", POINTER
, spoolss_notify_username
},
2425 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2426 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2427 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2428 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2429 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2430 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_job_status
},
2431 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", POINTER
, spoolss_notify_job_status_string
},
2432 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, NULL
},
2433 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", POINTER
, spoolss_notify_job_name
},
2434 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2435 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", ONE_VALUE
, spoolss_notify_job_position
},
2436 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", POINTER
, spoolss_notify_submitted_time
},
2437 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2438 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2439 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", ONE_VALUE
, spoolss_notify_job_time
},
2440 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE
, spoolss_notify_total_pages
},
2441 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE
, spoolss_notify_pages_printed
},
2442 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE
, spoolss_notify_job_size
},
2443 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_BYTES_PRINTED
, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE
, NULL
},
2444 { END
, END
, "", END
, NULL
}
2447 /*******************************************************************
2448 Return the size of info_data structure.
2449 ********************************************************************/
2451 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2455 while (notify_info_data_table
[i
].type
!= END
)
2457 if ( (notify_info_data_table
[i
].type
== type
) &&
2458 (notify_info_data_table
[i
].field
== field
) )
2460 return (notify_info_data_table
[i
].size
);
2467 /*******************************************************************
2468 Return the type of notify_info_data.
2469 ********************************************************************/
2471 static BOOL
type_of_notify_info_data(uint16 type
, uint16 field
)
2475 while (notify_info_data_table
[i
].type
!= END
)
2477 if ( (notify_info_data_table
[i
].type
== type
) &&
2478 (notify_info_data_table
[i
].field
== field
) )
2480 if (notify_info_data_table
[i
].size
== POINTER
)
2494 /****************************************************************************
2495 ****************************************************************************/
2497 static int search_notify(uint16 type
, uint16 field
, int *value
)
2502 for (j
=0, found
=False
; found
==False
&& notify_info_data_table
[j
].type
!= END
; j
++)
2504 if ( (notify_info_data_table
[j
].type
== type
) &&
2505 (notify_info_data_table
[j
].field
== field
) )
2510 if ( found
&& (notify_info_data_table
[j
].fn
!= NULL
) )
2516 /****************************************************************************
2517 ****************************************************************************/
2519 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2521 info_data
->type
= type
;
2522 info_data
->field
= field
;
2523 info_data
->reserved
= 0;
2525 info_data
->size
= size_of_notify_info_data(type
, field
);
2526 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2530 /*******************************************************************
2532 * fill a notify_info struct with info asked
2534 ********************************************************************/
2536 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2537 snum
, SPOOL_NOTIFY_OPTION_TYPE
2538 *option_type
, uint32 id
,
2539 TALLOC_CTX
*mem_ctx
)
2545 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2546 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2547 print_queue_struct
*queue
=NULL
;
2549 type
=option_type
->type
;
2551 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2552 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2553 option_type
->count
, lp_servicename(snum
)));
2555 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2558 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2559 field
= option_type
->fields
[field_num
];
2560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2562 if (!search_notify(type
, field
, &j
) )
2565 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2569 else info
->data
= tid
;
2571 current_data
=&info
->data
[info
->count
];
2573 construct_info_data(current_data
, type
, field
, id
);
2575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2576 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
2578 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2584 free_a_printer(&printer
, 2);
2588 /*******************************************************************
2590 * fill a notify_info struct with info asked
2592 ********************************************************************/
2594 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
2595 SPOOL_NOTIFY_INFO
*info
,
2596 NT_PRINTER_INFO_LEVEL
*printer
,
2597 int snum
, SPOOL_NOTIFY_OPTION_TYPE
2598 *option_type
, uint32 id
,
2599 TALLOC_CTX
*mem_ctx
)
2605 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2607 DEBUG(4,("construct_notify_jobs_info\n"));
2609 type
= option_type
->type
;
2611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2612 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2613 option_type
->count
));
2615 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2616 field
= option_type
->fields
[field_num
];
2618 if (!search_notify(type
, field
, &j
) )
2621 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2625 else info
->data
= tid
;
2627 current_data
=&(info
->data
[info
->count
]);
2629 construct_info_data(current_data
, type
, field
, id
);
2630 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2639 * JFM: The enumeration is not that simple, it's even non obvious.
2641 * let's take an example: I want to monitor the PRINTER SERVER for
2642 * the printer's name and the number of jobs currently queued.
2643 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2644 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2646 * I have 3 printers on the back of my server.
2648 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2651 * 1 printer 1 name 1
2652 * 2 printer 1 cjob 1
2653 * 3 printer 2 name 2
2654 * 4 printer 2 cjob 2
2655 * 5 printer 3 name 3
2656 * 6 printer 3 name 3
2658 * that's the print server case, the printer case is even worse.
2661 /*******************************************************************
2663 * enumerate all printers on the printserver
2664 * fill a notify_info struct with info asked
2666 ********************************************************************/
2668 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
2669 SPOOL_NOTIFY_INFO
*info
,
2670 TALLOC_CTX
*mem_ctx
)
2673 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2674 int n_services
=lp_numservices();
2677 SPOOL_NOTIFY_OPTION
*option
;
2678 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2680 DEBUG(4,("printserver_notify_info\n"));
2685 option
=Printer
->notify
.option
;
2691 for (i
=0; i
<option
->count
; i
++) {
2692 option_type
=&(option
->ctr
.type
[i
]);
2694 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
2697 for (snum
=0; snum
<n_services
; snum
++)
2698 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
2699 if (construct_notify_printer_info
2700 (info
, snum
, option_type
, id
, mem_ctx
))
2705 * Debugging information, don't delete.
2708 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2709 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2710 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2712 for (i=0; i<info->count; i++) {
2713 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2714 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2715 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2722 /*******************************************************************
2724 * fill a notify_info struct with info asked
2726 ********************************************************************/
2728 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
2729 TALLOC_CTX
*mem_ctx
)
2732 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2735 SPOOL_NOTIFY_OPTION
*option
;
2736 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2738 print_queue_struct
*queue
=NULL
;
2739 print_status_struct status
;
2741 DEBUG(4,("printer_notify_info\n"));
2746 option
=Printer
->notify
.option
;
2752 get_printer_snum(p
, hnd
, &snum
);
2754 for (i
=0; i
<option
->count
; i
++) {
2755 option_type
=&option
->ctr
.type
[i
];
2757 switch ( option_type
->type
) {
2758 case PRINTER_NOTIFY_TYPE
:
2759 if(construct_notify_printer_info(info
, snum
,
2765 case JOB_NOTIFY_TYPE
: {
2766 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2768 count
= print_queue_status(snum
, &queue
, &status
);
2770 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
2771 lp_servicename(snum
))))
2774 for (j
=0; j
<count
; j
++) {
2775 construct_notify_jobs_info(&queue
[j
], info
,
2782 free_a_printer(&printer
, 2);
2792 * Debugging information, don't delete.
2795 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2796 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2797 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2799 for (i=0; i<info->count; i++) {
2800 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2801 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2802 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2808 /********************************************************************
2810 ********************************************************************/
2812 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
2814 POLICY_HND
*handle
= &q_u
->handle
;
2815 /* uint32 change = q_u->change; - notused. */
2816 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2817 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
2819 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2820 WERROR result
= WERR_BADFID
;
2822 /* we always have a NOTIFY_INFO struct */
2826 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2827 OUR_HANDLE(handle
)));
2831 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
2833 /* jfm: the change value isn't used right now.
2834 * we will honour it when
2835 * a) we'll be able to send notification to the client
2836 * b) we'll have a way to communicate between the spoolss process.
2838 * same thing for option->flags
2839 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2840 * I don't have a global notification system, I'm sending back all the
2841 * informations even when _NOTHING_ has changed.
2844 /* just ignore the SPOOL_NOTIFY_OPTION */
2846 switch (Printer
->printer_type
) {
2847 case PRINTER_HANDLE_IS_PRINTSERVER
:
2848 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
2851 case PRINTER_HANDLE_IS_PRINTER
:
2852 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
2860 /********************************************************************
2861 * construct_printer_info_0
2862 * fill a printer_info_0 struct
2863 ********************************************************************/
2865 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
2869 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2870 counter_printer_0
*session_counter
;
2871 uint32 global_counter
;
2874 print_status_struct status
;
2876 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2879 count
= print_queue_length(snum
, &status
);
2881 /* check if we already have a counter for this printer */
2882 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
2884 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
2885 if (session_counter
->snum
== snum
)
2889 /* it's the first time, add it to the list */
2890 if (session_counter
==NULL
) {
2891 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
2892 free_a_printer(&ntprinter
, 2);
2895 ZERO_STRUCTP(session_counter
);
2896 session_counter
->snum
=snum
;
2897 session_counter
->counter
=0;
2898 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
2902 session_counter
->counter
++;
2905 * the global_counter should be stored in a TDB as it's common to all the clients
2906 * and should be zeroed on samba startup
2908 global_counter
=session_counter
->counter
;
2910 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
2912 init_unistr(&printer
->printername
, chaine
);
2914 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
2915 init_unistr(&printer
->servername
, chaine
);
2917 printer
->cjobs
= count
;
2918 printer
->total_jobs
= 0;
2919 printer
->total_bytes
= 0;
2921 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
2922 t
=gmtime(&setuptime
);
2924 printer
->year
= t
->tm_year
+1900;
2925 printer
->month
= t
->tm_mon
+1;
2926 printer
->dayofweek
= t
->tm_wday
;
2927 printer
->day
= t
->tm_mday
;
2928 printer
->hour
= t
->tm_hour
;
2929 printer
->minute
= t
->tm_min
;
2930 printer
->second
= t
->tm_sec
;
2931 printer
->milliseconds
= 0;
2933 printer
->global_counter
= global_counter
;
2934 printer
->total_pages
= 0;
2936 printer
->major_version
= 0x0004; /* NT 4 */
2937 printer
->build_version
= 0x0565; /* build 1381 */
2939 printer
->major_version
= 0x0005; /* NT 5 */
2940 printer
->build_version
= 0x0893; /* build 2195 */
2942 printer
->unknown7
= 0x1;
2943 printer
->unknown8
= 0x0;
2944 printer
->unknown9
= 0x0;
2945 printer
->session_counter
= session_counter
->counter
;
2946 printer
->unknown11
= 0x0;
2947 printer
->printer_errors
= 0x0; /* number of print failure */
2948 printer
->unknown13
= 0x0;
2949 printer
->unknown14
= 0x1;
2950 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
2951 printer
->unknown16
= 0x0;
2952 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
2953 printer
->unknown18
= 0x0;
2954 printer
->status
= nt_printq_status(status
.status
);
2955 printer
->unknown20
= 0x0;
2956 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
2957 printer
->unknown22
= 0x0;
2958 printer
->unknown23
= 0x6; /* 6 ???*/
2959 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
2960 printer
->unknown25
= 0;
2961 printer
->unknown26
= 0;
2962 printer
->unknown27
= 0;
2963 printer
->unknown28
= 0;
2964 printer
->unknown29
= 0;
2966 free_a_printer(&ntprinter
,2);
2970 /********************************************************************
2971 * construct_printer_info_1
2972 * fill a printer_info_1 struct
2973 ********************************************************************/
2975 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
2979 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2981 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2984 printer
->flags
=flags
;
2986 if (*ntprinter
->info_2
->comment
== '\0') {
2987 init_unistr(&printer
->comment
, lp_comment(snum
));
2988 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
2989 ntprinter
->info_2
->drivername
, lp_comment(snum
));
2992 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2993 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
2994 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
2997 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
2999 init_unistr(&printer
->description
, chaine
);
3000 init_unistr(&printer
->name
, chaine2
);
3002 free_a_printer(&ntprinter
,2);
3007 /****************************************************************************
3008 Free a DEVMODE struct.
3009 ****************************************************************************/
3011 static void free_dev_mode(DEVICEMODE
*dev
)
3016 SAFE_FREE(dev
->private);
3020 /****************************************************************************
3021 Create a DEVMODE struct. Returns malloced memory.
3022 ****************************************************************************/
3024 static DEVICEMODE
*construct_dev_mode(int snum
)
3028 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3029 NT_DEVICEMODE
*ntdevmode
= NULL
;
3030 DEVICEMODE
*devmode
= NULL
;
3032 DEBUG(7,("construct_dev_mode\n"));
3034 DEBUGADD(8,("getting printer characteristics\n"));
3036 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3037 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3041 ZERO_STRUCTP(devmode
);
3043 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3046 if (printer
->info_2
->devmode
)
3047 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
3049 if (ntdevmode
== NULL
)
3052 DEBUGADD(8,("loading DEVICEMODE\n"));
3054 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
3055 init_unistr(&devmode
->devicename
, adevice
);
3057 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
3058 init_unistr(&devmode
->formname
, aform
);
3060 devmode
->specversion
= ntdevmode
->specversion
;
3061 devmode
->driverversion
= ntdevmode
->driverversion
;
3062 devmode
->size
= ntdevmode
->size
;
3063 devmode
->driverextra
= ntdevmode
->driverextra
;
3064 devmode
->fields
= ntdevmode
->fields
;
3066 devmode
->orientation
= ntdevmode
->orientation
;
3067 devmode
->papersize
= ntdevmode
->papersize
;
3068 devmode
->paperlength
= ntdevmode
->paperlength
;
3069 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3070 devmode
->scale
= ntdevmode
->scale
;
3071 devmode
->copies
= ntdevmode
->copies
;
3072 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3073 devmode
->printquality
= ntdevmode
->printquality
;
3074 devmode
->color
= ntdevmode
->color
;
3075 devmode
->duplex
= ntdevmode
->duplex
;
3076 devmode
->yresolution
= ntdevmode
->yresolution
;
3077 devmode
->ttoption
= ntdevmode
->ttoption
;
3078 devmode
->collate
= ntdevmode
->collate
;
3079 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3080 devmode
->icmintent
= ntdevmode
->icmintent
;
3081 devmode
->mediatype
= ntdevmode
->mediatype
;
3082 devmode
->dithertype
= ntdevmode
->dithertype
;
3084 if (ntdevmode
->private != NULL
) {
3085 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3089 free_nt_devicemode(&ntdevmode
);
3090 free_a_printer(&printer
,2);
3097 free_nt_devicemode(&ntdevmode
);
3099 free_a_printer(&printer
,2);
3100 free_dev_mode(devmode
);
3105 /********************************************************************
3106 * construct_printer_info_2
3107 * fill a printer_info_2 struct
3108 ********************************************************************/
3110 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
3113 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3115 print_status_struct status
;
3117 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3120 count
= print_queue_length(snum
, &status
);
3122 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3123 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3124 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
3125 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
3126 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
3128 if (*ntprinter
->info_2
->comment
== '\0')
3129 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
3131 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3133 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
3134 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
3135 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
3136 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
3137 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
3139 printer
->attributes
= ntprinter
->info_2
->attributes
;
3141 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
3142 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
3143 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
3144 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
3145 printer
->status
= nt_printq_status(status
.status
); /* status */
3146 printer
->cjobs
= count
; /* jobs */
3147 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
3149 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
3150 DEBUG(8, ("Returning NULL Devicemode!\n"));
3153 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3154 /* steal the printer info sec_desc structure. [badly done]. */
3155 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3156 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
3157 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
3158 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
3161 printer
->secdesc
= NULL
;
3164 free_a_printer(&ntprinter
, 2);
3168 /********************************************************************
3169 * construct_printer_info_3
3170 * fill a printer_info_3 struct
3171 ********************************************************************/
3173 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
3175 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3176 PRINTER_INFO_3
*printer
= NULL
;
3178 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3182 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
3183 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3187 ZERO_STRUCTP(printer
);
3189 printer
->flags
= 4; /* These are the components of the SD we are returning. */
3190 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3191 /* steal the printer info sec_desc structure. [badly done]. */
3192 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3196 * Set the flags for the components we are returning.
3199 if (printer
->secdesc
->owner_sid
)
3200 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
3202 if (printer
->secdesc
->grp_sid
)
3203 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
3205 if (printer
->secdesc
->dacl
)
3206 printer
->flags
|= DACL_SECURITY_INFORMATION
;
3208 if (printer
->secdesc
->sacl
)
3209 printer
->flags
|= SACL_SECURITY_INFORMATION
;
3212 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
3213 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
3214 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
3217 free_a_printer(&ntprinter
, 2);
3219 *pp_printer
= printer
;
3223 /********************************************************************
3224 * construct_printer_info_4
3225 * fill a printer_info_4 struct
3226 ********************************************************************/
3228 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
3230 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3232 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3235 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3236 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3237 printer
->attributes
= ntprinter
->info_2
->attributes
;
3239 free_a_printer(&ntprinter
, 2);
3243 /********************************************************************
3244 * construct_printer_info_5
3245 * fill a printer_info_5 struct
3246 ********************************************************************/
3248 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
3250 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3252 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3255 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3256 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
3257 printer
->attributes
= ntprinter
->info_2
->attributes
;
3258 printer
->device_not_selected_timeout
= 0x3a98;
3259 printer
->transmission_retry_timeout
= 0xafc8;
3261 free_a_printer(&ntprinter
, 2);
3265 /********************************************************************
3266 Spoolss_enumprinters.
3267 ********************************************************************/
3269 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3273 int n_services
=lp_numservices();
3274 PRINTER_INFO_1
*tp
, *printers
=NULL
;
3275 PRINTER_INFO_1 current_prt
;
3277 DEBUG(4,("enum_all_printers_info_1\n"));
3279 for (snum
=0; snum
<n_services
; snum
++) {
3280 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3281 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3283 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
3284 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
3285 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3286 SAFE_FREE(printers
);
3291 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
3293 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
3299 /* check the required size. */
3300 for (i
=0; i
<*returned
; i
++)
3301 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
3303 if (!alloc_buffer_size(buffer
, *needed
))
3304 return WERR_INSUFFICIENT_BUFFER
;
3306 /* fill the buffer with the structures */
3307 for (i
=0; i
<*returned
; i
++)
3308 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
3311 SAFE_FREE(printers
);
3313 if (*needed
> offered
) {
3315 return WERR_INSUFFICIENT_BUFFER
;
3321 /********************************************************************
3322 enum_all_printers_info_1_local.
3323 *********************************************************************/
3325 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3327 DEBUG(4,("enum_all_printers_info_1_local\n"));
3329 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3332 /********************************************************************
3333 enum_all_printers_info_1_name.
3334 *********************************************************************/
3336 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3340 DEBUG(4,("enum_all_printers_info_1_name\n"));
3342 if ((name
[0] == '\\') && (name
[1] == '\\'))
3345 if (is_myname_or_ipaddr(s
)) {
3346 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3349 return WERR_INVALID_NAME
;
3352 /********************************************************************
3353 enum_all_printers_info_1_remote.
3354 *********************************************************************/
3356 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3358 PRINTER_INFO_1
*printer
;
3359 fstring printername
;
3362 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3364 /* JFM: currently it's more a place holder than anything else.
3365 * In the spooler world there is a notion of server registration.
3366 * the print servers are registring (sp ?) on the PDC (in the same domain)
3368 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3371 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3376 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3377 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
3378 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3380 init_unistr(&printer
->description
, desc
);
3381 init_unistr(&printer
->name
, printername
);
3382 init_unistr(&printer
->comment
, comment
);
3383 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3385 /* check the required size. */
3386 *needed
+= spoolss_size_printer_info_1(printer
);
3388 if (!alloc_buffer_size(buffer
, *needed
)) {
3390 return WERR_INSUFFICIENT_BUFFER
;
3393 /* fill the buffer with the structures */
3394 smb_io_printer_info_1("", buffer
, printer
, 0);
3399 if (*needed
> offered
) {
3401 return WERR_INSUFFICIENT_BUFFER
;
3407 /********************************************************************
3408 enum_all_printers_info_1_network.
3409 *********************************************************************/
3411 static WERROR
enum_all_printers_info_1_network(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3413 DEBUG(4,("enum_all_printers_info_1_network\n"));
3415 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3418 /********************************************************************
3419 * api_spoolss_enumprinters
3421 * called from api_spoolss_enumprinters (see this to understand)
3422 ********************************************************************/
3424 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3428 int n_services
=lp_numservices();
3429 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3430 PRINTER_INFO_2 current_prt
;
3432 for (snum
=0; snum
<n_services
; snum
++) {
3433 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3434 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3436 if (construct_printer_info_2(¤t_prt
, snum
)) {
3437 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3438 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3439 SAFE_FREE(printers
);
3444 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3445 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3451 /* check the required size. */
3452 for (i
=0; i
<*returned
; i
++)
3453 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3455 if (!alloc_buffer_size(buffer
, *needed
)) {
3456 for (i
=0; i
<*returned
; i
++) {
3457 free_devmode(printers
[i
].devmode
);
3459 SAFE_FREE(printers
);
3460 return WERR_INSUFFICIENT_BUFFER
;
3463 /* fill the buffer with the structures */
3464 for (i
=0; i
<*returned
; i
++)
3465 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3468 for (i
=0; i
<*returned
; i
++) {
3469 free_devmode(printers
[i
].devmode
);
3471 SAFE_FREE(printers
);
3473 if (*needed
> offered
) {
3475 return WERR_INSUFFICIENT_BUFFER
;
3481 /********************************************************************
3482 * handle enumeration of printers at level 1
3483 ********************************************************************/
3485 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3486 NEW_BUFFER
*buffer
, uint32 offered
,
3487 uint32
*needed
, uint32
*returned
)
3489 /* Not all the flags are equals */
3491 if (flags
& PRINTER_ENUM_LOCAL
)
3492 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3494 if (flags
& PRINTER_ENUM_NAME
)
3495 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3497 if (flags
& PRINTER_ENUM_REMOTE
)
3498 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3500 if (flags
& PRINTER_ENUM_NETWORK
)
3501 return enum_all_printers_info_1_network(buffer
, offered
, needed
, returned
);
3503 return WERR_OK
; /* NT4sp5 does that */
3506 /********************************************************************
3507 * handle enumeration of printers at level 2
3508 ********************************************************************/
3510 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3511 NEW_BUFFER
*buffer
, uint32 offered
,
3512 uint32
*needed
, uint32
*returned
)
3514 char *s
= servername
;
3516 if (flags
& PRINTER_ENUM_LOCAL
) {
3517 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3520 if (flags
& PRINTER_ENUM_NAME
) {
3521 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3523 if (is_myname_or_ipaddr(s
))
3524 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3526 return WERR_INVALID_NAME
;
3529 if (flags
& PRINTER_ENUM_REMOTE
)
3530 return WERR_UNKNOWN_LEVEL
;
3535 /********************************************************************
3536 * handle enumeration of printers at level 5
3537 ********************************************************************/
3539 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3540 NEW_BUFFER
*buffer
, uint32 offered
,
3541 uint32
*needed
, uint32
*returned
)
3543 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3547 /********************************************************************
3548 * api_spoolss_enumprinters
3550 * called from api_spoolss_enumprinters (see this to understand)
3551 ********************************************************************/
3553 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3555 uint32 flags
= q_u
->flags
;
3556 UNISTR2
*servername
= &q_u
->servername
;
3557 uint32 level
= q_u
->level
;
3558 NEW_BUFFER
*buffer
= NULL
;
3559 uint32 offered
= q_u
->offered
;
3560 uint32
*needed
= &r_u
->needed
;
3561 uint32
*returned
= &r_u
->returned
;
3565 /* that's an [in out] buffer */
3566 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3567 buffer
= r_u
->buffer
;
3569 DEBUG(4,("_spoolss_enumprinters\n"));
3576 * flags==PRINTER_ENUM_NAME
3577 * if name=="" then enumerates all printers
3578 * if name!="" then enumerate the printer
3579 * flags==PRINTER_ENUM_REMOTE
3580 * name is NULL, enumerate printers
3581 * Level 2: name!="" enumerates printers, name can't be NULL
3582 * Level 3: doesn't exist
3583 * Level 4: does a local registry lookup
3584 * Level 5: same as Level 2
3587 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
3592 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
3594 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
3596 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
3601 return WERR_UNKNOWN_LEVEL
;
3604 /****************************************************************************
3605 ****************************************************************************/
3607 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3609 PRINTER_INFO_0
*printer
=NULL
;
3611 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
3614 construct_printer_info_0(printer
, snum
);
3616 /* check the required size. */
3617 *needed
+= spoolss_size_printer_info_0(printer
);
3619 if (!alloc_buffer_size(buffer
, *needed
)) {
3621 return WERR_INSUFFICIENT_BUFFER
;
3624 /* fill the buffer with the structures */
3625 smb_io_printer_info_0("", buffer
, printer
, 0);
3630 if (*needed
> offered
) {
3631 return WERR_INSUFFICIENT_BUFFER
;
3637 /****************************************************************************
3638 ****************************************************************************/
3640 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3642 PRINTER_INFO_1
*printer
=NULL
;
3644 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3647 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
3649 /* check the required size. */
3650 *needed
+= spoolss_size_printer_info_1(printer
);
3652 if (!alloc_buffer_size(buffer
, *needed
)) {
3654 return WERR_INSUFFICIENT_BUFFER
;
3657 /* fill the buffer with the structures */
3658 smb_io_printer_info_1("", buffer
, printer
, 0);
3663 if (*needed
> offered
) {
3664 return WERR_INSUFFICIENT_BUFFER
;
3670 /****************************************************************************
3671 ****************************************************************************/
3673 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3675 PRINTER_INFO_2
*printer
=NULL
;
3677 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
3680 construct_printer_info_2(printer
, snum
);
3682 /* check the required size. */
3683 *needed
+= spoolss_size_printer_info_2(printer
);
3685 if (!alloc_buffer_size(buffer
, *needed
)) {
3686 free_printer_info_2(printer
);
3687 return WERR_INSUFFICIENT_BUFFER
;
3690 /* fill the buffer with the structures */
3691 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
3692 free_printer_info_2(printer
);
3697 free_printer_info_2(printer
);
3699 if (*needed
> offered
) {
3700 return WERR_INSUFFICIENT_BUFFER
;
3706 /****************************************************************************
3707 ****************************************************************************/
3709 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3711 PRINTER_INFO_3
*printer
=NULL
;
3713 if (!construct_printer_info_3(&printer
, snum
))
3716 /* check the required size. */
3717 *needed
+= spoolss_size_printer_info_3(printer
);
3719 if (!alloc_buffer_size(buffer
, *needed
)) {
3720 free_printer_info_3(printer
);
3721 return WERR_INSUFFICIENT_BUFFER
;
3724 /* fill the buffer with the structures */
3725 smb_io_printer_info_3("", buffer
, printer
, 0);
3728 free_printer_info_3(printer
);
3730 if (*needed
> offered
) {
3731 return WERR_INSUFFICIENT_BUFFER
;
3737 /****************************************************************************
3738 ****************************************************************************/
3740 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3742 PRINTER_INFO_4
*printer
=NULL
;
3744 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
3747 if (!construct_printer_info_4(printer
, snum
))
3750 /* check the required size. */
3751 *needed
+= spoolss_size_printer_info_4(printer
);
3753 if (!alloc_buffer_size(buffer
, *needed
)) {
3754 free_printer_info_4(printer
);
3755 return WERR_INSUFFICIENT_BUFFER
;
3758 /* fill the buffer with the structures */
3759 smb_io_printer_info_4("", buffer
, printer
, 0);
3762 free_printer_info_4(printer
);
3764 if (*needed
> offered
) {
3765 return WERR_INSUFFICIENT_BUFFER
;
3771 /****************************************************************************
3772 ****************************************************************************/
3774 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3776 PRINTER_INFO_5
*printer
=NULL
;
3778 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
3781 if (!construct_printer_info_5(printer
, snum
))
3784 /* check the required size. */
3785 *needed
+= spoolss_size_printer_info_5(printer
);
3787 if (!alloc_buffer_size(buffer
, *needed
)) {
3788 free_printer_info_5(printer
);
3789 return WERR_INSUFFICIENT_BUFFER
;
3792 /* fill the buffer with the structures */
3793 smb_io_printer_info_5("", buffer
, printer
, 0);
3796 free_printer_info_5(printer
);
3798 if (*needed
> offered
) {
3799 return WERR_INSUFFICIENT_BUFFER
;
3805 /****************************************************************************
3806 ****************************************************************************/
3808 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
3810 POLICY_HND
*handle
= &q_u
->handle
;
3811 uint32 level
= q_u
->level
;
3812 NEW_BUFFER
*buffer
= NULL
;
3813 uint32 offered
= q_u
->offered
;
3814 uint32
*needed
= &r_u
->needed
;
3818 /* that's an [in out] buffer */
3819 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3820 buffer
= r_u
->buffer
;
3824 if (!get_printer_snum(p
, handle
, &snum
))
3829 return getprinter_level_0(snum
, buffer
, offered
, needed
);
3831 return getprinter_level_1(snum
, buffer
, offered
, needed
);
3833 return getprinter_level_2(snum
, buffer
, offered
, needed
);
3835 return getprinter_level_3(snum
, buffer
, offered
, needed
);
3837 return getprinter_level_4(snum
, buffer
, offered
, needed
);
3839 return getprinter_level_5(snum
, buffer
, offered
, needed
);
3841 return WERR_UNKNOWN_LEVEL
;
3844 /********************************************************************
3845 * fill a DRIVER_INFO_1 struct
3846 ********************************************************************/
3848 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
3850 init_unistr( &info
->name
, driver
.info_3
->name
);
3853 /********************************************************************
3854 * construct_printer_driver_info_1
3855 ********************************************************************/
3857 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3859 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3860 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3862 ZERO_STRUCT(driver
);
3864 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3865 return WERR_INVALID_PRINTER_NAME
;
3867 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3868 return WERR_UNKNOWN_PRINTER_DRIVER
;
3870 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
3872 free_a_printer(&printer
,2);
3877 /********************************************************************
3878 * construct_printer_driver_info_2
3879 * fill a printer_info_2 struct
3880 ********************************************************************/
3882 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3886 info
->version
=driver
.info_3
->cversion
;
3888 init_unistr( &info
->name
, driver
.info_3
->name
);
3889 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3892 if (strlen(driver
.info_3
->driverpath
)) {
3893 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3894 init_unistr( &info
->driverpath
, temp
);
3896 init_unistr( &info
->driverpath
, "" );
3898 if (strlen(driver
.info_3
->datafile
)) {
3899 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3900 init_unistr( &info
->datafile
, temp
);
3902 init_unistr( &info
->datafile
, "" );
3904 if (strlen(driver
.info_3
->configfile
)) {
3905 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3906 init_unistr( &info
->configfile
, temp
);
3908 init_unistr( &info
->configfile
, "" );
3911 /********************************************************************
3912 * construct_printer_driver_info_2
3913 * fill a printer_info_2 struct
3914 ********************************************************************/
3916 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3918 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3919 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3921 ZERO_STRUCT(printer
);
3922 ZERO_STRUCT(driver
);
3924 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3925 return WERR_INVALID_PRINTER_NAME
;
3927 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3928 return WERR_UNKNOWN_PRINTER_DRIVER
;
3930 fill_printer_driver_info_2(info
, driver
, servername
);
3932 free_a_printer(&printer
,2);
3937 /********************************************************************
3938 * copy a strings array and convert to UNICODE
3940 * convert an array of ascii string to a UNICODE string
3941 ********************************************************************/
3943 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
3951 DEBUG(6,("init_unistr_array\n"));
3955 if (char_array
== NULL
)
3959 if (!v
) v
= ""; /* hack to handle null lists */
3961 if (strlen(v
) == 0) break;
3962 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
3963 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
3964 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
3965 DEBUG(2,("init_unistr_array: Realloc error\n" ));
3969 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, 0)/ sizeof(uint16
));
3974 (*uni_array
)[j
]=0x0000;
3977 DEBUGADD(6,("last one:done\n"));
3980 /********************************************************************
3981 * construct_printer_info_3
3982 * fill a printer_info_3 struct
3983 ********************************************************************/
3985 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3991 info
->version
=driver
.info_3
->cversion
;
3993 init_unistr( &info
->name
, driver
.info_3
->name
);
3994 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3996 if (strlen(driver
.info_3
->driverpath
)) {
3997 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3998 init_unistr( &info
->driverpath
, temp
);
4000 init_unistr( &info
->driverpath
, "" );
4002 if (strlen(driver
.info_3
->datafile
)) {
4003 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4004 init_unistr( &info
->datafile
, temp
);
4006 init_unistr( &info
->datafile
, "" );
4008 if (strlen(driver
.info_3
->configfile
)) {
4009 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4010 init_unistr( &info
->configfile
, temp
);
4012 init_unistr( &info
->configfile
, "" );
4014 if (strlen(driver
.info_3
->helpfile
)) {
4015 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4016 init_unistr( &info
->helpfile
, temp
);
4018 init_unistr( &info
->helpfile
, "" );
4020 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4021 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4023 info
->dependentfiles
=NULL
;
4024 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4027 /********************************************************************
4028 * construct_printer_info_3
4029 * fill a printer_info_3 struct
4030 ********************************************************************/
4032 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4034 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4035 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4037 ZERO_STRUCT(driver
);
4039 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4040 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4041 if (!W_ERROR_IS_OK(status
))
4042 return WERR_INVALID_PRINTER_NAME
;
4044 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4045 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4050 * I put this code in during testing. Helpful when commenting out the
4051 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4052 * as win2k always queries the driver using an infor level of 6.
4053 * I've left it in (but ifdef'd out) because I'll probably
4054 * use it in experimentation again in the future. --jerry 22/01/2002
4057 if (!W_ERROR_IS_OK(status
)) {
4059 * Is this a W2k client ?
4062 /* Yes - try again with a WinNT driver. */
4064 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4065 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4069 if (!W_ERROR_IS_OK(status
)) {
4070 free_a_printer(&printer
,2);
4071 return WERR_UNKNOWN_PRINTER_DRIVER
;
4079 fill_printer_driver_info_3(info
, driver
, servername
);
4081 free_a_printer(&printer
,2);
4086 /********************************************************************
4087 * construct_printer_info_6
4088 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4089 ********************************************************************/
4091 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4097 memset(&nullstr
, '\0', sizeof(fstring
));
4099 info
->version
=driver
.info_3
->cversion
;
4101 init_unistr( &info
->name
, driver
.info_3
->name
);
4102 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4104 if (strlen(driver
.info_3
->driverpath
)) {
4105 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4106 init_unistr( &info
->driverpath
, temp
);
4108 init_unistr( &info
->driverpath
, "" );
4110 if (strlen(driver
.info_3
->datafile
)) {
4111 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4112 init_unistr( &info
->datafile
, temp
);
4114 init_unistr( &info
->datafile
, "" );
4116 if (strlen(driver
.info_3
->configfile
)) {
4117 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4118 init_unistr( &info
->configfile
, temp
);
4120 init_unistr( &info
->configfile
, "" );
4122 if (strlen(driver
.info_3
->helpfile
)) {
4123 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4124 init_unistr( &info
->helpfile
, temp
);
4126 init_unistr( &info
->helpfile
, "" );
4128 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4129 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4131 info
->dependentfiles
=NULL
;
4132 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4134 info
->previousdrivernames
=NULL
;
4135 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
4137 info
->driver_date
.low
=0;
4138 info
->driver_date
.high
=0;
4141 info
->driver_version_low
=0;
4142 info
->driver_version_high
=0;
4144 init_unistr( &info
->mfgname
, "");
4145 init_unistr( &info
->oem_url
, "");
4146 init_unistr( &info
->hardware_id
, "");
4147 init_unistr( &info
->provider
, "");
4150 /********************************************************************
4151 * construct_printer_info_6
4152 * fill a printer_info_6 struct
4153 ********************************************************************/
4155 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4157 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4158 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4160 ZERO_STRUCT(driver
);
4162 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4163 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4164 if (!W_ERROR_IS_OK(status
))
4165 return WERR_INVALID_PRINTER_NAME
;
4167 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4168 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4169 if (!W_ERROR_IS_OK(status
)) {
4171 * Is this a W2k client ?
4175 free_a_printer(&printer
,2);
4176 return WERR_UNKNOWN_PRINTER_DRIVER
;
4179 /* Yes - try again with a WinNT driver. */
4181 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4182 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4183 if (!W_ERROR_IS_OK(status
)) {
4184 free_a_printer(&printer
,2);
4185 return WERR_UNKNOWN_PRINTER_DRIVER
;
4189 fill_printer_driver_info_6(info
, driver
, servername
);
4191 free_a_printer(&printer
,2);
4196 /****************************************************************************
4197 ****************************************************************************/
4199 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
4201 SAFE_FREE(info
->dependentfiles
);
4204 /****************************************************************************
4205 ****************************************************************************/
4207 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
4209 SAFE_FREE(info
->dependentfiles
);
4213 /****************************************************************************
4214 ****************************************************************************/
4216 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4218 DRIVER_INFO_1
*info
=NULL
;
4221 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
4224 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
4225 if (!W_ERROR_IS_OK(status
)) {
4230 /* check the required size. */
4231 *needed
+= spoolss_size_printer_driver_info_1(info
);
4233 if (!alloc_buffer_size(buffer
, *needed
)) {
4235 return WERR_INSUFFICIENT_BUFFER
;
4238 /* fill the buffer with the structures */
4239 smb_io_printer_driver_info_1("", buffer
, info
, 0);
4244 if (*needed
> offered
)
4245 return WERR_INSUFFICIENT_BUFFER
;
4250 /****************************************************************************
4251 ****************************************************************************/
4253 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4255 DRIVER_INFO_2
*info
=NULL
;
4258 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
4261 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
4262 if (!W_ERROR_IS_OK(status
)) {
4267 /* check the required size. */
4268 *needed
+= spoolss_size_printer_driver_info_2(info
);
4270 if (!alloc_buffer_size(buffer
, *needed
)) {
4272 return WERR_INSUFFICIENT_BUFFER
;
4275 /* fill the buffer with the structures */
4276 smb_io_printer_driver_info_2("", buffer
, info
, 0);
4281 if (*needed
> offered
)
4282 return WERR_INSUFFICIENT_BUFFER
;
4287 /****************************************************************************
4288 ****************************************************************************/
4290 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4297 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
4298 if (!W_ERROR_IS_OK(status
)) {
4302 /* check the required size. */
4303 *needed
+= spoolss_size_printer_driver_info_3(&info
);
4305 if (!alloc_buffer_size(buffer
, *needed
)) {
4306 free_printer_driver_info_3(&info
);
4307 return WERR_INSUFFICIENT_BUFFER
;
4310 /* fill the buffer with the structures */
4311 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
4313 free_printer_driver_info_3(&info
);
4315 if (*needed
> offered
)
4316 return WERR_INSUFFICIENT_BUFFER
;
4321 /****************************************************************************
4322 ****************************************************************************/
4324 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4331 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
4332 if (!W_ERROR_IS_OK(status
)) {
4336 /* check the required size. */
4337 *needed
+= spoolss_size_printer_driver_info_6(&info
);
4339 if (!alloc_buffer_size(buffer
, *needed
)) {
4340 free_printer_driver_info_6(&info
);
4341 return WERR_INSUFFICIENT_BUFFER
;
4344 /* fill the buffer with the structures */
4345 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
4347 free_printer_driver_info_6(&info
);
4349 if (*needed
> offered
)
4350 return WERR_INSUFFICIENT_BUFFER
;
4355 /****************************************************************************
4356 ****************************************************************************/
4358 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
4360 POLICY_HND
*handle
= &q_u
->handle
;
4361 UNISTR2
*uni_arch
= &q_u
->architecture
;
4362 uint32 level
= q_u
->level
;
4363 uint32 clientmajorversion
= q_u
->clientmajorversion
;
4364 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4365 NEW_BUFFER
*buffer
= NULL
;
4366 uint32 offered
= q_u
->offered
;
4367 uint32
*needed
= &r_u
->needed
;
4368 uint32
*servermajorversion
= &r_u
->servermajorversion
;
4369 uint32
*serverminorversion
= &r_u
->serverminorversion
;
4372 fstring architecture
;
4375 /* that's an [in out] buffer */
4376 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4377 buffer
= r_u
->buffer
;
4379 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4382 *servermajorversion
=0;
4383 *serverminorversion
=0;
4385 pstrcpy(servername
, get_called_name());
4386 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
4388 if (!get_printer_snum(p
, handle
, &snum
))
4393 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4395 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4397 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4399 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4402 return WERR_UNKNOWN_LEVEL
;
4405 /****************************************************************************
4406 ****************************************************************************/
4408 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
4410 POLICY_HND
*handle
= &q_u
->handle
;
4412 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4415 DEBUG(3,("Error in startpageprinter printer handle\n"));
4419 Printer
->page_started
=True
;
4423 /****************************************************************************
4424 ****************************************************************************/
4426 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
4428 POLICY_HND
*handle
= &q_u
->handle
;
4430 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4433 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
4437 Printer
->page_started
=False
;
4438 print_job_endpage(Printer
->jobid
);
4443 /********************************************************************
4444 * api_spoolss_getprinter
4445 * called from the spoolss dispatcher
4447 ********************************************************************/
4449 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
4451 POLICY_HND
*handle
= &q_u
->handle
;
4452 /* uint32 level = q_u->doc_info_container.level; - notused. */
4453 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
4454 uint32
*jobid
= &r_u
->jobid
;
4456 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
4460 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4461 struct current_user user
;
4464 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4468 get_current_user(&user
, p
);
4471 * a nice thing with NT is it doesn't listen to what you tell it.
4472 * when asked to send _only_ RAW datas, it tries to send datas
4475 * So I add checks like in NT Server ...
4477 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4478 * there's a bug in NT client-side code, so we'll fix it in the
4479 * server-side code. *nnnnnggggh!*
4482 if (info_1
->p_datatype
!= 0) {
4483 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
4484 if (strcmp(datatype
, "RAW") != 0) {
4486 return WERR_INVALID_DATATYPE
;
4490 /* get the share number of the printer */
4491 if (!get_printer_snum(p
, handle
, &snum
)) {
4495 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
4497 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4499 /* An error occured in print_job_start() so return an appropriate
4502 if (Printer
->jobid
== -1) {
4503 return map_werror_from_unix(errno
);
4506 Printer
->document_started
=True
;
4507 (*jobid
) = Printer
->jobid
;
4512 /********************************************************************
4513 * api_spoolss_getprinter
4514 * called from the spoolss dispatcher
4516 ********************************************************************/
4518 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4520 POLICY_HND
*handle
= &q_u
->handle
;
4522 return _spoolss_enddocprinter_internal(p
, handle
);
4525 /****************************************************************************
4526 ****************************************************************************/
4528 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4530 POLICY_HND
*handle
= &q_u
->handle
;
4531 uint32 buffer_size
= q_u
->buffer_size
;
4532 uint8
*buffer
= q_u
->buffer
;
4533 uint32
*buffer_written
= &q_u
->buffer_size2
;
4535 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4538 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
4539 r_u
->buffer_written
= q_u
->buffer_size2
;
4543 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
, buffer_size
);
4546 r_u
->buffer_written
= q_u
->buffer_size2
;
4551 /********************************************************************
4552 * api_spoolss_getprinter
4553 * called from the spoolss dispatcher
4555 ********************************************************************/
4557 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
4560 struct current_user user
;
4562 WERROR errcode
= WERR_BADFUNC
;
4563 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4565 get_current_user(&user
, p
);
4568 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4572 if (!get_printer_snum(p
, handle
, &snum
))
4576 case PRINTER_CONTROL_PAUSE
:
4577 if (print_queue_pause(&user
, snum
, &errcode
)) {
4581 case PRINTER_CONTROL_RESUME
:
4582 case PRINTER_CONTROL_UNPAUSE
:
4583 if (print_queue_resume(&user
, snum
, &errcode
)) {
4587 case PRINTER_CONTROL_PURGE
:
4588 if (print_queue_purge(&user
, snum
, &errcode
)) {
4593 return WERR_UNKNOWN_LEVEL
;
4599 /********************************************************************
4600 * api_spoolss_abortprinter
4601 ********************************************************************/
4603 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
4605 POLICY_HND
*handle
= &q_u
->handle
;
4607 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
4610 /********************************************************************
4611 * called by spoolss_api_setprinter
4612 * when updating a printer description
4613 ********************************************************************/
4615 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
4616 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4617 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
4619 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
4620 struct current_user user
;
4624 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4626 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
4627 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4628 OUR_HANDLE(handle
)));
4630 result
= WERR_BADFID
;
4634 /* NT seems to like setting the security descriptor even though
4635 nothing may have actually changed. This causes annoying
4636 dialog boxes when the user doesn't have permission to change
4637 the security descriptor. */
4639 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
4641 if (DEBUGLEVEL
>= 10) {
4645 the_acl
= old_secdesc_ctr
->sec
->dacl
;
4646 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4647 PRINTERNAME(snum
), the_acl
->num_aces
));
4649 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4652 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4654 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4655 the_acl
->ace
[i
].info
.mask
));
4658 the_acl
= secdesc_ctr
->sec
->dacl
;
4661 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4662 PRINTERNAME(snum
), the_acl
->num_aces
));
4664 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4667 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4669 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4670 the_acl
->ace
[i
].info
.mask
));
4673 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4677 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
4679 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
4684 /* Work out which user is performing the operation */
4686 get_current_user(&user
, p
);
4688 /* Check the user has permissions to change the security
4689 descriptor. By experimentation with two NT machines, the user
4690 requires Full Access to the printer to change security
4693 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4694 result
= WERR_ACCESS_DENIED
;
4698 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
4705 /********************************************************************
4706 Do Samba sanity checks on a printer info struct.
4707 this has changed purpose: it now "canonicalises" printer
4708 info from a client rather than just checking it is correct
4709 ********************************************************************/
4711 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
4713 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4714 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
4716 /* we force some elements to "correct" values */
4717 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
4718 fstrcpy(info
->sharename
, lp_servicename(snum
));
4719 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
4720 get_called_name(), info
->sharename
);
4721 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
4726 /****************************************************************************
4727 ****************************************************************************/
4729 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
4731 char *cmd
= lp_addprinter_cmd();
4734 pstring driverlocation
;
4738 fstring remote_machine
= "%m";
4740 /* build driver path... only 9X architecture is needed for legacy reasons */
4741 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
4743 /* change \ to \\ for the shell */
4744 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
4746 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4747 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
4748 printer
->info_2
->portname
, printer
->info_2
->drivername
,
4749 printer
->info_2
->location
, driverlocation
, remote_machine
);
4751 /* Convert script args to unix-codepage */
4752 DEBUG(10,("Running [%s]\n", command
));
4753 ret
= smbrun(command
, &fd
);
4754 DEBUGADD(10,("returned [%d]\n", ret
));
4763 /* Get lines and convert them back to dos-codepage */
4764 qlines
= fd_lines_load(fd
, &numlines
);
4765 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4769 /* Set the portname to what the script says the portname should be. */
4770 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
4771 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
4773 /* Send SIGHUP to process group... is there a better way? */
4778 file_lines_free(qlines
);
4784 /* Return true if two devicemodes are equal */
4786 #define DEVMODE_CHECK_INT(field) \
4787 if (d1->field != d2->field) { \
4788 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4789 d1->field, d2->field)); \
4793 /************************************************************************
4794 Handy, but currently unused functions
4795 ***********************************************************************/
4797 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
4799 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
4802 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4803 return False
; /* if either is exclusively NULL are not equal */
4806 if (!strequal(d1
->devicename
, d2
->devicename
)) {
4807 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1
->devicename
, d2
->devicename
));
4811 if (!strequal(d1
->formname
, d2
->formname
)) {
4812 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1
->formname
, d2
->formname
));
4816 DEVMODE_CHECK_INT(specversion
);
4817 DEVMODE_CHECK_INT(driverversion
);
4818 DEVMODE_CHECK_INT(driverextra
);
4819 DEVMODE_CHECK_INT(orientation
);
4820 DEVMODE_CHECK_INT(papersize
);
4821 DEVMODE_CHECK_INT(paperlength
);
4822 DEVMODE_CHECK_INT(paperwidth
);
4823 DEVMODE_CHECK_INT(scale
);
4824 DEVMODE_CHECK_INT(copies
);
4825 DEVMODE_CHECK_INT(defaultsource
);
4826 DEVMODE_CHECK_INT(printquality
);
4827 DEVMODE_CHECK_INT(color
);
4828 DEVMODE_CHECK_INT(duplex
);
4829 DEVMODE_CHECK_INT(yresolution
);
4830 DEVMODE_CHECK_INT(ttoption
);
4831 DEVMODE_CHECK_INT(collate
);
4832 DEVMODE_CHECK_INT(logpixels
);
4834 DEVMODE_CHECK_INT(fields
);
4835 DEVMODE_CHECK_INT(bitsperpel
);
4836 DEVMODE_CHECK_INT(pelswidth
);
4837 DEVMODE_CHECK_INT(pelsheight
);
4838 DEVMODE_CHECK_INT(displayflags
);
4839 DEVMODE_CHECK_INT(displayfrequency
);
4840 DEVMODE_CHECK_INT(icmmethod
);
4841 DEVMODE_CHECK_INT(icmintent
);
4842 DEVMODE_CHECK_INT(mediatype
);
4843 DEVMODE_CHECK_INT(dithertype
);
4844 DEVMODE_CHECK_INT(reserved1
);
4845 DEVMODE_CHECK_INT(reserved2
);
4846 DEVMODE_CHECK_INT(panningwidth
);
4847 DEVMODE_CHECK_INT(panningheight
);
4849 /* compare the private data if it exists */
4850 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
4853 DEVMODE_CHECK_INT(driverextra
);
4855 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
4856 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4861 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4865 /* Return true if two NT_PRINTER_PARAM structures are equal */
4867 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
4868 NT_PRINTER_PARAM
*p2
)
4870 if (!p1
&& !p2
) goto equal
;
4872 if ((!p1
&& p2
) || (p1
&& !p2
)) {
4873 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4877 /* Compare lists of printer parameters */
4881 NT_PRINTER_PARAM
*q
= p1
;
4883 /* Find the parameter in the second structure */
4887 if (strequal(p1
->value
, q
->value
)) {
4889 if (p1
->type
!= q
->type
) {
4890 DEBUG(10, ("nt_printer_param_equal():"
4891 "types for %s differ (%d != %d)\n",
4892 p1
->value
, p1
->type
,
4897 if (p1
->data_len
!= q
->data_len
) {
4898 DEBUG(10, ("nt_printer_param_equal():"
4899 "len for %s differs (%d != %d)\n",
4900 p1
->value
, p1
->data_len
,
4905 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
4908 DEBUG(10, ("nt_printer_param_equal():"
4909 "data for %s differs\n", p1
->value
));
4919 DEBUG(10, ("nt_printer_param_equal(): param %s "
4920 "does not exist\n", p1
->value
));
4929 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4933 /********************************************************************
4934 * Called by update_printer when trying to work out whether to
4935 * actually update printer info.
4936 ********************************************************************/
4938 #define PI_CHECK_INT(field) \
4939 if (pi1->field != pi2->field) { \
4940 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4941 pi1->field, pi2->field)); \
4945 #define PI_CHECK_STR(field) \
4946 if (!strequal(pi1->field, pi2->field)) { \
4947 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4948 pi1->field, pi2->field)); \
4952 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
4953 NT_PRINTER_INFO_LEVEL
*p2
)
4955 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
4957 /* Trivial conditions */
4959 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
4963 if ((!p1
&& p2
) || (p1
&& !p2
) ||
4964 (!p1
->info_2
&& p2
->info_2
) ||
4965 (p1
->info_2
&& !p2
->info_2
)) {
4966 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4971 /* Compare two nt_printer_info_level structures. Don't compare
4972 status or cjobs as they seem to have something to do with the
4978 /* Don't check the attributes as we stomp on the value in
4979 check_printer_ok() anyway. */
4982 PI_CHECK_INT(attributes
);
4985 PI_CHECK_INT(priority
);
4986 PI_CHECK_INT(default_priority
);
4987 PI_CHECK_INT(starttime
);
4988 PI_CHECK_INT(untiltime
);
4989 PI_CHECK_INT(averageppm
);
4991 /* Yuck - don't check the printername or servername as the
4992 mod_a_printer() code plays games with them. You can't
4993 change the printername or the sharename through this interface
4996 PI_CHECK_STR(sharename
);
4997 PI_CHECK_STR(portname
);
4998 PI_CHECK_STR(drivername
);
4999 PI_CHECK_STR(comment
);
5000 PI_CHECK_STR(location
);
5002 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
5006 PI_CHECK_STR(sepfile
);
5007 PI_CHECK_STR(printprocessor
);
5008 PI_CHECK_STR(datatype
);
5009 PI_CHECK_STR(parameters
);
5011 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
5015 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
5019 PI_CHECK_INT(changeid
);
5020 PI_CHECK_INT(c_setprinter
);
5021 PI_CHECK_INT(setuptime
);
5024 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5030 /********************************************************************
5031 * Called by spoolss_api_setprinter
5032 * when updating a printer description.
5033 ********************************************************************/
5035 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5036 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5037 DEVICEMODE
*devmode
)
5040 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5041 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5042 PRINTER_MESSAGE_INFO msg
;
5045 DEBUG(8,("update_printer\n"));
5052 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5053 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5054 result
= WERR_UNKNOWN_LEVEL
;
5059 result
= WERR_BADFID
;
5063 if (!get_printer_snum(p
, handle
, &snum
)) {
5064 result
= WERR_BADFID
;
5068 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5069 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5070 result
= WERR_BADFID
;
5074 DEBUGADD(8,("Converting info_2 struct\n"));
5077 * convert_printer_info converts the incoming
5078 * info from the client and overwrites the info
5079 * just read from the tdb in the pointer 'printer'.
5082 if (!convert_printer_info(info
, printer
, level
)) {
5083 result
= WERR_NOMEM
;
5088 /* we have a valid devmode
5089 convert it and link it*/
5091 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5092 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5093 &printer
->info_2
->devmode
)) {
5094 result
= WERR_NOMEM
;
5099 /* Do sanity check on the requested changes for Samba */
5101 if (!check_printer_ok(printer
->info_2
, snum
)) {
5102 result
= WERR_INVALID_PARAM
;
5109 * Another one of those historical misunderstandings...
5110 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5111 * I'm leaving it here as a reminder. --jerry
5114 if (nt_printer_info_level_equal(printer
, old_printer
)) {
5115 DEBUG(3, ("update_printer: printer info has not changed\n"));
5122 /* Check calling user has permission to update printer description */
5124 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5125 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5126 result
= WERR_ACCESS_DENIED
;
5130 /* Call addprinter hook */
5132 if (*lp_addprinter_cmd()) {
5133 if ( !add_printer_hook(printer
) ) {
5134 result
= WERR_ACCESS_DENIED
;
5140 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5141 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5142 * requires Win32 client code (see other notes elsewhere in the code).
5144 if (printer
->info_2
->devmode
&&
5145 printer
->info_2
->devmode
->displayfrequency
== MAGIC_DISPLAY_FREQUENCY
) {
5147 DEBUG(10,("update_printer: Save printer driver init data\n"));
5148 printer
->info_2
->devmode
->displayfrequency
= 0;
5150 if (update_driver_init(*printer
, 2)!=0) {
5151 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5152 result
= WERR_ACCESS_DENIED
;
5157 * When a *new* driver is bound to a printer, the drivername is used to
5158 * lookup previously saved driver initialization info, which is then
5159 * bound to the printer, simulating what happens in the Windows arch.
5161 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)){
5162 set_driver_init(printer
, 2);
5163 msg
.flags
|= PRINTER_MESSAGE_DRIVER
;
5167 /* Update printer info */
5168 result
= mod_a_printer(*printer
, 2);
5170 /* flag which changes actually occured. This is a small subset of
5171 all the possible changes */
5173 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5174 msg
.flags
|= PRINTER_MESSAGE_COMMENT
;
5176 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5177 msg
.flags
|= PRINTER_MESSAGE_SHARENAME
;
5179 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5180 msg
.flags
|= PRINTER_MESSAGE_PORT
;
5182 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5183 msg
.flags
|= PRINTER_MESSAGE_LOCATION
;
5187 msg
.low
= PRINTER_CHANGE_ADD_PRINTER
;
5188 fstrcpy(msg
.printer_name
, printer
->info_2
->printername
);
5190 /* only send a notify if something changed */
5192 srv_spoolss_sendnotify(msg
.printer_name
, 0, PRINTER_CHANGE_ADD_PRINTER
, msg
.flags
);
5196 free_a_printer(&printer
, 2);
5197 free_a_printer(&old_printer
, 2);
5203 /****************************************************************************
5204 ****************************************************************************/
5206 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5208 POLICY_HND
*handle
= &q_u
->handle
;
5209 uint32 level
= q_u
->level
;
5210 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5211 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5212 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5213 uint32 command
= q_u
->command
;
5215 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5218 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5222 /* check the level */
5225 return control_printer(handle
, command
, p
);
5227 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
5229 return update_printer_sec(handle
, level
, info
, p
,
5232 return WERR_UNKNOWN_LEVEL
;
5236 /****************************************************************************
5237 ****************************************************************************/
5239 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
5241 POLICY_HND
*handle
= &q_u
->handle
;
5243 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5246 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5250 if (Printer
->notify
.client_connected
==True
)
5251 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
5253 Printer
->notify
.flags
=0;
5254 Printer
->notify
.options
=0;
5255 Printer
->notify
.localmachine
[0]='\0';
5256 Printer
->notify
.printerlocal
=0;
5257 if (Printer
->notify
.option
)
5258 free_spool_notify_option(&Printer
->notify
.option
);
5259 Printer
->notify
.client_connected
=False
;
5264 /****************************************************************************
5265 ****************************************************************************/
5267 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
5269 /* that's an [in out] buffer (despite appearences to the contrary) */
5270 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5273 return WERR_INVALID_PARAM
; /* this is what a NT server
5274 returns for AddJob. AddJob
5275 must fail on non-local
5279 /****************************************************************************
5280 ****************************************************************************/
5282 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
5283 int position
, int snum
)
5289 t
=gmtime(&queue
->time
);
5290 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5292 job_info
->jobid
=queue
->job
;
5293 init_unistr(&job_info
->printername
, lp_servicename(snum
));
5294 init_unistr(&job_info
->machinename
, temp_name
);
5295 init_unistr(&job_info
->username
, queue
->fs_user
);
5296 init_unistr(&job_info
->document
, queue
->fs_file
);
5297 init_unistr(&job_info
->datatype
, "RAW");
5298 init_unistr(&job_info
->text_status
, "");
5299 job_info
->status
=nt_printj_status(queue
->status
);
5300 job_info
->priority
=queue
->priority
;
5301 job_info
->position
=position
;
5302 job_info
->totalpages
=queue
->page_count
;
5303 job_info
->pagesprinted
=0;
5305 make_systemtime(&job_info
->submitted
, t
);
5308 /****************************************************************************
5309 ****************************************************************************/
5311 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
5312 int position
, int snum
,
5313 NT_PRINTER_INFO_LEVEL
*ntprinter
,
5314 DEVICEMODE
*devmode
)
5320 t
=gmtime(&queue
->time
);
5321 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5323 job_info
->jobid
=queue
->job
;
5325 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
5327 init_unistr(&job_info
->printername
, chaine
);
5329 init_unistr(&job_info
->machinename
, temp_name
);
5330 init_unistr(&job_info
->username
, queue
->fs_user
);
5331 init_unistr(&job_info
->document
, queue
->fs_file
);
5332 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
5333 init_unistr(&job_info
->datatype
, "RAW");
5334 init_unistr(&job_info
->printprocessor
, "winprint");
5335 init_unistr(&job_info
->parameters
, "");
5336 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
5337 init_unistr(&job_info
->text_status
, "");
5339 /* and here the security descriptor */
5341 job_info
->status
=nt_printj_status(queue
->status
);
5342 job_info
->priority
=queue
->priority
;
5343 job_info
->position
=position
;
5344 job_info
->starttime
=0;
5345 job_info
->untiltime
=0;
5346 job_info
->totalpages
=queue
->page_count
;
5347 job_info
->size
=queue
->size
;
5348 make_systemtime(&(job_info
->submitted
), t
);
5349 job_info
->timeelapsed
=0;
5350 job_info
->pagesprinted
=0;
5352 job_info
->devmode
= devmode
;
5357 /****************************************************************************
5358 Enumjobs at level 1.
5359 ****************************************************************************/
5361 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
5362 NEW_BUFFER
*buffer
, uint32 offered
,
5363 uint32
*needed
, uint32
*returned
)
5368 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
5375 for (i
=0; i
<*returned
; i
++)
5376 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
5380 /* check the required size. */
5381 for (i
=0; i
<*returned
; i
++)
5382 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
5384 if (!alloc_buffer_size(buffer
, *needed
)) {
5386 return WERR_INSUFFICIENT_BUFFER
;
5389 /* fill the buffer with the structures */
5390 for (i
=0; i
<*returned
; i
++)
5391 smb_io_job_info_1("", buffer
, &info
[i
], 0);
5396 if (*needed
> offered
) {
5398 return WERR_INSUFFICIENT_BUFFER
;
5404 /****************************************************************************
5405 Enumjobs at level 2.
5406 ****************************************************************************/
5408 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
5409 NEW_BUFFER
*buffer
, uint32 offered
,
5410 uint32
*needed
, uint32
*returned
)
5412 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
5413 JOB_INFO_2
*info
= NULL
;
5416 DEVICEMODE
*devmode
= NULL
;
5418 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
5421 result
= WERR_NOMEM
;
5425 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
5426 if (!W_ERROR_IS_OK(result
)) {
5431 if (!(devmode
= construct_dev_mode(snum
))) {
5433 result
= WERR_NOMEM
;
5437 for (i
=0; i
<*returned
; i
++)
5438 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
5441 free_a_printer(&ntprinter
, 2);
5444 /* check the required size. */
5445 for (i
=0; i
<*returned
; i
++)
5446 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
5448 if (*needed
> offered
) {
5450 result
= WERR_INSUFFICIENT_BUFFER
;
5454 if (!alloc_buffer_size(buffer
, *needed
)) {
5456 result
= WERR_INSUFFICIENT_BUFFER
;
5460 /* fill the buffer with the structures */
5461 for (i
=0; i
<*returned
; i
++)
5462 smb_io_job_info_2("", buffer
, &info
[i
], 0);
5467 free_a_printer(&ntprinter
, 2);
5468 free_devmode(devmode
);
5475 /****************************************************************************
5477 ****************************************************************************/
5479 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
5481 POLICY_HND
*handle
= &q_u
->handle
;
5482 /* uint32 firstjob = q_u->firstjob; - notused. */
5483 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5484 uint32 level
= q_u
->level
;
5485 NEW_BUFFER
*buffer
= NULL
;
5486 uint32 offered
= q_u
->offered
;
5487 uint32
*needed
= &r_u
->needed
;
5488 uint32
*returned
= &r_u
->returned
;
5491 print_status_struct prt_status
;
5492 print_queue_struct
*queue
=NULL
;
5494 /* that's an [in out] buffer */
5495 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5496 buffer
= r_u
->buffer
;
5498 DEBUG(4,("_spoolss_enumjobs\n"));
5503 if (!get_printer_snum(p
, handle
, &snum
))
5506 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
5507 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
5509 if (*returned
== 0) {
5516 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
5518 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
5522 return WERR_UNKNOWN_LEVEL
;
5526 /****************************************************************************
5527 ****************************************************************************/
5529 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
5534 /****************************************************************************
5535 ****************************************************************************/
5537 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
5539 POLICY_HND
*handle
= &q_u
->handle
;
5540 uint32 jobid
= q_u
->jobid
;
5541 /* uint32 level = q_u->level; - notused. */
5542 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5543 uint32 command
= q_u
->command
;
5545 struct current_user user
;
5547 WERROR errcode
= WERR_BADFUNC
;
5549 if (!get_printer_snum(p
, handle
, &snum
)) {
5553 if (!print_job_exists(jobid
)) {
5554 return WERR_INVALID_PRINTER_NAME
;
5557 get_current_user(&user
, p
);
5560 case JOB_CONTROL_CANCEL
:
5561 case JOB_CONTROL_DELETE
:
5562 if (print_job_delete(&user
, jobid
, &errcode
)) {
5566 case JOB_CONTROL_PAUSE
:
5567 if (print_job_pause(&user
, jobid
, &errcode
)) {
5571 case JOB_CONTROL_RESTART
:
5572 case JOB_CONTROL_RESUME
:
5573 if (print_job_resume(&user
, jobid
, &errcode
)) {
5578 return WERR_UNKNOWN_LEVEL
;
5584 /****************************************************************************
5585 Enumerates all printer drivers at level 1.
5586 ****************************************************************************/
5588 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5593 fstring
*list
= NULL
;
5595 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5596 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5600 #define MAX_VERSION 4
5602 for (version
=0; version
<MAX_VERSION
; version
++) {
5604 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5605 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5611 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5612 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5613 SAFE_FREE(driver_info_1
);
5617 else driver_info_1
= tdi1
;
5620 for (i
=0; i
<ndrivers
; i
++) {
5622 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5623 ZERO_STRUCT(driver
);
5624 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5625 architecture
, version
);
5626 if (!W_ERROR_IS_OK(status
)) {
5630 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5631 free_a_printer_driver(driver
, 3);
5634 *returned
+=ndrivers
;
5638 /* check the required size. */
5639 for (i
=0; i
<*returned
; i
++) {
5640 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5641 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5644 if (!alloc_buffer_size(buffer
, *needed
)) {
5645 SAFE_FREE(driver_info_1
);
5646 return WERR_INSUFFICIENT_BUFFER
;
5649 /* fill the buffer with the driver structures */
5650 for (i
=0; i
<*returned
; i
++) {
5651 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5652 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5655 SAFE_FREE(driver_info_1
);
5657 if (*needed
> offered
) {
5659 return WERR_INSUFFICIENT_BUFFER
;
5665 /****************************************************************************
5666 Enumerates all printer drivers at level 2.
5667 ****************************************************************************/
5669 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5674 fstring
*list
= NULL
;
5676 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5677 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
5681 #define MAX_VERSION 4
5683 for (version
=0; version
<MAX_VERSION
; version
++) {
5685 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5686 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5692 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
5693 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5694 SAFE_FREE(driver_info_2
);
5698 else driver_info_2
= tdi2
;
5701 for (i
=0; i
<ndrivers
; i
++) {
5704 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5705 ZERO_STRUCT(driver
);
5706 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5707 architecture
, version
);
5708 if (!W_ERROR_IS_OK(status
)) {
5712 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
5713 free_a_printer_driver(driver
, 3);
5716 *returned
+=ndrivers
;
5720 /* check the required size. */
5721 for (i
=0; i
<*returned
; i
++) {
5722 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5723 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
5726 if (!alloc_buffer_size(buffer
, *needed
)) {
5727 SAFE_FREE(driver_info_2
);
5728 return WERR_INSUFFICIENT_BUFFER
;
5731 /* fill the buffer with the form structures */
5732 for (i
=0; i
<*returned
; i
++) {
5733 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5734 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
5737 SAFE_FREE(driver_info_2
);
5739 if (*needed
> offered
) {
5741 return WERR_INSUFFICIENT_BUFFER
;
5747 /****************************************************************************
5748 Enumerates all printer drivers at level 3.
5749 ****************************************************************************/
5751 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5756 fstring
*list
= NULL
;
5758 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5759 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
5763 #define MAX_VERSION 4
5765 for (version
=0; version
<MAX_VERSION
; version
++) {
5767 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5768 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5774 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
5775 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5776 SAFE_FREE(driver_info_3
);
5780 else driver_info_3
= tdi3
;
5783 for (i
=0; i
<ndrivers
; i
++) {
5786 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5787 ZERO_STRUCT(driver
);
5788 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5789 architecture
, version
);
5790 if (!W_ERROR_IS_OK(status
)) {
5794 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
5795 free_a_printer_driver(driver
, 3);
5798 *returned
+=ndrivers
;
5802 /* check the required size. */
5803 for (i
=0; i
<*returned
; i
++) {
5804 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5805 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
5808 if (!alloc_buffer_size(buffer
, *needed
)) {
5809 SAFE_FREE(driver_info_3
);
5810 return WERR_INSUFFICIENT_BUFFER
;
5813 /* fill the buffer with the driver structures */
5814 for (i
=0; i
<*returned
; i
++) {
5815 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5816 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
5819 for (i
=0; i
<*returned
; i
++)
5820 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
5822 SAFE_FREE(driver_info_3
);
5824 if (*needed
> offered
) {
5826 return WERR_INSUFFICIENT_BUFFER
;
5832 /****************************************************************************
5833 Enumerates all printer drivers.
5834 ****************************************************************************/
5836 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
5838 /* UNISTR2 *name = &q_u->name; - notused. */
5839 UNISTR2
*environment
= &q_u
->environment
;
5840 uint32 level
= q_u
->level
;
5841 NEW_BUFFER
*buffer
= NULL
;
5842 uint32 offered
= q_u
->offered
;
5843 uint32
*needed
= &r_u
->needed
;
5844 uint32
*returned
= &r_u
->returned
;
5846 fstring
*list
= NULL
;
5848 fstring architecture
;
5850 /* that's an [in out] buffer */
5851 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5852 buffer
= r_u
->buffer
;
5854 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5855 fstrcpy(servername
, get_called_name());
5859 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
5863 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
5865 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
5867 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
5871 return WERR_UNKNOWN_LEVEL
;
5875 /****************************************************************************
5876 ****************************************************************************/
5878 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
5880 form
->flag
=list
->flag
;
5881 init_unistr(&form
->name
, list
->name
);
5882 form
->width
=list
->width
;
5883 form
->length
=list
->length
;
5884 form
->left
=list
->left
;
5885 form
->top
=list
->top
;
5886 form
->right
=list
->right
;
5887 form
->bottom
=list
->bottom
;
5890 /****************************************************************************
5891 ****************************************************************************/
5893 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
5895 /* POLICY_HND *handle = &q_u->handle; - notused. */
5896 uint32 level
= q_u
->level
;
5897 NEW_BUFFER
*buffer
= NULL
;
5898 uint32 offered
= q_u
->offered
;
5899 uint32
*needed
= &r_u
->needed
;
5900 uint32
*numofforms
= &r_u
->numofforms
;
5901 uint32 numbuiltinforms
;
5903 nt_forms_struct
*list
=NULL
;
5904 nt_forms_struct
*builtinlist
=NULL
;
5909 /* that's an [in out] buffer */
5910 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5911 buffer
= r_u
->buffer
;
5913 DEBUG(4,("_spoolss_enumforms\n"));
5914 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
5915 DEBUGADD(5,("Info level [%d]\n", level
));
5917 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
5918 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
5919 *numofforms
= get_ntforms(&list
);
5920 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
5921 *numofforms
+= numbuiltinforms
;
5923 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
5927 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
5932 /* construct the list of form structures */
5933 for (i
=0; i
<numbuiltinforms
; i
++) {
5934 DEBUGADD(6,("Filling form number [%d]\n",i
));
5935 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
5938 SAFE_FREE(builtinlist
);
5940 for (; i
<*numofforms
; i
++) {
5941 DEBUGADD(6,("Filling form number [%d]\n",i
));
5942 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
5947 /* check the required size. */
5948 for (i
=0; i
<numbuiltinforms
; i
++) {
5949 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5950 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5952 for (; i
<*numofforms
; i
++) {
5953 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5954 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5957 *needed
=buffer_size
;
5959 if (!alloc_buffer_size(buffer
, buffer_size
)){
5961 return WERR_INSUFFICIENT_BUFFER
;
5964 /* fill the buffer with the form structures */
5965 for (i
=0; i
<numbuiltinforms
; i
++) {
5966 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5967 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5969 for (; i
<*numofforms
; i
++) {
5970 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5971 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5976 if (*needed
> offered
) {
5978 return WERR_INSUFFICIENT_BUFFER
;
5985 SAFE_FREE(builtinlist
);
5986 return WERR_UNKNOWN_LEVEL
;
5991 /****************************************************************************
5992 ****************************************************************************/
5994 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
5996 /* POLICY_HND *handle = &q_u->handle; - notused. */
5997 uint32 level
= q_u
->level
;
5998 UNISTR2
*uni_formname
= &q_u
->formname
;
5999 NEW_BUFFER
*buffer
= NULL
;
6000 uint32 offered
= q_u
->offered
;
6001 uint32
*needed
= &r_u
->needed
;
6003 nt_forms_struct
*list
=NULL
;
6004 nt_forms_struct builtin_form
;
6009 int numofforms
=0, i
=0;
6011 /* that's an [in out] buffer */
6012 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6013 buffer
= r_u
->buffer
;
6015 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
6017 DEBUG(4,("_spoolss_getform\n"));
6018 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6019 DEBUGADD(5,("Info level [%d]\n", level
));
6021 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6022 if (!foundBuiltin
) {
6023 numofforms
= get_ntforms(&list
);
6024 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6026 if (numofforms
== 0)
6033 fill_form_1(&form_1
, &builtin_form
);
6036 /* Check if the requested name is in the list of form structures */
6037 for (i
=0; i
<numofforms
; i
++) {
6039 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6041 if (strequal(form_name
, list
[i
].name
)) {
6042 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6043 fill_form_1(&form_1
, &list
[i
]);
6049 if (i
== numofforms
) {
6053 /* check the required size. */
6055 *needed
=spoolss_size_form_1(&form_1
);
6057 if (!alloc_buffer_size(buffer
, buffer_size
)){
6058 return WERR_INSUFFICIENT_BUFFER
;
6061 if (*needed
> offered
) {
6062 return WERR_INSUFFICIENT_BUFFER
;
6065 /* fill the buffer with the form structures */
6066 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6067 smb_io_form_1("", buffer
, &form_1
, 0);
6073 return WERR_UNKNOWN_LEVEL
;
6077 /****************************************************************************
6078 ****************************************************************************/
6080 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
6082 init_unistr(&port
->port_name
, name
);
6085 /****************************************************************************
6086 ****************************************************************************/
6088 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
6090 init_unistr(&port
->port_name
, name
);
6091 init_unistr(&port
->monitor_name
, "Local Monitor");
6092 init_unistr(&port
->description
, "Local Port");
6093 #define PORT_TYPE_WRITE 1
6094 port
->port_type
=PORT_TYPE_WRITE
;
6098 /****************************************************************************
6100 ****************************************************************************/
6102 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6104 PORT_INFO_1
*ports
=NULL
;
6107 if (*lp_enumports_cmd()) {
6108 char *cmd
= lp_enumports_cmd();
6115 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6117 DEBUG(10,("Running [%s]\n", command
));
6118 ret
= smbrun(command
, &fd
);
6119 DEBUG(10,("Returned [%d]\n", ret
));
6123 /* Is this the best error to return here? */
6124 return WERR_ACCESS_DENIED
;
6128 qlines
= fd_lines_load(fd
, &numlines
);
6129 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6133 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6134 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6135 dos_errstr(WERR_NOMEM
)));
6136 file_lines_free(qlines
);
6140 for (i
=0; i
<numlines
; i
++) {
6141 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6142 fill_port_1(&ports
[i
], qlines
[i
]);
6145 file_lines_free(qlines
);
6148 *returned
= numlines
;
6151 *returned
= 1; /* Sole Samba port returned. */
6153 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6156 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6158 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6161 /* check the required size. */
6162 for (i
=0; i
<*returned
; i
++) {
6163 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6164 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6167 if (!alloc_buffer_size(buffer
, *needed
)) {
6169 return WERR_INSUFFICIENT_BUFFER
;
6172 /* fill the buffer with the ports structures */
6173 for (i
=0; i
<*returned
; i
++) {
6174 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6175 smb_io_port_1("", buffer
, &ports
[i
], 0);
6180 if (*needed
> offered
) {
6182 return WERR_INSUFFICIENT_BUFFER
;
6188 /****************************************************************************
6190 ****************************************************************************/
6192 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6194 PORT_INFO_2
*ports
=NULL
;
6197 if (*lp_enumports_cmd()) {
6198 char *cmd
= lp_enumports_cmd();
6207 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6208 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6210 path
= lp_lockdir();
6212 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6213 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6216 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6217 ret
= smbrun(command
, &fd
);
6218 DEBUGADD(10,("returned [%d]\n", ret
));
6222 /* Is this the best error to return here? */
6223 return WERR_ACCESS_DENIED
;
6227 qlines
= fd_lines_load(fd
, &numlines
);
6228 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6232 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
6233 file_lines_free(qlines
);
6237 for (i
=0; i
<numlines
; i
++) {
6238 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6239 fill_port_2(&(ports
[i
]), qlines
[i
]);
6242 file_lines_free(qlines
);
6245 *returned
= numlines
;
6251 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
6254 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6256 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6259 /* check the required size. */
6260 for (i
=0; i
<*returned
; i
++) {
6261 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6262 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
6265 if (!alloc_buffer_size(buffer
, *needed
)) {
6267 return WERR_INSUFFICIENT_BUFFER
;
6270 /* fill the buffer with the ports structures */
6271 for (i
=0; i
<*returned
; i
++) {
6272 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6273 smb_io_port_2("", buffer
, &ports
[i
], 0);
6278 if (*needed
> offered
) {
6280 return WERR_INSUFFICIENT_BUFFER
;
6286 /****************************************************************************
6288 ****************************************************************************/
6290 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
6292 /* UNISTR2 *name = &q_u->name; - notused. */
6293 uint32 level
= q_u
->level
;
6294 NEW_BUFFER
*buffer
= NULL
;
6295 uint32 offered
= q_u
->offered
;
6296 uint32
*needed
= &r_u
->needed
;
6297 uint32
*returned
= &r_u
->returned
;
6299 /* that's an [in out] buffer */
6300 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6301 buffer
= r_u
->buffer
;
6303 DEBUG(4,("_spoolss_enumports\n"));
6310 return enumports_level_1(buffer
, offered
, needed
, returned
);
6312 return enumports_level_2(buffer
, offered
, needed
, returned
);
6314 return WERR_UNKNOWN_LEVEL
;
6318 /****************************************************************************
6319 ****************************************************************************/
6321 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
6322 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6323 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
6324 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
6327 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6330 WERROR err
= WERR_OK
;
6332 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
6333 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6337 ZERO_STRUCTP(printer
);
6339 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6340 if (!convert_printer_info(info
, printer
, 2)) {
6341 free_a_printer(&printer
, 2);
6345 /* check to see if the printer already exists */
6347 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
6348 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6349 printer
->info_2
->sharename
));
6350 free_a_printer(&printer
, 2);
6351 return WERR_PRINTER_ALREADY_EXISTS
;
6354 if (*lp_addprinter_cmd() )
6355 if ( !add_printer_hook(printer
) ) {
6356 free_a_printer(&printer
,2);
6357 return WERR_ACCESS_DENIED
;
6360 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
6361 printer
->info_2
->sharename
);
6363 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
6364 free_a_printer(&printer
,2);
6365 return WERR_ACCESS_DENIED
;
6368 /* you must be a printer admin to add a new printer */
6369 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6370 free_a_printer(&printer
,2);
6371 return WERR_ACCESS_DENIED
;
6375 * Do sanity check on the requested changes for Samba.
6378 if (!check_printer_ok(printer
->info_2
, snum
)) {
6379 free_a_printer(&printer
,2);
6380 return WERR_INVALID_PARAM
;
6384 * When a printer is created, the drivername bound to the printer is used
6385 * to lookup previously saved driver initialization info, which is then
6386 * bound to the new printer, simulating what happens in the Windows arch.
6390 set_driver_init(printer
, 2);
6392 /* A valid devmode was included, convert and link it
6394 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6396 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6397 &printer
->info_2
->devmode
))
6401 set_driver_init(printer
, 2);
6403 /* write the ASCII on disk */
6404 err
= mod_a_printer(*printer
, 2);
6405 if (!W_ERROR_IS_OK(err
)) {
6406 free_a_printer(&printer
,2);
6410 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
6411 /* Handle open failed - remove addition. */
6412 del_a_printer(printer
->info_2
->sharename
);
6413 free_a_printer(&printer
,2);
6414 return WERR_ACCESS_DENIED
;
6417 update_c_setprinter(False
);
6419 srv_spoolss_sendnotify(printer
->info_2
->printername
, 0, PRINTER_CHANGE_ADD_PRINTER
, 0x0);
6421 free_a_printer(&printer
,2);
6426 /****************************************************************************
6427 ****************************************************************************/
6429 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
6431 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
6432 uint32 level
= q_u
->level
;
6433 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6434 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
6435 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
6436 uint32 user_switch
= q_u
->user_switch
;
6437 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
6438 POLICY_HND
*handle
= &r_u
->handle
;
6442 /* we don't handle yet */
6443 /* but I know what to do ... */
6444 return WERR_UNKNOWN_LEVEL
;
6446 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
6448 user_switch
, user
, handle
);
6450 return WERR_UNKNOWN_LEVEL
;
6454 /****************************************************************************
6455 ****************************************************************************/
6457 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
6459 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6460 uint32 level
= q_u
->level
;
6461 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
6462 WERROR err
= WERR_OK
;
6463 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6464 struct current_user user
;
6466 ZERO_STRUCT(driver
);
6468 get_current_user(&user
, p
);
6470 if (!convert_printer_driver_info(info
, &driver
, level
)) {
6475 DEBUG(5,("Cleaning driver's information\n"));
6476 err
= clean_up_driver_struct(driver
, level
, &user
);
6477 if (!W_ERROR_IS_OK(err
))
6480 DEBUG(5,("Moving driver to final destination\n"));
6481 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
6482 if (W_ERROR_IS_OK(err
))
6483 err
= WERR_ACCESS_DENIED
;
6487 if (add_a_printer_driver(driver
, level
)!=0) {
6488 err
= WERR_ACCESS_DENIED
;
6493 free_a_printer_driver(driver
, level
);
6497 /****************************************************************************
6498 ****************************************************************************/
6500 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
6502 init_unistr(&info
->name
, name
);
6505 /****************************************************************************
6506 ****************************************************************************/
6508 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6512 pstring short_archi
;
6513 DRIVER_DIRECTORY_1
*info
=NULL
;
6515 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
6517 if (get_short_archi(short_archi
, long_archi
)==False
)
6518 return WERR_INVALID_ENVIRONMENT
;
6520 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
6523 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
6525 DEBUG(4,("printer driver directory: [%s]\n", path
));
6527 fill_driverdir_1(info
, path
);
6529 *needed
+= spoolss_size_driverdir_info_1(info
);
6531 if (!alloc_buffer_size(buffer
, *needed
)) {
6533 return WERR_INSUFFICIENT_BUFFER
;
6536 smb_io_driverdir_1("", buffer
, info
, 0);
6540 if (*needed
> offered
)
6541 return WERR_INSUFFICIENT_BUFFER
;
6546 /****************************************************************************
6547 ****************************************************************************/
6549 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
6551 UNISTR2
*name
= &q_u
->name
;
6552 UNISTR2
*uni_environment
= &q_u
->environment
;
6553 uint32 level
= q_u
->level
;
6554 NEW_BUFFER
*buffer
= NULL
;
6555 uint32 offered
= q_u
->offered
;
6556 uint32
*needed
= &r_u
->needed
;
6558 /* that's an [in out] buffer */
6559 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6560 buffer
= r_u
->buffer
;
6562 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6568 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
6570 return WERR_UNKNOWN_LEVEL
;
6574 /****************************************************************************
6575 ****************************************************************************/
6577 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
6579 POLICY_HND
*handle
= &q_u
->handle
;
6580 uint32 idx
= q_u
->index
;
6581 uint32 in_value_len
= q_u
->valuesize
;
6582 uint32 in_data_len
= q_u
->datasize
;
6583 uint32
*out_max_value_len
= &r_u
->valuesize
;
6584 uint16
**out_value
= &r_u
->value
;
6585 uint32
*out_value_len
= &r_u
->realvaluesize
;
6586 uint32
*out_type
= &r_u
->type
;
6587 uint32
*out_max_data_len
= &r_u
->datasize
;
6588 uint8
**data_out
= &r_u
->data
;
6589 uint32
*out_data_len
= &r_u
->realdatasize
;
6591 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6596 uint32 biggest_valuesize
;
6597 uint32 biggest_datasize
;
6599 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6605 ZERO_STRUCT(printer
);
6609 *out_max_data_len
=0;
6613 DEBUG(5,("spoolss_enumprinterdata\n"));
6616 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6620 if (!get_printer_snum(p
,handle
, &snum
))
6623 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6624 if (!W_ERROR_IS_OK(result
))
6628 * The NT machine wants to know the biggest size of value and data
6630 * cf: MSDN EnumPrinterData remark section
6632 if ( (in_value_len
==0) && (in_data_len
==0) ) {
6633 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6637 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6638 * if this parameter size doesn't exist.
6639 * Ok - my opinion here is that the client is not asking for the greatest
6640 * possible size of all the parameters, but is asking specifically for the size needed
6641 * for this specific parameter. In that case we can remove the loop below and
6642 * simplify this lookup code considerably. JF - comments welcome. JRA.
6645 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6647 free_a_printer(&printer
, 2);
6648 return WERR_NO_MORE_ITEMS
;
6655 biggest_valuesize
=0;
6658 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
6659 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
6660 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
6662 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
6668 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6669 *out_value_len
=2*(1+biggest_valuesize
);
6670 *out_data_len
=biggest_datasize
;
6672 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
6674 free_a_printer(&printer
, 2);
6679 * the value len is wrong in NT sp3
6680 * that's the number of bytes not the number of unicode chars
6683 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6686 free_a_printer(&printer
, 2);
6688 /* out_value should default to "" or else NT4 has
6689 problems unmarshalling the response */
6691 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6692 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
6695 *out_value_len
= rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
6697 /* the data is counted in bytes */
6698 *out_max_data_len
= in_data_len
;
6699 *out_data_len
= in_data_len
;
6700 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
6703 return WERR_NO_MORE_ITEMS
;
6706 free_a_printer(&printer
, 2);
6710 * - counted in bytes in the request
6711 * - counted in UNICODE chars in the max reply
6712 * - counted in bytes in the real size
6714 * take a pause *before* coding not *during* coding
6717 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6718 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
,in_value_len
*sizeof(uint8
))) == NULL
) {
6723 *out_value_len
= rpcstr_push((char *)*out_value
,value
, in_value_len
, 0);
6727 /* the data is counted in bytes */
6728 *out_max_data_len
=in_data_len
;
6729 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) {
6734 memcpy(*data_out
, data
, (size_t)data_len
);
6735 *out_data_len
=data_len
;
6742 /****************************************************************************
6743 ****************************************************************************/
6745 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
6747 POLICY_HND
*handle
= &q_u
->handle
;
6748 UNISTR2
*value
= &q_u
->value
;
6749 uint32 type
= q_u
->type
;
6750 /* uint32 max_len = q_u->max_len; - notused. */
6751 uint8
*data
= q_u
->data
;
6752 uint32 real_len
= q_u
->real_len
;
6753 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6755 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6756 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
6758 WERROR status
= WERR_OK
;
6759 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6761 DEBUG(5,("spoolss_setprinterdata\n"));
6764 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6768 if (!get_printer_snum(p
,handle
, &snum
))
6771 ZERO_STRUCT(old_param
);
6774 * Access check : NT returns "access denied" if you make a
6775 * SetPrinterData call without the necessary privildge.
6776 * we were originally returning OK if nothing changed
6777 * which made Win2k issue **a lot** of SetPrinterData
6778 * when connecting to a printer --jerry
6781 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6782 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
6783 status
= WERR_ACCESS_DENIED
;
6787 /* Check if we are making any changes or not. Return true if
6788 nothing is actually changing. This is not needed anymore but
6789 has been left in as an optimization to keep from from
6790 writing to disk as often --jerry */
6792 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6793 if (!W_ERROR_IS_OK(status
))
6796 convert_specific_param(¶m
, value
, type
, data
, real_len
);
6798 unlink_specific_param_if_exist(printer
->info_2
, param
);
6801 * When client side code sets a magic printer data key, detect it and save
6802 * the current printer data and the magic key's data (its the DEVMODE) for
6803 * future printer/driver initializations.
6805 if (param
->type
==3 && !strcmp( param
->value
, PHANTOM_DEVMODE_KEY
)) {
6807 * Set devmode and printer initialization info
6809 status
= save_driver_init(printer
, 2, param
);
6812 add_a_specific_param(printer
->info_2
, ¶m
);
6813 status
= mod_a_printer(*printer
, 2);
6817 free_a_printer(&printer
, 2);
6819 free_nt_printer_param(¶m
);
6820 SAFE_FREE(old_param
.data
);
6825 /****************************************************************************
6826 ****************************************************************************/
6828 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
6830 POLICY_HND
*handle
= &q_u
->handle
;
6831 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6834 DEBUG(5,("_spoolss_resetprinter\n"));
6837 * All we do is to check to see if the handle and queue is valid.
6838 * This call really doesn't mean anything to us because we only
6839 * support RAW printing. --jerry
6843 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6847 if (!get_printer_snum(p
,handle
, &snum
))
6851 /* blindly return success */
6856 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
6858 POLICY_HND
*handle
= &q_u
->handle
;
6859 UNISTR2
*value
= &q_u
->valuename
;
6861 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6862 NT_PRINTER_PARAM param
;
6864 WERROR status
= WERR_OK
;
6865 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6867 DEBUG(5,("spoolss_deleteprinterdata\n"));
6870 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6874 if (!get_printer_snum(p
, handle
, &snum
))
6877 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6878 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
6879 return WERR_ACCESS_DENIED
;
6882 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6883 if (!W_ERROR_IS_OK(status
))
6886 ZERO_STRUCTP(¶m
);
6887 unistr2_to_ascii(param
.value
, value
, sizeof(param
.value
)-1);
6889 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
6890 status
= WERR_INVALID_PARAM
;
6892 status
= mod_a_printer(*printer
, 2);
6894 free_a_printer(&printer
, 2);
6898 /****************************************************************************
6899 ****************************************************************************/
6901 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
6903 POLICY_HND
*handle
= &q_u
->handle
;
6904 /* uint32 level = q_u->level; - notused. */
6905 FORM
*form
= &q_u
->form
;
6906 nt_forms_struct tmpForm
;
6908 WERROR status
= WERR_OK
;
6909 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6912 nt_forms_struct
*list
=NULL
;
6913 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6915 DEBUG(5,("spoolss_addform\n"));
6918 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6922 if (!get_printer_snum(p
,handle
, &snum
))
6925 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6926 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
6927 status
= WERR_ACCESS_DENIED
;
6931 /* can't add if builtin */
6932 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
6933 return WERR_ALREADY_EXISTS
;
6936 count
=get_ntforms(&list
);
6937 if(!add_a_form(&list
, form
, &count
))
6939 write_ntforms(&list
, count
);
6942 * ChangeID must always be set
6945 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6946 if (!W_ERROR_IS_OK(status
))
6949 status
= mod_a_printer(*printer
, 2);
6950 if (!W_ERROR_IS_OK(status
))
6954 free_a_printer(&printer
, 2);
6960 /****************************************************************************
6961 ****************************************************************************/
6963 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
6965 POLICY_HND
*handle
= &q_u
->handle
;
6966 UNISTR2
*form_name
= &q_u
->name
;
6967 nt_forms_struct tmpForm
;
6969 WERROR ret
= WERR_OK
;
6970 nt_forms_struct
*list
=NULL
;
6971 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6973 WERROR status
= WERR_OK
;
6974 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6976 DEBUG(5,("spoolss_deleteform\n"));
6979 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6983 if (!get_printer_snum(p
, handle
, &snum
))
6986 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6987 DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
6988 return WERR_ACCESS_DENIED
;
6991 /* can't delete if builtin */
6992 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
6993 return WERR_INVALID_PARAM
;
6996 count
= get_ntforms(&list
);
6997 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
6998 return WERR_INVALID_PARAM
;
7001 * ChangeID must always be set
7004 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7005 if (!W_ERROR_IS_OK(status
))
7008 status
= mod_a_printer(*printer
, 2);
7009 if (!W_ERROR_IS_OK(status
))
7013 free_a_printer(&printer
, 2);
7019 /****************************************************************************
7020 ****************************************************************************/
7022 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7024 POLICY_HND
*handle
= &q_u
->handle
;
7025 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7026 /* uint32 level = q_u->level; - notused. */
7027 FORM
*form
= &q_u
->form
;
7028 nt_forms_struct tmpForm
;
7030 WERROR status
= WERR_OK
;
7031 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7034 nt_forms_struct
*list
=NULL
;
7035 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7037 DEBUG(5,("spoolss_setform\n"));
7040 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7044 if (!get_printer_snum(p
, handle
, &snum
))
7047 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7048 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7049 return WERR_ACCESS_DENIED
;
7052 /* can't set if builtin */
7053 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7054 return WERR_INVALID_PARAM
;
7057 count
=get_ntforms(&list
);
7058 update_a_form(&list
, form
, count
);
7059 write_ntforms(&list
, count
);
7062 * ChangeID must always be set
7065 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7066 if (!W_ERROR_IS_OK(status
))
7069 status
= mod_a_printer(*printer
, 2);
7070 if (!W_ERROR_IS_OK(status
))
7074 free_a_printer(&printer
, 2);
7080 /****************************************************************************
7081 enumprintprocessors level 1.
7082 ****************************************************************************/
7084 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7086 PRINTPROCESSOR_1
*info_1
=NULL
;
7088 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
7093 init_unistr(&info_1
->name
, "winprint");
7095 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
7097 if (!alloc_buffer_size(buffer
, *needed
))
7098 return WERR_INSUFFICIENT_BUFFER
;
7100 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
7104 if (*needed
> offered
) {
7106 return WERR_INSUFFICIENT_BUFFER
;
7112 /****************************************************************************
7113 ****************************************************************************/
7115 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
7117 /* UNISTR2 *name = &q_u->name; - notused. */
7118 /* UNISTR2 *environment = &q_u->environment; - notused. */
7119 uint32 level
= q_u
->level
;
7120 NEW_BUFFER
*buffer
= NULL
;
7121 uint32 offered
= q_u
->offered
;
7122 uint32
*needed
= &r_u
->needed
;
7123 uint32
*returned
= &r_u
->returned
;
7125 /* that's an [in out] buffer */
7126 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7127 buffer
= r_u
->buffer
;
7129 DEBUG(5,("spoolss_enumprintprocessors\n"));
7132 * Enumerate the print processors ...
7134 * Just reply with "winprint", to keep NT happy
7135 * and I can use my nice printer checker.
7143 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
7145 return WERR_UNKNOWN_LEVEL
;
7149 /****************************************************************************
7150 enumprintprocdatatypes level 1.
7151 ****************************************************************************/
7153 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7155 PRINTPROCDATATYPE_1
*info_1
=NULL
;
7157 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
7162 init_unistr(&info_1
->name
, "RAW");
7164 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
7166 if (!alloc_buffer_size(buffer
, *needed
))
7167 return WERR_INSUFFICIENT_BUFFER
;
7169 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
7173 if (*needed
> offered
) {
7175 return WERR_INSUFFICIENT_BUFFER
;
7181 /****************************************************************************
7182 ****************************************************************************/
7184 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
7186 /* UNISTR2 *name = &q_u->name; - notused. */
7187 /* UNISTR2 *processor = &q_u->processor; - notused. */
7188 uint32 level
= q_u
->level
;
7189 NEW_BUFFER
*buffer
= NULL
;
7190 uint32 offered
= q_u
->offered
;
7191 uint32
*needed
= &r_u
->needed
;
7192 uint32
*returned
= &r_u
->returned
;
7194 /* that's an [in out] buffer */
7195 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7196 buffer
= r_u
->buffer
;
7198 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7205 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
7207 return WERR_UNKNOWN_LEVEL
;
7211 /****************************************************************************
7212 enumprintmonitors level 1.
7213 ****************************************************************************/
7215 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7217 PRINTMONITOR_1
*info_1
=NULL
;
7219 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
7224 init_unistr(&info_1
->name
, "Local Port");
7226 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
7228 if (!alloc_buffer_size(buffer
, *needed
))
7229 return WERR_INSUFFICIENT_BUFFER
;
7231 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
7235 if (*needed
> offered
) {
7237 return WERR_INSUFFICIENT_BUFFER
;
7243 /****************************************************************************
7244 enumprintmonitors level 2.
7245 ****************************************************************************/
7247 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7249 PRINTMONITOR_2
*info_2
=NULL
;
7251 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
7256 init_unistr(&info_2
->name
, "Local Port");
7257 init_unistr(&info_2
->environment
, "Windows NT X86");
7258 init_unistr(&info_2
->dll_name
, "localmon.dll");
7260 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
7262 if (!alloc_buffer_size(buffer
, *needed
))
7263 return WERR_INSUFFICIENT_BUFFER
;
7265 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
7269 if (*needed
> offered
) {
7271 return WERR_INSUFFICIENT_BUFFER
;
7277 /****************************************************************************
7278 ****************************************************************************/
7280 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
7282 /* UNISTR2 *name = &q_u->name; - notused. */
7283 uint32 level
= q_u
->level
;
7284 NEW_BUFFER
*buffer
= NULL
;
7285 uint32 offered
= q_u
->offered
;
7286 uint32
*needed
= &r_u
->needed
;
7287 uint32
*returned
= &r_u
->returned
;
7289 /* that's an [in out] buffer */
7290 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7291 buffer
= r_u
->buffer
;
7293 DEBUG(5,("spoolss_enumprintmonitors\n"));
7296 * Enumerate the print monitors ...
7298 * Just reply with "Local Port", to keep NT happy
7299 * and I can use my nice printer checker.
7307 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
7309 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
7311 return WERR_UNKNOWN_LEVEL
;
7315 /****************************************************************************
7316 ****************************************************************************/
7318 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7322 JOB_INFO_1
*info_1
=NULL
;
7324 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
7326 if (info_1
== NULL
) {
7331 for (i
=0; i
<count
&& found
==False
; i
++) {
7332 if (queue
[i
].job
==(int)jobid
)
7339 /* NT treats not found as bad param... yet another bad choice */
7340 return WERR_INVALID_PARAM
;
7343 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
7347 *needed
+= spoolss_size_job_info_1(info_1
);
7349 if (!alloc_buffer_size(buffer
, *needed
)) {
7351 return WERR_INSUFFICIENT_BUFFER
;
7354 smb_io_job_info_1("", buffer
, info_1
, 0);
7358 if (*needed
> offered
)
7359 return WERR_INSUFFICIENT_BUFFER
;
7364 /****************************************************************************
7365 ****************************************************************************/
7367 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7372 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
7374 DEVICEMODE
*devmode
= NULL
;
7376 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
7378 ZERO_STRUCTP(info_2
);
7380 if (info_2
== NULL
) {
7385 for (i
=0; i
<count
&& found
==False
; i
++) {
7386 if (queue
[i
].job
==(int)jobid
)
7391 /* NT treats not found as bad param... yet another bad
7393 ret
= WERR_INVALID_PARAM
;
7397 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
7398 if (!W_ERROR_IS_OK(ret
))
7400 if (construct_dev_mode(snum
) == NULL
) {
7405 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
7407 *needed
+= spoolss_size_job_info_2(info_2
);
7409 if (!alloc_buffer_size(buffer
, *needed
)) {
7410 ret
= WERR_INSUFFICIENT_BUFFER
;
7414 smb_io_job_info_2("", buffer
, info_2
, 0);
7416 if (*needed
> offered
) {
7417 ret
= WERR_INSUFFICIENT_BUFFER
;
7424 /* Cleanup allocated memory */
7427 free_job_info_2(info_2
); /* Also frees devmode */
7429 free_a_printer(&ntprinter
, 2);
7434 /****************************************************************************
7435 ****************************************************************************/
7437 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
7439 POLICY_HND
*handle
= &q_u
->handle
;
7440 uint32 jobid
= q_u
->jobid
;
7441 uint32 level
= q_u
->level
;
7442 NEW_BUFFER
*buffer
= NULL
;
7443 uint32 offered
= q_u
->offered
;
7444 uint32
*needed
= &r_u
->needed
;
7448 print_queue_struct
*queue
=NULL
;
7449 print_status_struct prt_status
;
7451 /* that's an [in out] buffer */
7452 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7453 buffer
= r_u
->buffer
;
7455 DEBUG(5,("spoolss_getjob\n"));
7459 if (!get_printer_snum(p
, handle
, &snum
))
7462 count
= print_queue_status(snum
, &queue
, &prt_status
);
7464 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7465 count
, prt_status
.status
, prt_status
.message
));
7469 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7471 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7474 return WERR_UNKNOWN_LEVEL
;
7478 /********************************************************************
7479 * spoolss_getprinterdataex
7480 ********************************************************************/
7482 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
7484 POLICY_HND
*handle
= &q_u
->handle
;
7485 uint32 in_size
= q_u
->size
;
7486 uint32
*type
= &r_u
->type
;
7487 uint32
*out_size
= &r_u
->size
;
7488 uint8
**data
= &r_u
->data
;
7489 uint32
*needed
= &r_u
->needed
;
7492 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7495 DEBUG(4,("_spoolss_getprinterdataex\n"));
7497 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
7498 unistr2_to_ascii(value
, &q_u
->valuename
, sizeof(value
) - 1);
7500 /* in case of problem, return some default values */
7507 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
7509 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7514 /* Is the handle to a printer or to the server? */
7516 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
7518 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7519 return WERR_INVALID_PARAM
;
7524 * From MSDN documentation of GetPrinterDataEx: pass request
7525 * to GetPrinterData if key is "PrinterDriverData". This is
7526 * the only key we really support. Other keys to implement:
7532 if (strcmp(key
, "PrinterDriverData") != 0)
7533 return WERR_BADFILE
;
7535 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7536 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
7537 type
, data
, needed
, in_size
);
7542 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
7544 /* reply this param doesn't exist */
7546 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
7552 return WERR_INVALID_PARAM
;
7555 if (*needed
> *out_size
)
7556 return WERR_MORE_DATA
;
7561 /********************************************************************
7562 * spoolss_setprinterdata
7563 ********************************************************************/
7565 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
7567 SPOOL_Q_SETPRINTERDATA q_u_local
;
7568 SPOOL_R_SETPRINTERDATA r_u_local
;
7571 DEBUG(4,("_spoolss_setprinterdataex\n"));
7573 /* From MSDN documentation of SetPrinterDataEx: pass request to
7574 SetPrinterData if key is "PrinterDriverData" */
7576 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7578 if (strcmp(key
, "PrinterDriverData") != 0)
7579 return WERR_INVALID_PARAM
;
7581 ZERO_STRUCT(q_u_local
);
7582 ZERO_STRUCT(r_u_local
);
7584 /* make a copy to call _spoolss_setprinterdata() */
7586 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
7587 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
7588 q_u_local
.type
= q_u
->type
;
7589 q_u_local
.max_len
= q_u
->max_len
;
7590 q_u_local
.data
= q_u
->data
;
7591 q_u_local
.real_len
= q_u
->real_len
;
7592 q_u_local
.numeric_data
= q_u
->numeric_data
;
7594 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
7597 /********************************************************************
7598 * spoolss_enumprinterkey
7599 ********************************************************************/
7601 /* constants for EnumPrinterKey() */
7602 #define ENUMERATED_KEY_SIZE 19
7604 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
7607 uint16 enumkeys
[ENUMERATED_KEY_SIZE
+1];
7610 char *PrinterKey
= "PrinterDriverData";
7612 DEBUG(4,("_spoolss_enumprinterkey\n"));
7614 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7617 * we only support enumating all keys (key == "")
7618 * Of course, the only key we support is the "PrinterDriverData"
7621 if (strlen(key
) == 0)
7623 r_u
->needed
= ENUMERATED_KEY_SIZE
*2;
7624 if (q_u
->size
< r_u
->needed
)
7625 return WERR_MORE_DATA
;
7628 for (i
=0; i
<ENUMERATED_KEY_SIZE
-2; i
++)
7630 enumkeys
[i
] = (uint16
)(*ptr
);
7634 /* tag of with 2 '\0's */
7635 enumkeys
[i
++] = '\0';
7638 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, ENUMERATED_KEY_SIZE
, enumkeys
))
7639 return WERR_BADFILE
;
7644 /* The "PrinterDriverData" key should have no subkeys */
7645 if (strcmp(key
, PrinterKey
) == 0)
7648 if (q_u
->size
< r_u
->needed
)
7649 return WERR_MORE_DATA
;
7651 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, enumkeys
))
7652 return WERR_BADFILE
;
7658 /* The return value for an unknown key is documented in MSDN
7659 EnumPrinterKey description */
7660 return WERR_BADFILE
;
7663 /********************************************************************
7664 * spoolss_enumprinterdataex
7665 ********************************************************************/
7667 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
7669 POLICY_HND
*handle
= &q_u
->handle
;
7670 uint32 in_size
= q_u
->size
;
7673 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7674 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
7676 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7685 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7688 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
7694 * The only key we support is "PrinterDriverData". This should return
7695 > an array of all the key/value pairs returned by EnumPrinterDataSee
7696 * _spoolss_getprinterdataex() for details --jerry
7699 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7700 if (strcmp(key
, "PrinterDriverData") != 0)
7702 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
7703 return WERR_INVALID_PARAM
;
7707 if (!get_printer_snum(p
,handle
, &snum
))
7710 ZERO_STRUCT(printer
);
7711 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7712 if (!W_ERROR_IS_OK(result
))
7717 * loop through all params and build the array to pass
7718 * back to the client
7725 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
))
7727 PRINTER_ENUM_VALUES
*ptr
;
7730 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries
, value
));
7732 if ((ptr
=talloc_realloc(p
->mem_ctx
, enum_values
, (num_entries
+1) * sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
7734 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7735 result
= WERR_NOMEM
;
7741 init_unistr(&enum_values
[num_entries
].valuename
, value
);
7742 enum_values
[num_entries
].value_len
= (strlen(value
)+1) * 2;
7743 enum_values
[num_entries
].type
= type
;
7745 if (!(enum_values
[num_entries
].data
=talloc_zero(p
->mem_ctx
, data_len
+add_len
))) {
7746 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7747 result
= WERR_NOMEM
;
7750 memcpy(enum_values
[num_entries
].data
, data
, data_len
);
7751 enum_values
[num_entries
].data_len
= data_len
+ add_len
;
7753 /* keep track of the size of the array in bytes */
7755 needed
+= spoolss_size_printer_enum_values(&enum_values
[num_entries
]);
7761 r_u
->needed
= needed
;
7762 r_u
->returned
= num_entries
;
7764 if (needed
> in_size
) {
7765 result
= WERR_MORE_DATA
;
7769 /* copy data into the reply */
7771 r_u
->ctr
.size
= r_u
->needed
;
7772 r_u
->ctr
.size_of_array
= r_u
->returned
;
7773 r_u
->ctr
.values
= enum_values
;
7778 free_a_printer(&printer
, 2);
7783 /****************************************************************************
7784 ****************************************************************************/
7786 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
7788 init_unistr(&info
->name
, name
);
7791 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
7792 UNISTR2
*environment
,
7799 pstring short_archi
;
7800 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
7802 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
7804 if (get_short_archi(short_archi
, long_archi
)==FALSE
)
7805 return WERR_INVALID_ENVIRONMENT
;
7807 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
7810 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
7812 fill_printprocessordirectory_1(info
, path
);
7814 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
7816 if (!alloc_buffer_size(buffer
, *needed
)) {
7818 return WERR_INSUFFICIENT_BUFFER
;
7821 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
7825 if (*needed
> offered
)
7826 return WERR_INSUFFICIENT_BUFFER
;
7831 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
7833 uint32 level
= q_u
->level
;
7834 NEW_BUFFER
*buffer
= NULL
;
7835 uint32 offered
= q_u
->offered
;
7836 uint32
*needed
= &r_u
->needed
;
7838 /* that's an [in out] buffer */
7839 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7840 buffer
= r_u
->buffer
;
7842 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7848 return getprintprocessordirectory_level_1
7849 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
7851 return WERR_UNKNOWN_LEVEL
;
7854 return WERR_ACCESS_DENIED
;