2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
8 * Copyright (C) Jeremy Allison 2001.
9 * Copyright (C) Gerald Carter 2000-2001.
10 * Copyright (C) Tim Potter 2001.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #ifndef MAX_OPEN_PRINTER_EXS
33 #define MAX_OPEN_PRINTER_EXS 50
36 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
37 #define PRINTER_HANDLE_IS_PRINTER 0
38 #define PRINTER_HANDLE_IS_PRINTSERVER 1
47 /* structure to store the printer handles */
48 /* and a reference to what it's pointing to */
49 /* and the notify info asked about */
50 /* that's the central struct */
51 typedef struct _Printer
{
52 BOOL document_started
;
54 int jobid
; /* jobid in printing backend */
58 fstring printerservername
;
67 SPOOL_NOTIFY_OPTION
*option
;
68 POLICY_HND client_hnd
;
69 uint32 client_connected
;
77 typedef struct _counter_printer_0
{
85 static ubi_dlList counter_list
;
87 static struct cli_state cli
;
88 static uint32 smb_connections
=0;
90 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
92 /* translate between internal status numbers and NT status numbers */
93 static int nt_printj_status(int v
)
99 return JOB_STATUS_PAUSED
;
101 return JOB_STATUS_SPOOLING
;
103 return JOB_STATUS_PRINTING
;
105 return JOB_STATUS_ERROR
;
107 return JOB_STATUS_DELETING
;
109 return JOB_STATUS_OFFLINE
;
111 return JOB_STATUS_PAPEROUT
;
113 return JOB_STATUS_PRINTED
;
115 return JOB_STATUS_DELETED
;
117 return JOB_STATUS_BLOCKED
;
118 case LPQ_USER_INTERVENTION
:
119 return JOB_STATUS_USER_INTERVENTION
;
124 static int nt_printq_status(int v
)
128 return PRINTER_STATUS_PAUSED
;
137 /****************************************************************************
138 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
139 ****************************************************************************/
141 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
146 SAFE_FREE((*pp
)->ctr
.type
);
150 /***************************************************************************
151 Disconnect from the client
152 ****************************************************************************/
154 static void srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
158 /* weird if the test succeds !!! */
159 if (smb_connections
==0) {
160 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
164 if(!cli_spoolss_reply_close_printer(&cli
, handle
, &status
))
165 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections
==1) {
169 if(!spoolss_disconnect_from_client(&cli
))
172 message_deregister(MSG_PRINTER_NOTIFY
);
178 /****************************************************************************
179 Functions to free a printer entry datastruct.
180 ****************************************************************************/
182 static void free_printer_entry(void *ptr
)
184 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
186 if (Printer
->notify
.client_connected
==True
)
187 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
189 Printer
->notify
.flags
=0;
190 Printer
->notify
.options
=0;
191 Printer
->notify
.localmachine
[0]='\0';
192 Printer
->notify
.printerlocal
=0;
193 free_spool_notify_option(&Printer
->notify
.option
);
194 Printer
->notify
.option
=NULL
;
195 Printer
->notify
.client_connected
=False
;
200 /****************************************************************************
201 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
202 ****************************************************************************/
204 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
206 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
211 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
218 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
220 if (!new_sp
->ctr
.type
) {
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
235 Printer_entry
*find_printer
= NULL
;
237 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
238 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
245 /****************************************************************************
246 close printer index by handle
247 ****************************************************************************/
249 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
251 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
254 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
258 close_policy_hnd(p
, hnd
);
263 /****************************************************************************
264 delete a printer given a handle
265 ****************************************************************************/
266 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
268 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
271 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
275 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
276 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
280 /* Check calling user has permission to delete printer. Note that
281 since we set the snum parameter to -1 only administrators can
282 delete the printer. This stops people with the Full Control
283 permission from deleting the printer. */
285 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
286 DEBUG(3, ("printer delete denied by security descriptor\n"));
287 return WERR_ACCESS_DENIED
;
290 if (*lp_deleteprinter_cmd()) {
292 char *cmd
= lp_deleteprinter_cmd();
297 /* Printer->dev.handlename equals portname equals sharename */
298 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
299 Printer
->dev
.handlename
);
301 DEBUG(10,("Running [%s]\n", command
));
302 ret
= smbrun(command
, NULL
);
304 return WERR_BADFID
; /* What to return here? */
306 DEBUGADD(10,("returned [%d]\n", ret
));
308 /* Send SIGHUP to process group... is there a better way? */
311 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) >= 0 ) {
315 return WERR_ACCESS_DENIED
;
321 /****************************************************************************
322 return the snum of a printer corresponding to an handle
323 ****************************************************************************/
324 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
326 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
329 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
333 switch (Printer
->printer_type
) {
334 case PRINTER_HANDLE_IS_PRINTER
:
335 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
336 *number
= print_queue_snum(Printer
->dev
.handlename
);
337 return (*number
!= -1);
338 case PRINTER_HANDLE_IS_PRINTSERVER
:
345 /****************************************************************************
346 set printer handle type.
347 ****************************************************************************/
348 static BOOL
set_printer_hnd_accesstype(pipes_struct
*p
, POLICY_HND
*hnd
, uint32 access_required
)
350 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
353 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd
)));
357 DEBUG(4,("Setting printer access=%x\n", access_required
));
358 Printer
->access
= access_required
;
362 /****************************************************************************
363 Set printer handle type.
364 Check if it's \\server or \\server\printer
365 ****************************************************************************/
367 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
369 DEBUG(3,("Setting printer type=%s\n", handlename
));
371 if ( strlen(handlename
) < 3 ) {
372 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
376 /* it's a print server */
377 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
378 DEBUGADD(4,("Printer is a print server\n"));
379 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
383 DEBUGADD(4,("Printer is a printer\n"));
384 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
390 /****************************************************************************
391 Set printer handle name.
392 ****************************************************************************/
394 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
396 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
398 int n_services
=lp_numservices();
402 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
404 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
405 ZERO_STRUCT(Printer
->dev
.printerservername
);
406 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
410 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
413 if (*handlename
=='\\') {
414 aprinter
=strchr_m(handlename
+2, '\\');
421 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
424 * store the Samba share name in it
425 * in back we have the long printer name
426 * need to iterate all the snum and do a
427 * get_a_printer each time to find the printer
428 * faster to do it here than later.
431 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
434 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
437 DEBUGADD(5,("share:%s\n",lp_servicename(snum
)));
439 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
442 printername
=strchr_m(printer
->info_2
->printername
+2, '\\');
445 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
446 printer
->info_2
->printername
, aprinter
));
448 if ( strlen(printername
) != strlen(aprinter
) ) {
449 free_a_printer(&printer
, 2);
453 if ( strncasecmp(printername
, aprinter
, strlen(aprinter
))) {
454 free_a_printer(&printer
, 2);
462 * if we haven't found a printer with the given handlename
463 * then it can be a share name as you can open both \\server\printer and
468 * we still check if the printer description file exists as NT won't be happy
469 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
473 DEBUGADD(5,("Printer not found, checking for share now\n"));
475 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
477 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
480 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum
)));
482 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
485 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
486 printer
->info_2
->printername
, aprinter
));
488 if ( strlen(lp_servicename(snum
)) != strlen(aprinter
) ) {
489 free_a_printer(&printer
, 2);
493 if ( strncasecmp(lp_servicename(snum
), aprinter
, strlen(aprinter
))) {
494 free_a_printer(&printer
, 2);
503 DEBUGADD(4,("Printer not found\n"));
508 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
509 printer
->info_2
->printername
, lp_servicename(snum
),snum
));
511 ZERO_STRUCT(Printer
->dev
.handlename
);
512 strncpy(Printer
->dev
.handlename
, lp_servicename(snum
), strlen(lp_servicename(snum
)));
514 free_a_printer(&printer
, 2);
519 /****************************************************************************
520 find first available printer slot. creates a printer handle for you.
521 ****************************************************************************/
523 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
)
525 Printer_entry
*new_printer
;
527 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
529 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
532 ZERO_STRUCTP(new_printer
);
534 new_printer
->notify
.option
=NULL
;
536 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
537 SAFE_FREE(new_printer
);
541 if (!set_printer_hnd_printertype(new_printer
, name
)) {
542 close_printer_handle(p
, hnd
);
546 if (!set_printer_hnd_name(new_printer
, name
)) {
547 close_printer_handle(p
, hnd
);
551 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
556 /********************************************************************
557 Return True is the handle is a print server.
558 ********************************************************************/
560 static BOOL
handle_is_printserver(pipes_struct
*p
, POLICY_HND
*handle
)
562 Printer_entry
*Printer
=find_printer_index_by_hnd(p
,handle
);
567 if (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
573 /****************************************************************************
574 allocate more memory for a BUFFER.
575 ****************************************************************************/
576 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
584 /* damn, I'm doing the reverse operation of prs_grow() :) */
585 if (buffer_size
< prs_data_size(ps
))
588 extra_space
= buffer_size
- prs_data_size(ps
);
591 * save the offset and move to the end of the buffer
592 * prs_grow() checks the extra_space against the offset
594 old_offset
=prs_offset(ps
);
595 prs_set_offset(ps
, prs_data_size(ps
));
597 if (!prs_grow(ps
, extra_space
))
600 prs_set_offset(ps
, old_offset
);
602 buffer
->string_at_end
=prs_data_size(ps
);
607 /***************************************************************************
608 receive the notify message
609 ****************************************************************************/
611 static void srv_spoolss_receive_message(int msg_type
, pid_t src
, void *buf
, size_t len
)
615 struct pipes_struct
*p
;
617 struct handle_list
*hl
;
620 fstrcpy(printer
,buf
);
623 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
627 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer
));
630 * We need to enumerate all printers. The handle list is shared
631 * across pipes of the same name, so just find the first open
636 for ( p
= get_first_internal_pipe(); p
; get_next_internal_pipe(p
)) {
637 if (strequal(p
->name
, "spoolss")) {
638 hl
= p
->pipe_handles
;
644 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
648 /* Iterate the printer list on this pipe. */
649 for (pol
= hl
->Policy
; pol
; pol
= pol
->next
) {
650 Printer_entry
*find_printer
= (Printer_entry
*)pol
->data_ptr
;
656 * if the entry is the given printer or if it's a printerserver
657 * we send the message
660 if (find_printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
661 if (strcmp(find_printer
->dev
.handlename
, printer
))
664 if (find_printer
->notify
.client_connected
==True
)
665 cli_spoolss_reply_rrpcn(&cli
, &find_printer
->notify
.client_hnd
, PRINTER_CHANGE_ALL
, 0x0, &status
);
669 /***************************************************************************
671 ****************************************************************************/
672 static BOOL
srv_spoolss_sendnotify(pipes_struct
*p
, POLICY_HND
*handle
)
676 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
679 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
683 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
684 fstrcpy(printer
, Printer
->dev
.handlename
);
686 fstrcpy(printer
, "");
688 /*srv_spoolss_receive_message(printer);*/
689 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer
));
691 broadcast_printer_notify(printer
);
696 /********************************************************************
697 * spoolss_open_printer
699 * called from the spoolss dispatcher
700 ********************************************************************/
702 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
705 WERROR result
= WERR_OK
;
708 UNISTR2
*printername
= NULL
;
709 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
710 /* uint32 user_switch = q_u->user_switch; - notused */
711 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
712 POLICY_HND
*handle
= &r_u
->handle
;
716 struct current_user user
;
718 if (q_u
->printername_ptr
!= 0)
719 printername
= &q_u
->printername
;
721 if (printername
== NULL
)
722 return WERR_INVALID_PRINTER_NAME
;
724 /* some sanity check because you can open a printer or a print server */
725 /* aka: \\server\printer or \\server */
726 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
728 DEBUGADD(3,("checking name: %s\n",name
));
730 if (!open_printer_hnd(p
, handle
, name
))
731 return WERR_INVALID_PRINTER_NAME
;
734 if (printer_default->datatype_ptr != NULL)
736 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
737 set_printer_hnd_datatype(handle, datatype);
740 set_printer_hnd_datatype(handle, "");
743 if (!set_printer_hnd_accesstype(p
, handle
, printer_default
->access_required
)) {
744 close_printer_handle(p
, handle
);
745 return WERR_ACCESS_DENIED
;
749 First case: the user is opening the print server:
751 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
752 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
754 Then both Win2k and WinNT clients try an OpenPrinterEx with
755 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
756 or if the user is listed in the smb.conf printer admin parameter.
758 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
759 client view printer folder, but does not show the MSAPW.
761 Note: this test needs code to check access rights here too. Jeremy
762 could you look at this?
765 Second case: the user is opening a printer:
766 NT doesn't let us connect to a printer if the connecting user
767 doesn't have print permission.
771 get_current_user(&user
, p
);
773 if (handle_is_printserver(p
, handle
)) {
774 if (printer_default
->access_required
== 0) {
777 else if ((printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
) == SERVER_ACCESS_ADMINISTER
) {
779 /* Printserver handles use global struct... */
782 if (!lp_ms_add_printer_wizard()) {
783 close_printer_handle(p
, handle
);
784 return WERR_ACCESS_DENIED
;
786 else if (user
.uid
== 0 || user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
))) {
790 close_printer_handle(p
, handle
);
791 return WERR_ACCESS_DENIED
;
797 /* NT doesn't let us connect to a printer if the connecting user
798 doesn't have print permission. */
800 if (!get_printer_snum(p
, handle
, &snum
))
803 /* map an empty access mask to the minimum access mask */
804 if (printer_default
->access_required
== 0x0)
805 printer_default
->access_required
= PRINTER_ACCESS_USE
;
809 * If we are not serving the printer driver for this printer,
810 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
811 * will keep NT clients happy --jerry
814 if (lp_use_client_driver(snum
)
815 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
817 printer_default
->access_required
= PRINTER_ACCESS_USE
;
820 if (!print_access_check(&user
, snum
, printer_default
->access_required
)) {
821 DEBUG(3, ("access DENIED for printer open\n"));
822 close_printer_handle(p
, handle
);
823 return WERR_ACCESS_DENIED
;
827 * If we have a default device pointer in the
828 * printer_default struct, then we need to get
829 * the printer info from the tdb and if there is
830 * no default devicemode there then we do a *SET*
831 * here ! This is insanity.... JRA.
835 * If the openprinterex rpc call contains a devmode,
836 * it's a per-user one. This per-user devmode is derivated
837 * from the global devmode. Openprinterex() contains a per-user
838 * devmode for when you do EMF printing and spooling.
839 * In the EMF case, the NT workstation is only doing half the job
840 * of rendering the page. The other half is done by running the printer
841 * driver on the server.
842 * The EMF file doesn't contain the page description (paper size, orientation, ...).
843 * The EMF file only contains what is to be printed on the page.
844 * So in order for the server to know how to print, the NT client sends
845 * a devicemode attached to the openprinterex call.
846 * But this devicemode is short lived, it's only valid for the current print job.
848 * If Samba would have supported EMF spooling, this devicemode would
849 * have been attached to the handle, to sent it to the driver to correctly
850 * rasterize the EMF file.
852 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
853 * we just act as a pass-thru between windows and the printer.
855 * In order to know that Samba supports only RAW spooling, NT has to call
856 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
857 * and until NT sends a RAW job, we refuse it.
859 * But to call getprinter() or startdoc(), you first need a valid handle,
860 * and to get an handle you have to call openprintex(). Hence why you have
861 * a devicemode in the openprinterex() call.
864 * Differences between NT4 and NT 2000.
867 * On NT4, you only have a global devicemode. This global devicemode can be changed
868 * by the administrator (or by a user with enough privs). Everytime a user
869 * wants to print, the devicemode is resetted to the default. In Word, everytime
870 * you print, the printer's characteristics are always reset to the global devicemode.
874 * In W2K, there is the notion of per-user devicemode. The first time you use
875 * a printer, a per-user devicemode is build from the global devicemode.
876 * If you change your per-user devicemode, it is saved in the registry, under the
877 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
878 * printer preferences available.
880 * To change the per-user devicemode: it's the "Printing Preferences ..." button
881 * on the General Tab of the printer properties windows.
883 * To change the global devicemode: it's the "Printing Defaults..." button
884 * on the Advanced Tab of the printer properties window.
892 if (printer_default
->devmode_cont
.devmode
!= NULL
) {
893 result
= printer_write_default_dev( snum
, printer_default
);
895 close_printer_handle(p
, handle
);
905 /****************************************************************************
906 ****************************************************************************/
907 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
908 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
914 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
923 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
924 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
930 printer
->info_3
=NULL
;
931 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
935 printer
->info_6
=NULL
;
936 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
946 BOOL
convert_devicemode(char *printername
, const DEVICEMODE
*devmode
,
947 NT_DEVICEMODE
**pp_nt_devmode
)
949 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
952 * Ensure nt_devmode is a valid pointer
953 * as we will be overwriting it.
956 if (nt_devmode
== NULL
) {
957 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
958 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
962 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
963 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
965 nt_devmode
->specversion
=devmode
->specversion
;
966 nt_devmode
->driverversion
=devmode
->driverversion
;
967 nt_devmode
->size
=devmode
->size
;
968 nt_devmode
->fields
=devmode
->fields
;
969 nt_devmode
->orientation
=devmode
->orientation
;
970 nt_devmode
->papersize
=devmode
->papersize
;
971 nt_devmode
->paperlength
=devmode
->paperlength
;
972 nt_devmode
->paperwidth
=devmode
->paperwidth
;
973 nt_devmode
->scale
=devmode
->scale
;
974 nt_devmode
->copies
=devmode
->copies
;
975 nt_devmode
->defaultsource
=devmode
->defaultsource
;
976 nt_devmode
->printquality
=devmode
->printquality
;
977 nt_devmode
->color
=devmode
->color
;
978 nt_devmode
->duplex
=devmode
->duplex
;
979 nt_devmode
->yresolution
=devmode
->yresolution
;
980 nt_devmode
->ttoption
=devmode
->ttoption
;
981 nt_devmode
->collate
=devmode
->collate
;
983 nt_devmode
->logpixels
=devmode
->logpixels
;
984 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
985 nt_devmode
->pelswidth
=devmode
->pelswidth
;
986 nt_devmode
->pelsheight
=devmode
->pelsheight
;
987 nt_devmode
->displayflags
=devmode
->displayflags
;
988 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
989 nt_devmode
->icmmethod
=devmode
->icmmethod
;
990 nt_devmode
->icmintent
=devmode
->icmintent
;
991 nt_devmode
->mediatype
=devmode
->mediatype
;
992 nt_devmode
->dithertype
=devmode
->dithertype
;
993 nt_devmode
->reserved1
=devmode
->reserved1
;
994 nt_devmode
->reserved2
=devmode
->reserved2
;
995 nt_devmode
->panningwidth
=devmode
->panningwidth
;
996 nt_devmode
->panningheight
=devmode
->panningheight
;
999 * Only change private and driverextra if the incoming devmode
1000 * has a new one. JRA.
1003 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1004 SAFE_FREE(nt_devmode
->private);
1005 nt_devmode
->driverextra
=devmode
->driverextra
;
1006 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1008 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1011 *pp_nt_devmode
= nt_devmode
;
1016 /********************************************************************
1017 * _spoolss_enddocprinter_internal.
1018 ********************************************************************/
1020 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1022 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1025 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
1029 Printer
->document_started
=False
;
1030 print_job_end(Printer
->jobid
,True
);
1031 /* error codes unhandled so far ... */
1036 /********************************************************************
1037 * api_spoolss_closeprinter
1038 ********************************************************************/
1040 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1042 POLICY_HND
*handle
= &q_u
->handle
;
1044 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1046 if (Printer
&& Printer
->document_started
)
1047 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1049 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1051 if (!close_printer_handle(p
, handle
))
1057 /********************************************************************
1058 * api_spoolss_deleteprinter
1060 ********************************************************************/
1062 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1064 POLICY_HND
*handle
= &q_u
->handle
;
1065 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1068 if (Printer
&& Printer
->document_started
)
1069 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1071 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1073 result
= delete_printer_handle(p
, handle
);
1075 if (W_ERROR_IS_OK(result
)) {
1076 srv_spoolss_sendnotify(p
, handle
);
1082 /*******************************************************************
1083 * static function to lookup the version id corresponding to an
1084 * long architecture string
1085 ******************************************************************/
1086 static int get_version_id (char * arch
)
1089 struct table_node archi_table
[]= {
1091 {"Windows 4.0", "WIN40", 0 },
1092 {"Windows NT x86", "W32X86", 2 },
1093 {"Windows NT R4000", "W32MIPS", 2 },
1094 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1095 {"Windows NT PowerPC", "W32PPC", 2 },
1099 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1101 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1102 return (archi_table
[i
].version
);
1108 /********************************************************************
1109 * _spoolss_deleteprinterdriver
1111 * We currently delete the driver for the architecture only.
1112 * This can leave the driver for other archtectures. However,
1113 * since every printer associates a "Windows NT x86" driver name
1114 * and we cannot delete that one while it is in use, **and** since
1115 * it is impossible to assign a driver to a Samba printer without
1116 * having the "Windows NT x86" driver installed,...
1118 * ....we should not get into trouble here.
1121 ********************************************************************/
1123 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
,
1124 SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1128 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1131 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1132 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1134 /* check that we have a valid driver name first */
1135 if ((version
=get_version_id(arch
)) == -1) {
1136 /* this is what NT returns */
1137 return WERR_INVALID_ENVIRONMENT
;
1141 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1142 return WERR_UNKNOWN_PRINTER_DRIVER
;
1146 if (printer_driver_in_use(arch
, driver
))
1148 return WERR_PRINTER_DRIVER_IN_USE
;
1151 return delete_printer_driver(info
.info_3
);
1155 /********************************************************************
1156 GetPrinterData on a printer server Handle.
1157 ********************************************************************/
1158 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1162 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1164 if (!strcmp(value
, "BeepEnabled")) {
1166 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1168 SIVAL(*data
, 0, 0x01);
1173 if (!strcmp(value
, "EventLog")) {
1175 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1177 SIVAL(*data
, 0, 0x1B);
1182 if (!strcmp(value
, "NetPopup")) {
1184 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1186 SIVAL(*data
, 0, 0x01);
1191 if (!strcmp(value
, "MajorVersion")) {
1193 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1195 SIVAL(*data
, 0, 0x02);
1200 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1201 pstring string
="You are using a Samba server";
1203 *needed
= 2*(strlen(string
)+1);
1204 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1206 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1208 /* it's done by hand ready to go on the wire */
1209 for (i
=0; i
<strlen(string
); i
++) {
1210 (*data
)[2*i
]=string
[i
];
1211 (*data
)[2*i
+1]='\0';
1216 if (!strcmp(value
, "Architecture")) {
1217 pstring string
="Windows NT x86";
1219 *needed
= 2*(strlen(string
)+1);
1220 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1222 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1223 for (i
=0; i
<strlen(string
); i
++) {
1224 (*data
)[2*i
]=string
[i
];
1225 (*data
)[2*i
+1]='\0';
1233 /********************************************************************
1234 GetPrinterData on a printer Handle.
1235 ********************************************************************/
1236 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1237 fstring value
, uint32
*type
,
1238 uint8
**data
, uint32
*needed
, uint32 in_size
)
1240 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1244 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1246 DEBUG(5,("getprinterdata_printer\n"));
1249 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1253 if(!get_printer_snum(p
, handle
, &snum
))
1256 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
1259 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
1260 free_a_printer(&printer
, 2);
1264 free_a_printer(&printer
, 2);
1266 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1269 if((*data
= (uint8
*)talloc(ctx
, in_size
*sizeof(uint8
) )) == NULL
) {
1273 memset(*data
, 0, in_size
*sizeof(uint8
));
1274 /* copy the min(in_size, len) */
1275 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
1282 DEBUG(5,("getprinterdata_printer:copy done\n"));
1289 /********************************************************************
1290 * spoolss_getprinterdata
1291 ********************************************************************/
1293 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1295 POLICY_HND
*handle
= &q_u
->handle
;
1296 UNISTR2
*valuename
= &q_u
->valuename
;
1297 uint32 in_size
= q_u
->size
;
1298 uint32
*type
= &r_u
->type
;
1299 uint32
*out_size
= &r_u
->size
;
1300 uint8
**data
= &r_u
->data
;
1301 uint32
*needed
= &r_u
->needed
;
1305 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1308 * Reminder: when it's a string, the length is in BYTES
1309 * even if UNICODE is negociated.
1316 /* in case of problem, return some default values */
1320 DEBUG(4,("_spoolss_getprinterdata\n"));
1323 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1325 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1329 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1331 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1332 found
=getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1334 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1337 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1338 /* reply this param doesn't exist */
1340 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1346 return WERR_INVALID_PARAM
;
1349 if (*needed
> *out_size
)
1350 return WERR_STATUS_MORE_ENTRIES
;
1355 /***************************************************************************
1356 connect to the client
1357 ****************************************************************************/
1358 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1363 * If it's the first connection, contact the client
1364 * and connect to the IPC$ share anonumously
1366 if (smb_connections
==0) {
1367 fstring unix_printer
;
1369 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
1371 if(!spoolss_connect_to_client(&cli
, unix_printer
))
1373 message_register(MSG_PRINTER_NOTIFY
, srv_spoolss_receive_message
);
1379 if(!cli_spoolss_reply_open_printer(&cli
, printer
, localprinter
, type
, &status
, handle
))
1385 /********************************************************************
1387 * ReplyFindFirstPrinterChangeNotifyEx
1389 * jfmxxxx: before replying OK: status=0
1390 * should do a rpc call to the workstation asking ReplyOpenPrinter
1391 * have to code it, later.
1393 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1394 * called from api_spoolss_rffpcnex
1395 ********************************************************************/
1397 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
1399 POLICY_HND
*handle
= &q_u
->handle
;
1400 uint32 flags
= q_u
->flags
;
1401 uint32 options
= q_u
->options
;
1402 UNISTR2
*localmachine
= &q_u
->localmachine
;
1403 uint32 printerlocal
= q_u
->printerlocal
;
1404 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
1406 /* store the notify value in the printer struct */
1408 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1411 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1415 Printer
->notify
.flags
=flags
;
1416 Printer
->notify
.options
=options
;
1417 Printer
->notify
.printerlocal
=printerlocal
;
1419 if (Printer
->notify
.option
)
1420 free_spool_notify_option(&Printer
->notify
.option
);
1422 Printer
->notify
.option
=dup_spool_notify_option(option
);
1424 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
, sizeof(Printer
->notify
.localmachine
)-1);
1426 /* connect to the client machine and send a ReplyOpenPrinter */
1427 if(srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
1428 Printer
->notify
.printerlocal
, 1,
1429 &Printer
->notify
.client_hnd
))
1430 Printer
->notify
.client_connected
=True
;
1435 /*******************************************************************
1436 * fill a notify_info_data with the servername
1437 ********************************************************************/
1439 static void spoolss_notify_server_name(int snum
,
1440 SPOOL_NOTIFY_INFO_DATA
*data
,
1441 print_queue_struct
*queue
,
1442 NT_PRINTER_INFO_LEVEL
*printer
,
1443 TALLOC_CTX
*mem_ctx
)
1445 pstring temp_name
, temp
;
1448 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
1450 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
1452 data
->notify_data
.data
.length
= len
/ 2;
1453 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1455 if (!data
->notify_data
.data
.string
) {
1456 data
->notify_data
.data
.length
= 0;
1460 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1463 /*******************************************************************
1464 * fill a notify_info_data with the printername (not including the servername).
1465 ********************************************************************/
1466 static void spoolss_notify_printer_name(int snum
,
1467 SPOOL_NOTIFY_INFO_DATA
*data
,
1468 print_queue_struct
*queue
,
1469 NT_PRINTER_INFO_LEVEL
*printer
,
1470 TALLOC_CTX
*mem_ctx
)
1475 /* the notify name should not contain the \\server\ part */
1476 char *p
= strrchr_m(printer
->info_2
->printername
, '\\');
1479 p
= printer
->info_2
->printername
;
1484 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
1485 data
->notify_data
.data
.length
= len
/ 2;
1486 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1488 if (!data
->notify_data
.data
.string
) {
1489 data
->notify_data
.data
.length
= 0;
1493 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1496 /*******************************************************************
1497 * fill a notify_info_data with the servicename
1498 ********************************************************************/
1499 static void spoolss_notify_share_name(int snum
,
1500 SPOOL_NOTIFY_INFO_DATA
*data
,
1501 print_queue_struct
*queue
,
1502 NT_PRINTER_INFO_LEVEL
*printer
,
1503 TALLOC_CTX
*mem_ctx
)
1508 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
1510 data
->notify_data
.data
.length
= len
/ 2;
1511 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1513 if (!data
->notify_data
.data
.string
) {
1514 data
->notify_data
.data
.length
= 0;
1518 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1521 /*******************************************************************
1522 * fill a notify_info_data with the port name
1523 ********************************************************************/
1524 static void spoolss_notify_port_name(int snum
,
1525 SPOOL_NOTIFY_INFO_DATA
*data
,
1526 print_queue_struct
*queue
,
1527 NT_PRINTER_INFO_LEVEL
*printer
,
1528 TALLOC_CTX
*mem_ctx
)
1533 /* even if it's strange, that's consistant in all the code */
1535 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
1537 data
->notify_data
.data
.length
= len
/ 2;
1538 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1540 if (!data
->notify_data
.data
.string
) {
1541 data
->notify_data
.data
.length
= 0;
1545 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1548 /*******************************************************************
1549 * fill a notify_info_data with the printername
1550 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1551 * but it doesn't exist, have to see what to do
1552 ********************************************************************/
1553 static void spoolss_notify_driver_name(int snum
,
1554 SPOOL_NOTIFY_INFO_DATA
*data
,
1555 print_queue_struct
*queue
,
1556 NT_PRINTER_INFO_LEVEL
*printer
,
1557 TALLOC_CTX
*mem_ctx
)
1562 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
1563 data
->notify_data
.data
.length
= len
/ 2;
1564 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1566 if (!data
->notify_data
.data
.string
) {
1567 data
->notify_data
.data
.length
= 0;
1571 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1574 /*******************************************************************
1575 * fill a notify_info_data with the comment
1576 ********************************************************************/
1577 static void spoolss_notify_comment(int snum
,
1578 SPOOL_NOTIFY_INFO_DATA
*data
,
1579 print_queue_struct
*queue
,
1580 NT_PRINTER_INFO_LEVEL
*printer
,
1581 TALLOC_CTX
*mem_ctx
)
1586 if (*printer
->info_2
->comment
== '\0')
1587 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
1590 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
1592 data
->notify_data
.data
.length
= len
/ 2;
1593 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1595 if (!data
->notify_data
.data
.string
) {
1596 data
->notify_data
.data
.length
= 0;
1600 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1603 /*******************************************************************
1604 * fill a notify_info_data with the comment
1605 * jfm:xxxx incorrect, have to create a new smb.conf option
1606 * location = "Room 1, floor 2, building 3"
1607 ********************************************************************/
1608 static void spoolss_notify_location(int snum
,
1609 SPOOL_NOTIFY_INFO_DATA
*data
,
1610 print_queue_struct
*queue
,
1611 NT_PRINTER_INFO_LEVEL
*printer
,
1612 TALLOC_CTX
*mem_ctx
)
1617 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
1619 data
->notify_data
.data
.length
= len
/ 2;
1620 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1622 if (!data
->notify_data
.data
.string
) {
1623 data
->notify_data
.data
.length
= 0;
1627 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1630 /*******************************************************************
1631 * fill a notify_info_data with the device mode
1632 * jfm:xxxx don't to it for know but that's a real problem !!!
1633 ********************************************************************/
1634 static void spoolss_notify_devmode(int snum
,
1635 SPOOL_NOTIFY_INFO_DATA
*data
,
1636 print_queue_struct
*queue
,
1637 NT_PRINTER_INFO_LEVEL
*printer
,
1638 TALLOC_CTX
*mem_ctx
)
1642 /*******************************************************************
1643 * fill a notify_info_data with the separator file name
1644 * jfm:xxxx just return no file could add an option to smb.conf
1645 * separator file = "separator.txt"
1646 ********************************************************************/
1647 static void spoolss_notify_sepfile(int snum
,
1648 SPOOL_NOTIFY_INFO_DATA
*data
,
1649 print_queue_struct
*queue
,
1650 NT_PRINTER_INFO_LEVEL
*printer
,
1651 TALLOC_CTX
*mem_ctx
)
1656 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
1658 data
->notify_data
.data
.length
= len
/ 2;
1659 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1661 if (!data
->notify_data
.data
.string
) {
1662 data
->notify_data
.data
.length
= 0;
1666 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1669 /*******************************************************************
1670 * fill a notify_info_data with the print processor
1671 * jfm:xxxx return always winprint to indicate we don't do anything to it
1672 ********************************************************************/
1673 static void spoolss_notify_print_processor(int snum
,
1674 SPOOL_NOTIFY_INFO_DATA
*data
,
1675 print_queue_struct
*queue
,
1676 NT_PRINTER_INFO_LEVEL
*printer
,
1677 TALLOC_CTX
*mem_ctx
)
1682 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
1684 data
->notify_data
.data
.length
= len
/ 2;
1685 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1687 if (!data
->notify_data
.data
.string
) {
1688 data
->notify_data
.data
.length
= 0;
1692 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1695 /*******************************************************************
1696 * fill a notify_info_data with the print processor options
1697 * jfm:xxxx send an empty string
1698 ********************************************************************/
1699 static void spoolss_notify_parameters(int snum
,
1700 SPOOL_NOTIFY_INFO_DATA
*data
,
1701 print_queue_struct
*queue
,
1702 NT_PRINTER_INFO_LEVEL
*printer
,
1703 TALLOC_CTX
*mem_ctx
)
1708 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
1710 data
->notify_data
.data
.length
= len
/ 2;
1711 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1713 if (!data
->notify_data
.data
.string
) {
1714 data
->notify_data
.data
.length
= 0;
1718 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1721 /*******************************************************************
1722 * fill a notify_info_data with the data type
1723 * jfm:xxxx always send RAW as data type
1724 ********************************************************************/
1725 static void spoolss_notify_datatype(int snum
,
1726 SPOOL_NOTIFY_INFO_DATA
*data
,
1727 print_queue_struct
*queue
,
1728 NT_PRINTER_INFO_LEVEL
*printer
,
1729 TALLOC_CTX
*mem_ctx
)
1734 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
1736 data
->notify_data
.data
.length
= len
/ 2;
1737 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1739 if (!data
->notify_data
.data
.string
) {
1740 data
->notify_data
.data
.length
= 0;
1744 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1747 /*******************************************************************
1748 * fill a notify_info_data with the security descriptor
1749 * jfm:xxxx send an null pointer to say no security desc
1750 * have to implement security before !
1751 ********************************************************************/
1752 static void spoolss_notify_security_desc(int snum
,
1753 SPOOL_NOTIFY_INFO_DATA
*data
,
1754 print_queue_struct
*queue
,
1755 NT_PRINTER_INFO_LEVEL
*printer
,
1756 TALLOC_CTX
*mem_ctx
)
1758 data
->notify_data
.data
.length
=0;
1759 data
->notify_data
.data
.string
= NULL
;
1762 /*******************************************************************
1763 * fill a notify_info_data with the attributes
1764 * jfm:xxxx a samba printer is always shared
1765 ********************************************************************/
1766 static void spoolss_notify_attributes(int snum
,
1767 SPOOL_NOTIFY_INFO_DATA
*data
,
1768 print_queue_struct
*queue
,
1769 NT_PRINTER_INFO_LEVEL
*printer
,
1770 TALLOC_CTX
*mem_ctx
)
1772 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
1773 data
->notify_data
.value
[1] = 0;
1776 /*******************************************************************
1777 * fill a notify_info_data with the priority
1778 ********************************************************************/
1779 static void spoolss_notify_priority(int snum
,
1780 SPOOL_NOTIFY_INFO_DATA
*data
,
1781 print_queue_struct
*queue
,
1782 NT_PRINTER_INFO_LEVEL
*printer
,
1783 TALLOC_CTX
*mem_ctx
)
1785 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
1786 data
->notify_data
.value
[1] = 0;
1789 /*******************************************************************
1790 * fill a notify_info_data with the default priority
1791 ********************************************************************/
1792 static void spoolss_notify_default_priority(int snum
,
1793 SPOOL_NOTIFY_INFO_DATA
*data
,
1794 print_queue_struct
*queue
,
1795 NT_PRINTER_INFO_LEVEL
*printer
,
1796 TALLOC_CTX
*mem_ctx
)
1798 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
1799 data
->notify_data
.value
[1] = 0;
1802 /*******************************************************************
1803 * fill a notify_info_data with the start time
1804 ********************************************************************/
1805 static void spoolss_notify_start_time(int snum
,
1806 SPOOL_NOTIFY_INFO_DATA
*data
,
1807 print_queue_struct
*queue
,
1808 NT_PRINTER_INFO_LEVEL
*printer
,
1809 TALLOC_CTX
*mem_ctx
)
1811 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
1812 data
->notify_data
.value
[1] = 0;
1815 /*******************************************************************
1816 * fill a notify_info_data with the until time
1817 ********************************************************************/
1818 static void spoolss_notify_until_time(int snum
,
1819 SPOOL_NOTIFY_INFO_DATA
*data
,
1820 print_queue_struct
*queue
,
1821 NT_PRINTER_INFO_LEVEL
*printer
,
1822 TALLOC_CTX
*mem_ctx
)
1824 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
1825 data
->notify_data
.value
[1] = 0;
1828 /*******************************************************************
1829 * fill a notify_info_data with the status
1830 ********************************************************************/
1831 static void spoolss_notify_status(int snum
,
1832 SPOOL_NOTIFY_INFO_DATA
*data
,
1833 print_queue_struct
*queue
,
1834 NT_PRINTER_INFO_LEVEL
*printer
,
1835 TALLOC_CTX
*mem_ctx
)
1837 print_status_struct status
;
1839 print_queue_length(snum
, &status
);
1840 data
->notify_data
.value
[0]=(uint32
) status
.status
;
1841 data
->notify_data
.value
[1] = 0;
1844 /*******************************************************************
1845 * fill a notify_info_data with the number of jobs queued
1846 ********************************************************************/
1847 static void spoolss_notify_cjobs(int snum
,
1848 SPOOL_NOTIFY_INFO_DATA
*data
,
1849 print_queue_struct
*queue
,
1850 NT_PRINTER_INFO_LEVEL
*printer
,
1851 TALLOC_CTX
*mem_ctx
)
1853 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
1854 data
->notify_data
.value
[1] = 0;
1857 /*******************************************************************
1858 * fill a notify_info_data with the average ppm
1859 ********************************************************************/
1860 static void spoolss_notify_average_ppm(int snum
,
1861 SPOOL_NOTIFY_INFO_DATA
*data
,
1862 print_queue_struct
*queue
,
1863 NT_PRINTER_INFO_LEVEL
*printer
,
1864 TALLOC_CTX
*mem_ctx
)
1866 /* always respond 8 pages per minutes */
1867 /* a little hard ! */
1868 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
1869 data
->notify_data
.value
[1] = 0;
1872 /*******************************************************************
1873 * fill a notify_info_data with username
1874 ********************************************************************/
1875 static void spoolss_notify_username(int snum
,
1876 SPOOL_NOTIFY_INFO_DATA
*data
,
1877 print_queue_struct
*queue
,
1878 NT_PRINTER_INFO_LEVEL
*printer
,
1879 TALLOC_CTX
*mem_ctx
)
1884 len
= rpcstr_push(temp
, queue
->user
, sizeof(temp
)-2, STR_TERMINATE
);
1887 data
->notify_data
.data
.length
= len
/ 2;
1888 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1890 if (!data
->notify_data
.data
.string
) {
1891 data
->notify_data
.data
.length
= 0;
1895 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1898 /*******************************************************************
1899 * fill a notify_info_data with job status
1900 ********************************************************************/
1901 static void spoolss_notify_job_status(int snum
,
1902 SPOOL_NOTIFY_INFO_DATA
*data
,
1903 print_queue_struct
*queue
,
1904 NT_PRINTER_INFO_LEVEL
*printer
,
1905 TALLOC_CTX
*mem_ctx
)
1907 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
1908 data
->notify_data
.value
[1] = 0;
1911 /*******************************************************************
1912 * fill a notify_info_data with job name
1913 ********************************************************************/
1914 static void spoolss_notify_job_name(int snum
,
1915 SPOOL_NOTIFY_INFO_DATA
*data
,
1916 print_queue_struct
*queue
,
1917 NT_PRINTER_INFO_LEVEL
*printer
,
1918 TALLOC_CTX
*mem_ctx
)
1923 len
= rpcstr_push(temp
, queue
->file
, sizeof(temp
)-2, STR_TERMINATE
);
1925 data
->notify_data
.data
.length
= len
/ 2;
1926 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1928 if (!data
->notify_data
.data
.string
) {
1929 data
->notify_data
.data
.length
= 0;
1933 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1936 /*******************************************************************
1937 * fill a notify_info_data with job status
1938 ********************************************************************/
1939 static void spoolss_notify_job_status_string(int snum
,
1940 SPOOL_NOTIFY_INFO_DATA
*data
,
1941 print_queue_struct
*queue
,
1942 NT_PRINTER_INFO_LEVEL
*printer
,
1943 TALLOC_CTX
*mem_ctx
)
1946 * Now we're returning job status codes we just return a "" here. JRA.
1953 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1956 switch (queue
->status
) {
1961 p
= ""; /* NT provides the paused string */
1970 #endif /* NO LONGER NEEDED. */
1972 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
1974 data
->notify_data
.data
.length
= len
/ 2;
1975 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1977 if (!data
->notify_data
.data
.string
) {
1978 data
->notify_data
.data
.length
= 0;
1982 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1985 /*******************************************************************
1986 * fill a notify_info_data with job time
1987 ********************************************************************/
1988 static void spoolss_notify_job_time(int snum
,
1989 SPOOL_NOTIFY_INFO_DATA
*data
,
1990 print_queue_struct
*queue
,
1991 NT_PRINTER_INFO_LEVEL
*printer
,
1992 TALLOC_CTX
*mem_ctx
)
1994 data
->notify_data
.value
[0]=0x0;
1995 data
->notify_data
.value
[1]=0;
1998 /*******************************************************************
1999 * fill a notify_info_data with job size
2000 ********************************************************************/
2001 static void spoolss_notify_job_size(int snum
,
2002 SPOOL_NOTIFY_INFO_DATA
*data
,
2003 print_queue_struct
*queue
,
2004 NT_PRINTER_INFO_LEVEL
*printer
,
2005 TALLOC_CTX
*mem_ctx
)
2007 data
->notify_data
.value
[0]=queue
->size
;
2008 data
->notify_data
.value
[1]=0;
2011 /*******************************************************************
2012 Fill a notify_info_data with job position.
2013 ********************************************************************/
2015 static void spoolss_notify_job_position(int snum
,
2016 SPOOL_NOTIFY_INFO_DATA
*data
,
2017 print_queue_struct
*queue
,
2018 NT_PRINTER_INFO_LEVEL
*printer
,
2019 TALLOC_CTX
*mem_ctx
)
2021 data
->notify_data
.value
[0]=queue
->job
;
2022 data
->notify_data
.value
[1]=0;
2025 /*******************************************************************
2026 Fill a notify_info_data with submitted time.
2027 ********************************************************************/
2029 static void spoolss_notify_submitted_time(int snum
,
2030 SPOOL_NOTIFY_INFO_DATA
*data
,
2031 print_queue_struct
*queue
,
2032 NT_PRINTER_INFO_LEVEL
*printer
,
2033 TALLOC_CTX
*mem_ctx
)
2040 t
=gmtime(&queue
->time
);
2042 len
= sizeof(SYSTEMTIME
);
2044 data
->notify_data
.data
.length
= len
;
2045 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2047 if (!data
->notify_data
.data
.string
) {
2048 data
->notify_data
.data
.length
= 0;
2052 make_systemtime(&st
, t
);
2055 * Systemtime must be linearized as a set of UINT16's.
2056 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
2059 p
= (char *)data
->notify_data
.data
.string
;
2060 SSVAL(p
, 0, st
.year
);
2061 SSVAL(p
, 2, st
.month
);
2062 SSVAL(p
, 4, st
.dayofweek
);
2063 SSVAL(p
, 6, st
.day
);
2064 SSVAL(p
, 8, st
.hour
);
2065 SSVAL(p
, 10, st
.minute
);
2066 SSVAL(p
, 12, st
.second
);
2067 SSVAL(p
, 14, st
.milliseconds
);
2072 struct s_notify_info_data_table
2078 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2079 print_queue_struct
*queue
,
2080 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2083 struct s_notify_info_data_table notify_info_data_table
[] =
2085 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", POINTER
, spoolss_notify_server_name
},
2086 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2087 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", POINTER
, spoolss_notify_share_name
},
2088 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2089 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2090 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", POINTER
, spoolss_notify_comment
},
2091 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", POINTER
, spoolss_notify_location
},
2092 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2093 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", POINTER
, spoolss_notify_sepfile
},
2094 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2095 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2096 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2097 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, spoolss_notify_security_desc
},
2098 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE
, spoolss_notify_attributes
},
2099 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2100 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE
, spoolss_notify_default_priority
},
2101 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2102 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2103 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_status
},
2104 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", POINTER
, NULL
},
2105 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", ONE_VALUE
, spoolss_notify_cjobs
},
2106 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE
, spoolss_notify_average_ppm
},
2107 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER
, NULL
},
2108 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER
, NULL
},
2109 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER
, NULL
},
2110 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER
, NULL
},
2111 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2112 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", POINTER
, spoolss_notify_server_name
},
2113 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2114 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", POINTER
, spoolss_notify_username
},
2115 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", POINTER
, spoolss_notify_username
},
2116 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2117 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2118 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2119 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2120 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2121 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_job_status
},
2122 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", POINTER
, spoolss_notify_job_status_string
},
2123 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, NULL
},
2124 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", POINTER
, spoolss_notify_job_name
},
2125 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2126 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", ONE_VALUE
, spoolss_notify_job_position
},
2127 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", POINTER
, spoolss_notify_submitted_time
},
2128 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2129 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2130 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", ONE_VALUE
, spoolss_notify_job_time
},
2131 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE
, NULL
},
2132 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE
, NULL
},
2133 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE
, spoolss_notify_job_size
},
2134 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_BYTES_PRINTED
, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE
, NULL
},
2135 { END
, END
, "", END
, NULL
}
2138 /*******************************************************************
2139 return the size of info_data structure
2140 ********************************************************************/
2141 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2145 while (notify_info_data_table
[i
].type
!= END
)
2147 if ( (notify_info_data_table
[i
].type
== type
) &&
2148 (notify_info_data_table
[i
].field
== field
) )
2150 return (notify_info_data_table
[i
].size
);
2157 /*******************************************************************
2158 return the type of notify_info_data
2159 ********************************************************************/
2160 static BOOL
type_of_notify_info_data(uint16 type
, uint16 field
)
2164 while (notify_info_data_table
[i
].type
!= END
)
2166 if ( (notify_info_data_table
[i
].type
== type
) &&
2167 (notify_info_data_table
[i
].field
== field
) )
2169 if (notify_info_data_table
[i
].size
== POINTER
)
2183 /****************************************************************************
2184 ****************************************************************************/
2185 static int search_notify(uint16 type
, uint16 field
, int *value
)
2190 for (j
=0, found
=False
; found
==False
&& notify_info_data_table
[j
].type
!= END
; j
++)
2192 if ( (notify_info_data_table
[j
].type
== type
) &&
2193 (notify_info_data_table
[j
].field
== field
) )
2198 if ( found
&& (notify_info_data_table
[j
].fn
!= NULL
) )
2204 /****************************************************************************
2205 ****************************************************************************/
2206 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2208 info_data
->type
= type
;
2209 info_data
->field
= field
;
2210 info_data
->reserved
= 0;
2212 info_data
->size
= size_of_notify_info_data(type
, field
);
2213 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2217 /*******************************************************************
2219 * fill a notify_info struct with info asked
2221 ********************************************************************/
2222 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2223 snum
, SPOOL_NOTIFY_OPTION_TYPE
2224 *option_type
, uint32 id
,
2225 TALLOC_CTX
*mem_ctx
)
2231 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2232 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2233 print_queue_struct
*queue
=NULL
;
2235 type
=option_type
->type
;
2237 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2238 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2239 option_type
->count
, lp_servicename(snum
)));
2241 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2244 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2245 field
= option_type
->fields
[field_num
];
2246 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2248 if (!search_notify(type
, field
, &j
) )
2251 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2252 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2255 else info
->data
= tid
;
2257 current_data
=&info
->data
[info
->count
];
2259 construct_info_data(current_data
, type
, field
, id
);
2261 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2262 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
2264 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2270 free_a_printer(&printer
, 2);
2274 /*******************************************************************
2276 * fill a notify_info struct with info asked
2278 ********************************************************************/
2279 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
2280 SPOOL_NOTIFY_INFO
*info
,
2281 NT_PRINTER_INFO_LEVEL
*printer
,
2282 int snum
, SPOOL_NOTIFY_OPTION_TYPE
2283 *option_type
, uint32 id
,
2284 TALLOC_CTX
*mem_ctx
)
2290 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2292 DEBUG(4,("construct_notify_jobs_info\n"));
2294 type
= option_type
->type
;
2296 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2297 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2298 option_type
->count
));
2300 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2301 field
= option_type
->fields
[field_num
];
2303 if (!search_notify(type
, field
, &j
) )
2306 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2307 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2310 else info
->data
= tid
;
2312 current_data
=&(info
->data
[info
->count
]);
2314 construct_info_data(current_data
, type
, field
, id
);
2315 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2324 * JFM: The enumeration is not that simple, it's even non obvious.
2326 * let's take an example: I want to monitor the PRINTER SERVER for
2327 * the printer's name and the number of jobs currently queued.
2328 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2329 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2331 * I have 3 printers on the back of my server.
2333 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2336 * 1 printer 1 name 1
2337 * 2 printer 1 cjob 1
2338 * 3 printer 2 name 2
2339 * 4 printer 2 cjob 2
2340 * 5 printer 3 name 3
2341 * 6 printer 3 name 3
2343 * that's the print server case, the printer case is even worse.
2346 /*******************************************************************
2348 * enumerate all printers on the printserver
2349 * fill a notify_info struct with info asked
2351 ********************************************************************/
2353 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
2354 SPOOL_NOTIFY_INFO
*info
,
2355 TALLOC_CTX
*mem_ctx
)
2358 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2359 int n_services
=lp_numservices();
2362 SPOOL_NOTIFY_OPTION
*option
;
2363 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2365 DEBUG(4,("printserver_notify_info\n"));
2367 option
=Printer
->notify
.option
;
2373 for (i
=0; i
<option
->count
; i
++) {
2374 option_type
=&(option
->ctr
.type
[i
]);
2376 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
2379 for (snum
=0; snum
<n_services
; snum
++)
2380 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
2381 if (construct_notify_printer_info
2382 (info
, snum
, option_type
, id
, mem_ctx
))
2387 * Debugging information, don't delete.
2390 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2391 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2392 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2394 for (i=0; i<info->count; i++) {
2395 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2396 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2397 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2404 /*******************************************************************
2406 * fill a notify_info struct with info asked
2408 ********************************************************************/
2409 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
2410 TALLOC_CTX
*mem_ctx
)
2413 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2416 SPOOL_NOTIFY_OPTION
*option
;
2417 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2419 print_queue_struct
*queue
=NULL
;
2420 print_status_struct status
;
2422 DEBUG(4,("printer_notify_info\n"));
2424 option
=Printer
->notify
.option
;
2430 get_printer_snum(p
, hnd
, &snum
);
2432 for (i
=0; i
<option
->count
; i
++) {
2433 option_type
=&option
->ctr
.type
[i
];
2435 switch ( option_type
->type
) {
2436 case PRINTER_NOTIFY_TYPE
:
2437 if(construct_notify_printer_info(info
, snum
,
2443 case JOB_NOTIFY_TYPE
: {
2444 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2446 count
= print_queue_status(snum
, &queue
, &status
);
2448 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
2449 lp_servicename(snum
))))
2452 for (j
=0; j
<count
; j
++) {
2453 construct_notify_jobs_info(&queue
[j
], info
,
2460 free_a_printer(&printer
, 2);
2470 * Debugging information, don't delete.
2473 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2474 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2475 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2477 for (i=0; i<info->count; i++) {
2478 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2479 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2480 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2486 /********************************************************************
2488 ********************************************************************/
2490 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
2492 POLICY_HND
*handle
= &q_u
->handle
;
2493 /* uint32 change = q_u->change; - notused. */
2494 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2495 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
2497 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2498 WERROR result
= WERR_BADFID
;
2500 /* we always have a NOTIFY_INFO struct */
2504 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2505 OUR_HANDLE(handle
)));
2509 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
2511 /* jfm: the change value isn't used right now.
2512 * we will honour it when
2513 * a) we'll be able to send notification to the client
2514 * b) we'll have a way to communicate between the spoolss process.
2516 * same thing for option->flags
2517 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2518 * I don't have a global notification system, I'm sending back all the
2519 * informations even when _NOTHING_ has changed.
2522 /* just ignore the SPOOL_NOTIFY_OPTION */
2524 switch (Printer
->printer_type
) {
2525 case PRINTER_HANDLE_IS_PRINTSERVER
:
2526 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
2529 case PRINTER_HANDLE_IS_PRINTER
:
2530 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
2538 /********************************************************************
2539 * construct_printer_info_0
2540 * fill a printer_info_0 struct
2541 ********************************************************************/
2542 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
2546 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2547 counter_printer_0
*session_counter
;
2548 uint32 global_counter
;
2551 print_status_struct status
;
2553 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2556 count
= print_queue_length(snum
, &status
);
2558 /* check if we already have a counter for this printer */
2559 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
2561 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
2562 if (session_counter
->snum
== snum
)
2566 /* it's the first time, add it to the list */
2567 if (session_counter
==NULL
) {
2568 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
2569 free_a_printer(&ntprinter
, 2);
2572 ZERO_STRUCTP(session_counter
);
2573 session_counter
->snum
=snum
;
2574 session_counter
->counter
=0;
2575 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
2579 session_counter
->counter
++;
2582 * the global_counter should be stored in a TDB as it's common to all the clients
2583 * and should be zeroed on samba startup
2585 global_counter
=session_counter
->counter
;
2587 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
2589 init_unistr(&printer
->printername
, chaine
);
2591 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_called_name());
2592 init_unistr(&printer
->servername
, chaine
);
2594 printer
->cjobs
= count
;
2595 printer
->total_jobs
= 0;
2596 printer
->total_bytes
= 0;
2598 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
2599 t
=gmtime(&setuptime
);
2601 printer
->year
= t
->tm_year
+1900;
2602 printer
->month
= t
->tm_mon
+1;
2603 printer
->dayofweek
= t
->tm_wday
;
2604 printer
->day
= t
->tm_mday
;
2605 printer
->hour
= t
->tm_hour
;
2606 printer
->minute
= t
->tm_min
;
2607 printer
->second
= t
->tm_sec
;
2608 printer
->milliseconds
= 0;
2610 printer
->global_counter
= global_counter
;
2611 printer
->total_pages
= 0;
2612 printer
->major_version
= 0x0004; /* NT 4 */
2613 printer
->build_version
= 0x0565; /* build 1381 */
2614 printer
->unknown7
= 0x1;
2615 printer
->unknown8
= 0x0;
2616 printer
->unknown9
= 0x0;
2617 printer
->session_counter
= session_counter
->counter
;
2618 printer
->unknown11
= 0x0;
2619 printer
->printer_errors
= 0x0; /* number of print failure */
2620 printer
->unknown13
= 0x0;
2621 printer
->unknown14
= 0x1;
2622 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
2623 printer
->unknown16
= 0x0;
2624 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
2625 printer
->unknown18
= 0x0;
2626 printer
->status
= nt_printq_status(status
.status
);
2627 printer
->unknown20
= 0x0;
2628 printer
->c_setprinter
= ntprinter
->info_2
->c_setprinter
; /* how many times setprinter has been called */
2629 printer
->unknown22
= 0x0;
2630 printer
->unknown23
= 0x6; /* 6 ???*/
2631 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
2632 printer
->unknown25
= 0;
2633 printer
->unknown26
= 0;
2634 printer
->unknown27
= 0;
2635 printer
->unknown28
= 0;
2636 printer
->unknown29
= 0;
2638 free_a_printer(&ntprinter
,2);
2642 /********************************************************************
2643 * construct_printer_info_1
2644 * fill a printer_info_1 struct
2645 ********************************************************************/
2646 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
2650 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2652 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2655 printer
->flags
=flags
;
2657 if (*ntprinter
->info_2
->comment
== '\0') {
2658 init_unistr(&printer
->comment
, lp_comment(snum
));
2659 slprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",get_called_name(), ntprinter
->info_2
->printername
,
2660 ntprinter
->info_2
->drivername
, lp_comment(snum
));
2663 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2664 slprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",get_called_name(), ntprinter
->info_2
->printername
,
2665 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
2668 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
2670 init_unistr(&printer
->description
, chaine
);
2671 init_unistr(&printer
->name
, chaine2
);
2673 free_a_printer(&ntprinter
,2);
2678 /****************************************************************************
2679 Free a DEVMODE struct.
2680 ****************************************************************************/
2682 static void free_dev_mode(DEVICEMODE
*dev
)
2687 SAFE_FREE(dev
->private);
2691 /****************************************************************************
2692 Create a DEVMODE struct. Returns malloced memory.
2693 ****************************************************************************/
2695 static DEVICEMODE
*construct_dev_mode(int snum
)
2699 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2700 NT_DEVICEMODE
*ntdevmode
= NULL
;
2701 DEVICEMODE
*devmode
= NULL
;
2703 DEBUG(7,("construct_dev_mode\n"));
2705 DEBUGADD(8,("getting printer characteristics\n"));
2707 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
2708 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2712 ZERO_STRUCTP(devmode
);
2714 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2717 if (printer
->info_2
->devmode
)
2718 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
2720 if (ntdevmode
== NULL
)
2723 DEBUGADD(8,("loading DEVICEMODE\n"));
2725 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
2726 init_unistr(&devmode
->devicename
, adevice
);
2728 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
2729 init_unistr(&devmode
->formname
, aform
);
2731 devmode
->specversion
= ntdevmode
->specversion
;
2732 devmode
->driverversion
= ntdevmode
->driverversion
;
2733 devmode
->size
= ntdevmode
->size
;
2734 devmode
->driverextra
= ntdevmode
->driverextra
;
2735 devmode
->fields
= ntdevmode
->fields
;
2737 devmode
->orientation
= ntdevmode
->orientation
;
2738 devmode
->papersize
= ntdevmode
->papersize
;
2739 devmode
->paperlength
= ntdevmode
->paperlength
;
2740 devmode
->paperwidth
= ntdevmode
->paperwidth
;
2741 devmode
->scale
= ntdevmode
->scale
;
2742 devmode
->copies
= ntdevmode
->copies
;
2743 devmode
->defaultsource
= ntdevmode
->defaultsource
;
2744 devmode
->printquality
= ntdevmode
->printquality
;
2745 devmode
->color
= ntdevmode
->color
;
2746 devmode
->duplex
= ntdevmode
->duplex
;
2747 devmode
->yresolution
= ntdevmode
->yresolution
;
2748 devmode
->ttoption
= ntdevmode
->ttoption
;
2749 devmode
->collate
= ntdevmode
->collate
;
2750 devmode
->icmmethod
= ntdevmode
->icmmethod
;
2751 devmode
->icmintent
= ntdevmode
->icmintent
;
2752 devmode
->mediatype
= ntdevmode
->mediatype
;
2753 devmode
->dithertype
= ntdevmode
->dithertype
;
2755 if (ntdevmode
->private != NULL
) {
2756 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
2760 free_nt_devicemode(&ntdevmode
);
2761 free_a_printer(&printer
,2);
2768 free_nt_devicemode(&ntdevmode
);
2770 free_a_printer(&printer
,2);
2771 free_dev_mode(devmode
);
2776 /********************************************************************
2777 * construct_printer_info_2
2778 * fill a printer_info_2 struct
2779 ********************************************************************/
2781 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
2784 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2786 print_status_struct status
;
2788 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2791 count
= print_queue_length(snum
, &status
);
2793 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
2794 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
2795 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
2796 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
2797 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
2799 if (*ntprinter
->info_2
->comment
== '\0')
2800 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
2802 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2804 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
2805 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
2806 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
2807 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
2808 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
2810 printer
->attributes
= ntprinter
->info_2
->attributes
;
2812 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
2813 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
2814 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
2815 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
2816 printer
->status
= nt_printq_status(status
.status
); /* status */
2817 printer
->cjobs
= count
; /* jobs */
2818 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
2820 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
2821 DEBUG(8, ("Returning NULL Devicemode!\n"));
2824 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2825 /* steal the printer info sec_desc structure. [badly done]. */
2826 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2827 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
2828 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
2829 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
2832 printer
->secdesc
= NULL
;
2835 free_a_printer(&ntprinter
, 2);
2839 /********************************************************************
2840 * construct_printer_info_3
2841 * fill a printer_info_3 struct
2842 ********************************************************************/
2843 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
2845 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2846 PRINTER_INFO_3
*printer
= NULL
;
2848 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2852 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
2853 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2857 ZERO_STRUCTP(printer
);
2859 printer
->flags
= 4; /* These are the components of the SD we are returning. */
2860 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2861 /* steal the printer info sec_desc structure. [badly done]. */
2862 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2866 * Set the flags for the components we are returning.
2869 if (printer
->secdesc
->owner_sid
)
2870 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
2872 if (printer
->secdesc
->grp_sid
)
2873 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
2875 if (printer
->secdesc
->dacl
)
2876 printer
->flags
|= DACL_SECURITY_INFORMATION
;
2878 if (printer
->secdesc
->sacl
)
2879 printer
->flags
|= SACL_SECURITY_INFORMATION
;
2882 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
2883 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
2884 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
2887 free_a_printer(&ntprinter
, 2);
2889 *pp_printer
= printer
;
2893 /********************************************************************
2894 * construct_printer_info_4
2895 * fill a printer_info_4 struct
2896 ********************************************************************/
2898 static BOOL
construct_printer_info_4(PRINTER_INFO_4
*printer
, int snum
)
2900 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2902 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2905 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
2906 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
2907 printer
->attributes
= ntprinter
->info_2
->attributes
;
2909 free_a_printer(&ntprinter
, 2);
2913 /********************************************************************
2914 * construct_printer_info_5
2915 * fill a printer_info_5 struct
2916 ********************************************************************/
2918 static BOOL
construct_printer_info_5(PRINTER_INFO_5
*printer
, int snum
)
2920 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2922 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2925 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
2926 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* portname */
2927 printer
->attributes
= ntprinter
->info_2
->attributes
;
2928 printer
->device_not_selected_timeout
= 0x3a98;
2929 printer
->transmission_retry_timeout
= 0xafc8;
2931 free_a_printer(&ntprinter
, 2);
2936 /********************************************************************
2937 Spoolss_enumprinters.
2938 ********************************************************************/
2939 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2943 int n_services
=lp_numservices();
2944 PRINTER_INFO_1
*tp
, *printers
=NULL
;
2945 PRINTER_INFO_1 current_prt
;
2947 DEBUG(4,("enum_all_printers_info_1\n"));
2949 for (snum
=0; snum
<n_services
; snum
++) {
2950 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
2951 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
2953 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
2954 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
2955 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2956 SAFE_FREE(printers
);
2961 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
2962 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
2968 /* check the required size. */
2969 for (i
=0; i
<*returned
; i
++)
2970 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
2972 if (!alloc_buffer_size(buffer
, *needed
))
2973 return WERR_INSUFFICIENT_BUFFER
;
2975 /* fill the buffer with the structures */
2976 for (i
=0; i
<*returned
; i
++)
2977 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
2980 SAFE_FREE(printers
);
2982 if (*needed
> offered
) {
2984 return WERR_INSUFFICIENT_BUFFER
;
2990 /********************************************************************
2991 enum_all_printers_info_1_local.
2992 *********************************************************************/
2993 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2995 DEBUG(4,("enum_all_printers_info_1_local\n"));
2997 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3000 /********************************************************************
3001 enum_all_printers_info_1_name.
3002 *********************************************************************/
3003 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3007 DEBUG(4,("enum_all_printers_info_1_name\n"));
3009 if ((name
[0] == '\\') && (name
[1] == '\\'))
3012 if (is_myname_or_ipaddr(s
)) {
3013 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
3016 return WERR_INVALID_NAME
;
3019 /********************************************************************
3020 enum_all_printers_info_1_remote.
3021 *********************************************************************/
3022 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3024 PRINTER_INFO_1
*printer
;
3025 fstring printername
;
3028 DEBUG(4,("enum_all_printers_info_1_remote\n"));
3030 /* JFM: currently it's more a place holder than anything else.
3031 * In the spooler world there is a notion of server registration.
3032 * the print servers are registring (sp ?) on the PDC (in the same domain)
3034 * We should have a TDB here. The registration is done thru an undocumented RPC call.
3037 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3042 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", get_called_name());
3043 slprintf(desc
, sizeof(desc
)-1,"%s", get_called_name());
3044 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3046 init_unistr(&printer
->description
, desc
);
3047 init_unistr(&printer
->name
, printername
);
3048 init_unistr(&printer
->comment
, comment
);
3049 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3051 /* check the required size. */
3052 *needed
+= spoolss_size_printer_info_1(printer
);
3054 if (!alloc_buffer_size(buffer
, *needed
)) {
3056 return WERR_INSUFFICIENT_BUFFER
;
3059 /* fill the buffer with the structures */
3060 smb_io_printer_info_1("", buffer
, printer
, 0);
3065 if (*needed
> offered
) {
3067 return WERR_INSUFFICIENT_BUFFER
;
3073 /********************************************************************
3074 enum_all_printers_info_1_network.
3075 *********************************************************************/
3077 static WERROR
enum_all_printers_info_1_network(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3079 DEBUG(4,("enum_all_printers_info_1_network\n"));
3081 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3084 /********************************************************************
3085 * api_spoolss_enumprinters
3087 * called from api_spoolss_enumprinters (see this to understand)
3088 ********************************************************************/
3090 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3094 int n_services
=lp_numservices();
3095 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3096 PRINTER_INFO_2 current_prt
;
3098 for (snum
=0; snum
<n_services
; snum
++) {
3099 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3100 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3102 if (construct_printer_info_2(¤t_prt
, snum
)) {
3103 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3104 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3105 SAFE_FREE(printers
);
3110 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3111 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3117 /* check the required size. */
3118 for (i
=0; i
<*returned
; i
++)
3119 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3121 if (!alloc_buffer_size(buffer
, *needed
)) {
3122 for (i
=0; i
<*returned
; i
++) {
3123 free_devmode(printers
[i
].devmode
);
3125 SAFE_FREE(printers
);
3126 return WERR_INSUFFICIENT_BUFFER
;
3129 /* fill the buffer with the structures */
3130 for (i
=0; i
<*returned
; i
++)
3131 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3134 for (i
=0; i
<*returned
; i
++) {
3135 free_devmode(printers
[i
].devmode
);
3137 SAFE_FREE(printers
);
3139 if (*needed
> offered
) {
3141 return WERR_INSUFFICIENT_BUFFER
;
3147 /********************************************************************
3148 * handle enumeration of printers at level 1
3149 ********************************************************************/
3150 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3151 NEW_BUFFER
*buffer
, uint32 offered
,
3152 uint32
*needed
, uint32
*returned
)
3154 /* Not all the flags are equals */
3156 if (flags
& PRINTER_ENUM_LOCAL
)
3157 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3159 if (flags
& PRINTER_ENUM_NAME
)
3160 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3162 if (flags
& PRINTER_ENUM_REMOTE
)
3163 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3165 if (flags
& PRINTER_ENUM_NETWORK
)
3166 return enum_all_printers_info_1_network(buffer
, offered
, needed
, returned
);
3168 return WERR_OK
; /* NT4sp5 does that */
3171 /********************************************************************
3172 * handle enumeration of printers at level 2
3173 ********************************************************************/
3174 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3175 NEW_BUFFER
*buffer
, uint32 offered
,
3176 uint32
*needed
, uint32
*returned
)
3178 char *s
= servername
;
3180 if (flags
& PRINTER_ENUM_LOCAL
) {
3181 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3184 if (flags
& PRINTER_ENUM_NAME
) {
3185 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3187 if (is_myname_or_ipaddr(s
))
3188 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3190 return WERR_INVALID_NAME
;
3193 if (flags
& PRINTER_ENUM_REMOTE
)
3194 return WERR_UNKNOWN_LEVEL
;
3199 /********************************************************************
3200 * handle enumeration of printers at level 5
3201 ********************************************************************/
3202 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3203 NEW_BUFFER
*buffer
, uint32 offered
,
3204 uint32
*needed
, uint32
*returned
)
3206 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3210 /********************************************************************
3211 * api_spoolss_enumprinters
3213 * called from api_spoolss_enumprinters (see this to understand)
3214 ********************************************************************/
3216 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3218 uint32 flags
= q_u
->flags
;
3219 UNISTR2
*servername
= &q_u
->servername
;
3220 uint32 level
= q_u
->level
;
3221 NEW_BUFFER
*buffer
= NULL
;
3222 uint32 offered
= q_u
->offered
;
3223 uint32
*needed
= &r_u
->needed
;
3224 uint32
*returned
= &r_u
->returned
;
3228 /* that's an [in out] buffer */
3229 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3230 buffer
= r_u
->buffer
;
3232 DEBUG(4,("_spoolss_enumprinters\n"));
3239 * flags==PRINTER_ENUM_NAME
3240 * if name=="" then enumerates all printers
3241 * if name!="" then enumerate the printer
3242 * flags==PRINTER_ENUM_REMOTE
3243 * name is NULL, enumerate printers
3244 * Level 2: name!="" enumerates printers, name can't be NULL
3245 * Level 3: doesn't exist
3246 * Level 4: does a local registry lookup
3247 * Level 5: same as Level 2
3250 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
3255 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
3257 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
3259 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
3264 return WERR_UNKNOWN_LEVEL
;
3267 /****************************************************************************
3268 ****************************************************************************/
3269 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3271 PRINTER_INFO_0
*printer
=NULL
;
3273 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
3276 construct_printer_info_0(printer
, snum
);
3278 /* check the required size. */
3279 *needed
+= spoolss_size_printer_info_0(printer
);
3281 if (!alloc_buffer_size(buffer
, *needed
)) {
3283 return WERR_INSUFFICIENT_BUFFER
;
3286 /* fill the buffer with the structures */
3287 smb_io_printer_info_0("", buffer
, printer
, 0);
3292 if (*needed
> offered
) {
3293 return WERR_INSUFFICIENT_BUFFER
;
3299 /****************************************************************************
3300 ****************************************************************************/
3301 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3303 PRINTER_INFO_1
*printer
=NULL
;
3305 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3308 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
3310 /* check the required size. */
3311 *needed
+= spoolss_size_printer_info_1(printer
);
3313 if (!alloc_buffer_size(buffer
, *needed
)) {
3315 return WERR_INSUFFICIENT_BUFFER
;
3318 /* fill the buffer with the structures */
3319 smb_io_printer_info_1("", buffer
, printer
, 0);
3324 if (*needed
> offered
) {
3325 return WERR_INSUFFICIENT_BUFFER
;
3331 /****************************************************************************
3332 ****************************************************************************/
3333 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3335 PRINTER_INFO_2
*printer
=NULL
;
3337 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
3340 construct_printer_info_2(printer
, snum
);
3342 /* check the required size. */
3343 *needed
+= spoolss_size_printer_info_2(printer
);
3345 if (!alloc_buffer_size(buffer
, *needed
)) {
3346 free_printer_info_2(printer
);
3347 return WERR_INSUFFICIENT_BUFFER
;
3350 /* fill the buffer with the structures */
3351 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
3352 free_printer_info_2(printer
);
3357 free_printer_info_2(printer
);
3359 if (*needed
> offered
) {
3360 return WERR_INSUFFICIENT_BUFFER
;
3366 /****************************************************************************
3367 ****************************************************************************/
3368 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3370 PRINTER_INFO_3
*printer
=NULL
;
3372 if (!construct_printer_info_3(&printer
, snum
))
3375 /* check the required size. */
3376 *needed
+= spoolss_size_printer_info_3(printer
);
3378 if (!alloc_buffer_size(buffer
, *needed
)) {
3379 free_printer_info_3(printer
);
3380 return WERR_INSUFFICIENT_BUFFER
;
3383 /* fill the buffer with the structures */
3384 smb_io_printer_info_3("", buffer
, printer
, 0);
3387 free_printer_info_3(printer
);
3389 if (*needed
> offered
) {
3390 return WERR_INSUFFICIENT_BUFFER
;
3396 /****************************************************************************
3397 ****************************************************************************/
3398 static WERROR
getprinter_level_4(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3400 PRINTER_INFO_4
*printer
=NULL
;
3402 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
3405 if (!construct_printer_info_4(printer
, snum
))
3408 /* check the required size. */
3409 *needed
+= spoolss_size_printer_info_4(printer
);
3411 if (!alloc_buffer_size(buffer
, *needed
)) {
3412 free_printer_info_4(printer
);
3413 return WERR_INSUFFICIENT_BUFFER
;
3416 /* fill the buffer with the structures */
3417 smb_io_printer_info_4("", buffer
, printer
, 0);
3420 free_printer_info_4(printer
);
3422 if (*needed
> offered
) {
3423 return WERR_INSUFFICIENT_BUFFER
;
3429 /****************************************************************************
3430 ****************************************************************************/
3431 static WERROR
getprinter_level_5(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3433 PRINTER_INFO_5
*printer
=NULL
;
3435 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
3438 if (!construct_printer_info_5(printer
, snum
))
3441 /* check the required size. */
3442 *needed
+= spoolss_size_printer_info_5(printer
);
3444 if (!alloc_buffer_size(buffer
, *needed
)) {
3445 free_printer_info_5(printer
);
3446 return WERR_INSUFFICIENT_BUFFER
;
3449 /* fill the buffer with the structures */
3450 smb_io_printer_info_5("", buffer
, printer
, 0);
3453 free_printer_info_5(printer
);
3455 if (*needed
> offered
) {
3456 return WERR_INSUFFICIENT_BUFFER
;
3462 /****************************************************************************
3463 ****************************************************************************/
3465 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
3467 POLICY_HND
*handle
= &q_u
->handle
;
3468 uint32 level
= q_u
->level
;
3469 NEW_BUFFER
*buffer
= NULL
;
3470 uint32 offered
= q_u
->offered
;
3471 uint32
*needed
= &r_u
->needed
;
3475 /* that's an [in out] buffer */
3476 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3477 buffer
= r_u
->buffer
;
3481 if (!get_printer_snum(p
, handle
, &snum
))
3486 return getprinter_level_0(snum
, buffer
, offered
, needed
);
3488 return getprinter_level_1(snum
, buffer
, offered
, needed
);
3490 return getprinter_level_2(snum
, buffer
, offered
, needed
);
3492 return getprinter_level_3(snum
, buffer
, offered
, needed
);
3494 return getprinter_level_4(snum
, buffer
, offered
, needed
);
3496 return getprinter_level_5(snum
, buffer
, offered
, needed
);
3498 return WERR_UNKNOWN_LEVEL
;
3501 /********************************************************************
3502 * fill a DRIVER_INFO_1 struct
3503 ********************************************************************/
3504 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
3506 init_unistr( &info
->name
, driver
.info_3
->name
);
3509 /********************************************************************
3510 * construct_printer_driver_info_1
3511 ********************************************************************/
3512 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3514 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3515 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3517 ZERO_STRUCT(driver
);
3519 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3520 return WERR_INVALID_PRINTER_NAME
;
3522 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3523 return WERR_UNKNOWN_PRINTER_DRIVER
;
3525 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
3527 free_a_printer(&printer
,2);
3532 /********************************************************************
3533 * construct_printer_driver_info_2
3534 * fill a printer_info_2 struct
3535 ********************************************************************/
3536 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3540 info
->version
=driver
.info_3
->cversion
;
3542 init_unistr( &info
->name
, driver
.info_3
->name
);
3543 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3546 if (strlen(driver
.info_3
->driverpath
)) {
3547 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3548 init_unistr( &info
->driverpath
, temp
);
3550 init_unistr( &info
->driverpath
, "" );
3552 if (strlen(driver
.info_3
->datafile
)) {
3553 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3554 init_unistr( &info
->datafile
, temp
);
3556 init_unistr( &info
->datafile
, "" );
3558 if (strlen(driver
.info_3
->configfile
)) {
3559 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3560 init_unistr( &info
->configfile
, temp
);
3562 init_unistr( &info
->configfile
, "" );
3565 /********************************************************************
3566 * construct_printer_driver_info_2
3567 * fill a printer_info_2 struct
3568 ********************************************************************/
3569 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3571 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3572 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3574 ZERO_STRUCT(printer
);
3575 ZERO_STRUCT(driver
);
3577 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3578 return WERR_INVALID_PRINTER_NAME
;
3580 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3581 return WERR_UNKNOWN_PRINTER_DRIVER
;
3583 fill_printer_driver_info_2(info
, driver
, servername
);
3585 free_a_printer(&printer
,2);
3590 /********************************************************************
3591 * copy a strings array and convert to UNICODE
3593 * convert an array of ascii string to a UNICODE string
3594 ********************************************************************/
3595 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
3603 DEBUG(6,("init_unistr_array\n"));
3607 if (char_array
== NULL
)
3611 if (!v
) v
= ""; /* hack to handle null lists */
3613 if (strlen(v
) == 0) break;
3614 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
3615 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
3616 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
3617 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3620 else *uni_array
= tuary
;
3621 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, 0)/ sizeof(uint16
));
3626 (*uni_array
)[j
]=0x0000;
3629 DEBUGADD(6,("last one:done\n"));
3632 /********************************************************************
3633 * construct_printer_info_3
3634 * fill a printer_info_3 struct
3635 ********************************************************************/
3636 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3642 info
->version
=driver
.info_3
->cversion
;
3644 init_unistr( &info
->name
, driver
.info_3
->name
);
3645 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3647 if (strlen(driver
.info_3
->driverpath
)) {
3648 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3649 init_unistr( &info
->driverpath
, temp
);
3651 init_unistr( &info
->driverpath
, "" );
3653 if (strlen(driver
.info_3
->datafile
)) {
3654 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3655 init_unistr( &info
->datafile
, temp
);
3657 init_unistr( &info
->datafile
, "" );
3659 if (strlen(driver
.info_3
->configfile
)) {
3660 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3661 init_unistr( &info
->configfile
, temp
);
3663 init_unistr( &info
->configfile
, "" );
3665 if (strlen(driver
.info_3
->helpfile
)) {
3666 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
3667 init_unistr( &info
->helpfile
, temp
);
3669 init_unistr( &info
->helpfile
, "" );
3671 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
3672 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
3674 info
->dependentfiles
=NULL
;
3675 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
3678 /********************************************************************
3679 * construct_printer_info_3
3680 * fill a printer_info_3 struct
3681 ********************************************************************/
3682 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3684 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3685 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3687 ZERO_STRUCT(driver
);
3689 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
3690 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status
)));
3691 if (!W_ERROR_IS_OK(status
))
3692 return WERR_INVALID_PRINTER_NAME
;
3694 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3695 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status
)));
3696 if (!W_ERROR_IS_OK(status
)) {
3697 free_a_printer(&printer
,2);
3698 return WERR_UNKNOWN_PRINTER_DRIVER
;
3701 fill_printer_driver_info_3(info
, driver
, servername
);
3703 free_a_printer(&printer
,2);
3708 /********************************************************************
3709 * construct_printer_info_6
3710 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3711 ********************************************************************/
3713 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3719 memset(&nullstr
, '\0', sizeof(fstring
));
3721 info
->version
=driver
.info_3
->cversion
;
3723 init_unistr( &info
->name
, driver
.info_3
->name
);
3724 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3726 if (strlen(driver
.info_3
->driverpath
)) {
3727 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3728 init_unistr( &info
->driverpath
, temp
);
3730 init_unistr( &info
->driverpath
, "" );
3732 if (strlen(driver
.info_3
->datafile
)) {
3733 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3734 init_unistr( &info
->datafile
, temp
);
3736 init_unistr( &info
->datafile
, "" );
3738 if (strlen(driver
.info_3
->configfile
)) {
3739 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3740 init_unistr( &info
->configfile
, temp
);
3742 init_unistr( &info
->configfile
, "" );
3744 if (strlen(driver
.info_3
->helpfile
)) {
3745 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
3746 init_unistr( &info
->helpfile
, temp
);
3748 init_unistr( &info
->helpfile
, "" );
3750 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
3751 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
3753 info
->dependentfiles
=NULL
;
3754 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
3756 info
->previousdrivernames
=NULL
;
3757 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
3759 info
->driver_date
.low
=0;
3760 info
->driver_date
.high
=0;
3763 info
->driver_version_low
=0;
3764 info
->driver_version_high
=0;
3766 init_unistr( &info
->mfgname
, "");
3767 init_unistr( &info
->oem_url
, "");
3768 init_unistr( &info
->hardware_id
, "");
3769 init_unistr( &info
->provider
, "");
3772 /********************************************************************
3773 * construct_printer_info_6
3774 * fill a printer_info_6 struct
3775 ********************************************************************/
3776 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3778 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3779 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3781 ZERO_STRUCT(driver
);
3783 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
3784 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3785 if (!W_ERROR_IS_OK(status
))
3786 return WERR_INVALID_PRINTER_NAME
;
3788 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3789 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3790 if (!W_ERROR_IS_OK(status
)) {
3792 * Is this a W2k client ?
3796 free_a_printer(&printer
,2);
3797 return WERR_UNKNOWN_PRINTER_DRIVER
;
3800 /* Yes - try again with a WinNT driver. */
3802 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3803 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3804 if (!W_ERROR_IS_OK(status
)) {
3805 free_a_printer(&printer
,2);
3806 return WERR_UNKNOWN_PRINTER_DRIVER
;
3810 fill_printer_driver_info_6(info
, driver
, servername
);
3812 free_a_printer(&printer
,2);
3817 /****************************************************************************
3818 ****************************************************************************/
3820 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
3822 SAFE_FREE(info
->dependentfiles
);
3825 /****************************************************************************
3826 ****************************************************************************/
3828 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
3830 SAFE_FREE(info
->dependentfiles
);
3834 /****************************************************************************
3835 ****************************************************************************/
3836 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3838 DRIVER_INFO_1
*info
=NULL
;
3841 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
3844 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
3845 if (!W_ERROR_IS_OK(status
)) {
3850 /* check the required size. */
3851 *needed
+= spoolss_size_printer_driver_info_1(info
);
3853 if (!alloc_buffer_size(buffer
, *needed
)) {
3855 return WERR_INSUFFICIENT_BUFFER
;
3858 /* fill the buffer with the structures */
3859 smb_io_printer_driver_info_1("", buffer
, info
, 0);
3864 if (*needed
> offered
)
3865 return WERR_INSUFFICIENT_BUFFER
;
3870 /****************************************************************************
3871 ****************************************************************************/
3872 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3874 DRIVER_INFO_2
*info
=NULL
;
3877 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
3880 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
3881 if (!W_ERROR_IS_OK(status
)) {
3886 /* check the required size. */
3887 *needed
+= spoolss_size_printer_driver_info_2(info
);
3889 if (!alloc_buffer_size(buffer
, *needed
)) {
3891 return WERR_INSUFFICIENT_BUFFER
;
3894 /* fill the buffer with the structures */
3895 smb_io_printer_driver_info_2("", buffer
, info
, 0);
3900 if (*needed
> offered
)
3901 return WERR_INSUFFICIENT_BUFFER
;
3906 /****************************************************************************
3907 ****************************************************************************/
3908 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3915 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
3916 if (!W_ERROR_IS_OK(status
)) {
3920 /* check the required size. */
3921 *needed
+= spoolss_size_printer_driver_info_3(&info
);
3923 if (!alloc_buffer_size(buffer
, *needed
)) {
3924 free_printer_driver_info_3(&info
);
3925 return WERR_INSUFFICIENT_BUFFER
;
3928 /* fill the buffer with the structures */
3929 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
3931 free_printer_driver_info_3(&info
);
3933 if (*needed
> offered
)
3934 return WERR_INSUFFICIENT_BUFFER
;
3939 /****************************************************************************
3940 ****************************************************************************/
3941 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3948 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
3949 if (!W_ERROR_IS_OK(status
)) {
3953 /* check the required size. */
3954 *needed
+= spoolss_size_printer_driver_info_6(&info
);
3956 if (!alloc_buffer_size(buffer
, *needed
)) {
3957 free_printer_driver_info_6(&info
);
3958 return WERR_INSUFFICIENT_BUFFER
;
3961 /* fill the buffer with the structures */
3962 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
3964 free_printer_driver_info_6(&info
);
3966 if (*needed
> offered
)
3967 return WERR_INSUFFICIENT_BUFFER
;
3972 /****************************************************************************
3973 ****************************************************************************/
3975 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
3977 POLICY_HND
*handle
= &q_u
->handle
;
3978 UNISTR2
*uni_arch
= &q_u
->architecture
;
3979 uint32 level
= q_u
->level
;
3980 uint32 clientmajorversion
= q_u
->clientmajorversion
;
3981 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3982 NEW_BUFFER
*buffer
= NULL
;
3983 uint32 offered
= q_u
->offered
;
3984 uint32
*needed
= &r_u
->needed
;
3985 uint32
*servermajorversion
= &r_u
->servermajorversion
;
3986 uint32
*serverminorversion
= &r_u
->serverminorversion
;
3989 fstring architecture
;
3992 /* that's an [in out] buffer */
3993 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3994 buffer
= r_u
->buffer
;
3996 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3999 *servermajorversion
=0;
4000 *serverminorversion
=0;
4002 pstrcpy(servername
, get_called_name());
4003 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
4005 if (!get_printer_snum(p
, handle
, &snum
))
4010 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4012 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4014 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4016 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
4019 return WERR_UNKNOWN_LEVEL
;
4022 /****************************************************************************
4023 ****************************************************************************/
4025 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
4027 POLICY_HND
*handle
= &q_u
->handle
;
4029 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4032 DEBUG(3,("Error in startpageprinter printer handle\n"));
4036 Printer
->page_started
=True
;
4040 /****************************************************************************
4041 ****************************************************************************/
4043 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
4045 POLICY_HND
*handle
= &q_u
->handle
;
4047 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4050 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle
)));
4054 Printer
->page_started
=False
;
4059 /********************************************************************
4060 * api_spoolss_getprinter
4061 * called from the spoolss dispatcher
4063 ********************************************************************/
4065 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
4067 POLICY_HND
*handle
= &q_u
->handle
;
4068 /* uint32 level = q_u->doc_info_container.level; - notused. */
4069 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
4070 uint32
*jobid
= &r_u
->jobid
;
4072 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
4076 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4077 struct current_user user
;
4080 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4084 get_current_user(&user
, p
);
4087 * a nice thing with NT is it doesn't listen to what you tell it.
4088 * when asked to send _only_ RAW datas, it tries to send datas
4091 * So I add checks like in NT Server ...
4093 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
4094 * there's a bug in NT client-side code, so we'll fix it in the
4095 * server-side code. *nnnnnggggh!*
4098 if (info_1
->p_datatype
!= 0) {
4099 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
4100 if (strcmp(datatype
, "RAW") != 0) {
4102 return WERR_INVALID_DATATYPE
;
4106 /* get the share number of the printer */
4107 if (!get_printer_snum(p
, handle
, &snum
)) {
4111 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
4113 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4115 /* An error occured in print_job_start() so return an appropriate
4118 if (Printer
->jobid
== -1) {
4119 return map_werror_from_unix(errno
);
4122 Printer
->document_started
=True
;
4123 (*jobid
) = Printer
->jobid
;
4128 /********************************************************************
4129 * api_spoolss_getprinter
4130 * called from the spoolss dispatcher
4132 ********************************************************************/
4134 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4136 POLICY_HND
*handle
= &q_u
->handle
;
4138 return _spoolss_enddocprinter_internal(p
, handle
);
4141 /****************************************************************************
4142 ****************************************************************************/
4144 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4146 POLICY_HND
*handle
= &q_u
->handle
;
4147 uint32 buffer_size
= q_u
->buffer_size
;
4148 uint8
*buffer
= q_u
->buffer
;
4149 uint32
*buffer_written
= &q_u
->buffer_size2
;
4151 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4154 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle
)));
4155 r_u
->buffer_written
= q_u
->buffer_size2
;
4159 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
, buffer_size
);
4162 r_u
->buffer_written
= q_u
->buffer_size2
;
4167 /********************************************************************
4168 * api_spoolss_getprinter
4169 * called from the spoolss dispatcher
4171 ********************************************************************/
4172 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
4175 struct current_user user
;
4177 WERROR errcode
= WERR_BADFUNC
;
4178 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4180 get_current_user(&user
, p
);
4183 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4187 if (!get_printer_snum(p
, handle
, &snum
))
4191 case PRINTER_CONTROL_PAUSE
:
4192 if (print_queue_pause(&user
, snum
, &errcode
)) {
4196 case PRINTER_CONTROL_RESUME
:
4197 case PRINTER_CONTROL_UNPAUSE
:
4198 if (print_queue_resume(&user
, snum
, &errcode
)) {
4202 case PRINTER_CONTROL_PURGE
:
4203 if (print_queue_purge(&user
, snum
, &errcode
)) {
4208 return WERR_UNKNOWN_LEVEL
;
4214 /********************************************************************
4215 * api_spoolss_abortprinter
4216 ********************************************************************/
4218 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
4220 POLICY_HND
*handle
= &q_u
->handle
;
4222 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
4225 /********************************************************************
4226 * called by spoolss_api_setprinter
4227 * when updating a printer description
4228 ********************************************************************/
4229 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
4230 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4231 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
4233 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
4234 struct current_user user
;
4238 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4240 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
4241 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4242 OUR_HANDLE(handle
)));
4244 result
= WERR_BADFID
;
4248 /* NT seems to like setting the security descriptor even though
4249 nothing may have actually changed. This causes annoying
4250 dialog boxes when the user doesn't have permission to change
4251 the security descriptor. */
4253 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
4255 if (DEBUGLEVEL
>= 10) {
4259 the_acl
= old_secdesc_ctr
->sec
->dacl
;
4260 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4261 PRINTERNAME(snum
), the_acl
->num_aces
));
4263 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4266 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4268 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4269 the_acl
->ace
[i
].info
.mask
));
4272 the_acl
= secdesc_ctr
->sec
->dacl
;
4275 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4276 PRINTERNAME(snum
), the_acl
->num_aces
));
4278 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4281 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4283 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4284 the_acl
->ace
[i
].info
.mask
));
4287 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4291 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
4293 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
4298 /* Work out which user is performing the operation */
4300 get_current_user(&user
, p
);
4302 /* Check the user has permissions to change the security
4303 descriptor. By experimentation with two NT machines, the user
4304 requires Full Access to the printer to change security
4307 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4308 result
= WERR_ACCESS_DENIED
;
4312 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
4319 /********************************************************************
4320 Do Samba sanity checks on a printer info struct.
4321 this has changed purpose: it now "canonicalises" printer
4322 info from a client rather than just checking it is correct
4323 ********************************************************************/
4325 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
4327 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4328 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
4330 /* we force some elements to "correct" values */
4331 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", get_called_name());
4332 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
4333 get_called_name(), lp_servicename(snum
));
4334 fstrcpy(info
->sharename
, lp_servicename(snum
));
4335 info
->attributes
= PRINTER_ATTRIBUTE_SHARED \
4336 | PRINTER_ATTRIBUTE_LOCAL \
4337 | PRINTER_ATTRIBUTE_RAW_ONLY \
4338 | PRINTER_ATTRIBUTE_QUEUED
;
4343 /****************************************************************************
4344 ****************************************************************************/
4345 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
4347 char *cmd
= lp_addprinter_cmd();
4350 pstring driverlocation
;
4355 /* build driver path... only 9X architecture is needed for legacy reasons */
4356 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
4358 /* change \ to \\ for the shell */
4359 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
4361 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4362 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
4363 printer
->info_2
->portname
, printer
->info_2
->drivername
,
4364 printer
->info_2
->location
, driverlocation
);
4366 DEBUG(10,("Running [%s]\n", command
));
4367 ret
= smbrun(command
, &fd
);
4368 DEBUGADD(10,("returned [%d]\n", ret
));
4377 /* Get lines and convert them back to dos-codepage */
4378 qlines
= fd_lines_load(fd
, &numlines
);
4379 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4383 /* Set the portname to what the script says the portname should be. */
4384 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
4385 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
4387 /* Send SIGHUP to process group... is there a better way? */
4392 file_lines_free(qlines
);
4396 /* Return true if two devicemodes are equal */
4398 #define DEVMODE_CHECK_INT(field) \
4399 if (d1->field != d2->field) { \
4400 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4401 d1->field, d2->field)); \
4405 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
4407 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
4410 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4411 return False
; /* if either is exclusively NULL are not equal */
4414 if (!strequal(d1
->devicename
, d2
->devicename
)) {
4415 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1
->devicename
, d2
->devicename
));
4419 if (!strequal(d1
->formname
, d2
->formname
)) {
4420 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1
->formname
, d2
->formname
));
4424 DEVMODE_CHECK_INT(specversion
);
4425 DEVMODE_CHECK_INT(driverversion
);
4426 DEVMODE_CHECK_INT(driverextra
);
4427 DEVMODE_CHECK_INT(orientation
);
4428 DEVMODE_CHECK_INT(papersize
);
4429 DEVMODE_CHECK_INT(paperlength
);
4430 DEVMODE_CHECK_INT(paperwidth
);
4431 DEVMODE_CHECK_INT(scale
);
4432 DEVMODE_CHECK_INT(copies
);
4433 DEVMODE_CHECK_INT(defaultsource
);
4434 DEVMODE_CHECK_INT(printquality
);
4435 DEVMODE_CHECK_INT(color
);
4436 DEVMODE_CHECK_INT(duplex
);
4437 DEVMODE_CHECK_INT(yresolution
);
4438 DEVMODE_CHECK_INT(ttoption
);
4439 DEVMODE_CHECK_INT(collate
);
4440 DEVMODE_CHECK_INT(logpixels
);
4442 DEVMODE_CHECK_INT(fields
);
4443 DEVMODE_CHECK_INT(bitsperpel
);
4444 DEVMODE_CHECK_INT(pelswidth
);
4445 DEVMODE_CHECK_INT(pelsheight
);
4446 DEVMODE_CHECK_INT(displayflags
);
4447 DEVMODE_CHECK_INT(displayfrequency
);
4448 DEVMODE_CHECK_INT(icmmethod
);
4449 DEVMODE_CHECK_INT(icmintent
);
4450 DEVMODE_CHECK_INT(mediatype
);
4451 DEVMODE_CHECK_INT(dithertype
);
4452 DEVMODE_CHECK_INT(reserved1
);
4453 DEVMODE_CHECK_INT(reserved2
);
4454 DEVMODE_CHECK_INT(panningwidth
);
4455 DEVMODE_CHECK_INT(panningheight
);
4457 /* compare the private data if it exists */
4458 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
4461 DEVMODE_CHECK_INT(driverextra
);
4463 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
4464 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4469 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4473 /* Return true if two NT_PRINTER_PARAM structures are equal */
4475 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
4476 NT_PRINTER_PARAM
*p2
)
4478 if (!p1
&& !p2
) goto equal
;
4480 if ((!p1
&& p2
) || (p1
&& !p2
)) {
4481 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4485 /* Compare lists of printer parameters */
4489 NT_PRINTER_PARAM
*q
= p1
;
4491 /* Find the parameter in the second structure */
4495 if (strequal(p1
->value
, q
->value
)) {
4497 if (p1
->type
!= q
->type
) {
4498 DEBUG(10, ("nt_printer_param_equal():"
4499 "types for %s differ (%d != %d)\n",
4500 p1
->value
, p1
->type
,
4505 if (p1
->data_len
!= q
->data_len
) {
4506 DEBUG(10, ("nt_printer_param_equal():"
4507 "len for %s differs (%d != %d)\n",
4508 p1
->value
, p1
->data_len
,
4513 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
4516 DEBUG(10, ("nt_printer_param_equal():"
4517 "data for %s differs\n", p1
->value
));
4527 DEBUG(10, ("nt_printer_param_equal(): param %s "
4528 "does not exist\n", p1
->value
));
4537 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4541 /********************************************************************
4542 * Called by update_printer when trying to work out whether to
4543 * actually update printer info.
4544 ********************************************************************/
4546 #define PI_CHECK_INT(field) \
4547 if (pi1->field != pi2->field) { \
4548 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4549 pi1->field, pi2->field)); \
4553 #define PI_CHECK_STR(field) \
4554 if (!strequal(pi1->field, pi2->field)) { \
4555 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4556 pi1->field, pi2->field)); \
4560 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
4561 NT_PRINTER_INFO_LEVEL
*p2
)
4563 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
4565 /* Trivial conditions */
4567 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
4571 if ((!p1
&& p2
) || (p1
&& !p2
) ||
4572 (!p1
->info_2
&& p2
->info_2
) ||
4573 (p1
->info_2
&& !p2
->info_2
)) {
4574 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4579 /* Compare two nt_printer_info_level structures. Don't compare
4580 status or cjobs as they seem to have something to do with the
4586 /* Don't check the attributes as we stomp on the value in
4587 check_printer_ok() anyway. */
4590 PI_CHECK_INT(attributes
);
4593 PI_CHECK_INT(priority
);
4594 PI_CHECK_INT(default_priority
);
4595 PI_CHECK_INT(starttime
);
4596 PI_CHECK_INT(untiltime
);
4597 PI_CHECK_INT(averageppm
);
4599 /* Yuck - don't check the printername or servername as the
4600 mod_a_printer() code plays games with them. You can't
4601 change the printername or the sharename through this interface
4604 PI_CHECK_STR(sharename
);
4605 PI_CHECK_STR(portname
);
4606 PI_CHECK_STR(drivername
);
4607 PI_CHECK_STR(comment
);
4608 PI_CHECK_STR(location
);
4610 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
4614 PI_CHECK_STR(sepfile
);
4615 PI_CHECK_STR(printprocessor
);
4616 PI_CHECK_STR(datatype
);
4617 PI_CHECK_STR(parameters
);
4619 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
4623 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
4627 PI_CHECK_INT(changeid
);
4628 PI_CHECK_INT(c_setprinter
);
4629 PI_CHECK_INT(setuptime
);
4632 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4636 /********************************************************************
4637 * called by spoolss_api_setprinter
4638 * when updating a printer description
4639 ********************************************************************/
4641 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
4642 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4643 DEVICEMODE
*devmode
)
4646 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
4647 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4650 DEBUG(8,("update_printer\n"));
4655 DEBUG(0,("Send a mail to samba@samba.org\n"));
4656 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4657 result
= WERR_UNKNOWN_LEVEL
;
4662 result
= WERR_BADFID
;
4666 if (!get_printer_snum(p
, handle
, &snum
)) {
4667 result
= WERR_BADFID
;
4671 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
4672 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
4673 result
= WERR_BADFID
;
4677 DEBUGADD(8,("Converting info_2 struct\n"));
4680 * convert_printer_info converts the incoming
4681 * info from the client and overwrites the info
4682 * just read from the tdb in the pointer 'printer'.
4685 if (!convert_printer_info(info
, printer
, level
)) {
4686 result
= WERR_NOMEM
;
4690 if (info
->info_2
->devmode_ptr
!= 0) {
4691 /* we have a valid devmode
4692 convert it and link it*/
4694 DEBUGADD(8,("Converting the devicemode struct\n"));
4695 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
4696 &printer
->info_2
->devmode
)) {
4697 result
= WERR_NOMEM
;
4702 /* Do sanity check on the requested changes for Samba */
4704 if (!check_printer_ok(printer
->info_2
, snum
)) {
4705 result
= WERR_INVALID_PARAM
;
4709 /* NT likes to call this function even though nothing has actually
4710 changed. Check this so the user doesn't end up with an
4711 annoying permission denied dialog box. */
4713 if (nt_printer_info_level_equal(printer
, old_printer
)) {
4714 DEBUG(3, ("printer info has not changed\n"));
4719 /* Check calling user has permission to update printer description */
4721 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4722 DEBUG(3, ("printer property change denied by security "
4724 result
= WERR_ACCESS_DENIED
;
4728 /* Call addprinter hook */
4730 if (*lp_addprinter_cmd()) {
4731 if (!add_printer_hook(printer
)) {
4732 result
= WERR_ACCESS_DENIED
;
4737 /* Update printer info */
4738 result
= mod_a_printer(*printer
, 2);
4741 free_a_printer(&printer
, 2);
4742 free_a_printer(&old_printer
, 2);
4744 srv_spoolss_sendnotify(p
, handle
);
4749 /****************************************************************************
4750 ****************************************************************************/
4752 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
4754 POLICY_HND
*handle
= &q_u
->handle
;
4755 uint32 level
= q_u
->level
;
4756 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
4757 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
4758 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
4759 uint32 command
= q_u
->command
;
4761 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4764 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4768 /* check the level */
4771 return control_printer(handle
, command
, p
);
4773 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
4775 return update_printer_sec(handle
, level
, info
, p
,
4778 return WERR_UNKNOWN_LEVEL
;
4782 /****************************************************************************
4783 ****************************************************************************/
4785 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
4787 POLICY_HND
*handle
= &q_u
->handle
;
4789 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4792 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4796 if (Printer
->notify
.client_connected
==True
)
4797 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
4799 Printer
->notify
.flags
=0;
4800 Printer
->notify
.options
=0;
4801 Printer
->notify
.localmachine
[0]='\0';
4802 Printer
->notify
.printerlocal
=0;
4803 if (Printer
->notify
.option
)
4804 free_spool_notify_option(&Printer
->notify
.option
);
4805 Printer
->notify
.client_connected
=False
;
4810 /****************************************************************************
4811 ****************************************************************************/
4813 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
4815 /* that's an [in out] buffer (despite appearences to the contrary) */
4816 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4819 return WERR_INVALID_PARAM
; /* this is what a NT server
4820 returns for AddJob. AddJob
4821 must fail on non-local
4825 /****************************************************************************
4826 ****************************************************************************/
4827 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
4828 int position
, int snum
)
4834 t
=gmtime(&queue
->time
);
4835 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
4837 job_info
->jobid
=queue
->job
;
4838 init_unistr(&job_info
->printername
, lp_servicename(snum
));
4839 init_unistr(&job_info
->machinename
, temp_name
);
4840 init_unistr(&job_info
->username
, queue
->user
);
4841 init_unistr(&job_info
->document
, queue
->file
);
4842 init_unistr(&job_info
->datatype
, "RAW");
4843 init_unistr(&job_info
->text_status
, "");
4844 job_info
->status
=nt_printj_status(queue
->status
);
4845 job_info
->priority
=queue
->priority
;
4846 job_info
->position
=position
;
4847 job_info
->totalpages
=0;
4848 job_info
->pagesprinted
=0;
4850 make_systemtime(&job_info
->submitted
, t
);
4853 /****************************************************************************
4854 ****************************************************************************/
4855 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
4856 int position
, int snum
,
4857 NT_PRINTER_INFO_LEVEL
*ntprinter
)
4863 t
=gmtime(&queue
->time
);
4864 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", get_called_name());
4866 job_info
->jobid
=queue
->job
;
4868 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", get_called_name(), ntprinter
->info_2
->printername
);
4870 init_unistr(&job_info
->printername
, chaine
);
4872 init_unistr(&job_info
->machinename
, temp_name
);
4873 init_unistr(&job_info
->username
, queue
->user
);
4874 init_unistr(&job_info
->document
, queue
->file
);
4875 init_unistr(&job_info
->notifyname
, queue
->user
);
4876 init_unistr(&job_info
->datatype
, "RAW");
4877 init_unistr(&job_info
->printprocessor
, "winprint");
4878 init_unistr(&job_info
->parameters
, "");
4879 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
4880 init_unistr(&job_info
->text_status
, "");
4882 /* and here the security descriptor */
4884 job_info
->status
=nt_printj_status(queue
->status
);
4885 job_info
->priority
=queue
->priority
;
4886 job_info
->position
=position
;
4887 job_info
->starttime
=0;
4888 job_info
->untiltime
=0;
4889 job_info
->totalpages
=0;
4890 job_info
->size
=queue
->size
;
4891 make_systemtime(&(job_info
->submitted
), t
);
4892 job_info
->timeelapsed
=0;
4893 job_info
->pagesprinted
=0;
4895 if((job_info
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4902 /****************************************************************************
4903 Enumjobs at level 1.
4904 ****************************************************************************/
4905 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
4906 NEW_BUFFER
*buffer
, uint32 offered
,
4907 uint32
*needed
, uint32
*returned
)
4912 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
4919 for (i
=0; i
<*returned
; i
++)
4920 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
4924 /* check the required size. */
4925 for (i
=0; i
<*returned
; i
++)
4926 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
4928 if (!alloc_buffer_size(buffer
, *needed
)) {
4930 return WERR_INSUFFICIENT_BUFFER
;
4933 /* fill the buffer with the structures */
4934 for (i
=0; i
<*returned
; i
++)
4935 smb_io_job_info_1("", buffer
, &info
[i
], 0);
4940 if (*needed
> offered
) {
4942 return WERR_INSUFFICIENT_BUFFER
;
4948 /****************************************************************************
4949 Enumjobs at level 2.
4950 ****************************************************************************/
4951 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
4952 NEW_BUFFER
*buffer
, uint32 offered
,
4953 uint32
*needed
, uint32
*returned
)
4955 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4960 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
4966 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
4967 if (!W_ERROR_IS_OK(result
)) {
4972 for (i
=0; i
<*returned
; i
++)
4973 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
);
4975 free_a_printer(&ntprinter
, 2);
4978 /* check the required size. */
4979 for (i
=0; i
<*returned
; i
++)
4980 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
4982 if (!alloc_buffer_size(buffer
, *needed
)) {
4984 return WERR_INSUFFICIENT_BUFFER
;
4987 /* fill the buffer with the structures */
4988 for (i
=0; i
<*returned
; i
++)
4989 smb_io_job_info_2("", buffer
, &info
[i
], 0);
4992 for (i
= 0; i
< *returned
; i
++)
4993 free_job_info_2(&info
[i
]);
4997 if (*needed
> offered
) {
4999 return WERR_INSUFFICIENT_BUFFER
;
5005 /****************************************************************************
5007 ****************************************************************************/
5009 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
5011 POLICY_HND
*handle
= &q_u
->handle
;
5012 /* uint32 firstjob = q_u->firstjob; - notused. */
5013 /* uint32 numofjobs = q_u->numofjobs; - notused. */
5014 uint32 level
= q_u
->level
;
5015 NEW_BUFFER
*buffer
= NULL
;
5016 uint32 offered
= q_u
->offered
;
5017 uint32
*needed
= &r_u
->needed
;
5018 uint32
*returned
= &r_u
->returned
;
5021 print_status_struct prt_status
;
5022 print_queue_struct
*queue
=NULL
;
5024 /* that's an [in out] buffer */
5025 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5026 buffer
= r_u
->buffer
;
5028 DEBUG(4,("_spoolss_enumjobs\n"));
5033 if (!get_printer_snum(p
, handle
, &snum
))
5036 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
5037 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
5039 if (*returned
== 0) {
5046 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
5048 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
5052 return WERR_UNKNOWN_LEVEL
;
5056 /****************************************************************************
5057 ****************************************************************************/
5059 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
5064 /****************************************************************************
5065 ****************************************************************************/
5067 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
5069 POLICY_HND
*handle
= &q_u
->handle
;
5070 uint32 jobid
= q_u
->jobid
;
5071 /* uint32 level = q_u->level; - notused. */
5072 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
5073 uint32 command
= q_u
->command
;
5075 struct current_user user
;
5077 WERROR errcode
= WERR_BADFUNC
;
5079 if (!get_printer_snum(p
, handle
, &snum
)) {
5083 if (!print_job_exists(jobid
)) {
5084 return WERR_INVALID_PRINTER_NAME
;
5087 get_current_user(&user
, p
);
5090 case JOB_CONTROL_CANCEL
:
5091 case JOB_CONTROL_DELETE
:
5092 if (print_job_delete(&user
, jobid
, &errcode
)) {
5096 case JOB_CONTROL_PAUSE
:
5097 if (print_job_pause(&user
, jobid
, &errcode
)) {
5101 case JOB_CONTROL_RESTART
:
5102 case JOB_CONTROL_RESUME
:
5103 if (print_job_resume(&user
, jobid
, &errcode
)) {
5108 return WERR_UNKNOWN_LEVEL
;
5114 /****************************************************************************
5115 Enumerates all printer drivers at level 1.
5116 ****************************************************************************/
5117 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5122 fstring
*list
= NULL
;
5124 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5125 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5129 #define MAX_VERSION 4
5131 for (version
=0; version
<MAX_VERSION
; version
++) {
5133 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5134 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5140 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5141 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5142 SAFE_FREE(driver_info_1
);
5146 else driver_info_1
= tdi1
;
5149 for (i
=0; i
<ndrivers
; i
++) {
5151 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5152 ZERO_STRUCT(driver
);
5153 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5154 architecture
, version
);
5155 if (!W_ERROR_IS_OK(status
)) {
5159 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5160 free_a_printer_driver(driver
, 3);
5163 *returned
+=ndrivers
;
5167 /* check the required size. */
5168 for (i
=0; i
<*returned
; i
++) {
5169 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5170 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5173 if (!alloc_buffer_size(buffer
, *needed
)) {
5174 SAFE_FREE(driver_info_1
);
5175 return WERR_INSUFFICIENT_BUFFER
;
5178 /* fill the buffer with the driver structures */
5179 for (i
=0; i
<*returned
; i
++) {
5180 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5181 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5184 SAFE_FREE(driver_info_1
);
5186 if (*needed
> offered
) {
5188 return WERR_INSUFFICIENT_BUFFER
;
5194 /****************************************************************************
5195 Enumerates all printer drivers at level 2.
5196 ****************************************************************************/
5197 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5202 fstring
*list
= NULL
;
5204 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5205 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
5209 #define MAX_VERSION 4
5211 for (version
=0; version
<MAX_VERSION
; version
++) {
5213 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5214 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5220 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
5221 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5222 SAFE_FREE(driver_info_2
);
5226 else driver_info_2
= tdi2
;
5229 for (i
=0; i
<ndrivers
; i
++) {
5232 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5233 ZERO_STRUCT(driver
);
5234 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5235 architecture
, version
);
5236 if (!W_ERROR_IS_OK(status
)) {
5240 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
5241 free_a_printer_driver(driver
, 3);
5244 *returned
+=ndrivers
;
5248 /* check the required size. */
5249 for (i
=0; i
<*returned
; i
++) {
5250 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5251 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
5254 if (!alloc_buffer_size(buffer
, *needed
)) {
5255 SAFE_FREE(driver_info_2
);
5256 return WERR_INSUFFICIENT_BUFFER
;
5259 /* fill the buffer with the form structures */
5260 for (i
=0; i
<*returned
; i
++) {
5261 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5262 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
5265 SAFE_FREE(driver_info_2
);
5267 if (*needed
> offered
) {
5269 return WERR_INSUFFICIENT_BUFFER
;
5275 /****************************************************************************
5276 Enumerates all printer drivers at level 3.
5277 ****************************************************************************/
5278 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5283 fstring
*list
= NULL
;
5285 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5286 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
5290 #define MAX_VERSION 4
5292 for (version
=0; version
<MAX_VERSION
; version
++) {
5294 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5295 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5301 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
5302 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5303 SAFE_FREE(driver_info_3
);
5307 else driver_info_3
= tdi3
;
5310 for (i
=0; i
<ndrivers
; i
++) {
5313 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5314 ZERO_STRUCT(driver
);
5315 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5316 architecture
, version
);
5317 if (!W_ERROR_IS_OK(status
)) {
5321 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
5322 free_a_printer_driver(driver
, 3);
5325 *returned
+=ndrivers
;
5329 /* check the required size. */
5330 for (i
=0; i
<*returned
; i
++) {
5331 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5332 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
5335 if (!alloc_buffer_size(buffer
, *needed
)) {
5336 SAFE_FREE(driver_info_3
);
5337 return WERR_INSUFFICIENT_BUFFER
;
5340 /* fill the buffer with the driver structures */
5341 for (i
=0; i
<*returned
; i
++) {
5342 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5343 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
5346 for (i
=0; i
<*returned
; i
++)
5347 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
5349 SAFE_FREE(driver_info_3
);
5351 if (*needed
> offered
) {
5353 return WERR_INSUFFICIENT_BUFFER
;
5359 /****************************************************************************
5360 Enumerates all printer drivers.
5361 ****************************************************************************/
5363 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
5365 /* UNISTR2 *name = &q_u->name; - notused. */
5366 UNISTR2
*environment
= &q_u
->environment
;
5367 uint32 level
= q_u
->level
;
5368 NEW_BUFFER
*buffer
= NULL
;
5369 uint32 offered
= q_u
->offered
;
5370 uint32
*needed
= &r_u
->needed
;
5371 uint32
*returned
= &r_u
->returned
;
5373 fstring
*list
= NULL
;
5375 fstring architecture
;
5377 /* that's an [in out] buffer */
5378 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5379 buffer
= r_u
->buffer
;
5381 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5382 fstrcpy(servername
, get_called_name());
5386 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
5390 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
5392 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
5394 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
5398 return WERR_UNKNOWN_LEVEL
;
5402 /****************************************************************************
5403 ****************************************************************************/
5405 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
5407 form
->flag
=list
->flag
;
5408 init_unistr(&form
->name
, list
->name
);
5409 form
->width
=list
->width
;
5410 form
->length
=list
->length
;
5411 form
->left
=list
->left
;
5412 form
->top
=list
->top
;
5413 form
->right
=list
->right
;
5414 form
->bottom
=list
->bottom
;
5417 /****************************************************************************
5418 ****************************************************************************/
5420 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
5422 /* POLICY_HND *handle = &q_u->handle; - notused. */
5423 uint32 level
= q_u
->level
;
5424 NEW_BUFFER
*buffer
= NULL
;
5425 uint32 offered
= q_u
->offered
;
5426 uint32
*needed
= &r_u
->needed
;
5427 uint32
*numofforms
= &r_u
->numofforms
;
5428 uint32 numbuiltinforms
;
5430 nt_forms_struct
*list
=NULL
;
5431 nt_forms_struct
*builtinlist
=NULL
;
5436 /* that's an [in out] buffer */
5437 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5438 buffer
= r_u
->buffer
;
5440 DEBUG(4,("_spoolss_enumforms\n"));
5441 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
5442 DEBUGADD(5,("Info level [%d]\n", level
));
5444 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
5445 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
5446 *numofforms
= get_ntforms(&list
);
5447 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
5448 *numofforms
+= numbuiltinforms
;
5450 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
5454 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
5459 /* construct the list of form structures */
5460 for (i
=0; i
<numbuiltinforms
; i
++) {
5461 DEBUGADD(6,("Filling form number [%d]\n",i
));
5462 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
5465 SAFE_FREE(builtinlist
);
5467 for (; i
<*numofforms
; i
++) {
5468 DEBUGADD(6,("Filling form number [%d]\n",i
));
5469 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
5474 /* check the required size. */
5475 for (i
=0; i
<numbuiltinforms
; i
++) {
5476 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5477 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5479 for (; i
<*numofforms
; i
++) {
5480 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5481 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5484 *needed
=buffer_size
;
5486 if (!alloc_buffer_size(buffer
, buffer_size
)){
5488 return WERR_INSUFFICIENT_BUFFER
;
5491 /* fill the buffer with the form structures */
5492 for (i
=0; i
<numbuiltinforms
; i
++) {
5493 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5494 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5496 for (; i
<*numofforms
; i
++) {
5497 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5498 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5503 if (*needed
> offered
) {
5505 return WERR_INSUFFICIENT_BUFFER
;
5512 SAFE_FREE(builtinlist
);
5513 return WERR_UNKNOWN_LEVEL
;
5518 /****************************************************************************
5519 ****************************************************************************/
5521 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
5523 /* POLICY_HND *handle = &q_u->handle; - notused. */
5524 uint32 level
= q_u
->level
;
5525 UNISTR2
*uni_formname
= &q_u
->formname
;
5526 NEW_BUFFER
*buffer
= NULL
;
5527 uint32 offered
= q_u
->offered
;
5528 uint32
*needed
= &r_u
->needed
;
5530 nt_forms_struct
*list
=NULL
;
5531 nt_forms_struct builtin_form
;
5536 int numofforms
=0, i
=0;
5538 /* that's an [in out] buffer */
5539 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5540 buffer
= r_u
->buffer
;
5542 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
5544 DEBUG(4,("_spoolss_getform\n"));
5545 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
5546 DEBUGADD(5,("Info level [%d]\n", level
));
5548 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
5549 if (!foundBuiltin
) {
5550 numofforms
= get_ntforms(&list
);
5551 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
5553 if (numofforms
== 0)
5560 fill_form_1(&form_1
, &builtin_form
);
5563 /* Check if the requested name is in the list of form structures */
5564 for (i
=0; i
<numofforms
; i
++) {
5566 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
5568 if (strequal(form_name
, list
[i
].name
)) {
5569 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
5570 fill_form_1(&form_1
, &list
[i
]);
5576 if (i
== numofforms
) {
5580 /* check the required size. */
5582 *needed
=spoolss_size_form_1(&form_1
);
5584 if (!alloc_buffer_size(buffer
, buffer_size
)){
5585 return WERR_INSUFFICIENT_BUFFER
;
5588 if (*needed
> offered
) {
5589 return WERR_INSUFFICIENT_BUFFER
;
5592 /* fill the buffer with the form structures */
5593 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
5594 smb_io_form_1("", buffer
, &form_1
, 0);
5600 return WERR_UNKNOWN_LEVEL
;
5604 /****************************************************************************
5605 ****************************************************************************/
5606 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
5608 init_unistr(&port
->port_name
, name
);
5611 /****************************************************************************
5612 ****************************************************************************/
5613 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
5615 init_unistr(&port
->port_name
, name
);
5616 init_unistr(&port
->monitor_name
, "Local Monitor");
5617 init_unistr(&port
->description
, "Local Port");
5618 #define PORT_TYPE_WRITE 1
5619 port
->port_type
=PORT_TYPE_WRITE
;
5623 /****************************************************************************
5625 ****************************************************************************/
5626 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5628 PORT_INFO_1
*ports
=NULL
;
5631 if (*lp_enumports_cmd()) {
5632 char *cmd
= lp_enumports_cmd();
5639 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
5641 DEBUG(10,("Running [%s]\n", command
));
5642 ret
= smbrun(command
, &fd
);
5643 DEBUG(10,("Returned [%d]\n", ret
));
5647 /* Is this the best error to return here? */
5648 return WERR_ACCESS_DENIED
;
5652 qlines
= fd_lines_load(fd
, &numlines
);
5653 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5657 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
5658 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5659 werror_str(WERR_NOMEM
)));
5660 file_lines_free(qlines
);
5664 for (i
=0; i
<numlines
; i
++) {
5665 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
5666 fill_port_1(&ports
[i
], qlines
[i
]);
5669 file_lines_free(qlines
);
5672 *returned
= numlines
;
5675 *returned
= 1; /* Sole Samba port returned. */
5677 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
5680 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
5682 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
5685 /* check the required size. */
5686 for (i
=0; i
<*returned
; i
++) {
5687 DEBUGADD(6,("adding port [%d]'s size\n", i
));
5688 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
5691 if (!alloc_buffer_size(buffer
, *needed
)) {
5693 return WERR_INSUFFICIENT_BUFFER
;
5696 /* fill the buffer with the ports structures */
5697 for (i
=0; i
<*returned
; i
++) {
5698 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
5699 smb_io_port_1("", buffer
, &ports
[i
], 0);
5704 if (*needed
> offered
) {
5706 return WERR_INSUFFICIENT_BUFFER
;
5712 /****************************************************************************
5714 ****************************************************************************/
5716 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5718 PORT_INFO_2
*ports
=NULL
;
5721 if (*lp_enumports_cmd()) {
5722 char *cmd
= lp_enumports_cmd();
5731 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
5732 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
5734 path
= lp_lockdir();
5736 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
5737 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
5740 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
5741 ret
= smbrun(command
, &fd
);
5742 DEBUGADD(10,("returned [%d]\n", ret
));
5746 /* Is this the best error to return here? */
5747 return WERR_ACCESS_DENIED
;
5751 qlines
= fd_lines_load(fd
, &numlines
);
5752 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5756 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
5757 file_lines_free(qlines
);
5761 for (i
=0; i
<numlines
; i
++) {
5762 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
5763 fill_port_2(&(ports
[i
]), qlines
[i
]);
5766 file_lines_free(qlines
);
5769 *returned
= numlines
;
5775 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
5778 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
5780 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
5783 /* check the required size. */
5784 for (i
=0; i
<*returned
; i
++) {
5785 DEBUGADD(6,("adding port [%d]'s size\n", i
));
5786 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
5789 if (!alloc_buffer_size(buffer
, *needed
)) {
5791 return WERR_INSUFFICIENT_BUFFER
;
5794 /* fill the buffer with the ports structures */
5795 for (i
=0; i
<*returned
; i
++) {
5796 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
5797 smb_io_port_2("", buffer
, &ports
[i
], 0);
5802 if (*needed
> offered
) {
5804 return WERR_INSUFFICIENT_BUFFER
;
5810 /****************************************************************************
5812 ****************************************************************************/
5814 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
5816 /* UNISTR2 *name = &q_u->name; - notused. */
5817 uint32 level
= q_u
->level
;
5818 NEW_BUFFER
*buffer
= NULL
;
5819 uint32 offered
= q_u
->offered
;
5820 uint32
*needed
= &r_u
->needed
;
5821 uint32
*returned
= &r_u
->returned
;
5823 /* that's an [in out] buffer */
5824 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5825 buffer
= r_u
->buffer
;
5827 DEBUG(4,("_spoolss_enumports\n"));
5834 return enumports_level_1(buffer
, offered
, needed
, returned
);
5836 return enumports_level_2(buffer
, offered
, needed
, returned
);
5838 return WERR_UNKNOWN_LEVEL
;
5842 /****************************************************************************
5843 ****************************************************************************/
5844 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
5845 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5846 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
5847 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
5850 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5853 WERROR err
= WERR_OK
;
5855 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
5856 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5860 ZERO_STRUCTP(printer
);
5862 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5863 if (!convert_printer_info(info
, printer
, 2)) {
5864 free_a_printer(&printer
, 2);
5868 /* check to see if the printer already exists */
5870 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
5871 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5872 printer
->info_2
->sharename
));
5873 free_a_printer(&printer
, 2);
5874 return WERR_PRINTER_ALREADY_EXISTS
;
5877 if (*lp_addprinter_cmd() )
5878 if ( !add_printer_hook(printer
) ) {
5879 free_a_printer(&printer
,2);
5880 return WERR_ACCESS_DENIED
;
5883 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", get_called_name(),
5884 printer
->info_2
->sharename
);
5886 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
5887 free_a_printer(&printer
,2);
5888 return WERR_ACCESS_DENIED
;
5891 /* you must be a printer admin to add a new printer */
5892 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5893 free_a_printer(&printer
,2);
5894 return WERR_ACCESS_DENIED
;
5898 * Do sanity check on the requested changes for Samba.
5901 if (!check_printer_ok(printer
->info_2
, snum
)) {
5902 free_a_printer(&printer
,2);
5903 return WERR_INVALID_PARAM
;
5907 * When a printer is created, the drivername bound to the printer is used
5908 * to lookup previously saved driver initialization info, which is then
5909 * bound to the new printer, simulating what happens in the Windows arch.
5911 set_driver_init(printer
, 2);
5913 /* write the ASCII on disk */
5914 err
= mod_a_printer(*printer
, 2);
5915 if (!W_ERROR_IS_OK(err
)) {
5916 free_a_printer(&printer
,2);
5920 if (!open_printer_hnd(p
, handle
, name
)) {
5921 /* Handle open failed - remove addition. */
5922 del_a_printer(printer
->info_2
->sharename
);
5923 free_a_printer(&printer
,2);
5924 return WERR_ACCESS_DENIED
;
5927 free_a_printer(&printer
,2);
5929 srv_spoolss_sendnotify(p
, handle
);
5934 /****************************************************************************
5935 ****************************************************************************/
5937 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
5939 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
5940 uint32 level
= q_u
->level
;
5941 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5942 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
5943 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
5944 uint32 user_switch
= q_u
->user_switch
;
5945 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
5946 POLICY_HND
*handle
= &r_u
->handle
;
5950 /* we don't handle yet */
5951 /* but I know what to do ... */
5952 return WERR_UNKNOWN_LEVEL
;
5954 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
5956 user_switch
, user
, handle
);
5958 return WERR_UNKNOWN_LEVEL
;
5962 /****************************************************************************
5963 ****************************************************************************/
5965 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
5967 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5968 uint32 level
= q_u
->level
;
5969 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
5970 WERROR err
= WERR_OK
;
5971 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5972 struct current_user user
;
5974 ZERO_STRUCT(driver
);
5976 get_current_user(&user
, p
);
5978 if (!convert_printer_driver_info(info
, &driver
, level
)) {
5983 DEBUG(5,("Cleaning driver's information\n"));
5984 err
= clean_up_driver_struct(driver
, level
, &user
);
5985 if (!W_ERROR_IS_OK(err
))
5988 DEBUG(5,("Moving driver to final destination\n"));
5989 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
5990 if (W_ERROR_IS_OK(err
))
5991 err
= WERR_ACCESS_DENIED
;
5995 if (add_a_printer_driver(driver
, level
)!=0) {
5996 err
= WERR_ACCESS_DENIED
;
6001 free_a_printer_driver(driver
, level
);
6005 /****************************************************************************
6006 ****************************************************************************/
6007 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
6009 init_unistr(&info
->name
, name
);
6012 /****************************************************************************
6013 ****************************************************************************/
6014 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6018 pstring short_archi
;
6019 DRIVER_DIRECTORY_1
*info
=NULL
;
6021 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
6023 if (get_short_archi(short_archi
, long_archi
)==False
)
6024 return WERR_INVALID_ENVIRONMENT
;
6026 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
6029 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
6031 DEBUG(4,("printer driver directory: [%s]\n", path
));
6033 fill_driverdir_1(info
, path
);
6035 *needed
+= spoolss_size_driverdir_info_1(info
);
6037 if (!alloc_buffer_size(buffer
, *needed
)) {
6039 return WERR_INSUFFICIENT_BUFFER
;
6042 smb_io_driverdir_1("", buffer
, info
, 0);
6046 if (*needed
> offered
)
6047 return WERR_INSUFFICIENT_BUFFER
;
6052 /****************************************************************************
6053 ****************************************************************************/
6055 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
6057 UNISTR2
*name
= &q_u
->name
;
6058 UNISTR2
*uni_environment
= &q_u
->environment
;
6059 uint32 level
= q_u
->level
;
6060 NEW_BUFFER
*buffer
= NULL
;
6061 uint32 offered
= q_u
->offered
;
6062 uint32
*needed
= &r_u
->needed
;
6064 /* that's an [in out] buffer */
6065 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6066 buffer
= r_u
->buffer
;
6068 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
6074 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
6076 return WERR_UNKNOWN_LEVEL
;
6080 /****************************************************************************
6081 ****************************************************************************/
6083 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
6085 POLICY_HND
*handle
= &q_u
->handle
;
6086 uint32 idx
= q_u
->index
;
6087 uint32 in_value_len
= q_u
->valuesize
;
6088 uint32 in_data_len
= q_u
->datasize
;
6089 uint32
*out_max_value_len
= &r_u
->valuesize
;
6090 uint16
**out_value
= &r_u
->value
;
6091 uint32
*out_value_len
= &r_u
->realvaluesize
;
6092 uint32
*out_type
= &r_u
->type
;
6093 uint32
*out_max_data_len
= &r_u
->datasize
;
6094 uint8
**data_out
= &r_u
->data
;
6095 uint32
*out_data_len
= &r_u
->realdatasize
;
6097 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6102 uint32 biggest_valuesize
;
6103 uint32 biggest_datasize
;
6105 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6111 ZERO_STRUCT(printer
);
6115 *out_max_data_len
=0;
6119 DEBUG(5,("spoolss_enumprinterdata\n"));
6122 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6126 if (!get_printer_snum(p
,handle
, &snum
))
6129 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6130 if (!W_ERROR_IS_OK(result
))
6134 * The NT machine wants to know the biggest size of value and data
6136 * cf: MSDN EnumPrinterData remark section
6138 if ( (in_value_len
==0) && (in_data_len
==0) ) {
6139 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6143 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6144 * if this parameter size doesn't exist.
6145 * Ok - my opinion here is that the client is not asking for the greatest
6146 * possible size of all the parameters, but is asking specifically for the size needed
6147 * for this specific parameter. In that case we can remove the loop below and
6148 * simplify this lookup code considerably. JF - comments welcome. JRA.
6151 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6153 free_a_printer(&printer
, 2);
6154 return WERR_NO_MORE_ITEMS
;
6161 biggest_valuesize
=0;
6164 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
6165 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
6166 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
6168 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
6174 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6175 *out_value_len
=2*(1+biggest_valuesize
);
6176 *out_data_len
=biggest_datasize
;
6178 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
6180 free_a_printer(&printer
, 2);
6185 * the value len is wrong in NT sp3
6186 * that's the number of bytes not the number of unicode chars
6189 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6192 free_a_printer(&printer
, 2);
6194 /* out_value should default to "" or else NT4 has
6195 problems unmarshalling the response */
6197 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6198 if((*out_value
=(uint16
*)malloc(in_value_len
*sizeof(uint8
))) == NULL
)
6201 ZERO_STRUCTP(*out_value
);
6202 *out_value_len
= rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
6204 /* the data is counted in bytes */
6205 *out_max_data_len
= in_data_len
;
6206 *out_data_len
= in_data_len
;
6207 if((*data_out
=(uint8
*)malloc(in_data_len
*sizeof(uint8
))) == NULL
)
6210 memset(*data_out
,'\0',in_data_len
);
6212 return WERR_NO_MORE_ITEMS
;
6215 free_a_printer(&printer
, 2);
6219 * - counted in bytes in the request
6220 * - counted in UNICODE chars in the max reply
6221 * - counted in bytes in the real size
6223 * take a pause *before* coding not *during* coding
6226 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6227 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
,in_value_len
*sizeof(uint8
))) == NULL
) {
6232 *out_value_len
= rpcstr_push((char *)*out_value
,value
, in_value_len
, 0);
6236 /* the data is counted in bytes */
6237 *out_max_data_len
=in_data_len
;
6238 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) {
6243 memcpy(*data_out
, data
, (size_t)data_len
);
6244 *out_data_len
=data_len
;
6251 /****************************************************************************
6252 ****************************************************************************/
6254 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
6256 POLICY_HND
*handle
= &q_u
->handle
;
6257 UNISTR2
*value
= &q_u
->value
;
6258 uint32 type
= q_u
->type
;
6259 /* uint32 max_len = q_u->max_len; - notused. */
6260 uint8
*data
= q_u
->data
;
6261 uint32 real_len
= q_u
->real_len
;
6262 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6264 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6265 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
6267 WERROR status
= WERR_OK
;
6268 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6270 DEBUG(5,("spoolss_setprinterdata\n"));
6273 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6277 if (!get_printer_snum(p
,handle
, &snum
))
6280 ZERO_STRUCT(old_param
);
6283 * Access check : NT returns "access denied" if you make a
6284 * SetPrinterData call without the necessary privildge.
6285 * we were originally returning OK if nothing changed
6286 * which made Win2k issue **a lot** of SetPrinterData
6287 * when connecting to a printer --jerry
6290 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6291 DEBUG(3, ("security descriptor change denied by existing "
6292 "security descriptor\n"));
6293 status
= WERR_ACCESS_DENIED
;
6297 /* Check if we are making any changes or not. Return true if
6298 nothing is actually changing. This is not needed anymore but
6299 has been left in as an optimization to keep from from
6300 writing to disk as often --jerry */
6302 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6303 if (!W_ERROR_IS_OK(status
))
6306 convert_specific_param(¶m
, value
, type
, data
, real_len
);
6309 if (get_specific_param(*printer
, 2, param
->value
, &old_param
.data
,
6310 &old_param
.type
, (uint32
*)&old_param
.data_len
)) {
6312 if (param
->type
== old_param
.type
&&
6313 param
->data_len
== old_param
.data_len
&&
6314 memcmp(param
->data
, old_param
.data
,
6315 old_param
.data_len
) == 0) {
6317 DEBUG(3, ("setprinterdata hasn't changed\n"));
6324 unlink_specific_param_if_exist(printer
->info_2
, param
);
6327 * When client side code sets a magic printer data key, detect it and save
6328 * the current printer data and the magic key's data (its the DEVMODE) for
6329 * future printer/driver initializations.
6331 if (param
->type
==3 && !strcmp( param
->value
, PHANTOM_DEVMODE_KEY
)) {
6333 * Set devmode and printer initialization info
6335 status
= save_driver_init(printer
, 2, param
);
6338 add_a_specific_param(printer
->info_2
, ¶m
);
6339 status
= mod_a_printer(*printer
, 2);
6343 free_a_printer(&printer
, 2);
6345 free_nt_printer_param(¶m
);
6346 SAFE_FREE(old_param
.data
);
6351 /****************************************************************************
6352 ****************************************************************************/
6354 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
6356 POLICY_HND
*handle
= &q_u
->handle
;
6357 UNISTR2
*value
= &q_u
->valuename
;
6359 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6360 NT_PRINTER_PARAM param
;
6362 WERROR status
= WERR_OK
;
6363 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6365 DEBUG(5,("spoolss_deleteprinterdata\n"));
6368 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6372 if (!get_printer_snum(p
, handle
, &snum
))
6375 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6376 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6377 "change denied by existing security descriptor\n"));
6378 return WERR_ACCESS_DENIED
;
6381 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6382 if (!W_ERROR_IS_OK(status
))
6385 ZERO_STRUCTP(¶m
);
6386 unistr2_to_ascii(param
.value
, value
, sizeof(param
.value
)-1);
6388 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
6389 status
= WERR_INVALID_PARAM
;
6391 status
= mod_a_printer(*printer
, 2);
6393 free_a_printer(&printer
, 2);
6397 /****************************************************************************
6398 ****************************************************************************/
6400 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
6402 POLICY_HND
*handle
= &q_u
->handle
;
6403 /* uint32 level = q_u->level; - notused. */
6404 FORM
*form
= &q_u
->form
;
6405 nt_forms_struct tmpForm
;
6408 nt_forms_struct
*list
=NULL
;
6409 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6411 DEBUG(5,("spoolss_addform\n"));
6414 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6419 * FIXME!! Feels like there should be an access check here, but haven't
6420 * had time to verify. --jerry
6423 /* can't add if builtin */
6424 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
6425 return WERR_INVALID_PARAM
;
6428 count
=get_ntforms(&list
);
6429 if(!add_a_form(&list
, form
, &count
))
6431 write_ntforms(&list
, count
);
6438 /****************************************************************************
6439 ****************************************************************************/
6441 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
6443 POLICY_HND
*handle
= &q_u
->handle
;
6444 UNISTR2
*form_name
= &q_u
->name
;
6445 nt_forms_struct tmpForm
;
6447 WERROR ret
= WERR_OK
;
6448 nt_forms_struct
*list
=NULL
;
6449 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6451 DEBUG(5,("spoolss_deleteform\n"));
6454 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6458 /* can't delete if builtin */
6459 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
6460 return WERR_INVALID_PARAM
;
6463 count
= get_ntforms(&list
);
6464 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
6465 return WERR_INVALID_PARAM
;
6472 /****************************************************************************
6473 ****************************************************************************/
6475 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
6477 POLICY_HND
*handle
= &q_u
->handle
;
6478 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6479 /* uint32 level = q_u->level; - notused. */
6480 FORM
*form
= &q_u
->form
;
6481 nt_forms_struct tmpForm
;
6484 nt_forms_struct
*list
=NULL
;
6485 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6487 DEBUG(5,("spoolss_setform\n"));
6490 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6493 /* can't set if builtin */
6494 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
6495 return WERR_INVALID_PARAM
;
6498 count
=get_ntforms(&list
);
6499 update_a_form(&list
, form
, count
);
6500 write_ntforms(&list
, count
);
6507 /****************************************************************************
6508 enumprintprocessors level 1.
6509 ****************************************************************************/
6510 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6512 PRINTPROCESSOR_1
*info_1
=NULL
;
6514 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
6519 init_unistr(&info_1
->name
, "winprint");
6521 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
6523 if (!alloc_buffer_size(buffer
, *needed
))
6524 return WERR_INSUFFICIENT_BUFFER
;
6526 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
6530 if (*needed
> offered
) {
6532 return WERR_INSUFFICIENT_BUFFER
;
6538 /****************************************************************************
6539 ****************************************************************************/
6541 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
6543 /* UNISTR2 *name = &q_u->name; - notused. */
6544 /* UNISTR2 *environment = &q_u->environment; - notused. */
6545 uint32 level
= q_u
->level
;
6546 NEW_BUFFER
*buffer
= NULL
;
6547 uint32 offered
= q_u
->offered
;
6548 uint32
*needed
= &r_u
->needed
;
6549 uint32
*returned
= &r_u
->returned
;
6551 /* that's an [in out] buffer */
6552 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6553 buffer
= r_u
->buffer
;
6555 DEBUG(5,("spoolss_enumprintprocessors\n"));
6558 * Enumerate the print processors ...
6560 * Just reply with "winprint", to keep NT happy
6561 * and I can use my nice printer checker.
6569 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
6571 return WERR_UNKNOWN_LEVEL
;
6575 /****************************************************************************
6576 enumprintprocdatatypes level 1.
6577 ****************************************************************************/
6578 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6580 PRINTPROCDATATYPE_1
*info_1
=NULL
;
6582 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
6587 init_unistr(&info_1
->name
, "RAW");
6589 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
6591 if (!alloc_buffer_size(buffer
, *needed
))
6592 return WERR_INSUFFICIENT_BUFFER
;
6594 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
6598 if (*needed
> offered
) {
6600 return WERR_INSUFFICIENT_BUFFER
;
6606 /****************************************************************************
6607 ****************************************************************************/
6609 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
6611 /* UNISTR2 *name = &q_u->name; - notused. */
6612 /* UNISTR2 *processor = &q_u->processor; - notused. */
6613 uint32 level
= q_u
->level
;
6614 NEW_BUFFER
*buffer
= NULL
;
6615 uint32 offered
= q_u
->offered
;
6616 uint32
*needed
= &r_u
->needed
;
6617 uint32
*returned
= &r_u
->returned
;
6619 /* that's an [in out] buffer */
6620 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6621 buffer
= r_u
->buffer
;
6623 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6630 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
6632 return WERR_UNKNOWN_LEVEL
;
6636 /****************************************************************************
6637 enumprintmonitors level 1.
6638 ****************************************************************************/
6640 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6642 PRINTMONITOR_1
*info_1
=NULL
;
6644 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
6649 init_unistr(&info_1
->name
, "Local Port");
6651 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
6653 if (!alloc_buffer_size(buffer
, *needed
))
6654 return WERR_INSUFFICIENT_BUFFER
;
6656 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
6660 if (*needed
> offered
) {
6662 return WERR_INSUFFICIENT_BUFFER
;
6668 /****************************************************************************
6669 enumprintmonitors level 2.
6670 ****************************************************************************/
6671 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6673 PRINTMONITOR_2
*info_2
=NULL
;
6675 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
6680 init_unistr(&info_2
->name
, "Local Port");
6681 init_unistr(&info_2
->environment
, "Windows NT X86");
6682 init_unistr(&info_2
->dll_name
, "localmon.dll");
6684 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
6686 if (!alloc_buffer_size(buffer
, *needed
))
6687 return WERR_INSUFFICIENT_BUFFER
;
6689 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
6693 if (*needed
> offered
) {
6695 return WERR_INSUFFICIENT_BUFFER
;
6701 /****************************************************************************
6702 ****************************************************************************/
6704 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
6706 /* UNISTR2 *name = &q_u->name; - notused. */
6707 uint32 level
= q_u
->level
;
6708 NEW_BUFFER
*buffer
= NULL
;
6709 uint32 offered
= q_u
->offered
;
6710 uint32
*needed
= &r_u
->needed
;
6711 uint32
*returned
= &r_u
->returned
;
6713 /* that's an [in out] buffer */
6714 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6715 buffer
= r_u
->buffer
;
6717 DEBUG(5,("spoolss_enumprintmonitors\n"));
6720 * Enumerate the print monitors ...
6722 * Just reply with "Local Port", to keep NT happy
6723 * and I can use my nice printer checker.
6731 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
6733 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
6735 return WERR_UNKNOWN_LEVEL
;
6739 /****************************************************************************
6740 ****************************************************************************/
6741 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6745 JOB_INFO_1
*info_1
=NULL
;
6747 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
6749 if (info_1
== NULL
) {
6754 for (i
=0; i
<count
&& found
==False
; i
++) {
6755 if (queue
[i
].job
==(int)jobid
)
6762 /* NT treats not found as bad param... yet another bad choice */
6763 return WERR_INVALID_PARAM
;
6766 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
6770 *needed
+= spoolss_size_job_info_1(info_1
);
6772 if (!alloc_buffer_size(buffer
, *needed
)) {
6774 return WERR_INSUFFICIENT_BUFFER
;
6777 smb_io_job_info_1("", buffer
, info_1
, 0);
6781 if (*needed
> offered
)
6782 return WERR_INSUFFICIENT_BUFFER
;
6788 /****************************************************************************
6789 ****************************************************************************/
6790 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6795 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6798 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
6800 ZERO_STRUCTP(info_2
);
6802 if (info_2
== NULL
) {
6807 for (i
=0; i
<count
&& found
==False
; i
++) {
6808 if (queue
[i
].job
==(int)jobid
)
6815 /* NT treats not found as bad param... yet another bad choice */
6816 return WERR_INVALID_PARAM
;
6819 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6820 if (!W_ERROR_IS_OK(ret
)) {
6825 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
);
6827 free_a_printer(&ntprinter
, 2);
6830 *needed
+= spoolss_size_job_info_2(info_2
);
6832 if (!alloc_buffer_size(buffer
, *needed
)) {
6834 return WERR_INSUFFICIENT_BUFFER
;
6837 smb_io_job_info_2("", buffer
, info_2
, 0);
6839 free_job_info_2(info_2
);
6842 if (*needed
> offered
)
6843 return WERR_INSUFFICIENT_BUFFER
;
6848 /****************************************************************************
6849 ****************************************************************************/
6851 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
6853 POLICY_HND
*handle
= &q_u
->handle
;
6854 uint32 jobid
= q_u
->jobid
;
6855 uint32 level
= q_u
->level
;
6856 NEW_BUFFER
*buffer
= NULL
;
6857 uint32 offered
= q_u
->offered
;
6858 uint32
*needed
= &r_u
->needed
;
6862 print_queue_struct
*queue
=NULL
;
6863 print_status_struct prt_status
;
6865 /* that's an [in out] buffer */
6866 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6867 buffer
= r_u
->buffer
;
6869 DEBUG(5,("spoolss_getjob\n"));
6873 if (!get_printer_snum(p
, handle
, &snum
))
6876 count
= print_queue_status(snum
, &queue
, &prt_status
);
6878 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6879 count
, prt_status
.status
, prt_status
.message
));
6883 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
6885 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
6888 return WERR_UNKNOWN_LEVEL
;
6892 /********************************************************************
6893 * spoolss_getprinterdataex
6894 ********************************************************************/
6896 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
6898 POLICY_HND
*handle
= &q_u
->handle
;
6899 uint32 in_size
= q_u
->size
;
6900 uint32
*type
= &r_u
->type
;
6901 uint32
*out_size
= &r_u
->size
;
6902 uint8
**data
= &r_u
->data
;
6903 uint32
*needed
= &r_u
->needed
;
6906 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6909 DEBUG(4,("_spoolss_getprinterdataex\n"));
6911 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
6912 unistr2_to_ascii(value
, &q_u
->valuename
, sizeof(value
) - 1);
6914 /* in case of problem, return some default values */
6921 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
6923 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6928 /* Is the handle to a printer or to the server? */
6930 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6932 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6933 return WERR_INVALID_PARAM
;
6938 * From MSDN documentation of GetPrinterDataEx: pass request
6939 * to GetPrinterData if key is "PrinterDriverData". This is
6940 * the only key we really support. Other keys to implement:
6946 if (strcmp(key
, "PrinterDriverData") != 0)
6947 return WERR_INVALID_PARAM
;
6949 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6950 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
6951 type
, data
, needed
, in_size
);
6956 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
6958 /* reply this param doesn't exist */
6960 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
6966 return WERR_INVALID_PARAM
;
6969 if (*needed
> *out_size
)
6970 return WERR_MORE_DATA
;
6975 /********************************************************************
6976 * spoolss_setprinterdata
6977 ********************************************************************/
6979 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
6981 SPOOL_Q_SETPRINTERDATA q_u_local
;
6982 SPOOL_R_SETPRINTERDATA r_u_local
;
6985 DEBUG(4,("_spoolss_setprinterdataex\n"));
6987 /* From MSDN documentation of SetPrinterDataEx: pass request to
6988 SetPrinterData if key is "PrinterDriverData" */
6990 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
6992 if (strcmp(key
, "PrinterDriverData") == 0)
6993 return WERR_INVALID_PARAM
;
6995 ZERO_STRUCT(q_u_local
);
6996 ZERO_STRUCT(r_u_local
);
6998 /* make a copy to call _spoolss_setprinterdata() */
7000 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
7001 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
7002 q_u_local
.type
= q_u
->type
;
7003 q_u_local
.max_len
= q_u
->max_len
;
7004 q_u_local
.data
= q_u
->data
;
7005 q_u_local
.real_len
= q_u
->real_len
;
7006 q_u_local
.numeric_data
= q_u
->numeric_data
;
7008 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
7011 /********************************************************************
7012 * spoolss_enumprinterkey
7013 ********************************************************************/
7015 /* constants for EnumPrinterKey() */
7016 #define ENUMERATED_KEY_SIZE 19
7018 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
7021 uint16 enumkeys
[ENUMERATED_KEY_SIZE
+1];
7024 char *PrinterKey
= "PrinterDriverData";
7026 DEBUG(4,("_spoolss_enumprinterkey\n"));
7028 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7031 * we only support enumating all keys (key == "")
7032 * Of course, the only key we support is the "PrinterDriverData"
7035 if (strlen(key
) == 0)
7037 r_u
->needed
= ENUMERATED_KEY_SIZE
*2;
7038 if (q_u
->size
< r_u
->needed
)
7039 return WERR_MORE_DATA
;
7042 for (i
=0; i
<ENUMERATED_KEY_SIZE
-2; i
++)
7044 enumkeys
[i
] = (uint16
)(*ptr
);
7048 /* tag of with 2 '\0's */
7049 enumkeys
[i
++] = '\0';
7052 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, ENUMERATED_KEY_SIZE
, enumkeys
))
7053 return WERR_BADFILE
;
7058 /* The "PrinterDriverData" key should have no subkeys */
7059 if (strcmp(key
, PrinterKey
) == 0)
7062 if (q_u
->size
< r_u
->needed
)
7063 return WERR_MORE_DATA
;
7065 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, enumkeys
))
7066 return WERR_BADFILE
;
7072 /* The return value for an unknown key is documented in MSDN
7073 EnumPrinterKey description */
7074 return WERR_BADFILE
;
7077 /********************************************************************
7078 * spoolss_enumprinterdataex
7079 ********************************************************************/
7081 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
7083 POLICY_HND
*handle
= &q_u
->handle
;
7084 uint32 in_size
= q_u
->size
;
7087 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7088 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
7090 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7099 DEBUG(4,("_spoolss_enumprinterdataex\n"));
7102 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
7108 * The only key we support is "PrinterDriverData". This should return
7109 > an array of all the key/value pairs returned by EnumPrinterDataSee
7110 * _spoolss_getprinterdataex() for details --jerry
7113 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
7114 if (strcmp(key
, "PrinterDriverData") != 0)
7116 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
7117 return WERR_INVALID_PARAM
;
7121 if (!get_printer_snum(p
,handle
, &snum
))
7124 ZERO_STRUCT(printer
);
7125 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7126 if (!W_ERROR_IS_OK(result
))
7131 * loop through all params and build the array to pass
7132 * back to the client
7139 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
))
7141 PRINTER_ENUM_VALUES
*ptr
;
7144 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries
, value
));
7146 if ((ptr
=talloc_realloc(p
->mem_ctx
, enum_values
, (num_entries
+1) * sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
7148 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7149 result
= WERR_NOMEM
;
7155 init_unistr(&enum_values
[num_entries
].valuename
, value
);
7156 enum_values
[num_entries
].value_len
= (strlen(value
)+1) * 2;
7157 enum_values
[num_entries
].type
= type
;
7160 * NULL terminate REG_SZ
7161 * FIXME!!! We should not be correctly problems in the way
7162 * we store PrinterData here. Need to investogate
7163 * SetPrinterData[Ex] --jerry
7166 if (type
== REG_SZ
) {
7167 /* fix alignment if the string was stored
7168 in a bizarre fashion */
7169 if ((data_len
% 2) == 0)
7172 add_len
= data_len
% 2;
7175 if (!(enum_values
[num_entries
].data
=talloc_zero(p
->mem_ctx
, data_len
+add_len
))) {
7176 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7177 result
= WERR_NOMEM
;
7180 memcpy(enum_values
[num_entries
].data
, data
, data_len
);
7181 enum_values
[num_entries
].data_len
= data_len
+ add_len
;
7183 /* keep track of the size of the array in bytes */
7185 needed
+= spoolss_size_printer_enum_values(&enum_values
[num_entries
]);
7191 r_u
->needed
= needed
;
7192 r_u
->returned
= num_entries
;
7194 if (needed
> in_size
) {
7195 result
= WERR_MORE_DATA
;
7199 /* copy data into the reply */
7201 r_u
->ctr
.size
= r_u
->needed
;
7202 r_u
->ctr
.size_of_array
= r_u
->returned
;
7203 r_u
->ctr
.values
= enum_values
;
7208 free_a_printer(&printer
, 2);
7213 /****************************************************************************
7214 ****************************************************************************/
7216 /* Disabled because it doesn't fix the bug I am looking at but it would be
7217 a shame to throw away the code. -tpot */
7221 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
7223 init_unistr(&info
->name
, name
);
7226 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
7227 UNISTR2
*environment
,
7234 pstring short_archi
;
7235 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
7237 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
7239 if (get_short_archi(short_archi
, long_archi
)==False
)
7240 return WERR_INVALID_ENVIRONMENT
;
7242 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
7245 /* Not sure what to return here - are UNC names valid here?.
7246 Windows returns the string: C:\WINNT\System32\spool\PRTPROCS\W32X86
7247 which is pretty bogus for a RPC. */
7249 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", get_called_name(), short_archi
);
7251 DEBUG(4,("print processor directory: [%s]\n", path
));
7253 fill_printprocessordirectory_1(info
, path
);
7255 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
7257 if (!alloc_buffer_size(buffer
, *needed
)) {
7259 return WERR_INSUFFICIENT_BUFFER
;
7262 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
7266 if (*needed
> offered
)
7267 return WERR_INSUFFICIENT_BUFFER
;
7272 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
7274 uint32 level
= q_u
->level
;
7275 NEW_BUFFER
*buffer
= NULL
;
7276 uint32 offered
= q_u
->offered
;
7277 uint32
*needed
= &r_u
->needed
;
7279 /* that's an [in out] buffer */
7280 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7281 buffer
= r_u
->buffer
;
7283 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
7289 return getprintprocessordirectory_level_1
7290 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
7292 return WERR_UNKNOWN_LEVEL
;
7295 return WERR_ACCESS_DENIED
;