2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2003,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
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
40 /* Table to map the driver version */
42 const char * drv_ver_to_os
[] = {
43 "WIN9X", /* driver version/cversion 0 */
45 "WINNT", /* driver version/cversion 2 */
46 "WIN2K", /* driver version/cversion 3 */
50 const char *long_archi
;
51 const char *short_archi
;
56 /* structure to store the printer handles */
57 /* and a reference to what it's pointing to */
58 /* and the notify info asked about */
59 /* that's the central struct */
60 typedef struct _Printer
{
61 struct _Printer
*prev
, *next
;
62 BOOL document_started
;
64 int jobid
; /* jobid in printing backend */
68 fstring printerservername
;
71 uint32 access_granted
;
77 SPOOL_NOTIFY_OPTION
*option
;
78 POLICY_HND client_hnd
;
79 uint32 client_connected
;
88 static Printer_entry
*printers_list
;
90 typedef struct _counter_printer_0
{
98 static ubi_dlList counter_list
;
100 static struct cli_state cli
;
101 static uint32 smb_connections
=0;
104 /* in printing/nt_printing.c */
106 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
108 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
109 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
111 /* translate between internal status numbers and NT status numbers */
112 static int nt_printj_status(int v
)
118 return JOB_STATUS_PAUSED
;
120 return JOB_STATUS_SPOOLING
;
122 return JOB_STATUS_PRINTING
;
124 return JOB_STATUS_ERROR
;
126 return JOB_STATUS_DELETING
;
128 return JOB_STATUS_OFFLINE
;
130 return JOB_STATUS_PAPEROUT
;
132 return JOB_STATUS_PRINTED
;
134 return JOB_STATUS_DELETED
;
136 return JOB_STATUS_BLOCKED
;
137 case LPQ_USER_INTERVENTION
:
138 return JOB_STATUS_USER_INTERVENTION
;
143 static int nt_printq_status(int v
)
147 return PRINTER_STATUS_PAUSED
;
156 /****************************************************************************
157 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
158 ****************************************************************************/
160 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
165 SAFE_FREE((*pp
)->ctr
.type
);
169 /***************************************************************************
170 Disconnect from the client
171 ****************************************************************************/
173 static void srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
177 /* weird if the test succeds !!! */
178 if (smb_connections
==0) {
179 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
183 result
= cli_spoolss_reply_close_printer(&cli
, cli
.mem_ctx
, handle
);
185 if (!W_ERROR_IS_OK(result
))
186 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
187 dos_errstr(result
)));
189 /* if it's the last connection, deconnect the IPC$ share */
190 if (smb_connections
==1) {
191 if(!spoolss_disconnect_from_client(&cli
))
194 message_deregister(MSG_PRINTER_NOTIFY
);
200 /****************************************************************************
201 Functions to free a printer entry datastruct.
202 ****************************************************************************/
204 static void free_printer_entry(void *ptr
)
206 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
208 if (Printer
->notify
.client_connected
==True
)
209 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
211 Printer
->notify
.flags
=0;
212 Printer
->notify
.options
=0;
213 Printer
->notify
.localmachine
[0]='\0';
214 Printer
->notify
.printerlocal
=0;
215 free_spool_notify_option(&Printer
->notify
.option
);
216 Printer
->notify
.option
=NULL
;
217 Printer
->notify
.client_connected
=False
;
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list
, Printer
);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
231 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
236 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
243 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
245 if (!new_sp
->ctr
.type
) {
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
260 Printer_entry
*find_printer
= NULL
;
262 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
276 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
283 close_policy_hnd(p
, hnd
);
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
292 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
294 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
297 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
302 * It turns out that Windows allows delete printer on a handle
303 * opened by an admin user, then used on a pipe handle created
304 * by an anonymous user..... but they're working on security.... riiight !
308 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
309 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
310 return WERR_ACCESS_DENIED
;
314 /* Check calling user has permission to delete printer. Note that
315 since we set the snum parameter to -1 only administrators can
316 delete the printer. This stops people with the Full Control
317 permission from deleting the printer. */
319 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
320 DEBUG(3, ("printer delete denied by security descriptor\n"));
321 return WERR_ACCESS_DENIED
;
325 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
326 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
330 if (*lp_deleteprinter_cmd()) {
332 char *cmd
= lp_deleteprinter_cmd();
337 /* Printer->dev.handlename equals portname equals sharename */
338 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
339 Printer
->dev
.handlename
);
340 dos_to_unix(command
); /* Convert printername to unix-codepage */
342 DEBUG(10,("Running [%s]\n", command
));
343 ret
= smbrun(command
, NULL
);
345 return WERR_BADFID
; /* What to return here? */
347 DEBUGADD(10,("returned [%d]\n", ret
));
349 /* Send SIGHUP to process group... is there a better way? */
352 /* go ahead and re-read the services immediately */
353 reload_services( False
);
355 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) < 0 )
356 return WERR_ACCESS_DENIED
;
362 /****************************************************************************
363 Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
366 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
368 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
371 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
375 switch (Printer
->printer_type
) {
376 case PRINTER_HANDLE_IS_PRINTER
:
377 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
378 *number
= print_queue_snum(Printer
->dev
.handlename
);
379 return (*number
!= -1);
380 case PRINTER_HANDLE_IS_PRINTSERVER
:
387 /****************************************************************************
388 Set printer handle type.
389 Check if it's \\server or \\server\printer
390 ****************************************************************************/
392 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
394 DEBUG(3,("Setting printer type=%s\n", handlename
));
396 if ( strlen(handlename
) < 3 ) {
397 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
401 /* it's a print server */
402 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr(handlename
+2, '\\')) {
403 DEBUGADD(4,("Printer is a print server\n"));
404 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
408 DEBUGADD(4,("Printer is a printer\n"));
409 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
415 /****************************************************************************
416 Set printer handle name.
417 ****************************************************************************/
419 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
422 int n_services
=lp_numservices();
427 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
429 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
430 ZERO_STRUCT(Printer
->dev
.printerservername
);
431 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
435 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
438 if (*handlename
=='\\') {
439 aprinter
=strchr(handlename
+2, '\\');
446 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
449 * The original code allowed smbd to store a printer name that
450 * was different from the share name. This is not possible
451 * anymore, so I've simplified this loop greatly. Here
452 * we are just verifying that the printer name is a valid
453 * printer service defined in smb.conf
454 * --jerry [Fri Feb 15 11:17:46 CST 2002]
457 for (snum
=0; snum
<n_services
; snum
++) {
459 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
462 fstrcpy(sname
, lp_servicename(snum
));
464 DEBUGADD(5,("share:%s\n",sname
));
466 if (! StrCaseCmp(sname
, aprinter
)) {
475 DEBUGADD(4,("Printer not found\n"));
479 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
481 ZERO_STRUCT(Printer
->dev
.handlename
);
482 fstrcpy(Printer
->dev
.handlename
, sname
);
487 /****************************************************************************
488 Find first available printer slot. creates a printer handle for you.
489 ****************************************************************************/
491 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
493 Printer_entry
*new_printer
;
495 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
497 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
500 ZERO_STRUCTP(new_printer
);
502 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
503 SAFE_FREE(new_printer
);
507 /* Add to the internal list. */
508 DLIST_ADD(printers_list
, new_printer
);
510 new_printer
->notify
.option
=NULL
;
512 if ( !(new_printer
->ctx
= talloc_init_named("Printer Entry [0x%x]", (uint32
)hnd
)) ) {
513 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
514 close_printer_handle(p
, hnd
);
518 if (!set_printer_hnd_printertype(new_printer
, name
)) {
519 close_printer_handle(p
, hnd
);
523 if (!set_printer_hnd_name(new_printer
, name
)) {
524 close_printer_handle(p
, hnd
);
528 new_printer
->access_granted
= access_granted
;
530 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
535 /****************************************************************************
536 Allocate more memory for a BUFFER.
537 ****************************************************************************/
539 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
547 /* damn, I'm doing the reverse operation of prs_grow() :) */
548 if (buffer_size
< prs_data_size(ps
))
551 extra_space
= buffer_size
- prs_data_size(ps
);
554 * save the offset and move to the end of the buffer
555 * prs_grow() checks the extra_space against the offset
557 old_offset
=prs_offset(ps
);
558 prs_set_offset(ps
, prs_data_size(ps
));
560 if (!prs_grow(ps
, extra_space
))
563 prs_set_offset(ps
, old_offset
);
565 buffer
->string_at_end
=prs_data_size(ps
);
569 /***************************************************************************
570 Always give preference Printer_entry.notify.option over
571 Printer_entry.notify.flags. Return True if we should send notification
572 events using SPOOLSS_RRPCN. False means that we should use
573 SPOOLSS_ROUTERREPLYPRINTER.
574 **************************************************************************/
575 static BOOL
valid_notify_options(Printer_entry
*printer
)
577 if (printer
->notify
.option
== NULL
)
583 /***************************************************************************
584 Simple check to see if the client motify handle is set to watch for events
585 represented by 'flags'
587 FIXME!!!! only a stub right now --jerry
588 **************************************************************************/
590 static BOOL
is_client_monitoring_event(Printer_entry
*p
, uint32 flags
)
596 /***************************************************************************
597 Server wrapper for cli_spoolss_routerreplyprinter() since the client
598 function can only send a single change notification at a time.
600 FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
602 **************************************************************************/
604 static WERROR
srv_spoolss_routerreplyprinter (struct cli_state
*reply_cli
, TALLOC_CTX
*mem_ctx
,
605 POLICY_HND
*pol
, PRINTER_MESSAGE_INFO
*info
,
606 NT_PRINTER_INFO_LEVEL
*printer
)
609 uint32 condition
= 0x0;
611 if (info
->flags
& PRINTER_MESSAGE_DRIVER
)
612 condition
= PRINTER_CHANGE_SET_PRINTER_DRIVER
;
614 result
= cli_spoolss_routerreplyprinter(reply_cli
, mem_ctx
, pol
, condition
,
615 printer
->info_2
->changeid
);
620 /***********************************************************************
621 Wrapper around the decision of which RPC use to in the change
623 **********************************************************************/
625 static WERROR
srv_spoolss_send_event_to_client(Printer_entry
* Printer
,
626 struct cli_state
*send_cli
, PRINTER_MESSAGE_INFO
*msg
,
627 NT_PRINTER_INFO_LEVEL
*info
)
631 if (valid_notify_options(Printer
)) {
632 /* This is a single call that can send information about multiple changes */
633 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
634 msg
->flags
|= PRINTER_MESSAGE_ATTRIBUTES
;
636 result
= cli_spoolss_reply_rrpcn(send_cli
, send_cli
->mem_ctx
, &Printer
->notify
.client_hnd
,
640 /* This requires that the server send an individual event notification for each change */
641 result
= srv_spoolss_routerreplyprinter(send_cli
, send_cli
->mem_ctx
, &Printer
->notify
.client_hnd
,
649 /***********************************************************************
650 Send a change notication message on all handles which have a call
652 **********************************************************************/
654 static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO
*msg
)
656 Printer_entry
*find_printer
;
658 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
661 DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
665 for(find_printer
= printers_list
; find_printer
; find_printer
= find_printer
->next
) {
668 * If the entry has a connected client we send the message. There should
669 * only be one of these normally when dealing with the NT/2k spooler.
670 * However, iterate over all to make sure we deal with user applications
671 * in addition to spooler service.
673 * While we are only maintaining a single connection to the client,
674 * the FindFirstPrinterChangeNotification() call is made on a printer
675 * handle, so "client_connected" represents the whether or not the
676 * client asked for change notication on this handle.
681 if (find_printer
->notify
.client_connected
==True
) {
683 msg
->low
= find_printer
->notify
.change
;
685 /* does the client care about what changed? */
687 if (msg
->flags
&& !is_client_monitoring_event(find_printer
, msg
->flags
)) {
688 DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
689 find_printer
->client
.machine
));
693 if (find_printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
694 DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer
->dev
.printerservername
));
696 DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer
->dev
.handlename
));
699 * if handle is a printer, only send if the printer_name matches.
700 * ...else if handle is a printerserver, send to all
703 if (*msg
->printer_name
&& (find_printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
704 && !strequal(msg
->printer_name
, find_printer
->dev
.handlename
))
706 DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
707 msg
->printer_name
, find_printer
->dev
.handlename
));
712 /* lookup the printer if we have a name if we don't already have a
713 valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
714 will always have a non-empty msg.printer_name */
716 if (!printer
|| !printer
->info_2
|| strcmp(msg
->printer_name
, printer
->info_2
->printername
))
720 free_a_printer(&printer
, 2);
724 result
= get_a_printer(&printer
, 2, msg
->printer_name
);
725 if (!W_ERROR_IS_OK(result
))
729 /* issue the client call */
731 result
= srv_spoolss_send_event_to_client(find_printer
, &cli
, msg
, printer
);
733 if (!W_ERROR_IS_OK(result
)) {
734 DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
735 dos_errstr(result
)));
742 /***************************************************************************
743 Receive the notify message and decode the message. Do not send
744 notification if we sent this originally as that would result in
746 ****************************************************************************/
748 static void srv_spoolss_receive_message(int msg_type
, pid_t src
, void *buf
, size_t len
)
750 PRINTER_MESSAGE_INFO msg
;
752 if (len
< sizeof(msg
)) {
753 DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len
));
757 memcpy(&msg
, buf
, sizeof(PRINTER_MESSAGE_INFO
));
759 DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
760 msg
.printer_name
, (unsigned int)msg
.low
, (unsigned int)msg
.high
, msg
.flags
));
762 /* Iterate the printer list */
764 send_spoolss_event_notification(&msg
);
768 /***************************************************************************
770 ****************************************************************************/
772 static BOOL
srv_spoolss_sendnotify(char* printer_name
, uint32 high
, uint32 low
, uint32 flags
)
774 char msg
[sizeof(PRINTER_MESSAGE_INFO
)];
775 PRINTER_MESSAGE_INFO info
;
782 fstrcpy(info
.printer_name
, printer_name
);
784 memcpy(msg
, &info
, sizeof(PRINTER_MESSAGE_INFO
));
786 DEBUG(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
787 low
, high
, printer_name
, flags
));
789 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY
, msg
, sizeof(PRINTER_MESSAGE_INFO
),
795 /********************************************************************
796 Send a message to ourself about new driver being installed
797 so we can upgrade the information for each printer bound to this
799 ********************************************************************/
801 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
803 int len
= strlen(drivername
);
808 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
811 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
816 /**********************************************************************
817 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
818 over all printers, upgrading ones as neessary
819 **********************************************************************/
821 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
825 int n_services
= lp_numservices();
827 len
= MIN(len
,sizeof(drivername
)-1);
828 strncpy(drivername
, buf
, len
);
830 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
832 /* Iterate the printer list */
834 for (snum
=0; snum
<n_services
; snum
++)
836 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
839 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
841 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
842 if (!W_ERROR_IS_OK(result
))
845 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
847 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
849 /* all we care about currently is the change_id */
851 result
= mod_a_printer(*printer
, 2);
852 if (!W_ERROR_IS_OK(result
)) {
853 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
854 dos_errstr(result
)));
858 free_a_printer(&printer
, 2);
865 /********************************************************************
866 Copy routines used by convert_to_openprinterex()
867 *******************************************************************/
869 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
877 DEBUG (8,("dup_devmode\n"));
879 /* bulk copy first */
881 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
885 /* dup the pointer members separately */
887 len
= unistrlen(devmode
->devicename
.buffer
);
889 d
->devicename
.buffer
= talloc(ctx
, len
*2);
890 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
895 len
= unistrlen(devmode
->formname
.buffer
);
897 d
->devicename
.buffer
= talloc(ctx
, len
*2);
898 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
902 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
907 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
909 if (!new_ctr
|| !ctr
)
912 DEBUG(8,("copy_devmode_ctr\n"));
914 new_ctr
->size
= ctr
->size
;
915 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
918 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
921 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
923 if (!new_def
|| !def
)
926 DEBUG(8,("copy_printer_defaults\n"));
928 new_def
->datatype_ptr
= def
->datatype_ptr
;
930 if (def
->datatype_ptr
)
931 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
933 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
935 new_def
->access_required
= def
->access_required
;
938 /********************************************************************
939 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
940 * SPOOL_Q_OPEN_PRINTER_EX structure
941 ********************************************************************/
943 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
948 DEBUG(8,("convert_to_openprinterex\n"));
950 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
952 if (q_u
->printername_ptr
)
953 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
955 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
958 /********************************************************************
959 * spoolss_open_printer
961 * called from the spoolss dispatcher
962 ********************************************************************/
964 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
966 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
967 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
975 /* convert the OpenPrinter() call to OpenPrinterEx() */
977 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
979 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
981 /* convert back to OpenPrinter() */
983 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
988 /********************************************************************
989 * spoolss_open_printer
991 * If the openprinterex rpc call contains a devmode,
992 * it's a per-user one. This per-user devmode is derivated
993 * from the global devmode. Openprinterex() contains a per-user
994 * devmode for when you do EMF printing and spooling.
995 * In the EMF case, the NT workstation is only doing half the job
996 * of rendering the page. The other half is done by running the printer
997 * driver on the server.
998 * The EMF file doesn't contain the page description (paper size, orientation, ...).
999 * The EMF file only contains what is to be printed on the page.
1000 * So in order for the server to know how to print, the NT client sends
1001 * a devicemode attached to the openprinterex call.
1002 * But this devicemode is short lived, it's only valid for the current print job.
1004 * If Samba would have supported EMF spooling, this devicemode would
1005 * have been attached to the handle, to sent it to the driver to correctly
1006 * rasterize the EMF file.
1008 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1009 * we just act as a pass-thru between windows and the printer.
1011 * In order to know that Samba supports only RAW spooling, NT has to call
1012 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1013 * and until NT sends a RAW job, we refuse it.
1015 * But to call getprinter() or startdoc(), you first need a valid handle,
1016 * and to get an handle you have to call openprintex(). Hence why you have
1017 * a devicemode in the openprinterex() call.
1020 * Differences between NT4 and NT 2000.
1023 * On NT4, you only have a global devicemode. This global devicemode can be changed
1024 * by the administrator (or by a user with enough privs). Everytime a user
1025 * wants to print, the devicemode is resetted to the default. In Word, everytime
1026 * you print, the printer's characteristics are always reset to the global devicemode.
1030 * In W2K, there is the notion of per-user devicemode. The first time you use
1031 * a printer, a per-user devicemode is build from the global devicemode.
1032 * If you change your per-user devicemode, it is saved in the registry, under the
1033 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1034 * printer preferences available.
1036 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1037 * on the General Tab of the printer properties windows.
1039 * To change the global devicemode: it's the "Printing Defaults..." button
1040 * on the Advanced Tab of the printer properties window.
1043 ********************************************************************/
1045 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1047 UNISTR2
*printername
= NULL
;
1048 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1049 /* uint32 user_switch = q_u->user_switch; - notused */
1050 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
1051 POLICY_HND
*handle
= &r_u
->handle
;
1055 struct current_user user
;
1056 Printer_entry
*Printer
=NULL
;
1058 if (q_u
->printername_ptr
!= 0)
1059 printername
= &q_u
->printername
;
1061 if (printername
== NULL
)
1062 return WERR_INVALID_PRINTER_NAME
;
1064 /* some sanity check because you can open a printer or a print server */
1065 /* aka: \\server\printer or \\server */
1066 unistr2_to_dos(name
, printername
, sizeof(name
)-1);
1068 DEBUGADD(3,("checking name: %s\n",name
));
1070 if (!open_printer_hnd(p
, handle
, name
, 0))
1071 return WERR_INVALID_PRINTER_NAME
;
1073 Printer
=find_printer_index_by_hnd(p
, handle
);
1075 DEBUG(0,(" _spoolss_open_printer_ex: logic error. \
1076 Can't find printer handle we created for printer %s\n", name
));
1077 close_printer_handle(p
,handle
);
1078 return WERR_INVALID_PRINTER_NAME
;
1081 get_current_user(&user
, p
);
1084 * First case: the user is opening the print server:
1086 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1087 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1089 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1090 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1091 * or if the user is listed in the smb.conf printer admin parameter.
1093 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1094 * client view printer folder, but does not show the MSAPW.
1096 * Note: this test needs code to check access rights here too. Jeremy
1097 * could you look at this?
1099 * Second case: the user is opening a printer:
1100 * NT doesn't let us connect to a printer if the connecting user
1101 * doesn't have print permission.
1104 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1106 /* Printserver handles use global struct... */
1110 /* Map standard access rights to object specific access rights */
1112 se_map_standard(&printer_default
->access_required
,
1113 &printserver_std_mapping
);
1115 /* Deny any object specific bits that don't apply to print
1116 servers (i.e printer and job specific bits) */
1118 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1120 if (printer_default
->access_required
&
1121 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1122 DEBUG(3, ("access DENIED for non-printserver bits"));
1123 close_printer_handle(p
, handle
);
1124 return WERR_ACCESS_DENIED
;
1127 /* Allow admin access */
1129 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1131 if (!lp_ms_add_printer_wizard()) {
1132 close_printer_handle(p
, handle
);
1133 return WERR_ACCESS_DENIED
;
1136 /* if the user is not root and not a printer admin, then fail */
1139 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
)) )
1141 close_printer_handle(p
, handle
);
1142 return WERR_ACCESS_DENIED
;
1145 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1149 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1152 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1153 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1155 /* We fall through to return WERR_OK */
1160 /* NT doesn't let us connect to a printer if the connecting user
1161 doesn't have print permission. */
1163 if (!get_printer_snum(p
, handle
, &snum
))
1166 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1168 /* map an empty access mask to the minimum access mask */
1169 if (printer_default
->access_required
== 0x0)
1170 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1173 * If we are not serving the printer driver for this printer,
1174 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1175 * will keep NT clients happy --jerry
1178 if (lp_use_client_driver(snum
)
1179 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1181 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1184 /* check smb.conf parameters and the the sec_desc */
1186 if (!user_ok(uidtoname(user
.uid
), snum
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1187 DEBUG(3, ("access DENIED for printer open\n"));
1188 close_printer_handle(p
, handle
);
1189 return WERR_ACCESS_DENIED
;
1192 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1193 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1194 close_printer_handle(p
, handle
);
1195 return WERR_ACCESS_DENIED
;
1198 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1199 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1201 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1203 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1204 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1207 Printer
->access_granted
= printer_default
->access_required
;
1212 /****************************************************************************
1213 ****************************************************************************/
1215 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1216 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1222 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1231 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1232 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1238 printer
->info_3
=NULL
;
1239 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1243 printer
->info_6
=NULL
;
1244 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1254 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1255 NT_DEVICEMODE
**pp_nt_devmode
)
1257 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1260 * Ensure nt_devmode is a valid pointer
1261 * as we will be overwriting it.
1264 if (nt_devmode
== NULL
) {
1265 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1266 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1270 unistr_to_dos(nt_devmode
->devicename
, (const char *)devmode
->devicename
.buffer
, 31);
1271 unistr_to_dos(nt_devmode
->formname
, (const char *)devmode
->formname
.buffer
, 31);
1273 nt_devmode
->specversion
=devmode
->specversion
;
1274 nt_devmode
->driverversion
=devmode
->driverversion
;
1275 nt_devmode
->size
=devmode
->size
;
1276 nt_devmode
->fields
=devmode
->fields
;
1277 nt_devmode
->orientation
=devmode
->orientation
;
1278 nt_devmode
->papersize
=devmode
->papersize
;
1279 nt_devmode
->paperlength
=devmode
->paperlength
;
1280 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1281 nt_devmode
->scale
=devmode
->scale
;
1282 nt_devmode
->copies
=devmode
->copies
;
1283 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1284 nt_devmode
->printquality
=devmode
->printquality
;
1285 nt_devmode
->color
=devmode
->color
;
1286 nt_devmode
->duplex
=devmode
->duplex
;
1287 nt_devmode
->yresolution
=devmode
->yresolution
;
1288 nt_devmode
->ttoption
=devmode
->ttoption
;
1289 nt_devmode
->collate
=devmode
->collate
;
1291 nt_devmode
->logpixels
=devmode
->logpixels
;
1292 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1293 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1294 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1295 nt_devmode
->displayflags
=devmode
->displayflags
;
1296 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1297 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1298 nt_devmode
->icmintent
=devmode
->icmintent
;
1299 nt_devmode
->mediatype
=devmode
->mediatype
;
1300 nt_devmode
->dithertype
=devmode
->dithertype
;
1301 nt_devmode
->reserved1
=devmode
->reserved1
;
1302 nt_devmode
->reserved2
=devmode
->reserved2
;
1303 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1304 nt_devmode
->panningheight
=devmode
->panningheight
;
1307 * Only change private and driverextra if the incoming devmode
1308 * has a new one. JRA.
1311 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1312 SAFE_FREE(nt_devmode
->private);
1313 nt_devmode
->driverextra
=devmode
->driverextra
;
1314 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1316 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1319 *pp_nt_devmode
= nt_devmode
;
1324 /********************************************************************
1325 * _spoolss_enddocprinter_internal.
1326 ********************************************************************/
1328 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1330 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1333 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1337 Printer
->document_started
=False
;
1338 print_job_end(Printer
->jobid
,True
);
1339 /* error codes unhandled so far ... */
1344 /********************************************************************
1345 * api_spoolss_closeprinter
1346 ********************************************************************/
1348 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1350 POLICY_HND
*handle
= &q_u
->handle
;
1352 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1354 if (Printer
&& Printer
->document_started
)
1355 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1357 if (!close_printer_handle(p
, handle
))
1360 /* clear the returned printer handle. Observed behavior
1361 from Win2k server. Don't think this really matters.
1362 Previous code just copied the value of the closed
1365 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1370 /********************************************************************
1371 * api_spoolss_deleteprinter
1373 ********************************************************************/
1375 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1377 POLICY_HND
*handle
= &q_u
->handle
;
1378 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1381 if (Printer
&& Printer
->document_started
)
1382 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1384 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1386 result
= delete_printer_handle(p
, handle
);
1388 update_c_setprinter(False
);
1390 if (W_ERROR_IS_OK(result
)) {
1391 srv_spoolss_sendnotify(Printer
->dev
.handlename
, 0, PRINTER_CHANGE_DELETE_PRINTER
, 0x0);
1397 /*******************************************************************
1398 * static function to lookup the version id corresponding to an
1399 * long architecture string
1400 ******************************************************************/
1402 static int get_version_id (char * arch
)
1405 struct table_node archi_table
[]= {
1407 {"Windows 4.0", "WIN40", 0 },
1408 {"Windows NT x86", "W32X86", 2 },
1409 {"Windows NT R4000", "W32MIPS", 2 },
1410 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1411 {"Windows NT PowerPC", "W32PPC", 2 },
1415 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1417 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1418 return (archi_table
[i
].version
);
1424 /********************************************************************
1425 * _spoolss_deleteprinterdriver
1427 * We currently delete the driver for the architecture only.
1428 * This can leave the driver for other archtectures. However,
1429 * since every printer associates a "Windows NT x86" driver name
1430 * and we cannot delete that one while it is in use, **and** since
1431 * it is impossible to assign a driver to a Samba printer without
1432 * having the "Windows NT x86" driver installed,...
1434 * ....we should not get into trouble here.
1437 ********************************************************************/
1439 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
,
1440 SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1444 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1445 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1447 struct current_user user
;
1449 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1451 unistr2_to_dos(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1452 unistr2_to_dos(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1453 get_current_user(&user
, p
);
1455 unistr2_to_dos(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1457 /* check that we have a valid driver name first */
1459 if ((version
=get_version_id(arch
)) == -1)
1460 return WERR_INVALID_ENVIRONMENT
;
1463 ZERO_STRUCT(info_win2k
);
1465 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1467 /* try for Win2k driver if "Windows NT x86" */
1469 if ( version
== 2 ) {
1471 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1472 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1476 /* otherwise it was a failure */
1478 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1484 if (printer_driver_in_use(info
.info_3
)) {
1485 status
= WERR_PRINTER_DRIVER_IN_USE
;
1491 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
1493 /* if we get to here, we now have 2 driver info structures to remove */
1494 /* remove the Win2k driver first*/
1496 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
1497 free_a_printer_driver( info_win2k
, 3 );
1499 /* this should not have failed---if it did, report to client */
1500 if ( !W_ERROR_IS_OK(status_win2k
) )
1505 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
1507 /* if at least one of the deletes succeeded return OK */
1509 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1513 free_a_printer_driver( info
, 3 );
1518 /********************************************************************
1519 GetPrinterData on a printer server Handle.
1520 ********************************************************************/
1522 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1526 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1528 if (!strcmp(value
, "W3SvcInstalled")) {
1530 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
1536 if (!strcmp(value
, "BeepEnabled")) {
1538 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1540 SIVAL(*data
, 0, 0x00);
1545 if (!strcmp(value
, "EventLog")) {
1547 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1549 /* formally was 0x1b */
1550 SIVAL(*data
, 0, 0x0);
1555 if (!strcmp(value
, "NetPopup")) {
1557 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1559 SIVAL(*data
, 0, 0x00);
1564 if (!strcmp(value
, "MajorVersion")) {
1566 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1568 #ifndef EMULATE_WIN2K_HACK /* JERRY */
1577 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1580 fstrcpy(string
, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
1582 *needed
= 2*(strlen(string
)+1);
1583 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1585 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1587 /* it's done by hand ready to go on the wire */
1588 for (i
=0; i
<strlen(string
); i
++) {
1589 (*data
)[2*i
]=string
[i
];
1590 (*data
)[2*i
+1]='\0';
1595 if (!strcmp(value
, "Architecture")) {
1596 pstring string
="Windows NT x86";
1598 *needed
= 2*(strlen(string
)+1);
1599 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1601 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1602 for (i
=0; i
<strlen(string
); i
++) {
1603 (*data
)[2*i
]=string
[i
];
1604 (*data
)[2*i
+1]='\0';
1612 /********************************************************************
1613 GetPrinterData on a printer Handle.
1614 ********************************************************************/
1616 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1617 fstring value
, uint32
*type
,
1618 uint8
**data
, uint32
*needed
, uint32 in_size
)
1620 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1624 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1626 DEBUG(5,("getprinterdata_printer\n"));
1629 DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1633 if(!get_printer_snum(p
, handle
, &snum
))
1636 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
1639 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
1640 free_a_printer(&printer
, 2);
1644 free_a_printer(&printer
, 2);
1646 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1649 if((*data
= (uint8
*)talloc(ctx
, in_size
*sizeof(uint8
) )) == NULL
) {
1653 memset(*data
, 0, in_size
*sizeof(uint8
));
1654 /* copy the min(in_size, len) */
1655 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
1662 DEBUG(5,("getprinterdata_printer:copy done\n"));
1669 /********************************************************************
1670 * spoolss_getprinterdata
1671 ********************************************************************/
1673 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1675 POLICY_HND
*handle
= &q_u
->handle
;
1676 UNISTR2
*valuename
= &q_u
->valuename
;
1677 uint32 in_size
= q_u
->size
;
1678 uint32
*type
= &r_u
->type
;
1679 uint32
*out_size
= &r_u
->size
;
1680 uint8
**data
= &r_u
->data
;
1681 uint32
*needed
= &r_u
->needed
;
1685 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1688 * Reminder: when it's a string, the length is in BYTES
1689 * even if UNICODE is negociated.
1696 /* in case of problem, return some default values */
1700 DEBUG(4,("_spoolss_getprinterdata\n"));
1703 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1705 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1709 unistr2_to_dos(value
, valuename
, sizeof(value
)-1);
1711 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1712 found
=getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1714 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1717 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1718 /* reply this param doesn't exist */
1720 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1726 /* error depends on handle type */
1728 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1729 return WERR_INVALID_PARAM
;
1731 return WERR_BADFILE
;
1734 if (*needed
> *out_size
)
1735 return WERR_MORE_DATA
;
1740 /***************************************************************************
1741 Connect to the client.
1742 ****************************************************************************/
1744 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1749 * If it's the first connection, contact the client
1750 * and connect to the IPC$ share anonumously
1752 if (smb_connections
==0) {
1753 fstring unix_printer
;
1755 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
1756 dos_to_unix(unix_printer
);
1758 if(!spoolss_connect_to_client(&cli
, unix_printer
))
1761 message_register(MSG_PRINTER_NOTIFY
, srv_spoolss_receive_message
);
1767 result
= cli_spoolss_reply_open_printer(&cli
, cli
.mem_ctx
, printer
, localprinter
,
1770 if (!W_ERROR_IS_OK(result
))
1771 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
1772 dos_errstr(result
)));
1774 return (W_ERROR_IS_OK(result
));
1777 /********************************************************************
1779 * ReplyFindFirstPrinterChangeNotifyEx
1781 * before replying OK: status=0 a rpc call is made to the workstation
1782 * asking ReplyOpenPrinter
1784 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1785 * called from api_spoolss_rffpcnex
1786 ********************************************************************/
1788 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
1790 POLICY_HND
*handle
= &q_u
->handle
;
1791 uint32 flags
= q_u
->flags
;
1792 uint32 options
= q_u
->options
;
1793 UNISTR2
*localmachine
= &q_u
->localmachine
;
1794 uint32 printerlocal
= q_u
->printerlocal
;
1795 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
1797 /* store the notify value in the printer struct */
1799 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1802 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
1806 Printer
->notify
.flags
=flags
;
1807 Printer
->notify
.options
=options
;
1808 Printer
->notify
.printerlocal
=printerlocal
;
1810 if (Printer
->notify
.option
)
1811 free_spool_notify_option(&Printer
->notify
.option
);
1813 Printer
->notify
.option
=dup_spool_notify_option(option
);
1815 unistr2_to_dos(Printer
->notify
.localmachine
, localmachine
, sizeof(Printer
->notify
.localmachine
)-1);
1817 /* connect to the client machine and send a ReplyOpenPrinter */
1818 if(srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
1819 Printer
->notify
.printerlocal
, 1,
1820 &Printer
->notify
.client_hnd
))
1822 Printer
->notify
.client_connected
=True
;
1828 /*******************************************************************
1829 * fill a notify_info_data with the servername
1830 ********************************************************************/
1832 void spoolss_notify_server_name(int snum
,
1833 SPOOL_NOTIFY_INFO_DATA
*data
,
1834 print_queue_struct
*queue
,
1835 NT_PRINTER_INFO_LEVEL
*printer
,
1836 TALLOC_CTX
*mem_ctx
)
1838 pstring temp_name
, temp
;
1841 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
1843 len
= (uint32
)dos_PutUniCode(temp
, temp_name
, sizeof(temp
) - 2, True
);
1845 data
->notify_data
.data
.length
= len
/ 2 - 1;
1846 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1848 if (!data
->notify_data
.data
.string
) {
1849 data
->notify_data
.data
.length
= 0;
1853 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1856 /*******************************************************************
1857 * fill a notify_info_data with the printername (not including the servername).
1858 ********************************************************************/
1860 void spoolss_notify_printer_name(int snum
,
1861 SPOOL_NOTIFY_INFO_DATA
*data
,
1862 print_queue_struct
*queue
,
1863 NT_PRINTER_INFO_LEVEL
*printer
,
1864 TALLOC_CTX
*mem_ctx
)
1869 /* the notify name should not contain the \\server\ part */
1870 char *p
= strrchr(printer
->info_2
->printername
, '\\');
1873 p
= printer
->info_2
->printername
;
1878 len
= (uint32
)dos_PutUniCode(temp
, p
, sizeof(temp
) - 2, True
);
1880 data
->notify_data
.data
.length
= len
/ 2 - 1;
1881 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1883 if (!data
->notify_data
.data
.string
) {
1884 data
->notify_data
.data
.length
= 0;
1888 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1891 /*******************************************************************
1892 * fill a notify_info_data with the servicename
1893 ********************************************************************/
1895 void spoolss_notify_share_name(int snum
,
1896 SPOOL_NOTIFY_INFO_DATA
*data
,
1897 print_queue_struct
*queue
,
1898 NT_PRINTER_INFO_LEVEL
*printer
,
1899 TALLOC_CTX
*mem_ctx
)
1904 len
= (uint32
)dos_PutUniCode(temp
, lp_servicename(snum
),
1905 sizeof(temp
) - 2, True
);
1907 data
->notify_data
.data
.length
= len
/ 2 - 1;
1908 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1910 if (!data
->notify_data
.data
.string
) {
1911 data
->notify_data
.data
.length
= 0;
1915 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1918 /*******************************************************************
1919 * fill a notify_info_data with the port name
1920 ********************************************************************/
1922 void spoolss_notify_port_name(int snum
,
1923 SPOOL_NOTIFY_INFO_DATA
*data
,
1924 print_queue_struct
*queue
,
1925 NT_PRINTER_INFO_LEVEL
*printer
,
1926 TALLOC_CTX
*mem_ctx
)
1931 /* even if it's strange, that's consistant in all the code */
1933 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->portname
,
1934 sizeof(temp
) - 2, True
);
1936 data
->notify_data
.data
.length
= len
/ 2 - 1;
1937 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1939 if (!data
->notify_data
.data
.string
) {
1940 data
->notify_data
.data
.length
= 0;
1944 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1947 /*******************************************************************
1948 * fill a notify_info_data with the printername
1949 * but it doesn't exist, have to see what to do
1950 ********************************************************************/
1952 void spoolss_notify_driver_name(int snum
,
1953 SPOOL_NOTIFY_INFO_DATA
*data
,
1954 print_queue_struct
*queue
,
1955 NT_PRINTER_INFO_LEVEL
*printer
,
1956 TALLOC_CTX
*mem_ctx
)
1961 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->drivername
,
1962 sizeof(temp
) - 2, True
);
1964 data
->notify_data
.data
.length
= len
/ 2 - 1;
1965 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1967 if (!data
->notify_data
.data
.string
) {
1968 data
->notify_data
.data
.length
= 0;
1972 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1975 /*******************************************************************
1976 * fill a notify_info_data with the comment
1977 ********************************************************************/
1979 void spoolss_notify_comment(int snum
,
1980 SPOOL_NOTIFY_INFO_DATA
*data
,
1981 print_queue_struct
*queue
,
1982 NT_PRINTER_INFO_LEVEL
*printer
,
1983 TALLOC_CTX
*mem_ctx
)
1988 if (*printer
->info_2
->comment
== '\0')
1989 len
= (uint32
)dos_PutUniCode(temp
, lp_comment(snum
),
1990 sizeof(temp
) - 2, True
);
1992 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->comment
,
1993 sizeof(temp
) - 2, True
);
1995 data
->notify_data
.data
.length
= len
/ 2 - 1;
1996 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1998 if (!data
->notify_data
.data
.string
) {
1999 data
->notify_data
.data
.length
= 0;
2003 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2006 /*******************************************************************
2007 * fill a notify_info_data with the comment
2008 * location = "Room 1, floor 2, building 3"
2009 ********************************************************************/
2011 void spoolss_notify_location(int snum
,
2012 SPOOL_NOTIFY_INFO_DATA
*data
,
2013 print_queue_struct
*queue
,
2014 NT_PRINTER_INFO_LEVEL
*printer
,
2015 TALLOC_CTX
*mem_ctx
)
2020 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->location
,
2021 sizeof(temp
) - 2, True
);
2023 data
->notify_data
.data
.length
= len
/ 2 - 1;
2024 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2026 if (!data
->notify_data
.data
.string
) {
2027 data
->notify_data
.data
.length
= 0;
2031 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2034 /*******************************************************************
2035 * fill a notify_info_data with the device mode
2036 * jfm:xxxx don't to it for know but that's a real problem !!!
2037 ********************************************************************/
2039 static void spoolss_notify_devmode(int snum
,
2040 SPOOL_NOTIFY_INFO_DATA
*data
,
2041 print_queue_struct
*queue
,
2042 NT_PRINTER_INFO_LEVEL
*printer
,
2043 TALLOC_CTX
*mem_ctx
)
2047 /*******************************************************************
2048 * fill a notify_info_data with the separator file name
2049 ********************************************************************/
2051 void spoolss_notify_sepfile(int snum
,
2052 SPOOL_NOTIFY_INFO_DATA
*data
,
2053 print_queue_struct
*queue
,
2054 NT_PRINTER_INFO_LEVEL
*printer
,
2055 TALLOC_CTX
*mem_ctx
)
2060 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->sepfile
,
2061 sizeof(temp
) - 2, True
);
2063 data
->notify_data
.data
.length
= len
/ 2 - 1;
2064 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2066 if (!data
->notify_data
.data
.string
) {
2067 data
->notify_data
.data
.length
= 0;
2071 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2074 /*******************************************************************
2075 * fill a notify_info_data with the print processor
2076 * jfm:xxxx return always winprint to indicate we don't do anything to it
2077 ********************************************************************/
2079 void spoolss_notify_print_processor(int snum
,
2080 SPOOL_NOTIFY_INFO_DATA
*data
,
2081 print_queue_struct
*queue
,
2082 NT_PRINTER_INFO_LEVEL
*printer
,
2083 TALLOC_CTX
*mem_ctx
)
2088 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->printprocessor
,
2089 sizeof(temp
) - 2, True
);
2091 data
->notify_data
.data
.length
= len
/ 2 - 1;
2092 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2094 if (!data
->notify_data
.data
.string
) {
2095 data
->notify_data
.data
.length
= 0;
2099 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2102 /*******************************************************************
2103 * fill a notify_info_data with the print processor options
2104 * jfm:xxxx send an empty string
2105 ********************************************************************/
2107 void spoolss_notify_parameters(int snum
,
2108 SPOOL_NOTIFY_INFO_DATA
*data
,
2109 print_queue_struct
*queue
,
2110 NT_PRINTER_INFO_LEVEL
*printer
,
2111 TALLOC_CTX
*mem_ctx
)
2116 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->parameters
,
2117 sizeof(temp
) - 2, True
);
2119 data
->notify_data
.data
.length
= len
/ 2 - 1;
2120 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2122 if (!data
->notify_data
.data
.string
) {
2123 data
->notify_data
.data
.length
= 0;
2127 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2130 /*******************************************************************
2131 * fill a notify_info_data with the data type
2132 * jfm:xxxx always send RAW as data type
2133 ********************************************************************/
2135 void spoolss_notify_datatype(int snum
,
2136 SPOOL_NOTIFY_INFO_DATA
*data
,
2137 print_queue_struct
*queue
,
2138 NT_PRINTER_INFO_LEVEL
*printer
,
2139 TALLOC_CTX
*mem_ctx
)
2144 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->datatype
,
2145 sizeof(pstring
) - 2, True
);
2147 data
->notify_data
.data
.length
= len
/ 2 - 1;
2148 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2150 if (!data
->notify_data
.data
.string
) {
2151 data
->notify_data
.data
.length
= 0;
2155 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2158 /*******************************************************************
2159 * fill a notify_info_data with the security descriptor
2160 * jfm:xxxx send an null pointer to say no security desc
2161 * have to implement security before !
2162 ********************************************************************/
2164 static void spoolss_notify_security_desc(int snum
,
2165 SPOOL_NOTIFY_INFO_DATA
*data
,
2166 print_queue_struct
*queue
,
2167 NT_PRINTER_INFO_LEVEL
*printer
,
2168 TALLOC_CTX
*mem_ctx
)
2170 data
->notify_data
.data
.length
=0;
2171 data
->notify_data
.data
.string
= NULL
;
2174 /*******************************************************************
2175 * fill a notify_info_data with the attributes
2176 * jfm:xxxx a samba printer is always shared
2177 ********************************************************************/
2179 void spoolss_notify_attributes(int snum
,
2180 SPOOL_NOTIFY_INFO_DATA
*data
,
2181 print_queue_struct
*queue
,
2182 NT_PRINTER_INFO_LEVEL
*printer
,
2183 TALLOC_CTX
*mem_ctx
)
2185 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
2186 data
->notify_data
.value
[1] = 0;
2189 /*******************************************************************
2190 * fill a notify_info_data with the priority
2191 ********************************************************************/
2193 static void spoolss_notify_priority(int snum
,
2194 SPOOL_NOTIFY_INFO_DATA
*data
,
2195 print_queue_struct
*queue
,
2196 NT_PRINTER_INFO_LEVEL
*printer
,
2197 TALLOC_CTX
*mem_ctx
)
2199 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
2200 data
->notify_data
.value
[1] = 0;
2203 /*******************************************************************
2204 * fill a notify_info_data with the default priority
2205 ********************************************************************/
2207 static void spoolss_notify_default_priority(int snum
,
2208 SPOOL_NOTIFY_INFO_DATA
*data
,
2209 print_queue_struct
*queue
,
2210 NT_PRINTER_INFO_LEVEL
*printer
,
2211 TALLOC_CTX
*mem_ctx
)
2213 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
2214 data
->notify_data
.value
[1] = 0;
2217 /*******************************************************************
2218 * fill a notify_info_data with the start time
2219 ********************************************************************/
2221 static void spoolss_notify_start_time(int snum
,
2222 SPOOL_NOTIFY_INFO_DATA
*data
,
2223 print_queue_struct
*queue
,
2224 NT_PRINTER_INFO_LEVEL
*printer
,
2225 TALLOC_CTX
*mem_ctx
)
2227 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
2228 data
->notify_data
.value
[1] = 0;
2231 /*******************************************************************
2232 * fill a notify_info_data with the until time
2233 ********************************************************************/
2235 static void spoolss_notify_until_time(int snum
,
2236 SPOOL_NOTIFY_INFO_DATA
*data
,
2237 print_queue_struct
*queue
,
2238 NT_PRINTER_INFO_LEVEL
*printer
,
2239 TALLOC_CTX
*mem_ctx
)
2241 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
2242 data
->notify_data
.value
[1] = 0;
2245 /*******************************************************************
2246 * fill a notify_info_data with the status
2247 ********************************************************************/
2249 static void spoolss_notify_status(int snum
,
2250 SPOOL_NOTIFY_INFO_DATA
*data
,
2251 print_queue_struct
*queue
,
2252 NT_PRINTER_INFO_LEVEL
*printer
,
2253 TALLOC_CTX
*mem_ctx
)
2255 print_status_struct status
;
2257 print_queue_length(snum
, &status
);
2258 data
->notify_data
.value
[0]=(uint32
) status
.status
;
2259 data
->notify_data
.value
[1] = 0;
2262 /*******************************************************************
2263 * fill a notify_info_data with the number of jobs queued
2264 ********************************************************************/
2266 void spoolss_notify_cjobs(int snum
,
2267 SPOOL_NOTIFY_INFO_DATA
*data
,
2268 print_queue_struct
*queue
,
2269 NT_PRINTER_INFO_LEVEL
*printer
,
2270 TALLOC_CTX
*mem_ctx
)
2272 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
2273 data
->notify_data
.value
[1] = 0;
2276 /*******************************************************************
2277 * fill a notify_info_data with the average ppm
2278 ********************************************************************/
2280 static void spoolss_notify_average_ppm(int snum
,
2281 SPOOL_NOTIFY_INFO_DATA
*data
,
2282 print_queue_struct
*queue
,
2283 NT_PRINTER_INFO_LEVEL
*printer
,
2284 TALLOC_CTX
*mem_ctx
)
2286 /* always respond 8 pages per minutes */
2287 /* a little hard ! */
2288 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
2289 data
->notify_data
.value
[1] = 0;
2292 /*******************************************************************
2293 * fill a notify_info_data with username
2294 ********************************************************************/
2296 static void spoolss_notify_username(int snum
,
2297 SPOOL_NOTIFY_INFO_DATA
*data
,
2298 print_queue_struct
*queue
,
2299 NT_PRINTER_INFO_LEVEL
*printer
,
2300 TALLOC_CTX
*mem_ctx
)
2305 len
= (uint32
)dos_PutUniCode(temp
, queue
->fs_user
,
2306 sizeof(temp
) - 2, True
);
2308 data
->notify_data
.data
.length
= len
/ 2 - 1;
2309 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2311 if (!data
->notify_data
.data
.string
) {
2312 data
->notify_data
.data
.length
= 0;
2316 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2319 /*******************************************************************
2320 * fill a notify_info_data with job status
2321 ********************************************************************/
2323 static void spoolss_notify_job_status(int snum
,
2324 SPOOL_NOTIFY_INFO_DATA
*data
,
2325 print_queue_struct
*queue
,
2326 NT_PRINTER_INFO_LEVEL
*printer
,
2327 TALLOC_CTX
*mem_ctx
)
2329 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
2330 data
->notify_data
.value
[1] = 0;
2333 /*******************************************************************
2334 * fill a notify_info_data with job name
2335 ********************************************************************/
2337 static void spoolss_notify_job_name(int snum
,
2338 SPOOL_NOTIFY_INFO_DATA
*data
,
2339 print_queue_struct
*queue
,
2340 NT_PRINTER_INFO_LEVEL
*printer
,
2341 TALLOC_CTX
*mem_ctx
)
2346 len
= (uint32
)dos_PutUniCode(temp
, queue
->fs_file
, sizeof(temp
) - 2,
2349 data
->notify_data
.data
.length
= len
/ 2 - 1;
2350 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2352 if (!data
->notify_data
.data
.string
) {
2353 data
->notify_data
.data
.length
= 0;
2357 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2360 /*******************************************************************
2361 * fill a notify_info_data with job status
2362 ********************************************************************/
2364 static void spoolss_notify_job_status_string(int snum
,
2365 SPOOL_NOTIFY_INFO_DATA
*data
,
2366 print_queue_struct
*queue
,
2367 NT_PRINTER_INFO_LEVEL
*printer
,
2368 TALLOC_CTX
*mem_ctx
)
2371 * Now we're returning job status codes we just return a "" here. JRA.
2378 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2381 switch (queue
->status
) {
2386 p
= ""; /* NT provides the paused string */
2395 #endif /* NO LONGER NEEDED. */
2397 len
= (uint32
)dos_PutUniCode(temp
, p
, sizeof(temp
) - 2, True
);
2399 data
->notify_data
.data
.length
= len
/ 2 - 1;
2400 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2402 if (!data
->notify_data
.data
.string
) {
2403 data
->notify_data
.data
.length
= 0;
2407 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2410 /*******************************************************************
2411 * fill a notify_info_data with job time
2412 ********************************************************************/
2414 static void spoolss_notify_job_time(int snum
,
2415 SPOOL_NOTIFY_INFO_DATA
*data
,
2416 print_queue_struct
*queue
,
2417 NT_PRINTER_INFO_LEVEL
*printer
,
2418 TALLOC_CTX
*mem_ctx
)
2420 data
->notify_data
.value
[0]=0x0;
2421 data
->notify_data
.value
[1]=0;
2424 /*******************************************************************
2425 * fill a notify_info_data with job size
2426 ********************************************************************/
2428 static void spoolss_notify_job_size(int snum
,
2429 SPOOL_NOTIFY_INFO_DATA
*data
,
2430 print_queue_struct
*queue
,
2431 NT_PRINTER_INFO_LEVEL
*printer
,
2432 TALLOC_CTX
*mem_ctx
)
2434 data
->notify_data
.value
[0]=queue
->size
;
2435 data
->notify_data
.value
[1]=0;
2438 /*******************************************************************
2439 * fill a notify_info_data with page info
2440 ********************************************************************/
2441 static void spoolss_notify_total_pages(int snum
,
2442 SPOOL_NOTIFY_INFO_DATA
*data
,
2443 print_queue_struct
*queue
,
2444 NT_PRINTER_INFO_LEVEL
*printer
,
2445 TALLOC_CTX
*mem_ctx
)
2447 data
->notify_data
.value
[0]=queue
->page_count
;
2448 data
->notify_data
.value
[1]=0;
2451 /*******************************************************************
2452 * fill a notify_info_data with pages printed info.
2453 ********************************************************************/
2454 static void spoolss_notify_pages_printed(int snum
,
2455 SPOOL_NOTIFY_INFO_DATA
*data
,
2456 print_queue_struct
*queue
,
2457 NT_PRINTER_INFO_LEVEL
*printer
,
2458 TALLOC_CTX
*mem_ctx
)
2460 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
2461 data
->notify_data
.value
[1]=0;
2464 /*******************************************************************
2465 Fill a notify_info_data with job position.
2466 ********************************************************************/
2468 static void spoolss_notify_job_position(int snum
,
2469 SPOOL_NOTIFY_INFO_DATA
*data
,
2470 print_queue_struct
*queue
,
2471 NT_PRINTER_INFO_LEVEL
*printer
,
2472 TALLOC_CTX
*mem_ctx
)
2474 data
->notify_data
.value
[0]=queue
->job
;
2475 data
->notify_data
.value
[1]=0;
2478 /*******************************************************************
2479 Fill a notify_info_data with submitted time.
2480 ********************************************************************/
2482 static void spoolss_notify_submitted_time(int snum
,
2483 SPOOL_NOTIFY_INFO_DATA
*data
,
2484 print_queue_struct
*queue
,
2485 NT_PRINTER_INFO_LEVEL
*printer
,
2486 TALLOC_CTX
*mem_ctx
)
2493 t
=gmtime(&queue
->time
);
2495 len
= sizeof(SYSTEMTIME
);
2497 data
->notify_data
.data
.length
= len
;
2498 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2500 if (!data
->notify_data
.data
.string
) {
2501 data
->notify_data
.data
.length
= 0;
2505 make_systemtime(&st
, t
);
2508 * Systemtime must be linearized as a set of UINT16's.
2509 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2512 p
= (char *)data
->notify_data
.data
.string
;
2513 SSVAL(p
, 0, st
.year
);
2514 SSVAL(p
, 2, st
.month
);
2515 SSVAL(p
, 4, st
.dayofweek
);
2516 SSVAL(p
, 6, st
.day
);
2517 SSVAL(p
, 8, st
.hour
);
2518 SSVAL(p
, 10, st
.minute
);
2519 SSVAL(p
, 12, st
.second
);
2520 SSVAL(p
, 14, st
.milliseconds
);
2525 struct s_notify_info_data_table
2531 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2532 print_queue_struct
*queue
,
2533 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2536 /* A table describing the various print notification constants and
2537 whether the notification data is a pointer to a variable sized
2538 buffer, a one value uint32 or a two value uint32. */
2540 struct s_notify_info_data_table notify_info_data_table
[] =
2542 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", POINTER
, spoolss_notify_server_name
},
2543 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2544 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", POINTER
, spoolss_notify_share_name
},
2545 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2546 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2547 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", POINTER
, spoolss_notify_comment
},
2548 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", POINTER
, spoolss_notify_location
},
2549 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2550 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", POINTER
, spoolss_notify_sepfile
},
2551 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2552 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2553 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2554 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, spoolss_notify_security_desc
},
2555 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE
, spoolss_notify_attributes
},
2556 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2557 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE
, spoolss_notify_default_priority
},
2558 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2559 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2560 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_status
},
2561 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", POINTER
, NULL
},
2562 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", ONE_VALUE
, spoolss_notify_cjobs
},
2563 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE
, spoolss_notify_average_ppm
},
2564 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER
, NULL
},
2565 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER
, NULL
},
2566 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER
, NULL
},
2567 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER
, NULL
},
2568 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2569 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", POINTER
, spoolss_notify_server_name
},
2570 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2571 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", POINTER
, spoolss_notify_username
},
2572 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", POINTER
, spoolss_notify_username
},
2573 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2574 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2575 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2576 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2577 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2578 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_job_status
},
2579 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", POINTER
, spoolss_notify_job_status_string
},
2580 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, NULL
},
2581 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", POINTER
, spoolss_notify_job_name
},
2582 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2583 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", ONE_VALUE
, spoolss_notify_job_position
},
2584 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", POINTER
, spoolss_notify_submitted_time
},
2585 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2586 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2587 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", ONE_VALUE
, spoolss_notify_job_time
},
2588 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE
, spoolss_notify_total_pages
},
2589 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE
, spoolss_notify_pages_printed
},
2590 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE
, spoolss_notify_job_size
},
2591 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_BYTES_PRINTED
, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE
, NULL
},
2592 { END
, END
, "", END
, NULL
}
2595 /*******************************************************************
2596 Return the size of info_data structure.
2597 ********************************************************************/
2599 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2603 while (notify_info_data_table
[i
].type
!= END
)
2605 if ( (notify_info_data_table
[i
].type
== type
) &&
2606 (notify_info_data_table
[i
].field
== field
) )
2608 return (notify_info_data_table
[i
].size
);
2615 /*******************************************************************
2616 Return the type of notify_info_data.
2617 ********************************************************************/
2619 static BOOL
type_of_notify_info_data(uint16 type
, uint16 field
)
2623 while (notify_info_data_table
[i
].type
!= END
)
2625 if ( (notify_info_data_table
[i
].type
== type
) &&
2626 (notify_info_data_table
[i
].field
== field
) )
2628 if (notify_info_data_table
[i
].size
== POINTER
)
2642 /****************************************************************************
2643 ****************************************************************************/
2645 static int search_notify(uint16 type
, uint16 field
, int *value
)
2650 for (j
=0, found
=False
; found
==False
&& notify_info_data_table
[j
].type
!= END
; j
++)
2652 if ( (notify_info_data_table
[j
].type
== type
) &&
2653 (notify_info_data_table
[j
].field
== field
) )
2658 if ( found
&& (notify_info_data_table
[j
].fn
!= NULL
) )
2664 /****************************************************************************
2665 ****************************************************************************/
2667 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2669 info_data
->type
= type
;
2670 info_data
->field
= field
;
2671 info_data
->reserved
= 0;
2673 info_data
->size
= size_of_notify_info_data(type
, field
);
2674 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2678 /*******************************************************************
2680 * fill a notify_info struct with info asked
2682 ********************************************************************/
2684 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2685 snum
, SPOOL_NOTIFY_OPTION_TYPE
2686 *option_type
, uint32 id
,
2687 TALLOC_CTX
*mem_ctx
)
2693 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2694 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2695 print_queue_struct
*queue
=NULL
;
2697 type
=option_type
->type
;
2699 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2700 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2701 option_type
->count
, lp_servicename(snum
)));
2703 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2706 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2707 field
= option_type
->fields
[field_num
];
2708 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2710 if (!search_notify(type
, field
, &j
) )
2713 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2714 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2717 else info
->data
= tid
;
2719 current_data
=&info
->data
[info
->count
];
2721 construct_info_data(current_data
, type
, field
, id
);
2723 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2724 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
2726 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2732 free_a_printer(&printer
, 2);
2736 /*******************************************************************
2738 * fill a notify_info struct with info asked
2740 ********************************************************************/
2742 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
2743 SPOOL_NOTIFY_INFO
*info
,
2744 NT_PRINTER_INFO_LEVEL
*printer
,
2745 int snum
, SPOOL_NOTIFY_OPTION_TYPE
2746 *option_type
, uint32 id
,
2747 TALLOC_CTX
*mem_ctx
)
2753 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2755 DEBUG(4,("construct_notify_jobs_info\n"));
2757 type
= option_type
->type
;
2759 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2760 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2761 option_type
->count
));
2763 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2764 field
= option_type
->fields
[field_num
];
2766 if (!search_notify(type
, field
, &j
) )
2769 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2770 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2773 else info
->data
= tid
;
2775 current_data
=&(info
->data
[info
->count
]);
2777 construct_info_data(current_data
, type
, field
, id
);
2778 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2787 * JFM: The enumeration is not that simple, it's even non obvious.
2789 * let's take an example: I want to monitor the PRINTER SERVER for
2790 * the printer's name and the number of jobs currently queued.
2791 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2792 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2794 * I have 3 printers on the back of my server.
2796 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2799 * 1 printer 1 name 1
2800 * 2 printer 1 cjob 1
2801 * 3 printer 2 name 2
2802 * 4 printer 2 cjob 2
2803 * 5 printer 3 name 3
2804 * 6 printer 3 name 3
2806 * that's the print server case, the printer case is even worse.
2809 /*******************************************************************
2811 * enumerate all printers on the printserver
2812 * fill a notify_info struct with info asked
2814 ********************************************************************/
2816 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
2817 SPOOL_NOTIFY_INFO
*info
,
2818 TALLOC_CTX
*mem_ctx
)
2821 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2822 int n_services
=lp_numservices();
2825 SPOOL_NOTIFY_OPTION
*option
;
2826 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2828 DEBUG(4,("printserver_notify_info\n"));
2833 option
=Printer
->notify
.option
;
2839 for (i
=0; i
<option
->count
; i
++) {
2840 option_type
=&(option
->ctr
.type
[i
]);
2842 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
2845 for (snum
=0; snum
<n_services
; snum
++)
2846 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
2847 if (construct_notify_printer_info
2848 (info
, snum
, option_type
, id
, mem_ctx
))
2853 * Debugging information, don't delete.
2856 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2857 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2858 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2860 for (i=0; i<info->count; i++) {
2861 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2862 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2863 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2870 /*******************************************************************
2872 * fill a notify_info struct with info asked
2874 ********************************************************************/
2876 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
2877 TALLOC_CTX
*mem_ctx
)
2880 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2883 SPOOL_NOTIFY_OPTION
*option
;
2884 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2886 print_queue_struct
*queue
=NULL
;
2887 print_status_struct status
;
2889 DEBUG(4,("printer_notify_info\n"));
2894 option
=Printer
->notify
.option
;
2900 get_printer_snum(p
, hnd
, &snum
);
2902 for (i
=0; i
<option
->count
; i
++) {
2903 option_type
=&option
->ctr
.type
[i
];
2905 switch ( option_type
->type
) {
2906 case PRINTER_NOTIFY_TYPE
:
2907 if(construct_notify_printer_info(info
, snum
,
2913 case JOB_NOTIFY_TYPE
: {
2914 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2916 count
= print_queue_status(snum
, &queue
, &status
);
2918 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
2919 lp_servicename(snum
))))
2922 for (j
=0; j
<count
; j
++) {
2923 construct_notify_jobs_info(&queue
[j
], info
,
2930 free_a_printer(&printer
, 2);
2940 * Debugging information, don't delete.
2943 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2944 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2945 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2947 for (i=0; i<info->count; i++) {
2948 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2949 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2950 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2956 /********************************************************************
2958 ********************************************************************/
2960 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
2962 POLICY_HND
*handle
= &q_u
->handle
;
2963 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2964 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
2966 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2967 WERROR result
= WERR_BADFID
;
2969 /* we always have a NOTIFY_INFO struct */
2973 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
2974 OUR_HANDLE(handle
)));
2978 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
2981 * same thing for option->flags
2982 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2983 * I don't have a global notification system, I'm sending back all the
2984 * informations even when _NOTHING_ has changed.
2987 if (Printer
->notify
.client_connected
)
2988 Printer
->notify
.change
= q_u
->change
;
2990 /* just ignore the SPOOL_NOTIFY_OPTION */
2992 switch (Printer
->printer_type
) {
2993 case PRINTER_HANDLE_IS_PRINTSERVER
:
2994 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
2997 case PRINTER_HANDLE_IS_PRINTER
:
2998 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3006 /********************************************************************
3007 * construct_printer_info_0
3008 * fill a printer_info_0 struct
3009 ********************************************************************/
3011 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
3015 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3016 counter_printer_0
*session_counter
;
3017 uint32 global_counter
;
3020 print_status_struct status
;
3022 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3025 count
= print_queue_length(snum
, &status
);
3027 /* check if we already have a counter for this printer */
3028 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
3030 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
3031 if (session_counter
->snum
== snum
)
3035 /* it's the first time, add it to the list */
3036 if (session_counter
==NULL
) {
3037 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3038 free_a_printer(&ntprinter
, 2);
3041 ZERO_STRUCTP(session_counter
);
3042 session_counter
->snum
=snum
;
3043 session_counter
->counter
=0;
3044 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
3048 session_counter
->counter
++;
3051 * the global_counter should be stored in a TDB as it's common to all the clients
3052 * and should be zeroed on samba startup
3054 global_counter
=session_counter
->counter
;
3056 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3058 init_unistr(&printer
->printername
, chaine
);
3060 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
3061 init_unistr(&printer
->servername
, chaine
);
3063 printer
->cjobs
= count
;
3064 printer
->total_jobs
= 0;
3065 printer
->total_bytes
= 0;
3067 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3068 t
=gmtime(&setuptime
);
3070 printer
->year
= t
->tm_year
+1900;
3071 printer
->month
= t
->tm_mon
+1;
3072 printer
->dayofweek
= t
->tm_wday
;
3073 printer
->day
= t
->tm_mday
;
3074 printer
->hour
= t
->tm_hour
;
3075 printer
->minute
= t
->tm_min
;
3076 printer
->second
= t
->tm_sec
;
3077 printer
->milliseconds
= 0;
3079 printer
->global_counter
= global_counter
;
3080 printer
->total_pages
= 0;
3081 #ifndef EMULATE_WIN2K_HACK /* JERRY */
3082 printer
->major_version
= 0x0004; /* NT 4 */
3083 printer
->build_version
= 0x0565; /* build 1381 */
3085 printer
->major_version
= 0x0005; /* NT 5 */
3086 printer
->build_version
= 0x0893; /* build 2195 */
3088 printer
->unknown7
= 0x1;
3089 printer
->unknown8
= 0x0;
3090 printer
->unknown9
= 0x0;
3091 printer
->session_counter
= session_counter
->counter
;
3092 printer
->unknown11
= 0x0;
3093 printer
->printer_errors
= 0x0; /* number of print failure */
3094 printer
->unknown13
= 0x0;
3095 printer
->unknown14
= 0x1;
3096 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3097 printer
->unknown16
= 0x0;
3098 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3099 printer
->unknown18
= 0x0;
3100 printer
->status
= nt_printq_status(status
.status
);
3101 printer
->unknown20
= 0x0;
3102 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3103 printer
->unknown22
= 0x0;
3104 printer
->unknown23
= 0x6; /* 6 ???*/
3105 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3106 printer
->unknown25
= 0;
3107 printer
->unknown26
= 0;
3108 printer
->unknown27
= 0;
3109 printer
->unknown28
= 0;
3110 printer
->unknown29
= 0;
3112 free_a_printer(&ntprinter
,2);
3116 /********************************************************************
3117 * construct_printer_info_1
3118 * fill a printer_info_1 struct
3119 ********************************************************************/
3120 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3124 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3126 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3129 printer
->flags
=flags
;
3131 if (*ntprinter
->info_2
->comment
== '\0') {
3132 init_unistr(&printer
->comment
, lp_comment(snum
));
3133 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3134 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3137 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3138 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3139 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3142 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3144 init_unistr(&printer
->description
, chaine
);
3145 init_unistr(&printer
->name
, chaine2
);
3147 free_a_printer(&ntprinter
,2);
3152 /****************************************************************************
3153 Free a DEVMODE struct.
3154 ****************************************************************************/
3156 static void free_dev_mode(DEVICEMODE
*dev
)
3161 SAFE_FREE(dev
->private);
3165 /****************************************************************************
3166 Create a DEVMODE struct. Returns malloced memory.
3167 ****************************************************************************/
3169 static DEVICEMODE
*construct_dev_mode(int snum
)
3173 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3174 NT_DEVICEMODE
*ntdevmode
= NULL
;
3175 DEVICEMODE
*devmode
= NULL
;
3177 DEBUG(7,("construct_dev_mode\n"));
3179 DEBUGADD(8,("getting printer characteristics\n"));
3181 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
3182 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
3186 ZERO_STRUCTP(devmode
);
3188 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3191 if (printer
->info_2
->devmode
)
3192 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
3194 if (ntdevmode
== NULL
)
3197 DEBUGADD(8,("loading DEVICEMODE\n"));
3199 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
3200 init_unistr(&devmode
->devicename
, adevice
);
3202 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
3203 init_unistr(&devmode
->formname
, aform
);
3205 devmode
->specversion
= ntdevmode
->specversion
;
3206 devmode
->driverversion
= ntdevmode
->driverversion
;
3207 devmode
->size
= ntdevmode
->size
;
3208 devmode
->driverextra
= ntdevmode
->driverextra
;
3209 devmode
->fields
= ntdevmode
->fields
;
3211 devmode
->orientation
= ntdevmode
->orientation
;
3212 devmode
->papersize
= ntdevmode
->papersize
;
3213 devmode
->paperlength
= ntdevmode
->paperlength
;
3214 devmode
->paperwidth
= ntdevmode
->paperwidth
;
3215 devmode
->scale
= ntdevmode
->scale
;
3216 devmode
->copies
= ntdevmode
->copies
;
3217 devmode
->defaultsource
= ntdevmode
->defaultsource
;
3218 devmode
->printquality
= ntdevmode
->printquality
;
3219 devmode
->color
= ntdevmode
->color
;
3220 devmode
->duplex
= ntdevmode
->duplex
;
3221 devmode
->yresolution
= ntdevmode
->yresolution
;
3222 devmode
->ttoption
= ntdevmode
->ttoption
;
3223 devmode
->collate
= ntdevmode
->collate
;
3224 devmode
->icmmethod
= ntdevmode
->icmmethod
;
3225 devmode
->icmintent
= ntdevmode
->icmintent
;
3226 devmode
->mediatype
= ntdevmode
->mediatype
;
3227 devmode
->dithertype
= ntdevmode
->dithertype
;
3229 if (ntdevmode
->private != NULL
) {
3230 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
3234 free_nt_devicemode(&ntdevmode
);
3235 free_a_printer(&printer
,2);
3242 free_nt_devicemode(&ntdevmode
);
3244 free_a_printer(&printer
,2);
3245 free_dev_mode(devmode
);
3250 /********************************************************************
3251 * construct_printer_info_2
3252 * fill a printer_info_2 struct
3253 ********************************************************************/
3255 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
3258 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3260 print_status_struct status
;
3262 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3265 count
= print_queue_length(snum
, &status
);
3267 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3268 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3269 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
3270 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
3271 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
3273 if (*ntprinter
->info_2
->comment
== '\0')
3274 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
3276 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3278 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
3279 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
3280 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
3281 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
3282 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
3284 printer
->attributes
= ntprinter
->info_2
->attributes
;
3286 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
3287 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
3288 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
3289 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
3290 printer
->status
= nt_printq_status(status
.status
); /* status */
3291 printer
->cjobs
= count
; /* jobs */
3292 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
3294 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
3295 DEBUG(8, ("Returning NULL Devicemode!\n"));
3298 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3299 /* steal the printer info sec_desc structure. [badly done]. */
3300 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3301 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
3302 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
3303 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
3306 printer
->secdesc
= NULL
;
3309 free_a_printer(&ntprinter
, 2);
3313 /********************************************************************
3314 * construct_printer_info_3
3315 * fill a printer_info_3 struct
3316 ********************************************************************/
3318 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
3320 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3321 PRINTER_INFO_3
*printer
= NULL
;
3323 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3327 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
3328 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
3332 ZERO_STRUCTP(printer
);
3334 printer
->flags
= 4; /* These are the components of the SD we are returning. */
3335 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
3336 /* steal the printer info sec_desc structure. [badly done]. */
3337 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
3341 * Set the flags for the components we are returning.
3344 if (printer
->secdesc
->owner_sid
)
3345 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
3347 if (printer
->secdesc
->grp_sid
)
3348 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
3350 if (printer
->secdesc
->dacl
)
3351 printer
->flags
|= DACL_SECURITY_INFORMATION
;
3353 if (printer
->secdesc
->sacl
)
3354 printer
->flags
|= SACL_SECURITY_INFORMATION
;
3357 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
3358 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
3359 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
3362 free_a_printer(&ntprinter
, 2);
3364 *pp_printer
= printer
;
3368 /********************************************************************
3369 * construct_printer_info_4
3370 * fill a printer_info_4 struct
3371 ********************************************************************/
3373 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
3375 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3377 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3380 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3381 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
3382 printer
->attributes
= ntprinter
->info_2
->attributes
;
3384 free_a_printer(&ntprinter
, 2);
3388 /********************************************************************
3389 * construct_printer_info_5
3390 * fill a printer_info_5 struct
3391 ********************************************************************/
3393 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
3395 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3397 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
3400 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
3401 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
3402 printer
->attributes
= ntprinter
->info_2
->attributes
;
3403 printer
->device_not_selected_timeout
= 0x3a98;
3404 printer
->transmission_retry_timeout
= 0xafc8;
3406 free_a_printer(&ntprinter
, 2);
3410 /********************************************************************
3411 Spoolss_enumprinters.
3412 ********************************************************************/
3414 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3418 int n_services
=lp_numservices();
3419 PRINTER_INFO_1
*tp
, *printers
=NULL
;
3420 PRINTER_INFO_1 current_prt
;
3422 DEBUG(4,("enum_all_printers_info_1\n"));
3424 for (snum
=0; snum
<n_services
; snum
++) {
3425 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3426 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3428 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
3429 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
3430 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
3431 SAFE_FREE(printers
);
3436 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
3438 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
3444 /* check the required size. */
3445 for (i
=0; i
<*returned
; i
++)
3446 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
3448 if (!alloc_buffer_size(buffer
, *needed
))
3449 return WERR_INSUFFICIENT_BUFFER
;
3451 /* fill the buffer with the structures */
3452 for (i
=0; i
<*returned
; i
++)
3453 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
3456 SAFE_FREE(printers
);
3458 if (*needed
> offered
) {
3460 return WERR_INSUFFICIENT_BUFFER
;
3466 /********************************************************************
3467 enum_all_printers_info_1_local.
3468 *********************************************************************/
3470 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3472 DEBUG(4,("enum_all_printers_info_1_local\n"));
3474 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3477 /********************************************************************
3478 enum_all_printers_info_1_name.
3479 *********************************************************************/
3481 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3485 DEBUG(4,("enum_all_printers_info_1_name\n"));
3487 if ((name
[0] == '\\') && (name
[1] == '\\'))
3490 if (is_myname_or_ipaddr(s
)) {
3491 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3494 return WERR_INVALID_NAME
;
3497 /********************************************************************
3498 enum_all_printers_info_1_remote.
3499 *********************************************************************/
3501 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3503 PRINTER_INFO_1
*printer
;
3504 fstring printername
;
3507 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3509 /* JFM: currently it's more a place holder than anything else.
3510 * In the spooler world there is a notion of server registration.
3511 * the print servers are registring (sp ?) on the PDC (in the same domain)
3513 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3516 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3521 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3522 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
3523 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3525 init_unistr(&printer
->description
, desc
);
3526 init_unistr(&printer
->name
, printername
);
3527 init_unistr(&printer
->comment
, comment
);
3528 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3530 /* check the required size. */
3531 *needed
+= spoolss_size_printer_info_1(printer
);
3533 if (!alloc_buffer_size(buffer
, *needed
)) {
3535 return WERR_INSUFFICIENT_BUFFER
;
3538 /* fill the buffer with the structures */
3539 smb_io_printer_info_1("", buffer
, printer
, 0);
3544 if (*needed
> offered
) {
3546 return WERR_INSUFFICIENT_BUFFER
;
3552 /********************************************************************
3553 enum_all_printers_info_1_network.
3554 *********************************************************************/
3556 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3560 DEBUG(4,("enum_all_printers_info_1_network\n"));
3562 /* If we respond to a enum_printers level 1 on our name with flags
3563 set to PRINTER_ENUM_REMOTE with a list of printers then these
3564 printers incorrectly appear in the APW browse list.
3565 Specifically the printers for the server appear at the workgroup
3566 level where all the other servers in the domain are
3567 listed. Windows responds to this call with a
3568 WERR_CAN_NOT_COMPLETE so we should do the same. */
3570 if (name
[0] == '\\' && name
[1] == '\\')
3573 if (is_myname_or_ipaddr(s
))
3574 return WERR_CAN_NOT_COMPLETE
;
3576 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3579 /********************************************************************
3580 * api_spoolss_enumprinters
3582 * called from api_spoolss_enumprinters (see this to understand)
3583 ********************************************************************/
3585 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3589 int n_services
=lp_numservices();
3590 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3591 PRINTER_INFO_2 current_prt
;
3593 for (snum
=0; snum
<n_services
; snum
++) {
3594 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3595 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3597 if (construct_printer_info_2(¤t_prt
, snum
)) {
3598 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3599 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3600 SAFE_FREE(printers
);
3605 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3606 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3612 /* check the required size. */
3613 for (i
=0; i
<*returned
; i
++)
3614 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3616 if (!alloc_buffer_size(buffer
, *needed
)) {
3617 for (i
=0; i
<*returned
; i
++) {
3618 free_devmode(printers
[i
].devmode
);
3620 SAFE_FREE(printers
);
3621 return WERR_INSUFFICIENT_BUFFER
;
3624 /* fill the buffer with the structures */
3625 for (i
=0; i
<*returned
; i
++)
3626 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3629 for (i
=0; i
<*returned
; i
++) {
3630 free_devmode(printers
[i
].devmode
);
3632 SAFE_FREE(printers
);
3634 if (*needed
> offered
) {
3636 return WERR_INSUFFICIENT_BUFFER
;
3642 /********************************************************************
3643 * handle enumeration of printers at level 1
3644 ********************************************************************/
3646 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3647 NEW_BUFFER
*buffer
, uint32 offered
,
3648 uint32
*needed
, uint32
*returned
)
3650 /* Not all the flags are equals */
3652 if (flags
& PRINTER_ENUM_LOCAL
)
3653 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3655 if (flags
& PRINTER_ENUM_NAME
)
3656 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3658 if (flags
& PRINTER_ENUM_REMOTE
)
3659 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3661 if (flags
& PRINTER_ENUM_NETWORK
)
3662 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
3664 return WERR_OK
; /* NT4sp5 does that */
3667 /********************************************************************
3668 * handle enumeration of printers at level 2
3669 ********************************************************************/
3671 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3672 NEW_BUFFER
*buffer
, uint32 offered
,
3673 uint32
*needed
, uint32
*returned
)
3675 char *s
= servername
;
3677 if (flags
& PRINTER_ENUM_LOCAL
) {
3678 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3681 if (flags
& PRINTER_ENUM_NAME
) {
3682 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3684 if (is_myname_or_ipaddr(s
))
3685 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3687 return WERR_INVALID_NAME
;
3690 if (flags
& PRINTER_ENUM_REMOTE
)
3691 return WERR_UNKNOWN_LEVEL
;
3696 /********************************************************************
3697 * handle enumeration of printers at level 5
3698 ********************************************************************/
3700 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3701 NEW_BUFFER
*buffer
, uint32 offered
,
3702 uint32
*needed
, uint32
*returned
)
3704 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3708 /********************************************************************
3709 * api_spoolss_enumprinters
3711 * called from api_spoolss_enumprinters (see this to understand)
3712 ********************************************************************/
3714 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3716 uint32 flags
= q_u
->flags
;
3717 UNISTR2
*servername
= &q_u
->servername
;
3718 uint32 level
= q_u
->level
;
3719 NEW_BUFFER
*buffer
= NULL
;
3720 uint32 offered
= q_u
->offered
;
3721 uint32
*needed
= &r_u
->needed
;
3722 uint32
*returned
= &r_u
->returned
;
3726 /* that's an [in out] buffer */
3727 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3728 buffer
= r_u
->buffer
;
3730 DEBUG(4,("_spoolss_enumprinters\n"));
3737 * flags==PRINTER_ENUM_NAME
3738 * if name=="" then enumerates all printers
3739 * if name!="" then enumerate the printer
3740 * flags==PRINTER_ENUM_REMOTE
3741 * name is NULL, enumerate printers
3742 * Level 2: name!="" enumerates printers, name can't be NULL
3743 * Level 3: doesn't exist
3744 * Level 4: does a local registry lookup
3745 * Level 5: same as Level 2
3748 unistr2_to_dos(name
, servername
, sizeof(name
)-1);
3753 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
3755 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
3757 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
3762 return WERR_UNKNOWN_LEVEL
;
3765 /****************************************************************************
3766 ****************************************************************************/
3768 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3770 PRINTER_INFO_0
*printer
=NULL
;
3772 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
3775 construct_printer_info_0(printer
, snum
);
3777 /* check the required size. */
3778 *needed
+= spoolss_size_printer_info_0(printer
);
3780 if (!alloc_buffer_size(buffer
, *needed
)) {
3782 return WERR_INSUFFICIENT_BUFFER
;
3785 /* fill the buffer with the structures */
3786 smb_io_printer_info_0("", buffer
, printer
, 0);
3791 if (*needed
> offered
) {
3792 return WERR_INSUFFICIENT_BUFFER
;
3798 /****************************************************************************
3799 ****************************************************************************/
3801 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3803 PRINTER_INFO_1
*printer
=NULL
;
3805 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3808 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
3810 /* check the required size. */
3811 *needed
+= spoolss_size_printer_info_1(printer
);
3813 if (!alloc_buffer_size(buffer
, *needed
)) {
3815 return WERR_INSUFFICIENT_BUFFER
;
3818 /* fill the buffer with the structures */
3819 smb_io_printer_info_1("", buffer
, printer
, 0);
3824 if (*needed
> offered
) {
3825 return WERR_INSUFFICIENT_BUFFER
;
3831 /****************************************************************************
3832 ****************************************************************************/
3834 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3836 PRINTER_INFO_2
*printer
=NULL
;
3838 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
3841 construct_printer_info_2(printer
, snum
);
3843 /* check the required size. */
3844 *needed
+= spoolss_size_printer_info_2(printer
);
3846 if (!alloc_buffer_size(buffer
, *needed
)) {
3847 free_printer_info_2(printer
);
3848 return WERR_INSUFFICIENT_BUFFER
;
3851 /* fill the buffer with the structures */
3852 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
3853 free_printer_info_2(printer
);
3858 free_printer_info_2(printer
);
3860 if (*needed
> offered
) {
3861 return WERR_INSUFFICIENT_BUFFER
;
3867 /****************************************************************************
3868 ****************************************************************************/
3870 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3872 PRINTER_INFO_3
*printer
=NULL
;
3874 if (!construct_printer_info_3(&printer
, snum
))
3877 /* check the required size. */
3878 *needed
+= spoolss_size_printer_info_3(printer
);
3880 if (!alloc_buffer_size(buffer
, *needed
)) {
3881 free_printer_info_3(printer
);
3882 return WERR_INSUFFICIENT_BUFFER
;
3885 /* fill the buffer with the structures */
3886 smb_io_printer_info_3("", buffer
, printer
, 0);
3889 free_printer_info_3(printer
);
3891 if (*needed
> offered
) {
3892 return WERR_INSUFFICIENT_BUFFER
;
3898 /****************************************************************************
3899 ****************************************************************************/
3901 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3903 PRINTER_INFO_4
*printer
=NULL
;
3905 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
3908 if (!construct_printer_info_4(printer
, snum
))
3911 /* check the required size. */
3912 *needed
+= spoolss_size_printer_info_4(printer
);
3914 if (!alloc_buffer_size(buffer
, *needed
)) {
3915 free_printer_info_4(printer
);
3916 return WERR_INSUFFICIENT_BUFFER
;
3919 /* fill the buffer with the structures */
3920 smb_io_printer_info_4("", buffer
, printer
, 0);
3923 free_printer_info_4(printer
);
3925 if (*needed
> offered
) {
3926 return WERR_INSUFFICIENT_BUFFER
;
3932 /****************************************************************************
3933 ****************************************************************************/
3935 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3937 PRINTER_INFO_5
*printer
=NULL
;
3939 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
3942 if (!construct_printer_info_5(printer
, snum
))
3945 /* check the required size. */
3946 *needed
+= spoolss_size_printer_info_5(printer
);
3948 if (!alloc_buffer_size(buffer
, *needed
)) {
3949 free_printer_info_5(printer
);
3950 return WERR_INSUFFICIENT_BUFFER
;
3953 /* fill the buffer with the structures */
3954 smb_io_printer_info_5("", buffer
, printer
, 0);
3957 free_printer_info_5(printer
);
3959 if (*needed
> offered
) {
3960 return WERR_INSUFFICIENT_BUFFER
;
3966 /****************************************************************************
3967 ****************************************************************************/
3969 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
3971 POLICY_HND
*handle
= &q_u
->handle
;
3972 uint32 level
= q_u
->level
;
3973 NEW_BUFFER
*buffer
= NULL
;
3974 uint32 offered
= q_u
->offered
;
3975 uint32
*needed
= &r_u
->needed
;
3979 /* that's an [in out] buffer */
3980 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3981 buffer
= r_u
->buffer
;
3985 if (!get_printer_snum(p
, handle
, &snum
))
3990 return getprinter_level_0(snum
, buffer
, offered
, needed
);
3992 return getprinter_level_1(snum
, buffer
, offered
, needed
);
3994 return getprinter_level_2(snum
, buffer
, offered
, needed
);
3996 return getprinter_level_3(snum
, buffer
, offered
, needed
);
3998 return getprinter_level_4(snum
, buffer
, offered
, needed
);
4000 return getprinter_level_5(snum
, buffer
, offered
, needed
);
4002 return WERR_UNKNOWN_LEVEL
;
4005 /********************************************************************
4006 * fill a DRIVER_INFO_1 struct
4007 ********************************************************************/
4009 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4011 init_unistr( &info
->name
, driver
.info_3
->name
);
4014 /********************************************************************
4015 * construct_printer_driver_info_1
4016 ********************************************************************/
4018 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4020 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4021 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4023 ZERO_STRUCT(driver
);
4025 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4026 return WERR_INVALID_PRINTER_NAME
;
4028 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4029 return WERR_UNKNOWN_PRINTER_DRIVER
;
4031 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4033 free_a_printer(&printer
,2);
4038 /********************************************************************
4039 * construct_printer_driver_info_2
4040 * fill a printer_info_2 struct
4041 ********************************************************************/
4043 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4047 info
->version
=driver
.info_3
->cversion
;
4049 init_unistr( &info
->name
, driver
.info_3
->name
);
4050 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4053 if (strlen(driver
.info_3
->driverpath
)) {
4054 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4055 init_unistr( &info
->driverpath
, temp
);
4057 init_unistr( &info
->driverpath
, "" );
4059 if (strlen(driver
.info_3
->datafile
)) {
4060 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4061 init_unistr( &info
->datafile
, temp
);
4063 init_unistr( &info
->datafile
, "" );
4065 if (strlen(driver
.info_3
->configfile
)) {
4066 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4067 init_unistr( &info
->configfile
, temp
);
4069 init_unistr( &info
->configfile
, "" );
4072 /********************************************************************
4073 * construct_printer_driver_info_2
4074 * fill a printer_info_2 struct
4075 ********************************************************************/
4077 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4079 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4080 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4082 ZERO_STRUCT(printer
);
4083 ZERO_STRUCT(driver
);
4085 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
4086 return WERR_INVALID_PRINTER_NAME
;
4088 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
4089 return WERR_UNKNOWN_PRINTER_DRIVER
;
4091 fill_printer_driver_info_2(info
, driver
, servername
);
4093 free_a_printer(&printer
,2);
4098 /********************************************************************
4099 * copy a strings array and convert to UNICODE
4101 * convert an array of ascii string to a UNICODE string
4102 ********************************************************************/
4104 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
4112 DEBUG(6,("init_unistr_array\n"));
4116 if (char_array
== NULL
)
4120 if (!v
) v
= ""; /* hack to handle null lists */
4122 if (strlen(v
) == 0) break;
4123 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
4124 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
4125 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
4126 DEBUG(2,("init_unistr_array: Realloc error\n" ));
4130 j
+= (dos_PutUniCode((char *)(*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
), True
) / sizeof(uint16
) );
4135 (*uni_array
)[j
]=0x0000;
4138 DEBUGADD(6,("last one:done\n"));
4141 /********************************************************************
4142 * construct_printer_info_3
4143 * fill a printer_info_3 struct
4144 ********************************************************************/
4146 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4152 info
->version
=driver
.info_3
->cversion
;
4154 init_unistr( &info
->name
, driver
.info_3
->name
);
4155 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4157 if (strlen(driver
.info_3
->driverpath
)) {
4158 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4159 init_unistr( &info
->driverpath
, temp
);
4161 init_unistr( &info
->driverpath
, "" );
4163 if (strlen(driver
.info_3
->datafile
)) {
4164 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4165 init_unistr( &info
->datafile
, temp
);
4167 init_unistr( &info
->datafile
, "" );
4169 if (strlen(driver
.info_3
->configfile
)) {
4170 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4171 init_unistr( &info
->configfile
, temp
);
4173 init_unistr( &info
->configfile
, "" );
4175 if (strlen(driver
.info_3
->helpfile
)) {
4176 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4177 init_unistr( &info
->helpfile
, temp
);
4179 init_unistr( &info
->helpfile
, "" );
4181 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4182 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4184 info
->dependentfiles
=NULL
;
4185 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4188 /********************************************************************
4189 * construct_printer_info_3
4190 * fill a printer_info_3 struct
4191 ********************************************************************/
4193 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4195 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4196 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4198 ZERO_STRUCT(driver
);
4200 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4201 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4202 if (!W_ERROR_IS_OK(status
))
4203 return WERR_INVALID_PRINTER_NAME
;
4205 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4206 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4211 * I put this code in during testing. Helpful when commenting out the
4212 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
4213 * as win2k always queries the driver using an infor level of 6.
4214 * I've left it in (but ifdef'd out) because I'll probably
4215 * use it in experimentation again in the future. --jerry 22/01/2002
4218 if (!W_ERROR_IS_OK(status
)) {
4220 * Is this a W2k client ?
4223 /* Yes - try again with a WinNT driver. */
4225 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4226 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
4230 if (!W_ERROR_IS_OK(status
)) {
4231 free_a_printer(&printer
,2);
4232 return WERR_UNKNOWN_PRINTER_DRIVER
;
4240 fill_printer_driver_info_3(info
, driver
, servername
);
4242 free_a_printer(&printer
,2);
4247 /********************************************************************
4248 * construct_printer_info_6
4249 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
4250 ********************************************************************/
4252 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
4258 memset(&nullstr
, '\0', sizeof(fstring
));
4260 info
->version
=driver
.info_3
->cversion
;
4262 init_unistr( &info
->name
, driver
.info_3
->name
);
4263 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
4265 if (strlen(driver
.info_3
->driverpath
)) {
4266 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
4267 init_unistr( &info
->driverpath
, temp
);
4269 init_unistr( &info
->driverpath
, "" );
4271 if (strlen(driver
.info_3
->datafile
)) {
4272 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
4273 init_unistr( &info
->datafile
, temp
);
4275 init_unistr( &info
->datafile
, "" );
4277 if (strlen(driver
.info_3
->configfile
)) {
4278 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
4279 init_unistr( &info
->configfile
, temp
);
4281 init_unistr( &info
->configfile
, "" );
4283 if (strlen(driver
.info_3
->helpfile
)) {
4284 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
4285 init_unistr( &info
->helpfile
, temp
);
4287 init_unistr( &info
->helpfile
, "" );
4289 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
4290 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
4292 info
->dependentfiles
=NULL
;
4293 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
4295 info
->previousdrivernames
=NULL
;
4296 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
4298 info
->driver_date
.low
=0;
4299 info
->driver_date
.high
=0;
4302 info
->driver_version_low
=0;
4303 info
->driver_version_high
=0;
4305 init_unistr( &info
->mfgname
, "");
4306 init_unistr( &info
->oem_url
, "");
4307 init_unistr( &info
->hardware_id
, "");
4308 init_unistr( &info
->provider
, "");
4311 /********************************************************************
4312 * construct_printer_info_6
4313 * fill a printer_info_6 struct
4314 ********************************************************************/
4316 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4318 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4319 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4321 ZERO_STRUCT(driver
);
4323 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
4324 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4325 if (!W_ERROR_IS_OK(status
))
4326 return WERR_INVALID_PRINTER_NAME
;
4328 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4329 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4330 if (!W_ERROR_IS_OK(status
)) {
4332 * Is this a W2k client ?
4336 free_a_printer(&printer
,2);
4337 return WERR_UNKNOWN_PRINTER_DRIVER
;
4340 /* Yes - try again with a WinNT driver. */
4342 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
4343 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
4344 if (!W_ERROR_IS_OK(status
)) {
4345 free_a_printer(&printer
,2);
4346 return WERR_UNKNOWN_PRINTER_DRIVER
;
4350 fill_printer_driver_info_6(info
, driver
, servername
);
4352 free_a_printer(&printer
,2);
4357 /****************************************************************************
4358 ****************************************************************************/
4360 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
4362 SAFE_FREE(info
->dependentfiles
);
4365 /****************************************************************************
4366 ****************************************************************************/
4368 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
4370 SAFE_FREE(info
->dependentfiles
);
4374 /****************************************************************************
4375 ****************************************************************************/
4377 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4379 DRIVER_INFO_1
*info
=NULL
;
4382 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
4385 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
4386 if (!W_ERROR_IS_OK(status
)) {
4391 /* check the required size. */
4392 *needed
+= spoolss_size_printer_driver_info_1(info
);
4394 if (!alloc_buffer_size(buffer
, *needed
)) {
4396 return WERR_INSUFFICIENT_BUFFER
;
4399 /* fill the buffer with the structures */
4400 smb_io_printer_driver_info_1("", buffer
, info
, 0);
4405 if (*needed
> offered
)
4406 return WERR_INSUFFICIENT_BUFFER
;
4411 /****************************************************************************
4412 ****************************************************************************/
4414 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4416 DRIVER_INFO_2
*info
=NULL
;
4419 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
4422 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
4423 if (!W_ERROR_IS_OK(status
)) {
4428 /* check the required size. */
4429 *needed
+= spoolss_size_printer_driver_info_2(info
);
4431 if (!alloc_buffer_size(buffer
, *needed
)) {
4433 return WERR_INSUFFICIENT_BUFFER
;
4436 /* fill the buffer with the structures */
4437 smb_io_printer_driver_info_2("", buffer
, info
, 0);
4442 if (*needed
> offered
)
4443 return WERR_INSUFFICIENT_BUFFER
;
4448 /****************************************************************************
4449 ****************************************************************************/
4451 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4458 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
4459 if (!W_ERROR_IS_OK(status
)) {
4463 /* check the required size. */
4464 *needed
+= spoolss_size_printer_driver_info_3(&info
);
4466 if (!alloc_buffer_size(buffer
, *needed
)) {
4467 free_printer_driver_info_3(&info
);
4468 return WERR_INSUFFICIENT_BUFFER
;
4471 /* fill the buffer with the structures */
4472 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
4474 free_printer_driver_info_3(&info
);
4476 if (*needed
> offered
)
4477 return WERR_INSUFFICIENT_BUFFER
;
4482 /****************************************************************************
4483 ****************************************************************************/
4485 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4492 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
4493 if (!W_ERROR_IS_OK(status
)) {
4497 /* check the required size. */
4498 *needed
+= spoolss_size_printer_driver_info_6(&info
);
4500 if (!alloc_buffer_size(buffer
, *needed
)) {
4501 free_printer_driver_info_6(&info
);
4502 return WERR_INSUFFICIENT_BUFFER
;
4505 /* fill the buffer with the structures */
4506 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
4508 free_printer_driver_info_6(&info
);
4510 if (*needed
> offered
)
4511 return WERR_INSUFFICIENT_BUFFER
;
4516 /****************************************************************************
4517 ****************************************************************************/
4519 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
4521 POLICY_HND
*handle
= &q_u
->handle
;
4522 UNISTR2
*uni_arch
= &q_u
->architecture
;
4523 uint32 level
= q_u
->level
;
4524 uint32 clientmajorversion
= q_u
->clientmajorversion
;
4525 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
4526 NEW_BUFFER
*buffer
= NULL
;
4527 uint32 offered
= q_u
->offered
;
4528 uint32
*needed
= &r_u
->needed
;
4529 uint32
*servermajorversion
= &r_u
->servermajorversion
;
4530 uint32
*serverminorversion
= &r_u
->serverminorversion
;
4533 fstring architecture
;
4536 /* that's an [in out] buffer */
4537 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4538 buffer
= r_u
->buffer
;
4540 DEBUG(4,("_spoolss_getprinterdriver2\n"));
4543 *servermajorversion
=0;
4544 *serverminorversion
=0;
4546 pstrcpy(servername
, get_called_name());
4547 unistr2_to_dos(architecture
, uni_arch
, sizeof(architecture
)-1);
4549 if (!get_printer_snum(p
, handle
, &snum
))
4554 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4556 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4558 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4560 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4563 return WERR_UNKNOWN_LEVEL
;
4566 /****************************************************************************
4567 ****************************************************************************/
4569 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
4571 POLICY_HND
*handle
= &q_u
->handle
;
4573 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4576 DEBUG(3,("Error in startpageprinter printer handle\n"));
4580 Printer
->page_started
=True
;
4584 /****************************************************************************
4585 ****************************************************************************/
4587 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
4589 POLICY_HND
*handle
= &q_u
->handle
;
4591 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4594 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
4598 Printer
->page_started
=False
;
4599 print_job_endpage(Printer
->jobid
);
4604 /********************************************************************
4605 * api_spoolss_getprinter
4606 * called from the spoolss dispatcher
4608 ********************************************************************/
4610 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
4612 POLICY_HND
*handle
= &q_u
->handle
;
4613 /* uint32 level = q_u->doc_info_container.level; - notused. */
4614 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
4615 uint32
*jobid
= &r_u
->jobid
;
4617 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
4621 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4622 struct current_user user
;
4625 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4629 get_current_user(&user
, p
);
4632 * a nice thing with NT is it doesn't listen to what you tell it.
4633 * when asked to send _only_ RAW datas, it tries to send datas
4636 * So I add checks like in NT Server ...
4638 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4639 * there's a bug in NT client-side code, so we'll fix it in the
4640 * server-side code. *nnnnnggggh!*
4643 if (info_1
->p_datatype
!= 0) {
4644 unistr2_to_dos(datatype
, &info_1
->datatype
, sizeof(datatype
));
4645 if (strcmp(datatype
, "RAW") != 0) {
4647 return WERR_INVALID_DATATYPE
;
4651 /* get the share number of the printer */
4652 if (!get_printer_snum(p
, handle
, &snum
)) {
4656 unistr2_to_dos(jobname
, &info_1
->docname
, sizeof(jobname
));
4658 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4660 /* An error occured in print_job_start() so return an appropriate
4663 if (Printer
->jobid
== -1) {
4664 return map_werror_from_unix(errno
);
4667 Printer
->document_started
=True
;
4668 (*jobid
) = Printer
->jobid
;
4673 /********************************************************************
4674 * api_spoolss_getprinter
4675 * called from the spoolss dispatcher
4677 ********************************************************************/
4679 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4681 POLICY_HND
*handle
= &q_u
->handle
;
4683 return _spoolss_enddocprinter_internal(p
, handle
);
4686 /****************************************************************************
4687 ****************************************************************************/
4689 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4691 POLICY_HND
*handle
= &q_u
->handle
;
4692 uint32 buffer_size
= q_u
->buffer_size
;
4693 uint8
*buffer
= q_u
->buffer
;
4694 uint32
*buffer_written
= &q_u
->buffer_size2
;
4696 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4699 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
4700 r_u
->buffer_written
= q_u
->buffer_size2
;
4704 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
, buffer_size
);
4707 r_u
->buffer_written
= q_u
->buffer_size2
;
4712 /********************************************************************
4713 * api_spoolss_getprinter
4714 * called from the spoolss dispatcher
4716 ********************************************************************/
4718 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
4721 struct current_user user
;
4723 WERROR errcode
= WERR_BADFUNC
;
4724 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4726 get_current_user(&user
, p
);
4729 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
4733 if (!get_printer_snum(p
, handle
, &snum
))
4737 case PRINTER_CONTROL_PAUSE
:
4738 if (print_queue_pause(&user
, snum
, &errcode
)) {
4742 case PRINTER_CONTROL_RESUME
:
4743 case PRINTER_CONTROL_UNPAUSE
:
4744 if (print_queue_resume(&user
, snum
, &errcode
)) {
4748 case PRINTER_CONTROL_PURGE
:
4749 if (print_queue_purge(&user
, snum
, &errcode
)) {
4754 return WERR_UNKNOWN_LEVEL
;
4760 /********************************************************************
4761 * api_spoolss_abortprinter
4762 ********************************************************************/
4764 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
4766 POLICY_HND
*handle
= &q_u
->handle
;
4768 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
4771 /********************************************************************
4772 * called by spoolss_api_setprinter
4773 * when updating a printer description
4774 ********************************************************************/
4776 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
4777 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4778 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
4780 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
4781 struct current_user user
;
4785 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4787 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
4788 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
4789 OUR_HANDLE(handle
)));
4791 result
= WERR_BADFID
;
4795 /* NT seems to like setting the security descriptor even though
4796 nothing may have actually changed. This causes annoying
4797 dialog boxes when the user doesn't have permission to change
4798 the security descriptor. */
4800 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
4802 if (DEBUGLEVEL
>= 10) {
4806 the_acl
= old_secdesc_ctr
->sec
->dacl
;
4807 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4808 PRINTERNAME(snum
), the_acl
->num_aces
));
4810 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4813 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4815 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4816 the_acl
->ace
[i
].info
.mask
));
4819 the_acl
= secdesc_ctr
->sec
->dacl
;
4822 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4823 PRINTERNAME(snum
), the_acl
->num_aces
));
4825 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4828 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4830 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4831 the_acl
->ace
[i
].info
.mask
));
4834 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4838 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
4840 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
4845 /* Work out which user is performing the operation */
4847 get_current_user(&user
, p
);
4849 /* Check the user has permissions to change the security
4850 descriptor. By experimentation with two NT machines, the user
4851 requires Full Access to the printer to change security
4854 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4855 result
= WERR_ACCESS_DENIED
;
4859 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
4866 /********************************************************************
4867 Do Samba sanity checks on a printer info struct.
4868 this has changed purpose: it now "canonicalises" printer
4869 info from a client rather than just checking it is correct
4870 ********************************************************************/
4872 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
4874 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4875 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
4877 /* we force some elements to "correct" values */
4878 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
4879 fstrcpy(info
->sharename
, lp_servicename(snum
));
4880 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
4881 get_called_name(), info
->sharename
);
4882 info
->attributes
= PRINTER_ATTRIBUTE_SHARED
| PRINTER_ATTRIBUTE_NETWORK
;
4887 /****************************************************************************
4888 ****************************************************************************/
4890 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
4892 char *cmd
= lp_addprinter_cmd();
4895 pstring driverlocation
;
4899 fstring remote_machine
= "%m";
4901 /* build driver path... only 9X architecture is needed for legacy reasons */
4902 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
4904 /* change \ to \\ for the shell */
4905 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
4906 standard_sub_basic(remote_machine
,sizeof(remote_machine
));
4908 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4909 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
4910 printer
->info_2
->portname
, printer
->info_2
->drivername
,
4911 printer
->info_2
->location
, driverlocation
, remote_machine
);
4913 /* Convert script args to unix-codepage */
4914 dos_to_unix(command
);
4915 DEBUG(10,("Running [%s]\n", command
));
4916 ret
= smbrun(command
, &fd
);
4917 DEBUGADD(10,("returned [%d]\n", ret
));
4926 /* Get lines and convert them back to dos-codepage */
4927 qlines
= fd_lines_load(fd
, &numlines
, True
);
4928 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4932 /* Set the portname to what the script says the portname should be. */
4933 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
4934 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
4936 /* Send SIGHUP to process group... is there a better way? */
4939 /* reload our services immediately */
4940 reload_services( False
);
4943 file_lines_free(qlines
);
4949 /* Return true if two devicemodes are equal */
4951 #define DEVMODE_CHECK_INT(field) \
4952 if (d1->field != d2->field) { \
4953 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4954 d1->field, d2->field)); \
4958 /************************************************************************
4959 Handy, but currently unused functions
4960 ***********************************************************************/
4962 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
4964 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
4967 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4968 return False
; /* if either is exclusively NULL are not equal */
4971 if (!strequal(d1
->devicename
, d2
->devicename
)) {
4972 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1
->devicename
, d2
->devicename
));
4976 if (!strequal(d1
->formname
, d2
->formname
)) {
4977 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1
->formname
, d2
->formname
));
4981 DEVMODE_CHECK_INT(specversion
);
4982 DEVMODE_CHECK_INT(driverversion
);
4983 DEVMODE_CHECK_INT(driverextra
);
4984 DEVMODE_CHECK_INT(orientation
);
4985 DEVMODE_CHECK_INT(papersize
);
4986 DEVMODE_CHECK_INT(paperlength
);
4987 DEVMODE_CHECK_INT(paperwidth
);
4988 DEVMODE_CHECK_INT(scale
);
4989 DEVMODE_CHECK_INT(copies
);
4990 DEVMODE_CHECK_INT(defaultsource
);
4991 DEVMODE_CHECK_INT(printquality
);
4992 DEVMODE_CHECK_INT(color
);
4993 DEVMODE_CHECK_INT(duplex
);
4994 DEVMODE_CHECK_INT(yresolution
);
4995 DEVMODE_CHECK_INT(ttoption
);
4996 DEVMODE_CHECK_INT(collate
);
4997 DEVMODE_CHECK_INT(logpixels
);
4999 DEVMODE_CHECK_INT(fields
);
5000 DEVMODE_CHECK_INT(bitsperpel
);
5001 DEVMODE_CHECK_INT(pelswidth
);
5002 DEVMODE_CHECK_INT(pelsheight
);
5003 DEVMODE_CHECK_INT(displayflags
);
5004 DEVMODE_CHECK_INT(displayfrequency
);
5005 DEVMODE_CHECK_INT(icmmethod
);
5006 DEVMODE_CHECK_INT(icmintent
);
5007 DEVMODE_CHECK_INT(mediatype
);
5008 DEVMODE_CHECK_INT(dithertype
);
5009 DEVMODE_CHECK_INT(reserved1
);
5010 DEVMODE_CHECK_INT(reserved2
);
5011 DEVMODE_CHECK_INT(panningwidth
);
5012 DEVMODE_CHECK_INT(panningheight
);
5014 /* compare the private data if it exists */
5015 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
5018 DEVMODE_CHECK_INT(driverextra
);
5020 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
5021 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
5026 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
5030 /* Return true if two NT_PRINTER_PARAM structures are equal */
5032 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
5033 NT_PRINTER_PARAM
*p2
)
5035 if (!p1
&& !p2
) goto equal
;
5037 if ((!p1
&& p2
) || (p1
&& !p2
)) {
5038 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
5042 /* Compare lists of printer parameters */
5046 NT_PRINTER_PARAM
*q
= p1
;
5048 /* Find the parameter in the second structure */
5052 if (strequal(p1
->value
, q
->value
)) {
5054 if (p1
->type
!= q
->type
) {
5055 DEBUG(10, ("nt_printer_param_equal():"
5056 "types for %s differ (%d != %d)\n",
5057 p1
->value
, p1
->type
,
5062 if (p1
->data_len
!= q
->data_len
) {
5063 DEBUG(10, ("nt_printer_param_equal():"
5064 "len for %s differs (%d != %d)\n",
5065 p1
->value
, p1
->data_len
,
5070 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
5073 DEBUG(10, ("nt_printer_param_equal():"
5074 "data for %s differs\n", p1
->value
));
5084 DEBUG(10, ("nt_printer_param_equal(): param %s "
5085 "does not exist\n", p1
->value
));
5094 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
5098 /********************************************************************
5099 * Called by update_printer when trying to work out whether to
5100 * actually update printer info.
5101 ********************************************************************/
5103 #define PI_CHECK_INT(field) \
5104 if (pi1->field != pi2->field) { \
5105 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
5106 pi1->field, pi2->field)); \
5110 #define PI_CHECK_STR(field) \
5111 if (!strequal(pi1->field, pi2->field)) { \
5112 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
5113 pi1->field, pi2->field)); \
5117 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
5118 NT_PRINTER_INFO_LEVEL
*p2
)
5120 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
5122 /* Trivial conditions */
5124 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
5128 if ((!p1
&& p2
) || (p1
&& !p2
) ||
5129 (!p1
->info_2
&& p2
->info_2
) ||
5130 (p1
->info_2
&& !p2
->info_2
)) {
5131 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
5136 /* Compare two nt_printer_info_level structures. Don't compare
5137 status or cjobs as they seem to have something to do with the
5143 /* Don't check the attributes as we stomp on the value in
5144 check_printer_ok() anyway. */
5147 PI_CHECK_INT(attributes
);
5150 PI_CHECK_INT(priority
);
5151 PI_CHECK_INT(default_priority
);
5152 PI_CHECK_INT(starttime
);
5153 PI_CHECK_INT(untiltime
);
5154 PI_CHECK_INT(averageppm
);
5156 /* Yuck - don't check the printername or servername as the
5157 mod_a_printer() code plays games with them. You can't
5158 change the printername or the sharename through this interface
5161 PI_CHECK_STR(sharename
);
5162 PI_CHECK_STR(portname
);
5163 PI_CHECK_STR(drivername
);
5164 PI_CHECK_STR(comment
);
5165 PI_CHECK_STR(location
);
5167 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
5171 PI_CHECK_STR(sepfile
);
5172 PI_CHECK_STR(printprocessor
);
5173 PI_CHECK_STR(datatype
);
5174 PI_CHECK_STR(parameters
);
5176 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
5180 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
5184 PI_CHECK_INT(changeid
);
5185 PI_CHECK_INT(c_setprinter
);
5186 PI_CHECK_INT(setuptime
);
5189 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
5195 /********************************************************************
5196 * Called by spoolss_api_setprinter
5197 * when updating a printer description.
5198 ********************************************************************/
5200 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
5201 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5202 DEVICEMODE
*devmode
)
5205 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5206 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5207 PRINTER_MESSAGE_INFO msg
;
5210 DEBUG(8,("update_printer\n"));
5217 DEBUG(0,("update_printer: Send a mail to samba@samba.org\n"));
5218 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
5219 result
= WERR_UNKNOWN_LEVEL
;
5224 result
= WERR_BADFID
;
5228 if (!get_printer_snum(p
, handle
, &snum
)) {
5229 result
= WERR_BADFID
;
5233 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
5234 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
5235 result
= WERR_BADFID
;
5239 DEBUGADD(8,("Converting info_2 struct\n"));
5242 * convert_printer_info converts the incoming
5243 * info from the client and overwrites the info
5244 * just read from the tdb in the pointer 'printer'.
5247 if (!convert_printer_info(info
, printer
, level
)) {
5248 result
= WERR_NOMEM
;
5253 /* we have a valid devmode
5254 convert it and link it*/
5256 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5257 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5258 &printer
->info_2
->devmode
)) {
5259 result
= WERR_NOMEM
;
5264 * make sure we actually reload the services after
5265 * this as smb.conf could have a new section in it
5266 * .... shouldn't .... but could
5268 reload_services(False
);
5271 /* Do sanity check on the requested changes for Samba */
5273 if (!check_printer_ok(printer
->info_2
, snum
)) {
5274 result
= WERR_INVALID_PARAM
;
5281 * Another one of those historical misunderstandings...
5282 * This is reminisent of a similar call we had in _spoolss_setprinterdata()
5283 * I'm leaving it here as a reminder. --jerry
5286 if (nt_printer_info_level_equal(printer
, old_printer
)) {
5287 DEBUG(3, ("update_printer: printer info has not changed\n"));
5294 /* Check calling user has permission to update printer description */
5296 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5297 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5298 result
= WERR_ACCESS_DENIED
;
5302 /* Call addprinter hook */
5304 if (*lp_addprinter_cmd()) {
5305 if ( !add_printer_hook(printer
) ) {
5306 result
= WERR_ACCESS_DENIED
;
5312 * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
5313 * DEVMODE.displayfrequency, which is not used for printer drivers. This
5314 * requires Win32 client code (see other notes elsewhere in the code).
5316 if (printer
->info_2
->devmode
&&
5317 printer
->info_2
->devmode
->displayfrequency
== MAGIC_DISPLAY_FREQUENCY
) {
5319 DEBUG(10,("update_printer: Save printer driver init data\n"));
5320 printer
->info_2
->devmode
->displayfrequency
= 0;
5322 if (update_driver_init(*printer
, 2)!=0) {
5323 DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
5324 result
= WERR_ACCESS_DENIED
;
5329 * When a *new* driver is bound to a printer, the drivername is used to
5330 * lookup previously saved driver initialization info, which is then
5331 * bound to the printer, simulating what happens in the Windows arch.
5333 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)){
5334 if (!set_driver_init(printer
, 2)) {
5335 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
5336 printer
->info_2
->drivername
));
5338 msg
.flags
|= PRINTER_MESSAGE_DRIVER
;
5342 /* Update printer info */
5343 result
= mod_a_printer(*printer
, 2);
5345 /* flag which changes actually occured. This is a small subset of
5346 all the possible changes */
5348 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
))
5349 msg
.flags
|= PRINTER_MESSAGE_COMMENT
;
5351 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
))
5352 msg
.flags
|= PRINTER_MESSAGE_SHARENAME
;
5354 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
))
5355 msg
.flags
|= PRINTER_MESSAGE_PORT
;
5357 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
))
5358 msg
.flags
|= PRINTER_MESSAGE_LOCATION
;
5360 msg
.low
= PRINTER_CHANGE_ADD_PRINTER
;
5361 fstrcpy(msg
.printer_name
, printer
->info_2
->printername
);
5363 /* only send a notify if something changed */
5365 srv_spoolss_sendnotify(msg
.printer_name
, 0, PRINTER_CHANGE_ADD_PRINTER
, msg
.flags
);
5369 free_a_printer(&printer
, 2);
5370 free_a_printer(&old_printer
, 2);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
5381 POLICY_HND
*handle
= &q_u
->handle
;
5382 uint32 level
= q_u
->level
;
5383 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5384 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
5385 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
5386 uint32 command
= q_u
->command
;
5388 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5391 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5395 /* check the level */
5398 return control_printer(handle
, command
, p
);
5400 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
5402 return update_printer_sec(handle
, level
, info
, p
,
5405 return WERR_UNKNOWN_LEVEL
;
5409 /****************************************************************************
5410 ****************************************************************************/
5412 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
5414 POLICY_HND
*handle
= &q_u
->handle
;
5416 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5419 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5423 if (Printer
->notify
.client_connected
==True
)
5424 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
5426 Printer
->notify
.flags
=0;
5427 Printer
->notify
.options
=0;
5428 Printer
->notify
.localmachine
[0]='\0';
5429 Printer
->notify
.printerlocal
=0;
5430 if (Printer
->notify
.option
)
5431 free_spool_notify_option(&Printer
->notify
.option
);
5432 Printer
->notify
.client_connected
=False
;
5437 /****************************************************************************
5438 ****************************************************************************/
5440 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
5442 /* that's an [in out] buffer (despite appearences to the contrary) */
5443 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5446 return WERR_INVALID_PARAM
; /* this is what a NT server
5447 returns for AddJob. AddJob
5448 must fail on non-local
5452 /****************************************************************************
5453 ****************************************************************************/
5455 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
5456 int position
, int snum
)
5462 t
=gmtime(&queue
->time
);
5463 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5465 job_info
->jobid
=queue
->job
;
5466 init_unistr(&job_info
->printername
, lp_servicename(snum
));
5467 init_unistr(&job_info
->machinename
, temp_name
);
5468 init_unistr(&job_info
->username
, queue
->fs_user
);
5469 init_unistr(&job_info
->document
, queue
->fs_file
);
5470 init_unistr(&job_info
->datatype
, "RAW");
5471 init_unistr(&job_info
->text_status
, "");
5472 job_info
->status
=nt_printj_status(queue
->status
);
5473 job_info
->priority
=queue
->priority
;
5474 job_info
->position
=position
;
5475 job_info
->totalpages
=queue
->page_count
;
5476 job_info
->pagesprinted
=0;
5478 make_systemtime(&job_info
->submitted
, t
);
5481 /****************************************************************************
5482 ****************************************************************************/
5484 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
5485 int position
, int snum
,
5486 NT_PRINTER_INFO_LEVEL
*ntprinter
,
5487 DEVICEMODE
*devmode
)
5492 t
=gmtime(&queue
->time
);
5493 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
5495 job_info
->jobid
=queue
->job
;
5497 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
5499 init_unistr(&job_info
->machinename
, temp_name
);
5500 init_unistr(&job_info
->username
, queue
->fs_user
);
5501 init_unistr(&job_info
->document
, queue
->fs_file
);
5502 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
5503 init_unistr(&job_info
->datatype
, "RAW");
5504 init_unistr(&job_info
->printprocessor
, "winprint");
5505 init_unistr(&job_info
->parameters
, "");
5506 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
5507 init_unistr(&job_info
->text_status
, "");
5509 /* and here the security descriptor */
5511 job_info
->status
=nt_printj_status(queue
->status
);
5512 job_info
->priority
=queue
->priority
;
5513 job_info
->position
=position
;
5514 job_info
->starttime
=0;
5515 job_info
->untiltime
=0;
5516 job_info
->totalpages
=queue
->page_count
;
5517 job_info
->size
=queue
->size
;
5518 make_systemtime(&(job_info
->submitted
), t
);
5519 job_info
->timeelapsed
=0;
5520 job_info
->pagesprinted
=0;
5522 job_info
->devmode
= devmode
;
5527 /****************************************************************************
5528 Enumjobs at level 1.
5529 ****************************************************************************/
5531 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
5532 NEW_BUFFER
*buffer
, uint32 offered
,
5533 uint32
*needed
, uint32
*returned
)
5538 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
5545 for (i
=0; i
<*returned
; i
++)
5546 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
5550 /* check the required size. */
5551 for (i
=0; i
<*returned
; i
++)
5552 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
5554 if (!alloc_buffer_size(buffer
, *needed
)) {
5556 return WERR_INSUFFICIENT_BUFFER
;
5559 /* fill the buffer with the structures */
5560 for (i
=0; i
<*returned
; i
++)
5561 smb_io_job_info_1("", buffer
, &info
[i
], 0);
5566 if (*needed
> offered
) {
5568 return WERR_INSUFFICIENT_BUFFER
;
5574 /****************************************************************************
5575 Enumjobs at level 2.
5576 ****************************************************************************/
5578 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
5579 NEW_BUFFER
*buffer
, uint32 offered
,
5580 uint32
*needed
, uint32
*returned
)
5582 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
5583 JOB_INFO_2
*info
= NULL
;
5586 DEVICEMODE
*devmode
= NULL
;
5588 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
5591 result
= WERR_NOMEM
;
5595 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
5596 if (!W_ERROR_IS_OK(result
)) {
5601 /* this should not be a failure condition if the devmode is NULL */
5603 devmode
= construct_dev_mode(snum
);
5605 for (i
=0; i
<*returned
; i
++)
5606 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
5609 free_a_printer(&ntprinter
, 2);
5612 /* check the required size. */
5613 for (i
=0; i
<*returned
; i
++)
5614 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
5616 if (*needed
> offered
) {
5618 result
= WERR_INSUFFICIENT_BUFFER
;
5622 if (!alloc_buffer_size(buffer
, *needed
)) {
5624 result
= WERR_INSUFFICIENT_BUFFER
;
5628 /* fill the buffer with the structures */
5629 for (i
=0; i
<*returned
; i
++)
5630 smb_io_job_info_2("", buffer
, &info
[i
], 0);
5635 free_a_printer(&ntprinter
, 2);
5636 free_devmode(devmode
);
5644 /****************************************************************************
5646 ****************************************************************************/
5648 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
5650 POLICY_HND
*handle
= &q_u
->handle
;
5651 /* uint32 firstjob = q_u->firstjob; - notused. */
5652 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5653 uint32 level
= q_u
->level
;
5654 NEW_BUFFER
*buffer
= NULL
;
5655 uint32 offered
= q_u
->offered
;
5656 uint32
*needed
= &r_u
->needed
;
5657 uint32
*returned
= &r_u
->returned
;
5660 print_status_struct prt_status
;
5661 print_queue_struct
*queue
=NULL
;
5663 /* that's an [in out] buffer */
5664 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5665 buffer
= r_u
->buffer
;
5667 DEBUG(4,("_spoolss_enumjobs\n"));
5672 if (!get_printer_snum(p
, handle
, &snum
))
5675 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
5676 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
5678 if (*returned
== 0) {
5685 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
5687 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
5691 return WERR_UNKNOWN_LEVEL
;
5695 /****************************************************************************
5696 ****************************************************************************/
5698 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
5703 /****************************************************************************
5704 ****************************************************************************/
5706 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
5708 POLICY_HND
*handle
= &q_u
->handle
;
5709 uint32 jobid
= q_u
->jobid
;
5710 /* uint32 level = q_u->level; - notused. */
5711 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5712 uint32 command
= q_u
->command
;
5714 struct current_user user
;
5716 WERROR errcode
= WERR_BADFUNC
;
5718 if (!get_printer_snum(p
, handle
, &snum
)) {
5722 if (!print_job_exists(jobid
)) {
5723 return WERR_INVALID_PRINTER_NAME
;
5726 get_current_user(&user
, p
);
5729 case JOB_CONTROL_CANCEL
:
5730 case JOB_CONTROL_DELETE
:
5731 if (print_job_delete(&user
, jobid
, &errcode
)) {
5735 case JOB_CONTROL_PAUSE
:
5736 if (print_job_pause(&user
, jobid
, &errcode
)) {
5740 case JOB_CONTROL_RESTART
:
5741 case JOB_CONTROL_RESUME
:
5742 if (print_job_resume(&user
, jobid
, &errcode
)) {
5747 return WERR_UNKNOWN_LEVEL
;
5753 /****************************************************************************
5754 Enumerates all printer drivers at level 1.
5755 ****************************************************************************/
5757 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5762 fstring
*list
= NULL
;
5764 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5765 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5769 #define MAX_VERSION 4
5771 for (version
=0; version
<MAX_VERSION
; version
++) {
5773 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5774 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5780 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5781 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5782 SAFE_FREE(driver_info_1
);
5786 else driver_info_1
= tdi1
;
5789 for (i
=0; i
<ndrivers
; i
++) {
5791 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5792 ZERO_STRUCT(driver
);
5793 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5794 architecture
, version
);
5795 if (!W_ERROR_IS_OK(status
)) {
5799 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5800 free_a_printer_driver(driver
, 3);
5803 *returned
+=ndrivers
;
5807 /* check the required size. */
5808 for (i
=0; i
<*returned
; i
++) {
5809 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5810 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5813 if (!alloc_buffer_size(buffer
, *needed
)) {
5814 SAFE_FREE(driver_info_1
);
5815 return WERR_INSUFFICIENT_BUFFER
;
5818 /* fill the buffer with the driver structures */
5819 for (i
=0; i
<*returned
; i
++) {
5820 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5821 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5824 SAFE_FREE(driver_info_1
);
5826 if (*needed
> offered
) {
5828 return WERR_INSUFFICIENT_BUFFER
;
5834 /****************************************************************************
5835 Enumerates all printer drivers at level 2.
5836 ****************************************************************************/
5838 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5843 fstring
*list
= NULL
;
5845 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5846 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
5850 #define MAX_VERSION 4
5852 for (version
=0; version
<MAX_VERSION
; version
++) {
5854 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5855 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5861 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
5862 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5863 SAFE_FREE(driver_info_2
);
5867 else driver_info_2
= tdi2
;
5870 for (i
=0; i
<ndrivers
; i
++) {
5873 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5874 ZERO_STRUCT(driver
);
5875 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5876 architecture
, version
);
5877 if (!W_ERROR_IS_OK(status
)) {
5881 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
5882 free_a_printer_driver(driver
, 3);
5885 *returned
+=ndrivers
;
5889 /* check the required size. */
5890 for (i
=0; i
<*returned
; i
++) {
5891 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5892 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
5895 if (!alloc_buffer_size(buffer
, *needed
)) {
5896 SAFE_FREE(driver_info_2
);
5897 return WERR_INSUFFICIENT_BUFFER
;
5900 /* fill the buffer with the form structures */
5901 for (i
=0; i
<*returned
; i
++) {
5902 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5903 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
5906 SAFE_FREE(driver_info_2
);
5908 if (*needed
> offered
) {
5910 return WERR_INSUFFICIENT_BUFFER
;
5916 /****************************************************************************
5917 Enumerates all printer drivers at level 3.
5918 ****************************************************************************/
5920 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5925 fstring
*list
= NULL
;
5927 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5928 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
5932 #define MAX_VERSION 4
5934 for (version
=0; version
<MAX_VERSION
; version
++) {
5936 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5937 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5943 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
5944 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5945 SAFE_FREE(driver_info_3
);
5949 else driver_info_3
= tdi3
;
5952 for (i
=0; i
<ndrivers
; i
++) {
5955 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5956 ZERO_STRUCT(driver
);
5957 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5958 architecture
, version
);
5959 if (!W_ERROR_IS_OK(status
)) {
5963 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
5964 free_a_printer_driver(driver
, 3);
5967 *returned
+=ndrivers
;
5971 /* check the required size. */
5972 for (i
=0; i
<*returned
; i
++) {
5973 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5974 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
5977 if (!alloc_buffer_size(buffer
, *needed
)) {
5978 SAFE_FREE(driver_info_3
);
5979 return WERR_INSUFFICIENT_BUFFER
;
5982 /* fill the buffer with the driver structures */
5983 for (i
=0; i
<*returned
; i
++) {
5984 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5985 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
5988 for (i
=0; i
<*returned
; i
++)
5989 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
5991 SAFE_FREE(driver_info_3
);
5993 if (*needed
> offered
) {
5995 return WERR_INSUFFICIENT_BUFFER
;
6001 /****************************************************************************
6002 Enumerates all printer drivers.
6003 ****************************************************************************/
6005 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6007 /* UNISTR2 *name = &q_u->name; - notused. */
6008 UNISTR2
*environment
= &q_u
->environment
;
6009 uint32 level
= q_u
->level
;
6010 NEW_BUFFER
*buffer
= NULL
;
6011 uint32 offered
= q_u
->offered
;
6012 uint32
*needed
= &r_u
->needed
;
6013 uint32
*returned
= &r_u
->returned
;
6015 fstring
*list
= NULL
;
6017 fstring architecture
;
6019 /* that's an [in out] buffer */
6020 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6021 buffer
= r_u
->buffer
;
6023 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6024 fstrcpy(servername
, get_called_name());
6028 unistr2_to_dos(architecture
, environment
, sizeof(architecture
)-1);
6032 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6034 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6036 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6040 return WERR_UNKNOWN_LEVEL
;
6044 /****************************************************************************
6045 ****************************************************************************/
6047 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6049 form
->flag
=list
->flag
;
6050 init_unistr(&form
->name
, list
->name
);
6051 form
->width
=list
->width
;
6052 form
->length
=list
->length
;
6053 form
->left
=list
->left
;
6054 form
->top
=list
->top
;
6055 form
->right
=list
->right
;
6056 form
->bottom
=list
->bottom
;
6059 /****************************************************************************
6060 ****************************************************************************/
6062 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6064 /* POLICY_HND *handle = &q_u->handle; - notused. */
6065 uint32 level
= q_u
->level
;
6066 NEW_BUFFER
*buffer
= NULL
;
6067 uint32 offered
= q_u
->offered
;
6068 uint32
*needed
= &r_u
->needed
;
6069 uint32
*numofforms
= &r_u
->numofforms
;
6070 uint32 numbuiltinforms
;
6072 nt_forms_struct
*list
=NULL
;
6073 nt_forms_struct
*builtinlist
=NULL
;
6078 /* that's an [in out] buffer */
6079 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6080 buffer
= r_u
->buffer
;
6082 DEBUG(4,("_spoolss_enumforms\n"));
6083 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6084 DEBUGADD(5,("Info level [%d]\n", level
));
6086 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6087 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6088 *numofforms
= get_ntforms(&list
);
6089 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6090 *numofforms
+= numbuiltinforms
;
6092 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6096 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6101 /* construct the list of form structures */
6102 for (i
=0; i
<numbuiltinforms
; i
++) {
6103 DEBUGADD(6,("Filling form number [%d]\n",i
));
6104 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
6107 SAFE_FREE(builtinlist
);
6109 for (; i
<*numofforms
; i
++) {
6110 DEBUGADD(6,("Filling form number [%d]\n",i
));
6111 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
6116 /* check the required size. */
6117 for (i
=0; i
<numbuiltinforms
; i
++) {
6118 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6119 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6121 for (; i
<*numofforms
; i
++) {
6122 DEBUGADD(6,("adding form [%d]'s size\n",i
));
6123 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
6126 *needed
=buffer_size
;
6128 if (!alloc_buffer_size(buffer
, buffer_size
)){
6130 return WERR_INSUFFICIENT_BUFFER
;
6133 /* fill the buffer with the form structures */
6134 for (i
=0; i
<numbuiltinforms
; i
++) {
6135 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6136 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6138 for (; i
<*numofforms
; i
++) {
6139 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
6140 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
6145 if (*needed
> offered
) {
6147 return WERR_INSUFFICIENT_BUFFER
;
6154 SAFE_FREE(builtinlist
);
6155 return WERR_UNKNOWN_LEVEL
;
6160 /****************************************************************************
6161 ****************************************************************************/
6163 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
6165 /* POLICY_HND *handle = &q_u->handle; - notused. */
6166 uint32 level
= q_u
->level
;
6167 UNISTR2
*uni_formname
= &q_u
->formname
;
6168 NEW_BUFFER
*buffer
= NULL
;
6169 uint32 offered
= q_u
->offered
;
6170 uint32
*needed
= &r_u
->needed
;
6172 nt_forms_struct
*list
=NULL
;
6173 nt_forms_struct builtin_form
;
6178 int numofforms
=0, i
=0;
6180 /* that's an [in out] buffer */
6181 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6182 buffer
= r_u
->buffer
;
6184 unistr2_to_dos(form_name
, uni_formname
, sizeof(form_name
)-1);
6186 DEBUG(4,("_spoolss_getform\n"));
6187 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6188 DEBUGADD(5,("Info level [%d]\n", level
));
6190 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
6191 if (!foundBuiltin
) {
6192 numofforms
= get_ntforms(&list
);
6193 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
6195 if (numofforms
== 0)
6202 fill_form_1(&form_1
, &builtin_form
);
6205 /* Check if the requested name is in the list of form structures */
6206 for (i
=0; i
<numofforms
; i
++) {
6208 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
6210 if (strequal(form_name
, list
[i
].name
)) {
6211 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
6212 fill_form_1(&form_1
, &list
[i
]);
6218 if (i
== numofforms
) {
6222 /* check the required size. */
6224 *needed
=spoolss_size_form_1(&form_1
);
6226 if (!alloc_buffer_size(buffer
, buffer_size
)){
6227 return WERR_INSUFFICIENT_BUFFER
;
6230 if (*needed
> offered
) {
6231 return WERR_INSUFFICIENT_BUFFER
;
6234 /* fill the buffer with the form structures */
6235 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
6236 smb_io_form_1("", buffer
, &form_1
, 0);
6242 return WERR_UNKNOWN_LEVEL
;
6246 /****************************************************************************
6247 ****************************************************************************/
6249 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
6251 init_unistr(&port
->port_name
, name
);
6254 /****************************************************************************
6255 ****************************************************************************/
6257 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
6259 init_unistr(&port
->port_name
, name
);
6260 init_unistr(&port
->monitor_name
, "Local Monitor");
6261 init_unistr(&port
->description
, "Local Port");
6262 #define PORT_TYPE_WRITE 1
6263 port
->port_type
=PORT_TYPE_WRITE
;
6267 /****************************************************************************
6269 ****************************************************************************/
6271 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6273 PORT_INFO_1
*ports
=NULL
;
6276 if (*lp_enumports_cmd()) {
6277 char *cmd
= lp_enumports_cmd();
6284 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
6286 DEBUG(10,("Running [%s]\n", command
));
6287 ret
= smbrun(command
, &fd
);
6288 DEBUG(10,("Returned [%d]\n", ret
));
6292 /* Is this the best error to return here? */
6293 return WERR_ACCESS_DENIED
;
6297 qlines
= fd_lines_load(fd
, &numlines
,True
);
6298 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6302 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
6303 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
6304 dos_errstr(WERR_NOMEM
)));
6305 file_lines_free(qlines
);
6309 for (i
=0; i
<numlines
; i
++) {
6310 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6311 fill_port_1(&ports
[i
], qlines
[i
]);
6314 file_lines_free(qlines
);
6317 *returned
= numlines
;
6320 *returned
= 1; /* Sole Samba port returned. */
6322 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
6325 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6327 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6330 /* check the required size. */
6331 for (i
=0; i
<*returned
; i
++) {
6332 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6333 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
6336 if (!alloc_buffer_size(buffer
, *needed
)) {
6338 return WERR_INSUFFICIENT_BUFFER
;
6341 /* fill the buffer with the ports structures */
6342 for (i
=0; i
<*returned
; i
++) {
6343 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6344 smb_io_port_1("", buffer
, &ports
[i
], 0);
6349 if (*needed
> offered
) {
6351 return WERR_INSUFFICIENT_BUFFER
;
6357 /****************************************************************************
6359 ****************************************************************************/
6361 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6363 PORT_INFO_2
*ports
=NULL
;
6366 if (*lp_enumports_cmd()) {
6367 char *cmd
= lp_enumports_cmd();
6376 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
6377 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
6379 path
= lp_lockdir();
6381 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
6382 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
6385 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
6386 ret
= smbrun(command
, &fd
);
6387 DEBUGADD(10,("returned [%d]\n", ret
));
6391 /* Is this the best error to return here? */
6392 return WERR_ACCESS_DENIED
;
6396 qlines
= fd_lines_load(fd
, &numlines
,True
);
6397 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6401 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
6402 file_lines_free(qlines
);
6406 for (i
=0; i
<numlines
; i
++) {
6407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
6408 fill_port_2(&(ports
[i
]), qlines
[i
]);
6411 file_lines_free(qlines
);
6414 *returned
= numlines
;
6420 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
6423 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
6425 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
6428 /* check the required size. */
6429 for (i
=0; i
<*returned
; i
++) {
6430 DEBUGADD(6,("adding port [%d]'s size\n", i
));
6431 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
6434 if (!alloc_buffer_size(buffer
, *needed
)) {
6436 return WERR_INSUFFICIENT_BUFFER
;
6439 /* fill the buffer with the ports structures */
6440 for (i
=0; i
<*returned
; i
++) {
6441 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
6442 smb_io_port_2("", buffer
, &ports
[i
], 0);
6447 if (*needed
> offered
) {
6449 return WERR_INSUFFICIENT_BUFFER
;
6455 /****************************************************************************
6457 ****************************************************************************/
6459 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
6461 /* UNISTR2 *name = &q_u->name; - notused. */
6462 uint32 level
= q_u
->level
;
6463 NEW_BUFFER
*buffer
= NULL
;
6464 uint32 offered
= q_u
->offered
;
6465 uint32
*needed
= &r_u
->needed
;
6466 uint32
*returned
= &r_u
->returned
;
6468 /* that's an [in out] buffer */
6469 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6470 buffer
= r_u
->buffer
;
6472 DEBUG(4,("_spoolss_enumports\n"));
6479 return enumports_level_1(buffer
, offered
, needed
, returned
);
6481 return enumports_level_2(buffer
, offered
, needed
, returned
);
6483 return WERR_UNKNOWN_LEVEL
;
6487 /****************************************************************************
6488 ****************************************************************************/
6490 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
6491 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6492 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
6493 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
6496 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6499 WERROR err
= WERR_OK
;
6501 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
6502 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
6506 ZERO_STRUCTP(printer
);
6508 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
6509 if (!convert_printer_info(info
, printer
, 2)) {
6510 free_a_printer(&printer
, 2);
6514 /* check to see if the printer already exists */
6516 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
6517 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
6518 printer
->info_2
->sharename
));
6519 free_a_printer(&printer
, 2);
6520 return WERR_PRINTER_ALREADY_EXISTS
;
6523 if (*lp_addprinter_cmd() ) {
6524 if ( !add_printer_hook(printer
) ) {
6525 free_a_printer(&printer
,2);
6526 return WERR_ACCESS_DENIED
;
6530 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
6531 printer
->info_2
->sharename
);
6534 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
6535 free_a_printer(&printer
,2);
6536 return WERR_ACCESS_DENIED
;
6539 /* you must be a printer admin to add a new printer */
6540 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6541 free_a_printer(&printer
,2);
6542 return WERR_ACCESS_DENIED
;
6546 * Do sanity check on the requested changes for Samba.
6549 if (!check_printer_ok(printer
->info_2
, snum
)) {
6550 free_a_printer(&printer
,2);
6551 return WERR_INVALID_PARAM
;
6555 * When a printer is created, the drivername bound to the printer is used
6556 * to lookup previously saved driver initialization info, which is then
6557 * bound to the new printer, simulating what happens in the Windows arch.
6561 set_driver_init(printer
, 2);
6563 /* A valid devmode was included, convert and link it
6565 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
6567 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6568 &printer
->info_2
->devmode
))
6572 set_driver_init(printer
, 2);
6574 /* write the ASCII on disk */
6575 err
= mod_a_printer(*printer
, 2);
6576 if (!W_ERROR_IS_OK(err
)) {
6577 free_a_printer(&printer
,2);
6581 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
6582 /* Handle open failed - remove addition. */
6583 del_a_printer(printer
->info_2
->sharename
);
6584 free_a_printer(&printer
,2);
6585 return WERR_ACCESS_DENIED
;
6588 update_c_setprinter(False
);
6590 srv_spoolss_sendnotify(printer
->info_2
->printername
, 0, PRINTER_CHANGE_ADD_PRINTER
, 0x0);
6592 free_a_printer(&printer
,2);
6597 /****************************************************************************
6598 ****************************************************************************/
6600 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
6602 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
6603 uint32 level
= q_u
->level
;
6604 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6605 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
6606 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
6607 uint32 user_switch
= q_u
->user_switch
;
6608 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
6609 POLICY_HND
*handle
= &r_u
->handle
;
6613 /* we don't handle yet */
6614 /* but I know what to do ... */
6615 return WERR_UNKNOWN_LEVEL
;
6617 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
6619 user_switch
, user
, handle
);
6621 return WERR_UNKNOWN_LEVEL
;
6625 /****************************************************************************
6626 ****************************************************************************/
6628 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
6630 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
6631 uint32 level
= q_u
->level
;
6632 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
6633 WERROR err
= WERR_OK
;
6634 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6635 struct current_user user
;
6636 fstring driver_name
;
6639 ZERO_STRUCT(driver
);
6641 get_current_user(&user
, p
);
6643 if (!convert_printer_driver_info(info
, &driver
, level
)) {
6648 DEBUG(5,("Cleaning driver's information\n"));
6649 err
= clean_up_driver_struct(driver
, level
, &user
);
6650 if (!W_ERROR_IS_OK(err
))
6653 DEBUG(5,("Moving driver to final destination\n"));
6654 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
6655 if (W_ERROR_IS_OK(err
))
6656 err
= WERR_ACCESS_DENIED
;
6660 if (add_a_printer_driver(driver
, level
)!=0) {
6661 err
= WERR_ACCESS_DENIED
;
6665 /* BEGIN_ADMIN_LOG */
6668 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6669 driver
.info_3
->name
,drv_ver_to_os
[driver
.info_3
->cversion
],uidtoname(user
.uid
));
6670 fstrcpy(driver_name
, driver
.info_3
->name
);
6673 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
6674 driver
.info_6
->name
,drv_ver_to_os
[driver
.info_6
->version
],uidtoname(user
.uid
));
6675 fstrcpy(driver_name
, driver
.info_6
->name
);
6681 * I think this is where he DrvUpgradePrinter() hook would be
6682 * be called in a driver's interface DLL on a Windows NT 4.0/2k
6683 * server. Right now, we just need to send ourselves a message
6684 * to update each printer bound to this driver. --jerry
6687 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
6688 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
6693 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
6694 * decide if the driver init data should be deleted. The rules are:
6695 * 1) never delete init data if it is a 9x driver, they don't use it anyway
6696 * 2) delete init data only if there is no 2k/Xp driver
6697 * 3) always delete init data
6698 * The generalized rule is always use init data from the highest order driver.
6699 * It is necessary to follow the driver install by an initialization step to
6700 * finish off this process.
6703 version
= driver
.info_3
->cversion
;
6704 else if (level
== 6)
6705 version
= driver
.info_6
->version
;
6710 * 9x printer driver - never delete init data
6713 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
6718 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
6719 * there is no 2k/Xp driver init data for this driver name.
6723 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
6725 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
6727 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
6729 if (!del_driver_init(driver_name
))
6730 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
6733 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
6735 free_a_printer_driver(driver1
,3);
6736 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
6743 * 2k or Xp printer driver - always delete init data
6746 if (!del_driver_init(driver_name
))
6747 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
6751 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
6757 free_a_printer_driver(driver
, level
);
6761 /****************************************************************************
6762 ****************************************************************************/
6764 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
6766 init_unistr(&info
->name
, name
);
6769 /****************************************************************************
6770 ****************************************************************************/
6772 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6776 pstring short_archi
;
6777 DRIVER_DIRECTORY_1
*info
=NULL
;
6779 unistr2_to_dos(long_archi
, uni_environment
, sizeof(long_archi
)-1);
6781 if (get_short_archi(short_archi
, long_archi
)==False
)
6782 return WERR_INVALID_ENVIRONMENT
;
6784 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
6787 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
6789 DEBUG(4,("printer driver directory: [%s]\n", path
));
6791 fill_driverdir_1(info
, path
);
6793 *needed
+= spoolss_size_driverdir_info_1(info
);
6795 if (!alloc_buffer_size(buffer
, *needed
)) {
6797 return WERR_INSUFFICIENT_BUFFER
;
6800 smb_io_driverdir_1("", buffer
, info
, 0);
6804 if (*needed
> offered
)
6805 return WERR_INSUFFICIENT_BUFFER
;
6810 /****************************************************************************
6811 ****************************************************************************/
6813 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
6815 UNISTR2
*name
= &q_u
->name
;
6816 UNISTR2
*uni_environment
= &q_u
->environment
;
6817 uint32 level
= q_u
->level
;
6818 NEW_BUFFER
*buffer
= NULL
;
6819 uint32 offered
= q_u
->offered
;
6820 uint32
*needed
= &r_u
->needed
;
6822 /* that's an [in out] buffer */
6823 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6824 buffer
= r_u
->buffer
;
6826 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6832 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
6834 return WERR_UNKNOWN_LEVEL
;
6838 /****************************************************************************
6839 ****************************************************************************/
6841 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
6843 POLICY_HND
*handle
= &q_u
->handle
;
6844 uint32 idx
= q_u
->index
;
6845 uint32 in_value_len
= q_u
->valuesize
;
6846 uint32 in_data_len
= q_u
->datasize
;
6847 uint32
*out_max_value_len
= &r_u
->valuesize
;
6848 uint16
**out_value
= &r_u
->value
;
6849 uint32
*out_value_len
= &r_u
->realvaluesize
;
6850 uint32
*out_type
= &r_u
->type
;
6851 uint32
*out_max_data_len
= &r_u
->datasize
;
6852 uint8
**data_out
= &r_u
->data
;
6853 uint32
*out_data_len
= &r_u
->realdatasize
;
6855 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6860 uint32 biggest_valuesize
;
6861 uint32 biggest_datasize
;
6863 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6869 ZERO_STRUCT(printer
);
6873 *out_max_data_len
=0;
6877 DEBUG(5,("spoolss_enumprinterdata\n"));
6880 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
6884 if (!get_printer_snum(p
,handle
, &snum
))
6887 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6888 if (!W_ERROR_IS_OK(result
))
6892 * The NT machine wants to know the biggest size of value and data
6894 * cf: MSDN EnumPrinterData remark section
6896 if ( (in_value_len
==0) && (in_data_len
==0) ) {
6897 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6902 biggest_valuesize
=0;
6905 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
6906 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
6907 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
6909 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
6915 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6916 *out_value_len
=2*(1+biggest_valuesize
);
6917 *out_data_len
=biggest_datasize
;
6919 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
6921 free_a_printer(&printer
, 2);
6926 * the value len is wrong in NT sp3
6927 * that's the number of bytes not the number of unicode chars
6930 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6933 free_a_printer(&printer
, 2);
6935 /* out_value should default to "" or else NT4 has
6936 problems unmarshalling the response */
6938 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6939 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
6942 *out_value_len
= (uint32
)dos_PutUniCode((char *)*out_value
, "", in_value_len
, True
);
6944 /* the data is counted in bytes */
6945 *out_max_data_len
= in_data_len
;
6946 *out_data_len
= in_data_len
;
6947 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
6950 return WERR_NO_MORE_ITEMS
;
6953 free_a_printer(&printer
, 2);
6957 * - counted in bytes in the request
6958 * - counted in UNICODE chars in the max reply
6959 * - counted in bytes in the real size
6961 * take a pause *before* coding not *during* coding
6964 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6965 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
,in_value_len
*sizeof(uint8
))) == NULL
) {
6970 *out_value_len
= (uint32
)dos_PutUniCode((char *)*out_value
, value
, in_value_len
, True
);
6974 /* the data is counted in bytes */
6975 *out_max_data_len
=in_data_len
;
6976 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) {
6981 memcpy(*data_out
, data
, (size_t)data_len
);
6982 *out_data_len
=data_len
;
6989 /****************************************************************************
6990 ****************************************************************************/
6992 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
6994 POLICY_HND
*handle
= &q_u
->handle
;
6995 UNISTR2
*value
= &q_u
->value
;
6996 uint32 type
= q_u
->type
;
6997 /* uint32 max_len = q_u->max_len; - notused. */
6998 uint8
*data
= q_u
->data
;
6999 uint32 real_len
= q_u
->real_len
;
7000 /* uint32 numeric_data = q_u->numeric_data; - notused. */
7002 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7003 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
7005 WERROR status
= WERR_OK
;
7006 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7008 DEBUG(5,("spoolss_setprinterdata\n"));
7011 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7015 if (!get_printer_snum(p
,handle
, &snum
))
7018 ZERO_STRUCT(old_param
);
7021 * Access check : NT returns "access denied" if you make a
7022 * SetPrinterData call without the necessary privildge.
7023 * we were originally returning OK if nothing changed
7024 * which made Win2k issue **a lot** of SetPrinterData
7025 * when connecting to a printer --jerry
7028 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7029 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
7030 status
= WERR_ACCESS_DENIED
;
7034 /* Check if we are making any changes or not. Return true if
7035 nothing is actually changing. This is not needed anymore but
7036 has been left in as an optimization to keep from from
7037 writing to disk as often --jerry */
7039 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7040 if (!W_ERROR_IS_OK(status
))
7043 convert_specific_param(¶m
, value
, type
, data
, real_len
);
7045 unlink_specific_param_if_exist(printer
->info_2
, param
);
7048 * When client side code sets a magic printer data key, detect it and save
7049 * the current printer data and the magic key's data (its the DEVMODE) for
7050 * future printer/driver initializations.
7052 if (param
->type
==3 && !strcmp( param
->value
, PHANTOM_DEVMODE_KEY
)) {
7054 * Set devmode and printer initialization info
7056 status
= save_driver_init(printer
, 2, param
);
7059 add_a_specific_param(printer
->info_2
, ¶m
);
7060 status
= mod_a_printer(*printer
, 2);
7064 free_a_printer(&printer
, 2);
7066 free_nt_printer_param(¶m
);
7067 SAFE_FREE(old_param
.data
);
7072 /****************************************************************************
7073 ****************************************************************************/
7075 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
7077 POLICY_HND
*handle
= &q_u
->handle
;
7078 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7081 DEBUG(5,("_spoolss_resetprinter\n"));
7084 * All we do is to check to see if the handle and queue is valid.
7085 * This call really doesn't mean anything to us because we only
7086 * support RAW printing. --jerry
7090 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7094 if (!get_printer_snum(p
,handle
, &snum
))
7098 /* blindly return success */
7103 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
7105 POLICY_HND
*handle
= &q_u
->handle
;
7106 UNISTR2
*value
= &q_u
->valuename
;
7108 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7109 NT_PRINTER_PARAM param
;
7111 WERROR status
= WERR_OK
;
7112 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7114 DEBUG(5,("spoolss_deleteprinterdata\n"));
7117 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7121 if (!get_printer_snum(p
, handle
, &snum
))
7124 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
7125 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
7126 return WERR_ACCESS_DENIED
;
7129 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7130 if (!W_ERROR_IS_OK(status
))
7133 ZERO_STRUCTP(¶m
);
7134 unistr2_to_dos(param
.value
, value
, sizeof(param
.value
)-1);
7136 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
7137 status
= WERR_INVALID_PARAM
;
7139 status
= mod_a_printer(*printer
, 2);
7141 free_a_printer(&printer
, 2);
7145 /****************************************************************************
7146 ****************************************************************************/
7148 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
7150 POLICY_HND
*handle
= &q_u
->handle
;
7151 /* uint32 level = q_u->level; - notused. */
7152 FORM
*form
= &q_u
->form
;
7153 nt_forms_struct tmpForm
;
7155 WERROR status
= WERR_OK
;
7156 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7159 nt_forms_struct
*list
=NULL
;
7160 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7162 DEBUG(5,("spoolss_addform\n"));
7165 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7170 /* forms can be added on printer of on the print server handle */
7172 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7174 if (!get_printer_snum(p
,handle
, &snum
))
7177 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7178 if (!W_ERROR_IS_OK(status
))
7182 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7183 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
7184 status
= WERR_ACCESS_DENIED
;
7188 /* can't add if builtin */
7190 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7191 status
= WERR_ALREADY_EXISTS
;
7195 count
= get_ntforms(&list
);
7197 if(!add_a_form(&list
, form
, &count
)) {
7198 status
= WERR_NOMEM
;
7202 write_ntforms(&list
, count
);
7205 * ChangeID must always be set if this is a printer
7208 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7209 status
= mod_a_printer(*printer
, 2);
7213 free_a_printer(&printer
, 2);
7219 /****************************************************************************
7220 ****************************************************************************/
7222 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
7224 POLICY_HND
*handle
= &q_u
->handle
;
7225 UNISTR2
*form_name
= &q_u
->name
;
7226 nt_forms_struct tmpForm
;
7228 nt_forms_struct
*list
=NULL
;
7229 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7231 WERROR status
= WERR_OK
;
7232 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7234 DEBUG(5,("spoolss_deleteform\n"));
7237 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7241 /* forms can be deleted on printer of on the print server handle */
7243 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7245 if (!get_printer_snum(p
,handle
, &snum
))
7248 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7249 if (!W_ERROR_IS_OK(status
))
7253 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7254 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
7255 status
= WERR_ACCESS_DENIED
;
7259 /* can't delete if builtin */
7261 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
7262 status
= WERR_INVALID_PARAM
;
7266 count
= get_ntforms(&list
);
7268 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
7272 * ChangeID must always be set if this is a printer
7275 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7276 status
= mod_a_printer(*printer
, 2);
7280 free_a_printer(&printer
, 2);
7286 /****************************************************************************
7287 ****************************************************************************/
7289 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
7291 POLICY_HND
*handle
= &q_u
->handle
;
7292 /* UNISTR2 *uni_name = &q_u->name; - notused. */
7293 /* uint32 level = q_u->level; - notused. */
7294 FORM
*form
= &q_u
->form
;
7295 nt_forms_struct tmpForm
;
7297 WERROR status
= WERR_OK
;
7298 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7301 nt_forms_struct
*list
=NULL
;
7302 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7304 DEBUG(5,("spoolss_setform\n"));
7307 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7311 /* forms can be modified on printer of on the print server handle */
7313 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7315 if (!get_printer_snum(p
,handle
, &snum
))
7318 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7319 if (!W_ERROR_IS_OK(status
))
7323 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
7324 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
7325 status
= WERR_ACCESS_DENIED
;
7329 /* can't set if builtin */
7330 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
7331 status
= WERR_INVALID_PARAM
;
7335 count
= get_ntforms(&list
);
7336 update_a_form(&list
, form
, count
);
7337 write_ntforms(&list
, count
);
7340 * ChangeID must always be set if this is a printer
7343 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
7344 status
= mod_a_printer(*printer
, 2);
7349 free_a_printer(&printer
, 2);
7355 /****************************************************************************
7356 enumprintprocessors level 1.
7357 ****************************************************************************/
7359 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7361 PRINTPROCESSOR_1
*info_1
=NULL
;
7363 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
7368 init_unistr(&info_1
->name
, "winprint");
7370 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
7372 if (!alloc_buffer_size(buffer
, *needed
))
7373 return WERR_INSUFFICIENT_BUFFER
;
7375 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
7379 if (*needed
> offered
) {
7381 return WERR_INSUFFICIENT_BUFFER
;
7387 /****************************************************************************
7388 ****************************************************************************/
7390 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
7392 /* UNISTR2 *name = &q_u->name; - notused. */
7393 /* UNISTR2 *environment = &q_u->environment; - notused. */
7394 uint32 level
= q_u
->level
;
7395 NEW_BUFFER
*buffer
= NULL
;
7396 uint32 offered
= q_u
->offered
;
7397 uint32
*needed
= &r_u
->needed
;
7398 uint32
*returned
= &r_u
->returned
;
7400 /* that's an [in out] buffer */
7401 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7402 buffer
= r_u
->buffer
;
7404 DEBUG(5,("spoolss_enumprintprocessors\n"));
7407 * Enumerate the print processors ...
7409 * Just reply with "winprint", to keep NT happy
7410 * and I can use my nice printer checker.
7418 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
7420 return WERR_UNKNOWN_LEVEL
;
7424 /****************************************************************************
7425 enumprintprocdatatypes level 1.
7426 ****************************************************************************/
7428 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7430 PRINTPROCDATATYPE_1
*info_1
=NULL
;
7432 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
7437 init_unistr(&info_1
->name
, "RAW");
7439 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
7441 if (!alloc_buffer_size(buffer
, *needed
))
7442 return WERR_INSUFFICIENT_BUFFER
;
7444 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
7448 if (*needed
> offered
) {
7450 return WERR_INSUFFICIENT_BUFFER
;
7456 /****************************************************************************
7457 ****************************************************************************/
7459 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
7461 /* UNISTR2 *name = &q_u->name; - notused. */
7462 /* UNISTR2 *processor = &q_u->processor; - notused. */
7463 uint32 level
= q_u
->level
;
7464 NEW_BUFFER
*buffer
= NULL
;
7465 uint32 offered
= q_u
->offered
;
7466 uint32
*needed
= &r_u
->needed
;
7467 uint32
*returned
= &r_u
->returned
;
7469 /* that's an [in out] buffer */
7470 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7471 buffer
= r_u
->buffer
;
7473 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
7480 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
7482 return WERR_UNKNOWN_LEVEL
;
7486 /****************************************************************************
7487 enumprintmonitors level 1.
7488 ****************************************************************************/
7490 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7492 PRINTMONITOR_1
*info_1
=NULL
;
7494 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
7499 init_unistr(&info_1
->name
, "Local Port");
7501 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
7503 if (!alloc_buffer_size(buffer
, *needed
))
7504 return WERR_INSUFFICIENT_BUFFER
;
7506 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
7510 if (*needed
> offered
) {
7512 return WERR_INSUFFICIENT_BUFFER
;
7518 /****************************************************************************
7519 enumprintmonitors level 2.
7520 ****************************************************************************/
7522 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7524 PRINTMONITOR_2
*info_2
=NULL
;
7526 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
7531 init_unistr(&info_2
->name
, "Local Port");
7532 init_unistr(&info_2
->environment
, "Windows NT X86");
7533 init_unistr(&info_2
->dll_name
, "localmon.dll");
7535 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
7537 if (!alloc_buffer_size(buffer
, *needed
))
7538 return WERR_INSUFFICIENT_BUFFER
;
7540 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
7544 if (*needed
> offered
) {
7546 return WERR_INSUFFICIENT_BUFFER
;
7552 /****************************************************************************
7553 ****************************************************************************/
7555 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
7557 /* UNISTR2 *name = &q_u->name; - notused. */
7558 uint32 level
= q_u
->level
;
7559 NEW_BUFFER
*buffer
= NULL
;
7560 uint32 offered
= q_u
->offered
;
7561 uint32
*needed
= &r_u
->needed
;
7562 uint32
*returned
= &r_u
->returned
;
7564 /* that's an [in out] buffer */
7565 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7566 buffer
= r_u
->buffer
;
7568 DEBUG(5,("spoolss_enumprintmonitors\n"));
7571 * Enumerate the print monitors ...
7573 * Just reply with "Local Port", to keep NT happy
7574 * and I can use my nice printer checker.
7582 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
7584 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
7586 return WERR_UNKNOWN_LEVEL
;
7590 /****************************************************************************
7591 ****************************************************************************/
7593 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7597 JOB_INFO_1
*info_1
=NULL
;
7599 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
7601 if (info_1
== NULL
) {
7606 for (i
=0; i
<count
&& found
==False
; i
++) {
7607 if (queue
[i
].job
==(int)jobid
)
7614 /* NT treats not found as bad param... yet another bad choice */
7615 return WERR_INVALID_PARAM
;
7618 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
7622 *needed
+= spoolss_size_job_info_1(info_1
);
7624 if (!alloc_buffer_size(buffer
, *needed
)) {
7626 return WERR_INSUFFICIENT_BUFFER
;
7629 smb_io_job_info_1("", buffer
, info_1
, 0);
7633 if (*needed
> offered
)
7634 return WERR_INSUFFICIENT_BUFFER
;
7639 /****************************************************************************
7640 ****************************************************************************/
7642 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7647 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
7649 DEVICEMODE
*devmode
= NULL
;
7651 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
7653 ZERO_STRUCTP(info_2
);
7655 if (info_2
== NULL
) {
7660 for (i
=0; i
<count
&& found
==False
; i
++) {
7661 if (queue
[i
].job
==(int)jobid
)
7666 /* NT treats not found as bad param... yet another bad
7668 ret
= WERR_INVALID_PARAM
;
7672 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
7673 if (!W_ERROR_IS_OK(ret
))
7676 /* not a failure condition if devmode == NULL */
7678 construct_dev_mode(snum
);
7680 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
, devmode
);
7682 *needed
+= spoolss_size_job_info_2(info_2
);
7684 if (!alloc_buffer_size(buffer
, *needed
)) {
7685 ret
= WERR_INSUFFICIENT_BUFFER
;
7689 smb_io_job_info_2("", buffer
, info_2
, 0);
7691 if (*needed
> offered
) {
7692 ret
= WERR_INSUFFICIENT_BUFFER
;
7699 /* Cleanup allocated memory */
7702 free_job_info_2(info_2
); /* Also frees devmode */
7704 free_a_printer(&ntprinter
, 2);
7709 /****************************************************************************
7710 ****************************************************************************/
7712 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
7714 POLICY_HND
*handle
= &q_u
->handle
;
7715 uint32 jobid
= q_u
->jobid
;
7716 uint32 level
= q_u
->level
;
7717 NEW_BUFFER
*buffer
= NULL
;
7718 uint32 offered
= q_u
->offered
;
7719 uint32
*needed
= &r_u
->needed
;
7723 print_queue_struct
*queue
=NULL
;
7724 print_status_struct prt_status
;
7726 /* that's an [in out] buffer */
7727 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7728 buffer
= r_u
->buffer
;
7730 DEBUG(5,("spoolss_getjob\n"));
7734 if (!get_printer_snum(p
, handle
, &snum
))
7737 count
= print_queue_status(snum
, &queue
, &prt_status
);
7739 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
7740 count
, prt_status
.status
, prt_status
.message
));
7744 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7746 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
7749 return WERR_UNKNOWN_LEVEL
;
7753 /********************************************************************
7754 * spoolss_getprinterdataex
7755 ********************************************************************/
7757 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
7759 POLICY_HND
*handle
= &q_u
->handle
;
7760 uint32 in_size
= q_u
->size
;
7761 uint32
*type
= &r_u
->type
;
7762 uint32
*out_size
= &r_u
->size
;
7763 uint8
**data
= &r_u
->data
;
7764 uint32
*needed
= &r_u
->needed
;
7767 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7770 DEBUG(4,("_spoolss_getprinterdataex\n"));
7772 unistr2_to_dos(key
, &q_u
->keyname
, sizeof(key
) - 1);
7773 unistr2_to_dos(value
, &q_u
->valuename
, sizeof(value
) - 1);
7775 /* in case of problem, return some default values */
7782 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
7784 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7789 /* Is the handle to a printer or to the server? */
7791 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
7793 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
7794 return WERR_INVALID_PARAM
;
7799 * From MSDN documentation of GetPrinterDataEx: pass request
7800 * to GetPrinterData if key is "PrinterDriverData". This is
7801 * the only key we really support. Other keys to implement:
7807 if (strcmp(key
, "PrinterDriverData") != 0)
7808 return WERR_BADFILE
;
7810 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
7811 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
7812 type
, data
, needed
, in_size
);
7817 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
7819 /* reply this param doesn't exist */
7821 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
7827 return WERR_INVALID_PARAM
;
7830 if (*needed
> *out_size
)
7831 return WERR_MORE_DATA
;
7836 /********************************************************************
7837 * spoolss_setprinterdata
7838 ********************************************************************/
7840 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
7842 SPOOL_Q_SETPRINTERDATA q_u_local
;
7843 SPOOL_R_SETPRINTERDATA r_u_local
;
7846 DEBUG(4,("_spoolss_setprinterdataex\n"));
7848 /* From MSDN documentation of SetPrinterDataEx: pass request to
7849 SetPrinterData if key is "PrinterDriverData" */
7851 unistr2_to_dos(key
, &q_u
->key
, sizeof(key
) - 1);
7853 if (strcmp(key
, "PrinterDriverData") != 0)
7854 return WERR_INVALID_PARAM
;
7856 ZERO_STRUCT(q_u_local
);
7857 ZERO_STRUCT(r_u_local
);
7859 /* make a copy to call _spoolss_setprinterdata() */
7861 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
7862 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
7863 q_u_local
.type
= q_u
->type
;
7864 q_u_local
.max_len
= q_u
->max_len
;
7865 q_u_local
.data
= q_u
->data
;
7866 q_u_local
.real_len
= q_u
->real_len
;
7867 q_u_local
.numeric_data
= q_u
->numeric_data
;
7869 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
7872 /********************************************************************
7873 * spoolss_enumprinterkey
7874 ********************************************************************/
7876 /* constants for EnumPrinterKey() */
7877 #define ENUMERATED_KEY_SIZE 19
7879 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
7882 uint16 enumkeys
[ENUMERATED_KEY_SIZE
+1];
7887 DEBUG(4,("_spoolss_enumprinterkey\n"));
7889 unistr2_to_dos(key
, &q_u
->key
, sizeof(key
) - 1);
7891 ZERO_STRUCTP(PrinterKey
);
7892 fstrcpy( PrinterKey
, "PrinterDriverData" );
7894 /* add space for 2 terminating NULLs */
7896 enum_key_len
= strlen( PrinterKey
) + 2;
7900 * we only support enumating all keys (key == "")
7901 * Of course, the only key we support is the "PrinterDriverData"
7904 if (strlen(key
) == 0)
7906 r_u
->needed
= enum_key_len
*2;
7907 if (q_u
->size
< r_u
->needed
)
7908 return WERR_MORE_DATA
;
7910 init_unistr2( &uni_keys
, PrinterKey
, enum_key_len
);
7912 if ( !make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, enum_key_len
, uni_keys
.buffer
) )
7913 return WERR_BADFILE
;
7918 /* The "PrinterDriverData" key should have no subkeys */
7919 if (strcmp(key
, PrinterKey
) == 0)
7922 if (q_u
->size
< r_u
->needed
)
7923 return WERR_MORE_DATA
;
7925 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, enumkeys
))
7926 return WERR_BADFILE
;
7932 /* The return value for an unknown key is documented in MSDN
7933 EnumPrinterKey description */
7934 return WERR_BADFILE
;
7937 /********************************************************************
7938 * spoolss_enumprinterdataex
7939 ********************************************************************/
7941 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
7943 POLICY_HND
*handle
= &q_u
->handle
;
7944 uint32 in_size
= q_u
->size
;
7947 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7948 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
7950 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7959 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7962 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
7968 * The only key we support is "PrinterDriverData". This should return
7969 > an array of all the key/value pairs returned by EnumPrinterDataSee
7970 * _spoolss_getprinterdataex() for details --jerry
7973 unistr2_to_dos(key
, &q_u
->key
, sizeof(key
) - 1);
7974 if (strcmp(key
, "PrinterDriverData") != 0)
7976 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
7977 return WERR_INVALID_PARAM
;
7981 if (!get_printer_snum(p
,handle
, &snum
))
7984 ZERO_STRUCT(printer
);
7985 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7986 if (!W_ERROR_IS_OK(result
))
7991 * loop through all params and build the array to pass
7992 * back to the client
7999 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
))
8001 PRINTER_ENUM_VALUES
*ptr
;
8003 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries
, value
));
8005 if ((ptr
=talloc_realloc(p
->mem_ctx
, enum_values
, (num_entries
+1) * sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
8007 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
8008 result
= WERR_NOMEM
;
8013 ZERO_STRUCTP( &enum_values
[num_entries
] );
8017 init_unistr(&enum_values
[num_entries
].valuename
, value
);
8018 enum_values
[num_entries
].value_len
= (strlen(value
)+1) * 2;
8019 enum_values
[num_entries
].type
= type
;
8023 if ( !(enum_values
[num_entries
].data
= talloc_zero(p
->mem_ctx
, data_len
)) ) {
8024 DEBUG(0,("talloc_realloc failed to allocate more memory [data_len=%d] for data!\n", data_len
));
8025 result
= WERR_NOMEM
;
8028 memcpy(enum_values
[num_entries
].data
, data
, data_len
);
8031 enum_values
[num_entries
].data_len
= data_len
;
8033 /* keep track of the size of the array in bytes */
8035 needed
+= spoolss_size_printer_enum_values(&enum_values
[num_entries
]);
8041 r_u
->needed
= needed
;
8042 r_u
->returned
= num_entries
;
8044 if (needed
> in_size
) {
8045 result
= WERR_MORE_DATA
;
8049 /* copy data into the reply */
8051 r_u
->ctr
.size
= r_u
->needed
;
8052 r_u
->ctr
.size_of_array
= r_u
->returned
;
8053 r_u
->ctr
.values
= enum_values
;
8058 free_a_printer(&printer
, 2);
8063 /****************************************************************************
8064 ****************************************************************************/
8066 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
8068 init_unistr(&info
->name
, name
);
8071 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
8072 UNISTR2
*environment
,
8079 pstring short_archi
;
8080 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
8082 unistr2_to_dos(long_archi
, environment
, sizeof(long_archi
)-1);
8084 if (get_short_archi(short_archi
, long_archi
)==False
)
8085 return WERR_INVALID_ENVIRONMENT
;
8087 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
8090 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
8092 fill_printprocessordirectory_1(info
, path
);
8094 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
8096 if (!alloc_buffer_size(buffer
, *needed
)) {
8098 return WERR_INSUFFICIENT_BUFFER
;
8101 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
8105 if (*needed
> offered
)
8106 return WERR_INSUFFICIENT_BUFFER
;
8111 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
8113 uint32 level
= q_u
->level
;
8114 NEW_BUFFER
*buffer
= NULL
;
8115 uint32 offered
= q_u
->offered
;
8116 uint32
*needed
= &r_u
->needed
;
8119 /* that's an [in out] buffer */
8120 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8121 buffer
= r_u
->buffer
;
8123 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
8129 result
= getprintprocessordirectory_level_1
8130 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
8133 result
= WERR_UNKNOWN_LEVEL
;