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.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern pstring global_myname
;
33 #ifndef MAX_OPEN_PRINTER_EXS
34 #define MAX_OPEN_PRINTER_EXS 50
37 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
38 #define PRINTER_HANDLE_IS_PRINTER 0
39 #define PRINTER_HANDLE_IS_PRINTSERVER 1
48 /* structure to store the printer handles */
49 /* and a reference to what it's pointing to */
50 /* and the notify info asked about */
51 /* that's the central struct */
52 typedef struct _Printer
{
53 BOOL document_started
;
55 int jobid
; /* jobid in printing backend */
59 fstring printerservername
;
68 SPOOL_NOTIFY_OPTION
*option
;
69 POLICY_HND client_hnd
;
70 uint32 client_connected
;
78 typedef struct _counter_printer_0
{
86 static ubi_dlList counter_list
;
88 static struct cli_state cli
;
89 static uint32 smb_connections
=0;
91 #define OUR_HANDLE(hnd) ((hnd==NULL)?"NULL":(IVAL(hnd->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER"))
93 /* translate between internal status numbers and NT status numbers */
94 static int nt_printj_status(int v
)
100 return JOB_STATUS_PAUSED
;
102 return JOB_STATUS_SPOOLING
;
104 return JOB_STATUS_PRINTING
;
106 return JOB_STATUS_ERROR
;
108 return JOB_STATUS_DELETING
;
110 return JOB_STATUS_OFFLINE
;
112 return JOB_STATUS_PAPEROUT
;
114 return JOB_STATUS_PRINTED
;
116 return JOB_STATUS_DELETED
;
118 return JOB_STATUS_BLOCKED
;
119 case LPQ_USER_INTERVENTION
:
120 return JOB_STATUS_USER_INTERVENTION
;
125 static int nt_printq_status(int v
)
129 return PRINTER_STATUS_PAUSED
;
138 /****************************************************************************
139 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
140 ****************************************************************************/
142 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
147 SAFE_FREE((*pp
)->ctr
.type
);
151 /***************************************************************************
152 Disconnect from the client
153 ****************************************************************************/
155 static void srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
159 /* weird if the test succeds !!! */
160 if (smb_connections
==0) {
161 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
165 if(!cli_spoolss_reply_close_printer(&cli
, handle
, &status
))
166 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed.\n"));
168 /* if it's the last connection, deconnect the IPC$ share */
169 if (smb_connections
==1) {
170 if(!spoolss_disconnect_from_client(&cli
))
173 message_deregister(MSG_PRINTER_NOTIFY
);
179 /****************************************************************************
180 Functions to free a printer entry datastruct.
181 ****************************************************************************/
183 static void free_printer_entry(void *ptr
)
185 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
187 if (Printer
->notify
.client_connected
==True
)
188 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
190 Printer
->notify
.flags
=0;
191 Printer
->notify
.options
=0;
192 Printer
->notify
.localmachine
[0]='\0';
193 Printer
->notify
.printerlocal
=0;
194 free_spool_notify_option(&Printer
->notify
.option
);
195 Printer
->notify
.option
=NULL
;
196 Printer
->notify
.client_connected
=False
;
201 /****************************************************************************
202 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
203 ****************************************************************************/
205 SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
207 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
212 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
219 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
221 if (!new_sp
->ctr
.type
) {
230 /****************************************************************************
231 find printer index by handle
232 ****************************************************************************/
234 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
236 Printer_entry
*find_printer
= NULL
;
238 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
239 DEBUG(3,("find_printer_index_by_hnd: Printer handle not found: "));
246 /****************************************************************************
247 close printer index by handle
248 ****************************************************************************/
250 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
252 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
255 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
259 close_policy_hnd(p
, hnd
);
264 /****************************************************************************
265 delete a printer given a handle
266 ****************************************************************************/
267 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
269 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
272 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
276 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
277 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
281 /* Check calling user has permission to delete printer. Note that
282 since we set the snum parameter to -1 only administrators can
283 delete the printer. This stops people with the Full Control
284 permission from deleting the printer. */
286 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
287 DEBUG(3, ("printer delete denied by security descriptor\n"));
288 return WERR_ACCESS_DENIED
;
291 if (*lp_deleteprinter_cmd()) {
293 char *cmd
= lp_deleteprinter_cmd();
298 /* Printer->dev.handlename equals portname equals sharename */
299 slprintf(command
, sizeof(command
)-1, "%s \"%s\"", cmd
,
300 Printer
->dev
.handlename
);
301 dos_to_unix(command
, True
); /* Convert printername to unix-codepage */
303 DEBUG(10,("Running [%s]\n", command
));
304 ret
= smbrun(command
, NULL
);
306 return WERR_BADFID
; /* What to return here? */
308 DEBUGADD(10,("returned [%d]\n", ret
));
310 /* Send SIGHUP to process group... is there a better way? */
313 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) >= 0 ) {
317 return WERR_ACCESS_DENIED
;
323 /****************************************************************************
324 return the snum of a printer corresponding to an handle
325 ****************************************************************************/
326 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
328 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
331 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
335 switch (Printer
->printer_type
) {
336 case PRINTER_HANDLE_IS_PRINTER
:
337 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
338 *number
= print_queue_snum(Printer
->dev
.handlename
);
339 return (*number
!= -1);
340 case PRINTER_HANDLE_IS_PRINTSERVER
:
347 /****************************************************************************
348 set printer handle type.
349 ****************************************************************************/
350 static BOOL
set_printer_hnd_accesstype(pipes_struct
*p
, POLICY_HND
*hnd
, uint32 access_required
)
352 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
355 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd
)));
359 DEBUG(4,("Setting printer access=%x\n", access_required
));
360 Printer
->access
= access_required
;
364 /****************************************************************************
365 Set printer handle type.
366 Check if it's \\server or \\server\printer
367 ****************************************************************************/
369 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
371 DEBUG(3,("Setting printer type=%s\n", handlename
));
373 if ( strlen(handlename
) < 3 ) {
374 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
378 /* it's a print server */
379 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr(handlename
+2, '\\')) {
380 DEBUGADD(4,("Printer is a print server\n"));
381 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
385 DEBUGADD(4,("Printer is a printer\n"));
386 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
392 /****************************************************************************
393 Set printer handle name.
394 ****************************************************************************/
396 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
398 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
400 int n_services
=lp_numservices();
404 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
406 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
407 ZERO_STRUCT(Printer
->dev
.printerservername
);
408 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
412 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
415 if (*handlename
=='\\') {
416 aprinter
=strchr(handlename
+2, '\\');
423 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
426 * store the Samba share name in it
427 * in back we have the long printer name
428 * need to iterate all the snum and do a
429 * get_a_printer each time to find the printer
430 * faster to do it here than later.
433 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
436 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
439 DEBUGADD(5,("share:%s\n",lp_servicename(snum
)));
441 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
444 printername
=strchr(printer
->info_2
->printername
+2, '\\');
447 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
448 printer
->info_2
->printername
, aprinter
));
450 if ( strlen(printername
) != strlen(aprinter
) ) {
451 free_a_printer(&printer
, 2);
455 if ( strncasecmp(printername
, aprinter
, strlen(aprinter
))) {
456 free_a_printer(&printer
, 2);
464 * if we haven't found a printer with the given handlename
465 * then it can be a share name as you can open both \\server\printer and
470 * we still check if the printer description file exists as NT won't be happy
471 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
475 DEBUGADD(5,("Printer not found, checking for share now\n"));
477 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
479 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
482 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum
)));
484 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
487 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
488 printer
->info_2
->printername
, aprinter
));
490 if ( strlen(lp_servicename(snum
)) != strlen(aprinter
) ) {
491 free_a_printer(&printer
, 2);
495 if ( strncasecmp(lp_servicename(snum
), aprinter
, strlen(aprinter
))) {
496 free_a_printer(&printer
, 2);
505 DEBUGADD(4,("Printer not found\n"));
510 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
511 printer
->info_2
->printername
, lp_servicename(snum
),snum
));
513 ZERO_STRUCT(Printer
->dev
.handlename
);
514 strncpy(Printer
->dev
.handlename
, lp_servicename(snum
), strlen(lp_servicename(snum
)));
516 free_a_printer(&printer
, 2);
521 /****************************************************************************
522 find first available printer slot. creates a printer handle for you.
523 ****************************************************************************/
525 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
)
527 Printer_entry
*new_printer
;
529 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
531 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
534 ZERO_STRUCTP(new_printer
);
536 new_printer
->notify
.option
=NULL
;
538 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
539 SAFE_FREE(new_printer
);
543 if (!set_printer_hnd_printertype(new_printer
, name
)) {
544 close_printer_handle(p
, hnd
);
548 if (!set_printer_hnd_name(new_printer
, name
)) {
549 close_printer_handle(p
, hnd
);
553 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
558 /********************************************************************
559 Return True is the handle is a print server.
560 ********************************************************************/
562 static BOOL
handle_is_printserver(pipes_struct
*p
, POLICY_HND
*handle
)
564 Printer_entry
*Printer
=find_printer_index_by_hnd(p
,handle
);
569 if (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
575 /****************************************************************************
576 allocate more memory for a BUFFER.
577 ****************************************************************************/
578 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
586 /* damn, I'm doing the reverse operation of prs_grow() :) */
587 if (buffer_size
< prs_data_size(ps
))
590 extra_space
= buffer_size
- prs_data_size(ps
);
593 * save the offset and move to the end of the buffer
594 * prs_grow() checks the extra_space against the offset
596 old_offset
=prs_offset(ps
);
597 prs_set_offset(ps
, prs_data_size(ps
));
599 if (!prs_grow(ps
, extra_space
))
602 prs_set_offset(ps
, old_offset
);
604 buffer
->string_at_end
=prs_data_size(ps
);
609 /***************************************************************************
610 receive the notify message
611 ****************************************************************************/
613 static void srv_spoolss_receive_message(int msg_type
, pid_t src
, void *buf
, size_t len
)
617 struct pipes_struct
*p
;
619 struct handle_list
*hl
;
622 fstrcpy(printer
,buf
);
625 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
629 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer
));
632 * We need to enumerate all printers. The handle list is shared
633 * across pipes of the same name, so just find the first open
638 for ( p
= get_first_pipe(); p
; get_next_pipe(p
)) {
639 if (strequal(p
->name
, "spoolss")) {
640 hl
= p
->pipe_handles
;
646 DEBUG(0,("srv_spoolss_receive_message: no handle list on spoolss pipe !\n"));
650 /* Iterate the printer list on this pipe. */
651 for (pol
= hl
->Policy
; pol
; pol
= pol
->next
) {
652 Printer_entry
*find_printer
= (Printer_entry
*)pol
->data_ptr
;
658 * if the entry is the given printer or if it's a printerserver
659 * we send the message
662 if (find_printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
663 if (strcmp(find_printer
->dev
.handlename
, printer
))
666 if (find_printer
->notify
.client_connected
==True
)
667 cli_spoolss_reply_rrpcn(&cli
, &find_printer
->notify
.client_hnd
, PRINTER_CHANGE_ALL
, 0x0, &status
);
671 /***************************************************************************
673 ****************************************************************************/
674 static BOOL
srv_spoolss_sendnotify(pipes_struct
*p
, POLICY_HND
*handle
)
678 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
681 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
685 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
686 fstrcpy(printer
, Printer
->dev
.handlename
);
688 fstrcpy(printer
, "");
690 /*srv_spoolss_receive_message(printer);*/
691 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer
));
693 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY
, printer
, strlen(printer
) + 1, False
); /* Null terminate... */
698 /********************************************************************
699 * spoolss_open_printer
701 * called from the spoolss dispatcher
702 ********************************************************************/
704 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
707 WERROR result
= WERR_OK
;
710 UNISTR2
*printername
= NULL
;
711 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
712 /* uint32 user_switch = q_u->user_switch; - notused */
713 /* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
714 POLICY_HND
*handle
= &r_u
->handle
;
718 struct current_user user
;
720 if (q_u
->printername_ptr
!= 0)
721 printername
= &q_u
->printername
;
723 if (printername
== NULL
)
724 return WERR_INVALID_PRINTER_NAME
;
726 /* some sanity check because you can open a printer or a print server */
727 /* aka: \\server\printer or \\server */
728 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
730 DEBUGADD(3,("checking name: %s\n",name
));
732 if (!open_printer_hnd(p
, handle
, name
))
733 return WERR_INVALID_PRINTER_NAME
;
736 if (printer_default->datatype_ptr != NULL)
738 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
739 set_printer_hnd_datatype(handle, datatype);
742 set_printer_hnd_datatype(handle, "");
745 if (!set_printer_hnd_accesstype(p
, handle
, printer_default
->access_required
)) {
746 close_printer_handle(p
, handle
);
747 return WERR_ACCESS_DENIED
;
751 First case: the user is opening the print server:
753 Disallow MS AddPrinterWizard if parameter disables it. A Win2k
754 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
756 Then both Win2k and WinNT clients try an OpenPrinterEx with
757 SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
758 or if the user is listed in the smb.conf printer admin parameter.
760 Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
761 client view printer folder, but does not show the MSAPW.
763 Note: this test needs code to check access rights here too. Jeremy
764 could you look at this?
767 Second case: the user is opening a printer:
768 NT doesn't let us connect to a printer if the connecting user
769 doesn't have print permission.
773 get_current_user(&user
, p
);
775 if (handle_is_printserver(p
, handle
)) {
776 if (printer_default
->access_required
== 0) {
779 else if ((printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
) == SERVER_ACCESS_ADMINISTER
) {
781 /* Printserver handles use global struct... */
784 if (!lp_ms_add_printer_wizard()) {
785 close_printer_handle(p
, handle
);
786 return WERR_ACCESS_DENIED
;
788 else if (user
.uid
== 0 || user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
))) {
792 close_printer_handle(p
, handle
);
793 return WERR_ACCESS_DENIED
;
799 /* NT doesn't let us connect to a printer if the connecting user
800 doesn't have print permission. */
802 if (!get_printer_snum(p
, handle
, &snum
))
805 /* map an empty access mask to the minimum access mask */
806 if (printer_default
->access_required
== 0x0)
807 printer_default
->access_required
= PRINTER_ACCESS_USE
;
811 * If we are not serving the printer driver for this printer,
812 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
813 * will keep NT clients happy --jerry
816 if (lp_use_client_driver(snum
)
817 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
819 printer_default
->access_required
= PRINTER_ACCESS_USE
;
822 if (!print_access_check(&user
, snum
, printer_default
->access_required
)) {
823 DEBUG(3, ("access DENIED for printer open\n"));
824 close_printer_handle(p
, handle
);
825 return WERR_ACCESS_DENIED
;
829 * If we have a default device pointer in the
830 * printer_default struct, then we need to get
831 * the printer info from the tdb and if there is
832 * no default devicemode there then we do a *SET*
833 * here ! This is insanity.... JRA.
837 * If the openprinterex rpc call contains a devmode,
838 * it's a per-user one. This per-user devmode is derivated
839 * from the global devmode. Openprinterex() contains a per-user
840 * devmode for when you do EMF printing and spooling.
841 * In the EMF case, the NT workstation is only doing half the job
842 * of rendering the page. The other half is done by running the printer
843 * driver on the server.
844 * The EMF file doesn't contain the page description (paper size, orientation, ...).
845 * The EMF file only contains what is to be printed on the page.
846 * So in order for the server to know how to print, the NT client sends
847 * a devicemode attached to the openprinterex call.
848 * But this devicemode is short lived, it's only valid for the current print job.
850 * If Samba would have supported EMF spooling, this devicemode would
851 * have been attached to the handle, to sent it to the driver to correctly
852 * rasterize the EMF file.
854 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
855 * we just act as a pass-thru between windows and the printer.
857 * In order to know that Samba supports only RAW spooling, NT has to call
858 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
859 * and until NT sends a RAW job, we refuse it.
861 * But to call getprinter() or startdoc(), you first need a valid handle,
862 * and to get an handle you have to call openprintex(). Hence why you have
863 * a devicemode in the openprinterex() call.
866 * Differences between NT4 and NT 2000.
869 * On NT4, you only have a global devicemode. This global devicemode can be changed
870 * by the administrator (or by a user with enough privs). Everytime a user
871 * wants to print, the devicemode is resetted to the default. In Word, everytime
872 * you print, the printer's characteristics are always reset to the global devicemode.
876 * In W2K, there is the notion of per-user devicemode. The first time you use
877 * a printer, a per-user devicemode is build from the global devicemode.
878 * If you change your per-user devicemode, it is saved in the registry, under the
879 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
880 * printer preferences available.
882 * To change the per-user devicemode: it's the "Printing Preferences ..." button
883 * on the General Tab of the printer properties windows.
885 * To change the global devicemode: it's the "Printing Defaults..." button
886 * on the Advanced Tab of the printer properties window.
894 if (printer_default
->devmode_cont
.devmode
!= NULL
) {
895 result
= printer_write_default_dev( snum
, printer_default
);
897 close_printer_handle(p
, handle
);
907 /****************************************************************************
908 ****************************************************************************/
909 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
910 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
916 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
925 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
926 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
932 printer
->info_3
=NULL
;
933 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
937 printer
->info_6
=NULL
;
938 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
948 BOOL
convert_devicemode(char *printername
, const DEVICEMODE
*devmode
,
949 NT_DEVICEMODE
**pp_nt_devmode
)
951 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
954 * Ensure nt_devmode is a valid pointer
955 * as we will be overwriting it.
958 if (nt_devmode
== NULL
) {
959 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
960 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
964 unistr_to_dos(nt_devmode
->devicename
, (const char *)devmode
->devicename
.buffer
, 31);
965 unistr_to_dos(nt_devmode
->formname
, (const char *)devmode
->formname
.buffer
, 31);
967 nt_devmode
->specversion
=devmode
->specversion
;
968 nt_devmode
->driverversion
=devmode
->driverversion
;
969 nt_devmode
->size
=devmode
->size
;
970 nt_devmode
->fields
=devmode
->fields
;
971 nt_devmode
->orientation
=devmode
->orientation
;
972 nt_devmode
->papersize
=devmode
->papersize
;
973 nt_devmode
->paperlength
=devmode
->paperlength
;
974 nt_devmode
->paperwidth
=devmode
->paperwidth
;
975 nt_devmode
->scale
=devmode
->scale
;
976 nt_devmode
->copies
=devmode
->copies
;
977 nt_devmode
->defaultsource
=devmode
->defaultsource
;
978 nt_devmode
->printquality
=devmode
->printquality
;
979 nt_devmode
->color
=devmode
->color
;
980 nt_devmode
->duplex
=devmode
->duplex
;
981 nt_devmode
->yresolution
=devmode
->yresolution
;
982 nt_devmode
->ttoption
=devmode
->ttoption
;
983 nt_devmode
->collate
=devmode
->collate
;
985 nt_devmode
->logpixels
=devmode
->logpixels
;
986 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
987 nt_devmode
->pelswidth
=devmode
->pelswidth
;
988 nt_devmode
->pelsheight
=devmode
->pelsheight
;
989 nt_devmode
->displayflags
=devmode
->displayflags
;
990 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
991 nt_devmode
->icmmethod
=devmode
->icmmethod
;
992 nt_devmode
->icmintent
=devmode
->icmintent
;
993 nt_devmode
->mediatype
=devmode
->mediatype
;
994 nt_devmode
->dithertype
=devmode
->dithertype
;
995 nt_devmode
->reserved1
=devmode
->reserved1
;
996 nt_devmode
->reserved2
=devmode
->reserved2
;
997 nt_devmode
->panningwidth
=devmode
->panningwidth
;
998 nt_devmode
->panningheight
=devmode
->panningheight
;
1001 * Only change private and driverextra if the incoming devmode
1002 * has a new one. JRA.
1005 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1006 SAFE_FREE(nt_devmode
->private);
1007 nt_devmode
->driverextra
=devmode
->driverextra
;
1008 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1010 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1013 *pp_nt_devmode
= nt_devmode
;
1018 /********************************************************************
1019 * _spoolss_enddocprinter_internal.
1020 ********************************************************************/
1022 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1024 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1027 DEBUG(0,("_spoolss_enddocprinter_internal: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
1031 Printer
->document_started
=False
;
1032 print_job_end(Printer
->jobid
,True
);
1033 /* error codes unhandled so far ... */
1038 /********************************************************************
1039 * api_spoolss_closeprinter
1040 ********************************************************************/
1042 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1044 POLICY_HND
*handle
= &q_u
->handle
;
1046 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1048 if (Printer
&& Printer
->document_started
)
1049 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1051 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1053 if (!close_printer_handle(p
, handle
))
1059 /********************************************************************
1060 * api_spoolss_deleteprinter
1062 ********************************************************************/
1064 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1066 POLICY_HND
*handle
= &q_u
->handle
;
1067 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1070 if (Printer
&& Printer
->document_started
)
1071 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1073 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1075 result
= delete_printer_handle(p
, handle
);
1077 if (W_ERROR_IS_OK(result
)) {
1078 srv_spoolss_sendnotify(p
, handle
);
1084 /*******************************************************************
1085 * static function to lookup the version id corresponding to an
1086 * long architecture string
1087 ******************************************************************/
1088 static int get_version_id (char * arch
)
1091 struct table_node archi_table
[]= {
1093 {"Windows 4.0", "WIN40", 0 },
1094 {"Windows NT x86", "W32X86", 2 },
1095 {"Windows NT R4000", "W32MIPS", 2 },
1096 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1097 {"Windows NT PowerPC", "W32PPC", 2 },
1101 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1103 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1104 return (archi_table
[i
].version
);
1110 /********************************************************************
1111 * _spoolss_deleteprinterdriver
1113 * We currently delete the driver for the architecture only.
1114 * This can leave the driver for other archtectures. However,
1115 * since every printer associates a "Windows NT x86" driver name
1116 * and we cannot delete that one while it is in use, **and** since
1117 * it is impossible to assign a driver to a Samba printer without
1118 * having the "Windows NT x86" driver installed,...
1120 * ....we should not get into trouble here.
1123 ********************************************************************/
1125 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
,
1126 SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1130 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1133 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1134 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1136 /* check that we have a valid driver name first */
1137 if ((version
=get_version_id(arch
)) == -1) {
1138 /* this is what NT returns */
1139 return WERR_INVALID_ENVIRONMENT
;
1143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1144 return WERR_UNKNOWN_PRINTER_DRIVER
;
1148 if (printer_driver_in_use(arch
, driver
))
1150 return WERR_PRINTER_DRIVER_IN_USE
;
1153 return delete_printer_driver(info
.info_3
);
1157 /********************************************************************
1158 GetPrinterData on a printer server Handle.
1159 ********************************************************************/
1160 static BOOL
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
1164 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
1166 if (!strcmp(value
, "BeepEnabled")) {
1168 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1170 SIVAL(*data
, 0, 0x01);
1175 if (!strcmp(value
, "EventLog")) {
1177 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1179 SIVAL(*data
, 0, 0x1B);
1184 if (!strcmp(value
, "NetPopup")) {
1186 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1188 SIVAL(*data
, 0, 0x01);
1193 if (!strcmp(value
, "MajorVersion")) {
1195 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
1197 SIVAL(*data
, 0, 0x02);
1202 if (!strcmp(value
, "DefaultSpoolDirectory")) {
1203 pstring string
="You are using a Samba server";
1205 *needed
= 2*(strlen(string
)+1);
1206 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1208 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1210 /* it's done by hand ready to go on the wire */
1211 for (i
=0; i
<strlen(string
); i
++) {
1212 (*data
)[2*i
]=string
[i
];
1213 (*data
)[2*i
+1]='\0';
1218 if (!strcmp(value
, "Architecture")) {
1219 pstring string
="Windows NT x86";
1221 *needed
= 2*(strlen(string
)+1);
1222 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
1224 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
1225 for (i
=0; i
<strlen(string
); i
++) {
1226 (*data
)[2*i
]=string
[i
];
1227 (*data
)[2*i
+1]='\0';
1235 /********************************************************************
1236 GetPrinterData on a printer Handle.
1237 ********************************************************************/
1238 static BOOL
getprinterdata_printer(pipes_struct
*p
, TALLOC_CTX
*ctx
, POLICY_HND
*handle
,
1239 fstring value
, uint32
*type
,
1240 uint8
**data
, uint32
*needed
, uint32 in_size
)
1242 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1246 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1248 DEBUG(5,("getprinterdata_printer\n"));
1251 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1255 if(!get_printer_snum(p
, handle
, &snum
))
1258 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
1261 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
1262 free_a_printer(&printer
, 2);
1266 free_a_printer(&printer
, 2);
1268 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
1271 if((*data
= (uint8
*)talloc(ctx
, in_size
*sizeof(uint8
) )) == NULL
) {
1275 memset(*data
, 0, in_size
*sizeof(uint8
));
1276 /* copy the min(in_size, len) */
1277 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
1284 DEBUG(5,("getprinterdata_printer:copy done\n"));
1291 /********************************************************************
1292 * spoolss_getprinterdata
1293 ********************************************************************/
1295 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
1297 POLICY_HND
*handle
= &q_u
->handle
;
1298 UNISTR2
*valuename
= &q_u
->valuename
;
1299 uint32 in_size
= q_u
->size
;
1300 uint32
*type
= &r_u
->type
;
1301 uint32
*out_size
= &r_u
->size
;
1302 uint8
**data
= &r_u
->data
;
1303 uint32
*needed
= &r_u
->needed
;
1307 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
1310 * Reminder: when it's a string, the length is in BYTES
1311 * even if UNICODE is negociated.
1318 /* in case of problem, return some default values */
1322 DEBUG(4,("_spoolss_getprinterdata\n"));
1325 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
1327 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1331 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1333 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1334 found
=getprinterdata_printer_server(p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
1336 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
, type
, data
, needed
, *out_size
);
1339 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1340 /* reply this param doesn't exist */
1342 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
1348 return WERR_INVALID_PARAM
;
1351 if (*needed
> *out_size
)
1352 return WERR_STATUS_MORE_ENTRIES
;
1357 /***************************************************************************
1358 connect to the client
1359 ****************************************************************************/
1360 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1365 * If it's the first connection, contact the client
1366 * and connect to the IPC$ share anonumously
1368 if (smb_connections
==0) {
1369 fstring unix_printer
;
1371 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
1372 dos_to_unix(unix_printer
, True
);
1374 if(!spoolss_connect_to_client(&cli
, unix_printer
))
1376 message_register(MSG_PRINTER_NOTIFY
, srv_spoolss_receive_message
);
1382 if(!cli_spoolss_reply_open_printer(&cli
, printer
, localprinter
, type
, &status
, handle
))
1388 /********************************************************************
1390 * ReplyFindFirstPrinterChangeNotifyEx
1392 * jfmxxxx: before replying OK: status=0
1393 * should do a rpc call to the workstation asking ReplyOpenPrinter
1394 * have to code it, later.
1396 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1397 * called from api_spoolss_rffpcnex
1398 ********************************************************************/
1400 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
1402 POLICY_HND
*handle
= &q_u
->handle
;
1403 uint32 flags
= q_u
->flags
;
1404 uint32 options
= q_u
->options
;
1405 UNISTR2
*localmachine
= &q_u
->localmachine
;
1406 uint32 printerlocal
= q_u
->printerlocal
;
1407 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
1409 /* store the notify value in the printer struct */
1411 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1414 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1418 Printer
->notify
.flags
=flags
;
1419 Printer
->notify
.options
=options
;
1420 Printer
->notify
.printerlocal
=printerlocal
;
1422 if (Printer
->notify
.option
)
1423 free_spool_notify_option(&Printer
->notify
.option
);
1425 Printer
->notify
.option
=dup_spool_notify_option(option
);
1427 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
, sizeof(Printer
->notify
.localmachine
)-1);
1429 /* connect to the client machine and send a ReplyOpenPrinter */
1430 if(srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
1431 Printer
->notify
.printerlocal
, 1,
1432 &Printer
->notify
.client_hnd
))
1433 Printer
->notify
.client_connected
=True
;
1438 /*******************************************************************
1439 * fill a notify_info_data with the servername
1440 ********************************************************************/
1442 static void spoolss_notify_server_name(int snum
,
1443 SPOOL_NOTIFY_INFO_DATA
*data
,
1444 print_queue_struct
*queue
,
1445 NT_PRINTER_INFO_LEVEL
*printer
,
1446 TALLOC_CTX
*mem_ctx
)
1448 pstring temp_name
, temp
;
1451 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", global_myname
);
1453 len
= (uint32
)dos_PutUniCode(temp
, temp_name
, sizeof(temp
) - 2, True
);
1455 data
->notify_data
.data
.length
= len
/ 2 - 1;
1456 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1458 if (!data
->notify_data
.data
.string
) {
1459 data
->notify_data
.data
.length
= 0;
1463 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1466 /*******************************************************************
1467 * fill a notify_info_data with the printername (not including the servername).
1468 ********************************************************************/
1469 static void spoolss_notify_printer_name(int snum
,
1470 SPOOL_NOTIFY_INFO_DATA
*data
,
1471 print_queue_struct
*queue
,
1472 NT_PRINTER_INFO_LEVEL
*printer
,
1473 TALLOC_CTX
*mem_ctx
)
1478 /* the notify name should not contain the \\server\ part */
1479 char *p
= strrchr(printer
->info_2
->printername
, '\\');
1482 p
= printer
->info_2
->printername
;
1487 len
= (uint32
)dos_PutUniCode(temp
, p
, sizeof(temp
) - 2, True
);
1489 data
->notify_data
.data
.length
= len
/ 2 - 1;
1490 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1492 if (!data
->notify_data
.data
.string
) {
1493 data
->notify_data
.data
.length
= 0;
1497 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1500 /*******************************************************************
1501 * fill a notify_info_data with the servicename
1502 ********************************************************************/
1503 static void spoolss_notify_share_name(int snum
,
1504 SPOOL_NOTIFY_INFO_DATA
*data
,
1505 print_queue_struct
*queue
,
1506 NT_PRINTER_INFO_LEVEL
*printer
,
1507 TALLOC_CTX
*mem_ctx
)
1512 len
= (uint32
)dos_PutUniCode(temp
, lp_servicename(snum
),
1513 sizeof(temp
) - 2, True
);
1515 data
->notify_data
.data
.length
= len
/ 2 - 1;
1516 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1518 if (!data
->notify_data
.data
.string
) {
1519 data
->notify_data
.data
.length
= 0;
1523 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1526 /*******************************************************************
1527 * fill a notify_info_data with the port name
1528 ********************************************************************/
1529 static void spoolss_notify_port_name(int snum
,
1530 SPOOL_NOTIFY_INFO_DATA
*data
,
1531 print_queue_struct
*queue
,
1532 NT_PRINTER_INFO_LEVEL
*printer
,
1533 TALLOC_CTX
*mem_ctx
)
1538 /* even if it's strange, that's consistant in all the code */
1540 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->portname
,
1541 sizeof(temp
) - 2, True
);
1543 data
->notify_data
.data
.length
= len
/ 2 - 1;
1544 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1546 if (!data
->notify_data
.data
.string
) {
1547 data
->notify_data
.data
.length
= 0;
1551 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1554 /*******************************************************************
1555 * fill a notify_info_data with the printername
1556 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1557 * but it doesn't exist, have to see what to do
1558 ********************************************************************/
1559 static void spoolss_notify_driver_name(int snum
,
1560 SPOOL_NOTIFY_INFO_DATA
*data
,
1561 print_queue_struct
*queue
,
1562 NT_PRINTER_INFO_LEVEL
*printer
,
1563 TALLOC_CTX
*mem_ctx
)
1568 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->drivername
,
1569 sizeof(temp
) - 2, True
);
1571 data
->notify_data
.data
.length
= len
/ 2 - 1;
1572 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1574 if (!data
->notify_data
.data
.string
) {
1575 data
->notify_data
.data
.length
= 0;
1579 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1582 /*******************************************************************
1583 * fill a notify_info_data with the comment
1584 ********************************************************************/
1585 static void spoolss_notify_comment(int snum
,
1586 SPOOL_NOTIFY_INFO_DATA
*data
,
1587 print_queue_struct
*queue
,
1588 NT_PRINTER_INFO_LEVEL
*printer
,
1589 TALLOC_CTX
*mem_ctx
)
1594 if (*printer
->info_2
->comment
== '\0')
1595 len
= (uint32
)dos_PutUniCode(temp
, lp_comment(snum
),
1596 sizeof(temp
) - 2, True
);
1598 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->comment
,
1599 sizeof(temp
) - 2, True
);
1601 data
->notify_data
.data
.length
= len
/ 2 - 1;
1602 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1604 if (!data
->notify_data
.data
.string
) {
1605 data
->notify_data
.data
.length
= 0;
1609 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1612 /*******************************************************************
1613 * fill a notify_info_data with the comment
1614 * jfm:xxxx incorrect, have to create a new smb.conf option
1615 * location = "Room 1, floor 2, building 3"
1616 ********************************************************************/
1617 static void spoolss_notify_location(int snum
,
1618 SPOOL_NOTIFY_INFO_DATA
*data
,
1619 print_queue_struct
*queue
,
1620 NT_PRINTER_INFO_LEVEL
*printer
,
1621 TALLOC_CTX
*mem_ctx
)
1626 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->location
,
1627 sizeof(temp
) - 2, True
);
1629 data
->notify_data
.data
.length
= len
/ 2 - 1;
1630 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1632 if (!data
->notify_data
.data
.string
) {
1633 data
->notify_data
.data
.length
= 0;
1637 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1640 /*******************************************************************
1641 * fill a notify_info_data with the device mode
1642 * jfm:xxxx don't to it for know but that's a real problem !!!
1643 ********************************************************************/
1644 static void spoolss_notify_devmode(int snum
,
1645 SPOOL_NOTIFY_INFO_DATA
*data
,
1646 print_queue_struct
*queue
,
1647 NT_PRINTER_INFO_LEVEL
*printer
,
1648 TALLOC_CTX
*mem_ctx
)
1652 /*******************************************************************
1653 * fill a notify_info_data with the separator file name
1654 * jfm:xxxx just return no file could add an option to smb.conf
1655 * separator file = "separator.txt"
1656 ********************************************************************/
1657 static void spoolss_notify_sepfile(int snum
,
1658 SPOOL_NOTIFY_INFO_DATA
*data
,
1659 print_queue_struct
*queue
,
1660 NT_PRINTER_INFO_LEVEL
*printer
,
1661 TALLOC_CTX
*mem_ctx
)
1666 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->sepfile
,
1667 sizeof(temp
) - 2, True
);
1669 data
->notify_data
.data
.length
= len
/ 2 - 1;
1670 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1672 if (!data
->notify_data
.data
.string
) {
1673 data
->notify_data
.data
.length
= 0;
1677 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1680 /*******************************************************************
1681 * fill a notify_info_data with the print processor
1682 * jfm:xxxx return always winprint to indicate we don't do anything to it
1683 ********************************************************************/
1684 static void spoolss_notify_print_processor(int snum
,
1685 SPOOL_NOTIFY_INFO_DATA
*data
,
1686 print_queue_struct
*queue
,
1687 NT_PRINTER_INFO_LEVEL
*printer
,
1688 TALLOC_CTX
*mem_ctx
)
1693 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->printprocessor
,
1694 sizeof(temp
) - 2, True
);
1696 data
->notify_data
.data
.length
= len
/ 2 - 1;
1697 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1699 if (!data
->notify_data
.data
.string
) {
1700 data
->notify_data
.data
.length
= 0;
1704 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1707 /*******************************************************************
1708 * fill a notify_info_data with the print processor options
1709 * jfm:xxxx send an empty string
1710 ********************************************************************/
1711 static void spoolss_notify_parameters(int snum
,
1712 SPOOL_NOTIFY_INFO_DATA
*data
,
1713 print_queue_struct
*queue
,
1714 NT_PRINTER_INFO_LEVEL
*printer
,
1715 TALLOC_CTX
*mem_ctx
)
1720 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->parameters
,
1721 sizeof(temp
) - 2, True
);
1723 data
->notify_data
.data
.length
= len
/ 2 - 1;
1724 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1726 if (!data
->notify_data
.data
.string
) {
1727 data
->notify_data
.data
.length
= 0;
1731 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1734 /*******************************************************************
1735 * fill a notify_info_data with the data type
1736 * jfm:xxxx always send RAW as data type
1737 ********************************************************************/
1738 static void spoolss_notify_datatype(int snum
,
1739 SPOOL_NOTIFY_INFO_DATA
*data
,
1740 print_queue_struct
*queue
,
1741 NT_PRINTER_INFO_LEVEL
*printer
,
1742 TALLOC_CTX
*mem_ctx
)
1747 len
= (uint32
)dos_PutUniCode(temp
, printer
->info_2
->datatype
,
1748 sizeof(pstring
) - 2, True
);
1750 data
->notify_data
.data
.length
= len
/ 2 - 1;
1751 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1753 if (!data
->notify_data
.data
.string
) {
1754 data
->notify_data
.data
.length
= 0;
1758 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1761 /*******************************************************************
1762 * fill a notify_info_data with the security descriptor
1763 * jfm:xxxx send an null pointer to say no security desc
1764 * have to implement security before !
1765 ********************************************************************/
1766 static void spoolss_notify_security_desc(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
.data
.length
=0;
1773 data
->notify_data
.data
.string
= NULL
;
1776 /*******************************************************************
1777 * fill a notify_info_data with the attributes
1778 * jfm:xxxx a samba printer is always shared
1779 ********************************************************************/
1780 static void spoolss_notify_attributes(int snum
,
1781 SPOOL_NOTIFY_INFO_DATA
*data
,
1782 print_queue_struct
*queue
,
1783 NT_PRINTER_INFO_LEVEL
*printer
,
1784 TALLOC_CTX
*mem_ctx
)
1786 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
1787 data
->notify_data
.value
[1] = 0;
1790 /*******************************************************************
1791 * fill a notify_info_data with the priority
1792 ********************************************************************/
1793 static void spoolss_notify_priority(int snum
,
1794 SPOOL_NOTIFY_INFO_DATA
*data
,
1795 print_queue_struct
*queue
,
1796 NT_PRINTER_INFO_LEVEL
*printer
,
1797 TALLOC_CTX
*mem_ctx
)
1799 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
1800 data
->notify_data
.value
[1] = 0;
1803 /*******************************************************************
1804 * fill a notify_info_data with the default priority
1805 ********************************************************************/
1806 static void spoolss_notify_default_priority(int snum
,
1807 SPOOL_NOTIFY_INFO_DATA
*data
,
1808 print_queue_struct
*queue
,
1809 NT_PRINTER_INFO_LEVEL
*printer
,
1810 TALLOC_CTX
*mem_ctx
)
1812 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
1813 data
->notify_data
.value
[1] = 0;
1816 /*******************************************************************
1817 * fill a notify_info_data with the start time
1818 ********************************************************************/
1819 static void spoolss_notify_start_time(int snum
,
1820 SPOOL_NOTIFY_INFO_DATA
*data
,
1821 print_queue_struct
*queue
,
1822 NT_PRINTER_INFO_LEVEL
*printer
,
1823 TALLOC_CTX
*mem_ctx
)
1825 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
1826 data
->notify_data
.value
[1] = 0;
1829 /*******************************************************************
1830 * fill a notify_info_data with the until time
1831 ********************************************************************/
1832 static void spoolss_notify_until_time(int snum
,
1833 SPOOL_NOTIFY_INFO_DATA
*data
,
1834 print_queue_struct
*queue
,
1835 NT_PRINTER_INFO_LEVEL
*printer
,
1836 TALLOC_CTX
*mem_ctx
)
1838 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
1839 data
->notify_data
.value
[1] = 0;
1842 /*******************************************************************
1843 * fill a notify_info_data with the status
1844 ********************************************************************/
1845 static void spoolss_notify_status(int snum
,
1846 SPOOL_NOTIFY_INFO_DATA
*data
,
1847 print_queue_struct
*queue
,
1848 NT_PRINTER_INFO_LEVEL
*printer
,
1849 TALLOC_CTX
*mem_ctx
)
1851 print_status_struct status
;
1853 print_queue_length(snum
, &status
);
1854 data
->notify_data
.value
[0]=(uint32
) status
.status
;
1855 data
->notify_data
.value
[1] = 0;
1858 /*******************************************************************
1859 * fill a notify_info_data with the number of jobs queued
1860 ********************************************************************/
1861 static void spoolss_notify_cjobs(int snum
,
1862 SPOOL_NOTIFY_INFO_DATA
*data
,
1863 print_queue_struct
*queue
,
1864 NT_PRINTER_INFO_LEVEL
*printer
,
1865 TALLOC_CTX
*mem_ctx
)
1867 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
1868 data
->notify_data
.value
[1] = 0;
1871 /*******************************************************************
1872 * fill a notify_info_data with the average ppm
1873 ********************************************************************/
1874 static void spoolss_notify_average_ppm(int snum
,
1875 SPOOL_NOTIFY_INFO_DATA
*data
,
1876 print_queue_struct
*queue
,
1877 NT_PRINTER_INFO_LEVEL
*printer
,
1878 TALLOC_CTX
*mem_ctx
)
1880 /* always respond 8 pages per minutes */
1881 /* a little hard ! */
1882 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
1883 data
->notify_data
.value
[1] = 0;
1886 /*******************************************************************
1887 * fill a notify_info_data with username
1888 ********************************************************************/
1889 static void spoolss_notify_username(int snum
,
1890 SPOOL_NOTIFY_INFO_DATA
*data
,
1891 print_queue_struct
*queue
,
1892 NT_PRINTER_INFO_LEVEL
*printer
,
1893 TALLOC_CTX
*mem_ctx
)
1898 len
= (uint32
)dos_PutUniCode(temp
, queue
->user
,
1899 sizeof(temp
) - 2, True
);
1901 data
->notify_data
.data
.length
= len
/ 2 - 1;
1902 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1904 if (!data
->notify_data
.data
.string
) {
1905 data
->notify_data
.data
.length
= 0;
1909 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1912 /*******************************************************************
1913 * fill a notify_info_data with job status
1914 ********************************************************************/
1915 static void spoolss_notify_job_status(int snum
,
1916 SPOOL_NOTIFY_INFO_DATA
*data
,
1917 print_queue_struct
*queue
,
1918 NT_PRINTER_INFO_LEVEL
*printer
,
1919 TALLOC_CTX
*mem_ctx
)
1921 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
1922 data
->notify_data
.value
[1] = 0;
1925 /*******************************************************************
1926 * fill a notify_info_data with job name
1927 ********************************************************************/
1928 static void spoolss_notify_job_name(int snum
,
1929 SPOOL_NOTIFY_INFO_DATA
*data
,
1930 print_queue_struct
*queue
,
1931 NT_PRINTER_INFO_LEVEL
*printer
,
1932 TALLOC_CTX
*mem_ctx
)
1937 len
= (uint32
)dos_PutUniCode(temp
, queue
->file
, sizeof(temp
) - 2,
1940 data
->notify_data
.data
.length
= len
/ 2 - 1;
1941 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1943 if (!data
->notify_data
.data
.string
) {
1944 data
->notify_data
.data
.length
= 0;
1948 memcpy(data
->notify_data
.data
.string
, temp
, len
);
1951 /*******************************************************************
1952 * fill a notify_info_data with job status
1953 ********************************************************************/
1954 static void spoolss_notify_job_status_string(int snum
,
1955 SPOOL_NOTIFY_INFO_DATA
*data
,
1956 print_queue_struct
*queue
,
1957 NT_PRINTER_INFO_LEVEL
*printer
,
1958 TALLOC_CTX
*mem_ctx
)
1961 * Now we're returning job status codes we just return a "" here. JRA.
1968 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
1971 switch (queue
->status
) {
1976 p
= ""; /* NT provides the paused string */
1985 #endif /* NO LONGER NEEDED. */
1987 len
= (uint32
)dos_PutUniCode(temp
, p
, sizeof(temp
) - 2, True
);
1989 data
->notify_data
.data
.length
= len
/ 2 - 1;
1990 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
1992 if (!data
->notify_data
.data
.string
) {
1993 data
->notify_data
.data
.length
= 0;
1997 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2000 /*******************************************************************
2001 * fill a notify_info_data with job time
2002 ********************************************************************/
2003 static void spoolss_notify_job_time(int snum
,
2004 SPOOL_NOTIFY_INFO_DATA
*data
,
2005 print_queue_struct
*queue
,
2006 NT_PRINTER_INFO_LEVEL
*printer
,
2007 TALLOC_CTX
*mem_ctx
)
2009 data
->notify_data
.value
[0]=0x0;
2010 data
->notify_data
.value
[1]=0;
2013 /*******************************************************************
2014 * fill a notify_info_data with job size
2015 ********************************************************************/
2016 static void spoolss_notify_job_size(int snum
,
2017 SPOOL_NOTIFY_INFO_DATA
*data
,
2018 print_queue_struct
*queue
,
2019 NT_PRINTER_INFO_LEVEL
*printer
,
2020 TALLOC_CTX
*mem_ctx
)
2022 data
->notify_data
.value
[0]=queue
->size
;
2023 data
->notify_data
.value
[1]=0;
2026 /*******************************************************************
2027 * fill a notify_info_data with job position
2028 ********************************************************************/
2029 static void spoolss_notify_job_position(int snum
,
2030 SPOOL_NOTIFY_INFO_DATA
*data
,
2031 print_queue_struct
*queue
,
2032 NT_PRINTER_INFO_LEVEL
*printer
,
2033 TALLOC_CTX
*mem_ctx
)
2035 data
->notify_data
.value
[0]=queue
->job
;
2036 data
->notify_data
.value
[1]=0;
2039 /*******************************************************************
2040 * fill a notify_info_data with submitted time
2041 ********************************************************************/
2042 static void spoolss_notify_submitted_time(int snum
,
2043 SPOOL_NOTIFY_INFO_DATA
*data
,
2044 print_queue_struct
*queue
,
2045 NT_PRINTER_INFO_LEVEL
*printer
,
2046 TALLOC_CTX
*mem_ctx
)
2052 t
=gmtime(&queue
->time
);
2054 len
= sizeof(SYSTEMTIME
);
2056 data
->notify_data
.data
.length
= len
/2 - 1;
2057 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2059 if (!data
->notify_data
.data
.string
) {
2060 data
->notify_data
.data
.length
= 0;
2064 make_systemtime(&st
, t
);
2065 memcpy(data
->notify_data
.data
.string
,&st
,len
);
2070 struct s_notify_info_data_table
2076 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
2077 print_queue_struct
*queue
,
2078 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2081 struct s_notify_info_data_table notify_info_data_table
[] =
2083 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", POINTER
, spoolss_notify_server_name
},
2084 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2085 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", POINTER
, spoolss_notify_share_name
},
2086 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2087 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2088 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", POINTER
, spoolss_notify_comment
},
2089 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", POINTER
, spoolss_notify_location
},
2090 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2091 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", POINTER
, spoolss_notify_sepfile
},
2092 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2093 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2094 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2095 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, spoolss_notify_security_desc
},
2096 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE
, spoolss_notify_attributes
},
2097 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2098 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE
, spoolss_notify_default_priority
},
2099 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2100 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2101 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_status
},
2102 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", POINTER
, NULL
},
2103 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", ONE_VALUE
, spoolss_notify_cjobs
},
2104 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE
, spoolss_notify_average_ppm
},
2105 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER
, NULL
},
2106 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER
, NULL
},
2107 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER
, NULL
},
2108 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER
, NULL
},
2109 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
2110 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", POINTER
, spoolss_notify_server_name
},
2111 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
2112 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", POINTER
, spoolss_notify_username
},
2113 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", POINTER
, spoolss_notify_username
},
2114 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
2115 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
2116 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
2117 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
2118 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
2119 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_job_status
},
2120 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", POINTER
, spoolss_notify_job_status_string
},
2121 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, NULL
},
2122 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", POINTER
, spoolss_notify_job_name
},
2123 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
2124 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", ONE_VALUE
, spoolss_notify_job_position
},
2125 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", POINTER
, spoolss_notify_submitted_time
},
2126 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
2127 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
2128 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", ONE_VALUE
, spoolss_notify_job_time
},
2129 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE
, NULL
},
2130 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE
, NULL
},
2131 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE
, spoolss_notify_job_size
},
2132 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_BYTES_PRINTED
, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE
, NULL
},
2133 { END
, END
, "", END
, NULL
}
2136 /*******************************************************************
2137 return the size of info_data structure
2138 ********************************************************************/
2139 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
2143 while (notify_info_data_table
[i
].type
!= END
)
2145 if ( (notify_info_data_table
[i
].type
== type
) &&
2146 (notify_info_data_table
[i
].field
== field
) )
2148 return (notify_info_data_table
[i
].size
);
2155 /*******************************************************************
2156 return the type of notify_info_data
2157 ********************************************************************/
2158 static BOOL
type_of_notify_info_data(uint16 type
, uint16 field
)
2162 while (notify_info_data_table
[i
].type
!= END
)
2164 if ( (notify_info_data_table
[i
].type
== type
) &&
2165 (notify_info_data_table
[i
].field
== field
) )
2167 if (notify_info_data_table
[i
].size
== POINTER
)
2181 /****************************************************************************
2182 ****************************************************************************/
2183 static int search_notify(uint16 type
, uint16 field
, int *value
)
2188 for (j
=0, found
=False
; found
==False
&& notify_info_data_table
[j
].type
!= END
; j
++)
2190 if ( (notify_info_data_table
[j
].type
== type
) &&
2191 (notify_info_data_table
[j
].field
== field
) )
2196 if ( found
&& (notify_info_data_table
[j
].fn
!= NULL
) )
2202 /****************************************************************************
2203 ****************************************************************************/
2204 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
2206 info_data
->type
= type
;
2207 info_data
->field
= field
;
2208 info_data
->reserved
= 0;
2210 info_data
->size
= size_of_notify_info_data(type
, field
);
2211 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
2215 /*******************************************************************
2217 * fill a notify_info struct with info asked
2219 ********************************************************************/
2220 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int
2221 snum
, SPOOL_NOTIFY_OPTION_TYPE
2222 *option_type
, uint32 id
,
2223 TALLOC_CTX
*mem_ctx
)
2229 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2230 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2231 print_queue_struct
*queue
=NULL
;
2233 type
=option_type
->type
;
2235 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
2236 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2237 option_type
->count
, lp_servicename(snum
)));
2239 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2242 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2243 field
= option_type
->fields
[field_num
];
2244 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
2246 if (!search_notify(type
, field
, &j
) )
2249 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2250 DEBUG(0,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
2253 else info
->data
= tid
;
2255 current_data
=&info
->data
[info
->count
];
2257 construct_info_data(current_data
, type
, field
, id
);
2259 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
2260 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
2262 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2268 free_a_printer(&printer
, 2);
2272 /*******************************************************************
2274 * fill a notify_info struct with info asked
2276 ********************************************************************/
2277 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
2278 SPOOL_NOTIFY_INFO
*info
,
2279 NT_PRINTER_INFO_LEVEL
*printer
,
2280 int snum
, SPOOL_NOTIFY_OPTION_TYPE
2281 *option_type
, uint32 id
,
2282 TALLOC_CTX
*mem_ctx
)
2288 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
2290 DEBUG(4,("construct_notify_jobs_info\n"));
2292 type
= option_type
->type
;
2294 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
2295 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
2296 option_type
->count
));
2298 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
2299 field
= option_type
->fields
[field_num
];
2301 if (!search_notify(type
, field
, &j
) )
2304 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
2305 DEBUG(0,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
2308 else info
->data
= tid
;
2310 current_data
=&(info
->data
[info
->count
]);
2312 construct_info_data(current_data
, type
, field
, id
);
2313 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
2322 * JFM: The enumeration is not that simple, it's even non obvious.
2324 * let's take an example: I want to monitor the PRINTER SERVER for
2325 * the printer's name and the number of jobs currently queued.
2326 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
2327 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
2329 * I have 3 printers on the back of my server.
2331 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
2334 * 1 printer 1 name 1
2335 * 2 printer 1 cjob 1
2336 * 3 printer 2 name 2
2337 * 4 printer 2 cjob 2
2338 * 5 printer 3 name 3
2339 * 6 printer 3 name 3
2341 * that's the print server case, the printer case is even worse.
2344 /*******************************************************************
2346 * enumerate all printers on the printserver
2347 * fill a notify_info struct with info asked
2349 ********************************************************************/
2351 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
2352 SPOOL_NOTIFY_INFO
*info
,
2353 TALLOC_CTX
*mem_ctx
)
2356 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2357 int n_services
=lp_numservices();
2360 SPOOL_NOTIFY_OPTION
*option
;
2361 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2363 DEBUG(4,("printserver_notify_info\n"));
2365 option
=Printer
->notify
.option
;
2371 for (i
=0; i
<option
->count
; i
++) {
2372 option_type
=&(option
->ctr
.type
[i
]);
2374 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
2377 for (snum
=0; snum
<n_services
; snum
++)
2378 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
2379 if (construct_notify_printer_info
2380 (info
, snum
, option_type
, id
, mem_ctx
))
2385 * Debugging information, don't delete.
2388 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2389 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2390 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2392 for (i=0; i<info->count; i++) {
2393 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2394 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2395 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2402 /*******************************************************************
2404 * fill a notify_info struct with info asked
2406 ********************************************************************/
2407 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
2408 TALLOC_CTX
*mem_ctx
)
2411 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
2414 SPOOL_NOTIFY_OPTION
*option
;
2415 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
2417 print_queue_struct
*queue
=NULL
;
2418 print_status_struct status
;
2420 DEBUG(4,("printer_notify_info\n"));
2422 option
=Printer
->notify
.option
;
2428 get_printer_snum(p
, hnd
, &snum
);
2430 for (i
=0; i
<option
->count
; i
++) {
2431 option_type
=&option
->ctr
.type
[i
];
2433 switch ( option_type
->type
) {
2434 case PRINTER_NOTIFY_TYPE
:
2435 if(construct_notify_printer_info(info
, snum
,
2441 case JOB_NOTIFY_TYPE
: {
2442 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2444 count
= print_queue_status(snum
, &queue
, &status
);
2446 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2,
2447 lp_servicename(snum
))))
2450 for (j
=0; j
<count
; j
++) {
2451 construct_notify_jobs_info(&queue
[j
], info
,
2458 free_a_printer(&printer
, 2);
2468 * Debugging information, don't delete.
2471 DEBUG(1,("dumping the NOTIFY_INFO\n"));
2472 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
2473 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
2475 for (i=0; i<info->count; i++) {
2476 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
2477 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
2478 info->data[i].id, info->data[i].size, info->data[i].enc_type));
2484 /********************************************************************
2486 ********************************************************************/
2488 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
2490 POLICY_HND
*handle
= &q_u
->handle
;
2491 /* uint32 change = q_u->change; - notused. */
2492 /* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
2493 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
2495 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2496 WERROR result
= WERR_BADFID
;
2498 /* we always have a NOTIFY_INFO struct */
2502 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",
2503 OUR_HANDLE(handle
)));
2507 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
2509 /* jfm: the change value isn't used right now.
2510 * we will honour it when
2511 * a) we'll be able to send notification to the client
2512 * b) we'll have a way to communicate between the spoolss process.
2514 * same thing for option->flags
2515 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
2516 * I don't have a global notification system, I'm sending back all the
2517 * informations even when _NOTHING_ has changed.
2520 /* just ignore the SPOOL_NOTIFY_OPTION */
2522 switch (Printer
->printer_type
) {
2523 case PRINTER_HANDLE_IS_PRINTSERVER
:
2524 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
2527 case PRINTER_HANDLE_IS_PRINTER
:
2528 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
2536 /********************************************************************
2537 * construct_printer_info_0
2538 * fill a printer_info_0 struct
2539 ********************************************************************/
2540 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
2544 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2545 counter_printer_0
*session_counter
;
2546 uint32 global_counter
;
2549 print_status_struct status
;
2551 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2554 count
= print_queue_length(snum
, &status
);
2556 /* check if we already have a counter for this printer */
2557 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
2559 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
2560 if (session_counter
->snum
== snum
)
2564 /* it's the first time, add it to the list */
2565 if (session_counter
==NULL
) {
2566 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
2567 free_a_printer(&ntprinter
, 2);
2570 ZERO_STRUCTP(session_counter
);
2571 session_counter
->snum
=snum
;
2572 session_counter
->counter
=0;
2573 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
2577 session_counter
->counter
++;
2580 * the global_counter should be stored in a TDB as it's common to all the clients
2581 * and should be zeroed on samba startup
2583 global_counter
=session_counter
->counter
;
2585 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
2587 init_unistr(&printer
->printername
, chaine
);
2589 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", global_myname
);
2590 init_unistr(&printer
->servername
, chaine
);
2592 printer
->cjobs
= count
;
2593 printer
->total_jobs
= 0;
2594 printer
->total_bytes
= 0;
2596 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
2597 t
=gmtime(&setuptime
);
2599 printer
->year
= t
->tm_year
+1900;
2600 printer
->month
= t
->tm_mon
+1;
2601 printer
->dayofweek
= t
->tm_wday
;
2602 printer
->day
= t
->tm_mday
;
2603 printer
->hour
= t
->tm_hour
;
2604 printer
->minute
= t
->tm_min
;
2605 printer
->second
= t
->tm_sec
;
2606 printer
->milliseconds
= 0;
2608 printer
->global_counter
= global_counter
;
2609 printer
->total_pages
= 0;
2610 printer
->major_version
= 0x0004; /* NT 4 */
2611 printer
->build_version
= 0x0565; /* build 1381 */
2612 printer
->unknown7
= 0x1;
2613 printer
->unknown8
= 0x0;
2614 printer
->unknown9
= 0x0;
2615 printer
->session_counter
= session_counter
->counter
;
2616 printer
->unknown11
= 0x0;
2617 printer
->printer_errors
= 0x0; /* number of print failure */
2618 printer
->unknown13
= 0x0;
2619 printer
->unknown14
= 0x1;
2620 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
2621 printer
->unknown16
= 0x0;
2622 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
2623 printer
->unknown18
= 0x0;
2624 printer
->status
= nt_printq_status(status
.status
);
2625 printer
->unknown20
= 0x0;
2626 printer
->c_setprinter
= ntprinter
->info_2
->c_setprinter
; /* how many times setprinter has been called */
2627 printer
->unknown22
= 0x0;
2628 printer
->unknown23
= 0x6; /* 6 ???*/
2629 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
2630 printer
->unknown25
= 0;
2631 printer
->unknown26
= 0;
2632 printer
->unknown27
= 0;
2633 printer
->unknown28
= 0;
2634 printer
->unknown29
= 0;
2636 free_a_printer(&ntprinter
,2);
2640 /********************************************************************
2641 * construct_printer_info_1
2642 * fill a printer_info_1 struct
2643 ********************************************************************/
2644 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
2648 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2650 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2653 printer
->flags
=flags
;
2655 if (*ntprinter
->info_2
->comment
== '\0') {
2656 init_unistr(&printer
->comment
, lp_comment(snum
));
2657 slprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",global_myname
, ntprinter
->info_2
->printername
,
2658 ntprinter
->info_2
->drivername
, lp_comment(snum
));
2661 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2662 slprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",global_myname
, ntprinter
->info_2
->printername
,
2663 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
2666 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
2668 init_unistr(&printer
->description
, chaine
);
2669 init_unistr(&printer
->name
, chaine2
);
2671 free_a_printer(&ntprinter
,2);
2676 /****************************************************************************
2677 Free a DEVMODE struct.
2678 ****************************************************************************/
2680 static void free_dev_mode(DEVICEMODE
*dev
)
2685 SAFE_FREE(dev
->private);
2689 /****************************************************************************
2690 Create a DEVMODE struct. Returns malloced memory.
2691 ****************************************************************************/
2693 static DEVICEMODE
*construct_dev_mode(int snum
)
2697 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2698 NT_DEVICEMODE
*ntdevmode
= NULL
;
2699 DEVICEMODE
*devmode
= NULL
;
2701 DEBUG(7,("construct_dev_mode\n"));
2703 DEBUGADD(8,("getting printer characteristics\n"));
2705 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
2706 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2710 ZERO_STRUCTP(devmode
);
2712 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
2715 if (printer
->info_2
->devmode
)
2716 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
2718 if (ntdevmode
== NULL
)
2721 DEBUGADD(8,("loading DEVICEMODE\n"));
2723 slprintf(adevice
, sizeof(adevice
)-1, printer
->info_2
->printername
);
2724 init_unistr(&devmode
->devicename
, adevice
);
2726 slprintf(aform
, sizeof(aform
)-1, ntdevmode
->formname
);
2727 init_unistr(&devmode
->formname
, aform
);
2729 devmode
->specversion
= ntdevmode
->specversion
;
2730 devmode
->driverversion
= ntdevmode
->driverversion
;
2731 devmode
->size
= ntdevmode
->size
;
2732 devmode
->driverextra
= ntdevmode
->driverextra
;
2733 devmode
->fields
= ntdevmode
->fields
;
2735 devmode
->orientation
= ntdevmode
->orientation
;
2736 devmode
->papersize
= ntdevmode
->papersize
;
2737 devmode
->paperlength
= ntdevmode
->paperlength
;
2738 devmode
->paperwidth
= ntdevmode
->paperwidth
;
2739 devmode
->scale
= ntdevmode
->scale
;
2740 devmode
->copies
= ntdevmode
->copies
;
2741 devmode
->defaultsource
= ntdevmode
->defaultsource
;
2742 devmode
->printquality
= ntdevmode
->printquality
;
2743 devmode
->color
= ntdevmode
->color
;
2744 devmode
->duplex
= ntdevmode
->duplex
;
2745 devmode
->yresolution
= ntdevmode
->yresolution
;
2746 devmode
->ttoption
= ntdevmode
->ttoption
;
2747 devmode
->collate
= ntdevmode
->collate
;
2748 devmode
->icmmethod
= ntdevmode
->icmmethod
;
2749 devmode
->icmintent
= ntdevmode
->icmintent
;
2750 devmode
->mediatype
= ntdevmode
->mediatype
;
2751 devmode
->dithertype
= ntdevmode
->dithertype
;
2753 if (ntdevmode
->private != NULL
) {
2754 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
2758 free_nt_devicemode(&ntdevmode
);
2759 free_a_printer(&printer
,2);
2766 free_nt_devicemode(&ntdevmode
);
2768 free_a_printer(&printer
,2);
2769 free_dev_mode(devmode
);
2774 /********************************************************************
2775 * construct_printer_info_2
2776 * fill a printer_info_2 struct
2777 ********************************************************************/
2779 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
2782 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2784 print_status_struct status
;
2786 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2789 count
= print_queue_length(snum
, &status
);
2791 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
2792 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
2793 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
2794 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
2795 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
2797 if (*ntprinter
->info_2
->comment
== '\0')
2798 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
2800 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2802 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
2803 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
2804 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
2805 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
2806 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
2808 printer
->attributes
= ntprinter
->info_2
->attributes
;
2810 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
2811 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
2812 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
2813 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
2814 printer
->status
= nt_printq_status(status
.status
); /* status */
2815 printer
->cjobs
= count
; /* jobs */
2816 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
2818 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
2819 DEBUG(8, ("Returning NULL Devicemode!\n"));
2822 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2823 /* steal the printer info sec_desc structure. [badly done]. */
2824 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2825 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
2826 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
2827 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
2830 printer
->secdesc
= NULL
;
2833 free_a_printer(&ntprinter
, 2);
2837 /********************************************************************
2838 * construct_printer_info_3
2839 * fill a printer_info_3 struct
2840 ********************************************************************/
2841 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
2843 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2844 PRINTER_INFO_3
*printer
= NULL
;
2846 if (!W_ERROR_IS_OK(get_a_printer(&ntprinter
, 2, lp_servicename(snum
))))
2850 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
2851 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2855 ZERO_STRUCTP(printer
);
2857 printer
->flags
= 4; /* These are the components of the SD we are returning. */
2858 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2859 /* steal the printer info sec_desc structure. [badly done]. */
2860 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2864 * Set the flags for the components we are returning.
2867 if (printer
->secdesc
->owner_sid
)
2868 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
2870 if (printer
->secdesc
->grp_sid
)
2871 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
2873 if (printer
->secdesc
->dacl
)
2874 printer
->flags
|= DACL_SECURITY_INFORMATION
;
2876 if (printer
->secdesc
->sacl
)
2877 printer
->flags
|= SACL_SECURITY_INFORMATION
;
2880 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
2881 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
2882 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
2885 free_a_printer(&ntprinter
, 2);
2887 *pp_printer
= printer
;
2891 /********************************************************************
2892 Spoolss_enumprinters.
2893 ********************************************************************/
2894 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2898 int n_services
=lp_numservices();
2899 PRINTER_INFO_1
*tp
, *printers
=NULL
;
2900 PRINTER_INFO_1 current_prt
;
2902 DEBUG(4,("enum_all_printers_info_1\n"));
2904 for (snum
=0; snum
<n_services
; snum
++) {
2905 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
2906 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
2908 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
2909 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
2910 DEBUG(0,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
2911 SAFE_FREE(printers
);
2916 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
2917 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
2923 /* check the required size. */
2924 for (i
=0; i
<*returned
; i
++)
2925 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
2927 if (!alloc_buffer_size(buffer
, *needed
))
2928 return WERR_INSUFFICIENT_BUFFER
;
2930 /* fill the buffer with the structures */
2931 for (i
=0; i
<*returned
; i
++)
2932 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
2935 SAFE_FREE(printers
);
2937 if (*needed
> offered
) {
2939 return WERR_INSUFFICIENT_BUFFER
;
2945 /********************************************************************
2946 enum_all_printers_info_1_local.
2947 *********************************************************************/
2948 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2950 DEBUG(4,("enum_all_printers_info_1_local\n"));
2952 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
2955 /********************************************************************
2956 enum_all_printers_info_1_name.
2957 *********************************************************************/
2958 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2962 DEBUG(4,("enum_all_printers_info_1_name\n"));
2964 if ((name
[0] == '\\') && (name
[1] == '\\'))
2967 if (is_myname_or_ipaddr(s
)) {
2968 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
2971 return WERR_INVALID_NAME
;
2974 /********************************************************************
2975 enum_all_printers_info_1_remote.
2976 *********************************************************************/
2977 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2979 PRINTER_INFO_1
*printer
;
2980 fstring printername
;
2983 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2985 /* JFM: currently it's more a place holder than anything else.
2986 * In the spooler world there is a notion of server registration.
2987 * the print servers are registring (sp ?) on the PDC (in the same domain)
2989 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2992 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
2997 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", global_myname
);
2998 slprintf(desc
, sizeof(desc
)-1,"%s", global_myname
);
2999 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
3001 init_unistr(&printer
->description
, desc
);
3002 init_unistr(&printer
->name
, printername
);
3003 init_unistr(&printer
->comment
, comment
);
3004 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
3006 /* check the required size. */
3007 *needed
+= spoolss_size_printer_info_1(printer
);
3009 if (!alloc_buffer_size(buffer
, *needed
)) {
3011 return WERR_INSUFFICIENT_BUFFER
;
3014 /* fill the buffer with the structures */
3015 smb_io_printer_info_1("", buffer
, printer
, 0);
3020 if (*needed
> offered
) {
3022 return WERR_INSUFFICIENT_BUFFER
;
3028 /********************************************************************
3029 enum_all_printers_info_1_network.
3030 *********************************************************************/
3032 static WERROR
enum_all_printers_info_1_network(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3034 DEBUG(4,("enum_all_printers_info_1_network\n"));
3036 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
3039 /********************************************************************
3040 * api_spoolss_enumprinters
3042 * called from api_spoolss_enumprinters (see this to understand)
3043 ********************************************************************/
3045 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
3049 int n_services
=lp_numservices();
3050 PRINTER_INFO_2
*tp
, *printers
=NULL
;
3051 PRINTER_INFO_2 current_prt
;
3053 for (snum
=0; snum
<n_services
; snum
++) {
3054 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
3055 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
3057 if (construct_printer_info_2(¤t_prt
, snum
)) {
3058 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
3059 DEBUG(0,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
3060 SAFE_FREE(printers
);
3065 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
3066 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
3072 /* check the required size. */
3073 for (i
=0; i
<*returned
; i
++)
3074 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
3076 if (!alloc_buffer_size(buffer
, *needed
)) {
3077 for (i
=0; i
<*returned
; i
++) {
3078 free_devmode(printers
[i
].devmode
);
3080 SAFE_FREE(printers
);
3081 return WERR_INSUFFICIENT_BUFFER
;
3084 /* fill the buffer with the structures */
3085 for (i
=0; i
<*returned
; i
++)
3086 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
3089 for (i
=0; i
<*returned
; i
++) {
3090 free_devmode(printers
[i
].devmode
);
3092 SAFE_FREE(printers
);
3094 if (*needed
> offered
) {
3096 return WERR_INSUFFICIENT_BUFFER
;
3102 /********************************************************************
3103 * handle enumeration of printers at level 1
3104 ********************************************************************/
3105 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
3106 NEW_BUFFER
*buffer
, uint32 offered
,
3107 uint32
*needed
, uint32
*returned
)
3109 /* Not all the flags are equals */
3111 if (flags
& PRINTER_ENUM_LOCAL
)
3112 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
3114 if (flags
& PRINTER_ENUM_NAME
)
3115 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
3117 if (flags
& PRINTER_ENUM_REMOTE
)
3118 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
3120 if (flags
& PRINTER_ENUM_NETWORK
)
3121 return enum_all_printers_info_1_network(buffer
, offered
, needed
, returned
);
3123 return WERR_OK
; /* NT4sp5 does that */
3126 /********************************************************************
3127 * handle enumeration of printers at level 2
3128 ********************************************************************/
3129 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
3130 NEW_BUFFER
*buffer
, uint32 offered
,
3131 uint32
*needed
, uint32
*returned
)
3133 char *s
= servername
;
3135 if (flags
& PRINTER_ENUM_LOCAL
) {
3136 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3139 if (flags
& PRINTER_ENUM_NAME
) {
3140 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
3142 if (is_myname_or_ipaddr(s
))
3143 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
3145 return WERR_INVALID_NAME
;
3148 if (flags
& PRINTER_ENUM_REMOTE
)
3149 return WERR_UNKNOWN_LEVEL
;
3154 /********************************************************************
3155 * handle enumeration of printers at level 5
3156 ********************************************************************/
3157 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
3158 NEW_BUFFER
*buffer
, uint32 offered
,
3159 uint32
*needed
, uint32
*returned
)
3161 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
3165 /********************************************************************
3166 * api_spoolss_enumprinters
3168 * called from api_spoolss_enumprinters (see this to understand)
3169 ********************************************************************/
3171 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
3173 uint32 flags
= q_u
->flags
;
3174 UNISTR2
*servername
= &q_u
->servername
;
3175 uint32 level
= q_u
->level
;
3176 NEW_BUFFER
*buffer
= NULL
;
3177 uint32 offered
= q_u
->offered
;
3178 uint32
*needed
= &r_u
->needed
;
3179 uint32
*returned
= &r_u
->returned
;
3183 /* that's an [in out] buffer */
3184 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3185 buffer
= r_u
->buffer
;
3187 DEBUG(4,("_spoolss_enumprinters\n"));
3194 * flags==PRINTER_ENUM_NAME
3195 * if name=="" then enumerates all printers
3196 * if name!="" then enumerate the printer
3197 * flags==PRINTER_ENUM_REMOTE
3198 * name is NULL, enumerate printers
3199 * Level 2: name!="" enumerates printers, name can't be NULL
3200 * Level 3: doesn't exist
3201 * Level 4: does a local registry lookup
3202 * Level 5: same as Level 2
3205 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
3210 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
3212 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
3214 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
3219 return WERR_UNKNOWN_LEVEL
;
3222 /****************************************************************************
3223 ****************************************************************************/
3224 static WERROR
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3226 PRINTER_INFO_0
*printer
=NULL
;
3228 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
3231 construct_printer_info_0(printer
, snum
);
3233 /* check the required size. */
3234 *needed
+= spoolss_size_printer_info_0(printer
);
3236 if (!alloc_buffer_size(buffer
, *needed
)) {
3238 return WERR_INSUFFICIENT_BUFFER
;
3241 /* fill the buffer with the structures */
3242 smb_io_printer_info_0("", buffer
, printer
, 0);
3247 if (*needed
> offered
) {
3248 return WERR_INSUFFICIENT_BUFFER
;
3254 /****************************************************************************
3255 ****************************************************************************/
3256 static WERROR
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3258 PRINTER_INFO_1
*printer
=NULL
;
3260 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
3263 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
3265 /* check the required size. */
3266 *needed
+= spoolss_size_printer_info_1(printer
);
3268 if (!alloc_buffer_size(buffer
, *needed
)) {
3270 return WERR_INSUFFICIENT_BUFFER
;
3273 /* fill the buffer with the structures */
3274 smb_io_printer_info_1("", buffer
, printer
, 0);
3279 if (*needed
> offered
) {
3280 return WERR_INSUFFICIENT_BUFFER
;
3286 /****************************************************************************
3287 ****************************************************************************/
3288 static WERROR
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3290 PRINTER_INFO_2
*printer
=NULL
;
3292 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
3295 construct_printer_info_2(printer
, snum
);
3297 /* check the required size. */
3298 *needed
+= spoolss_size_printer_info_2(printer
);
3300 if (!alloc_buffer_size(buffer
, *needed
)) {
3301 free_printer_info_2(printer
);
3302 return WERR_INSUFFICIENT_BUFFER
;
3305 /* fill the buffer with the structures */
3306 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
3307 free_printer_info_2(printer
);
3312 free_printer_info_2(printer
);
3314 if (*needed
> offered
) {
3315 return WERR_INSUFFICIENT_BUFFER
;
3321 /****************************************************************************
3322 ****************************************************************************/
3323 static WERROR
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3325 PRINTER_INFO_3
*printer
=NULL
;
3327 if (!construct_printer_info_3(&printer
, snum
))
3330 /* check the required size. */
3331 *needed
+= spoolss_size_printer_info_3(printer
);
3333 if (!alloc_buffer_size(buffer
, *needed
)) {
3334 free_printer_info_3(printer
);
3335 return WERR_INSUFFICIENT_BUFFER
;
3338 /* fill the buffer with the structures */
3339 smb_io_printer_info_3("", buffer
, printer
, 0);
3342 free_printer_info_3(printer
);
3344 if (*needed
> offered
) {
3345 return WERR_INSUFFICIENT_BUFFER
;
3351 /****************************************************************************
3352 ****************************************************************************/
3354 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
3356 POLICY_HND
*handle
= &q_u
->handle
;
3357 uint32 level
= q_u
->level
;
3358 NEW_BUFFER
*buffer
= NULL
;
3359 uint32 offered
= q_u
->offered
;
3360 uint32
*needed
= &r_u
->needed
;
3364 /* that's an [in out] buffer */
3365 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3366 buffer
= r_u
->buffer
;
3370 if (!get_printer_snum(p
, handle
, &snum
))
3375 return getprinter_level_0(snum
, buffer
, offered
, needed
);
3377 return getprinter_level_1(snum
, buffer
, offered
, needed
);
3379 return getprinter_level_2(snum
, buffer
, offered
, needed
);
3381 return getprinter_level_3(snum
, buffer
, offered
, needed
);
3383 return WERR_UNKNOWN_LEVEL
;
3386 /********************************************************************
3387 * fill a DRIVER_INFO_1 struct
3388 ********************************************************************/
3389 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
3391 init_unistr( &info
->name
, driver
.info_3
->name
);
3394 /********************************************************************
3395 * construct_printer_driver_info_1
3396 ********************************************************************/
3397 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3399 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3400 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3402 ZERO_STRUCT(driver
);
3404 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3405 return WERR_INVALID_PRINTER_NAME
;
3407 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3408 return WERR_UNKNOWN_PRINTER_DRIVER
;
3410 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
3412 free_a_printer(&printer
,2);
3417 /********************************************************************
3418 * construct_printer_driver_info_2
3419 * fill a printer_info_2 struct
3420 ********************************************************************/
3421 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3425 info
->version
=driver
.info_3
->cversion
;
3427 init_unistr( &info
->name
, driver
.info_3
->name
);
3428 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3431 if (strlen(driver
.info_3
->driverpath
)) {
3432 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3433 init_unistr( &info
->driverpath
, temp
);
3435 init_unistr( &info
->driverpath
, "" );
3437 if (strlen(driver
.info_3
->datafile
)) {
3438 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3439 init_unistr( &info
->datafile
, temp
);
3441 init_unistr( &info
->datafile
, "" );
3443 if (strlen(driver
.info_3
->configfile
)) {
3444 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3445 init_unistr( &info
->configfile
, temp
);
3447 init_unistr( &info
->configfile
, "" );
3450 /********************************************************************
3451 * construct_printer_driver_info_2
3452 * fill a printer_info_2 struct
3453 ********************************************************************/
3454 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3456 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3457 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3459 ZERO_STRUCT(printer
);
3460 ZERO_STRUCT(driver
);
3462 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))))
3463 return WERR_INVALID_PRINTER_NAME
;
3465 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
3466 return WERR_UNKNOWN_PRINTER_DRIVER
;
3468 fill_printer_driver_info_2(info
, driver
, servername
);
3470 free_a_printer(&printer
,2);
3475 /********************************************************************
3476 * copy a strings array and convert to UNICODE
3478 * convert an array of ascii string to a UNICODE string
3479 ********************************************************************/
3480 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
3488 DEBUG(6,("init_unistr_array\n"));
3492 if (char_array
== NULL
)
3496 if (!v
) v
= ""; /* hack to handle null lists */
3498 if (strlen(v
) == 0) break;
3499 slprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
3500 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
3501 if((tuary
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
3502 DEBUG(0,("init_unistr_array: Realloc error\n" ));
3506 j
+= (dos_PutUniCode((char *)(*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
), True
) / sizeof(uint16
) );
3511 (*uni_array
)[j
]=0x0000;
3514 DEBUGADD(6,("last one:done\n"));
3517 /********************************************************************
3518 * construct_printer_info_3
3519 * fill a printer_info_3 struct
3520 ********************************************************************/
3521 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3527 info
->version
=driver
.info_3
->cversion
;
3529 init_unistr( &info
->name
, driver
.info_3
->name
);
3530 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3532 if (strlen(driver
.info_3
->driverpath
)) {
3533 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3534 init_unistr( &info
->driverpath
, temp
);
3536 init_unistr( &info
->driverpath
, "" );
3538 if (strlen(driver
.info_3
->datafile
)) {
3539 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3540 init_unistr( &info
->datafile
, temp
);
3542 init_unistr( &info
->datafile
, "" );
3544 if (strlen(driver
.info_3
->configfile
)) {
3545 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3546 init_unistr( &info
->configfile
, temp
);
3548 init_unistr( &info
->configfile
, "" );
3550 if (strlen(driver
.info_3
->helpfile
)) {
3551 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
3552 init_unistr( &info
->helpfile
, temp
);
3554 init_unistr( &info
->helpfile
, "" );
3556 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
3557 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
3559 info
->dependentfiles
=NULL
;
3560 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
3563 /********************************************************************
3564 * construct_printer_info_3
3565 * fill a printer_info_3 struct
3566 ********************************************************************/
3567 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3569 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3570 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3572 ZERO_STRUCT(driver
);
3574 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
3575 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status
)));
3576 if (!W_ERROR_IS_OK(status
))
3577 return WERR_INVALID_PRINTER_NAME
;
3579 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3580 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", werror_str(status
)));
3581 if (!W_ERROR_IS_OK(status
)) {
3582 free_a_printer(&printer
,2);
3583 return WERR_UNKNOWN_PRINTER_DRIVER
;
3586 fill_printer_driver_info_3(info
, driver
, servername
);
3588 free_a_printer(&printer
,2);
3593 /********************************************************************
3594 * construct_printer_info_6
3595 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
3596 ********************************************************************/
3598 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
3604 memset(&nullstr
, '\0', sizeof(fstring
));
3606 info
->version
=driver
.info_3
->cversion
;
3608 init_unistr( &info
->name
, driver
.info_3
->name
);
3609 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
3611 if (strlen(driver
.info_3
->driverpath
)) {
3612 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
3613 init_unistr( &info
->driverpath
, temp
);
3615 init_unistr( &info
->driverpath
, "" );
3617 if (strlen(driver
.info_3
->datafile
)) {
3618 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
3619 init_unistr( &info
->datafile
, temp
);
3621 init_unistr( &info
->datafile
, "" );
3623 if (strlen(driver
.info_3
->configfile
)) {
3624 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
3625 init_unistr( &info
->configfile
, temp
);
3627 init_unistr( &info
->configfile
, "" );
3629 if (strlen(driver
.info_3
->helpfile
)) {
3630 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
3631 init_unistr( &info
->helpfile
, temp
);
3633 init_unistr( &info
->helpfile
, "" );
3635 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
3636 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
3638 info
->dependentfiles
=NULL
;
3639 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
3641 info
->previousdrivernames
=NULL
;
3642 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
3644 info
->driver_date
.low
=0;
3645 info
->driver_date
.high
=0;
3648 info
->driver_version_low
=0;
3649 info
->driver_version_high
=0;
3651 init_unistr( &info
->mfgname
, "");
3652 init_unistr( &info
->oem_url
, "");
3653 init_unistr( &info
->hardware_id
, "");
3654 init_unistr( &info
->provider
, "");
3657 /********************************************************************
3658 * construct_printer_info_6
3659 * fill a printer_info_6 struct
3660 ********************************************************************/
3661 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
3663 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3664 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
3666 ZERO_STRUCT(driver
);
3668 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
3669 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3670 if (!W_ERROR_IS_OK(status
))
3671 return WERR_INVALID_PRINTER_NAME
;
3673 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3674 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3675 if (!W_ERROR_IS_OK(status
)) {
3677 * Is this a W2k client ?
3681 free_a_printer(&printer
,2);
3682 return WERR_UNKNOWN_PRINTER_DRIVER
;
3685 /* Yes - try again with a WinNT driver. */
3687 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
3688 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", werror_str(status
)));
3689 if (!W_ERROR_IS_OK(status
)) {
3690 free_a_printer(&printer
,2);
3691 return WERR_UNKNOWN_PRINTER_DRIVER
;
3695 fill_printer_driver_info_6(info
, driver
, servername
);
3697 free_a_printer(&printer
,2);
3702 /****************************************************************************
3703 ****************************************************************************/
3705 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
3707 SAFE_FREE(info
->dependentfiles
);
3710 /****************************************************************************
3711 ****************************************************************************/
3713 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
3715 SAFE_FREE(info
->dependentfiles
);
3719 /****************************************************************************
3720 ****************************************************************************/
3721 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3723 DRIVER_INFO_1
*info
=NULL
;
3726 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
3729 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
3730 if (!W_ERROR_IS_OK(status
)) {
3735 /* check the required size. */
3736 *needed
+= spoolss_size_printer_driver_info_1(info
);
3738 if (!alloc_buffer_size(buffer
, *needed
)) {
3740 return WERR_INSUFFICIENT_BUFFER
;
3743 /* fill the buffer with the structures */
3744 smb_io_printer_driver_info_1("", buffer
, info
, 0);
3749 if (*needed
> offered
)
3750 return WERR_INSUFFICIENT_BUFFER
;
3755 /****************************************************************************
3756 ****************************************************************************/
3757 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3759 DRIVER_INFO_2
*info
=NULL
;
3762 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
3765 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
3766 if (!W_ERROR_IS_OK(status
)) {
3771 /* check the required size. */
3772 *needed
+= spoolss_size_printer_driver_info_2(info
);
3774 if (!alloc_buffer_size(buffer
, *needed
)) {
3776 return WERR_INSUFFICIENT_BUFFER
;
3779 /* fill the buffer with the structures */
3780 smb_io_printer_driver_info_2("", buffer
, info
, 0);
3785 if (*needed
> offered
)
3786 return WERR_INSUFFICIENT_BUFFER
;
3791 /****************************************************************************
3792 ****************************************************************************/
3793 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3800 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
3801 if (!W_ERROR_IS_OK(status
)) {
3805 /* check the required size. */
3806 *needed
+= spoolss_size_printer_driver_info_3(&info
);
3808 if (!alloc_buffer_size(buffer
, *needed
)) {
3809 free_printer_driver_info_3(&info
);
3810 return WERR_INSUFFICIENT_BUFFER
;
3813 /* fill the buffer with the structures */
3814 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
3816 free_printer_driver_info_3(&info
);
3818 if (*needed
> offered
)
3819 return WERR_INSUFFICIENT_BUFFER
;
3824 /****************************************************************************
3825 ****************************************************************************/
3826 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3833 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
3834 if (!W_ERROR_IS_OK(status
)) {
3838 /* check the required size. */
3839 *needed
+= spoolss_size_printer_driver_info_6(&info
);
3841 if (!alloc_buffer_size(buffer
, *needed
)) {
3842 free_printer_driver_info_6(&info
);
3843 return WERR_INSUFFICIENT_BUFFER
;
3846 /* fill the buffer with the structures */
3847 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
3849 free_printer_driver_info_6(&info
);
3851 if (*needed
> offered
)
3852 return WERR_INSUFFICIENT_BUFFER
;
3857 /****************************************************************************
3858 ****************************************************************************/
3860 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
3862 POLICY_HND
*handle
= &q_u
->handle
;
3863 UNISTR2
*uni_arch
= &q_u
->architecture
;
3864 uint32 level
= q_u
->level
;
3865 uint32 clientmajorversion
= q_u
->clientmajorversion
;
3866 /* uint32 clientminorversion = q_u->clientminorversion; - notused. */
3867 NEW_BUFFER
*buffer
= NULL
;
3868 uint32 offered
= q_u
->offered
;
3869 uint32
*needed
= &r_u
->needed
;
3870 uint32
*servermajorversion
= &r_u
->servermajorversion
;
3871 uint32
*serverminorversion
= &r_u
->serverminorversion
;
3874 fstring architecture
;
3877 /* that's an [in out] buffer */
3878 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
3879 buffer
= r_u
->buffer
;
3881 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3884 *servermajorversion
=0;
3885 *serverminorversion
=0;
3887 pstrcpy(servername
, global_myname
);
3888 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
3890 if (!get_printer_snum(p
, handle
, &snum
))
3895 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3897 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3899 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3901 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3904 return WERR_UNKNOWN_LEVEL
;
3907 /****************************************************************************
3908 ****************************************************************************/
3910 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
3912 POLICY_HND
*handle
= &q_u
->handle
;
3914 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
3917 Printer
->page_started
=True
;
3921 DEBUG(3,("Error in startpageprinter printer handle\n"));
3925 /****************************************************************************
3926 ****************************************************************************/
3928 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
3930 POLICY_HND
*handle
= &q_u
->handle
;
3932 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
3935 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle
)));
3939 Printer
->page_started
=False
;
3944 /********************************************************************
3945 * api_spoolss_getprinter
3946 * called from the spoolss dispatcher
3948 ********************************************************************/
3950 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
3952 POLICY_HND
*handle
= &q_u
->handle
;
3953 /* uint32 level = q_u->doc_info_container.level; - notused. */
3954 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
3955 uint32
*jobid
= &r_u
->jobid
;
3957 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
3961 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
3962 struct current_user user
;
3965 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3969 get_current_user(&user
, p
);
3972 * a nice thing with NT is it doesn't listen to what you tell it.
3973 * when asked to send _only_ RAW datas, it tries to send datas
3976 * So I add checks like in NT Server ...
3978 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3979 * there's a bug in NT client-side code, so we'll fix it in the
3980 * server-side code. *nnnnnggggh!*
3983 if (info_1
->p_datatype
!= 0) {
3984 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
3985 if (strcmp(datatype
, "RAW") != 0) {
3987 return WERR_INVALID_DATATYPE
;
3991 /* get the share number of the printer */
3992 if (!get_printer_snum(p
, handle
, &snum
)) {
3996 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
3998 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
4000 /* An error occured in print_job_start() so return an appropriate
4003 if (Printer
->jobid
== -1) {
4004 return map_werror_from_unix(errno
);
4007 Printer
->document_started
=True
;
4008 (*jobid
) = Printer
->jobid
;
4013 /********************************************************************
4014 * api_spoolss_getprinter
4015 * called from the spoolss dispatcher
4017 ********************************************************************/
4019 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
4021 POLICY_HND
*handle
= &q_u
->handle
;
4023 return _spoolss_enddocprinter_internal(p
, handle
);
4026 /****************************************************************************
4027 ****************************************************************************/
4029 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
4031 POLICY_HND
*handle
= &q_u
->handle
;
4032 uint32 buffer_size
= q_u
->buffer_size
;
4033 uint8
*buffer
= q_u
->buffer
;
4034 uint32
*buffer_written
= &q_u
->buffer_size2
;
4036 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4039 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle
)));
4040 r_u
->buffer_written
= q_u
->buffer_size2
;
4044 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
, buffer_size
);
4047 r_u
->buffer_written
= q_u
->buffer_size2
;
4052 /********************************************************************
4053 * api_spoolss_getprinter
4054 * called from the spoolss dispatcher
4056 ********************************************************************/
4057 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
4060 struct current_user user
;
4062 WERROR errcode
= WERR_BADFUNC
;
4063 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4065 get_current_user(&user
, p
);
4068 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4072 if (!get_printer_snum(p
, handle
, &snum
))
4076 case PRINTER_CONTROL_PAUSE
:
4077 if (print_queue_pause(&user
, snum
, &errcode
)) {
4081 case PRINTER_CONTROL_RESUME
:
4082 case PRINTER_CONTROL_UNPAUSE
:
4083 if (print_queue_resume(&user
, snum
, &errcode
)) {
4087 case PRINTER_CONTROL_PURGE
:
4088 if (print_queue_purge(&user
, snum
, &errcode
)) {
4093 return WERR_UNKNOWN_LEVEL
;
4099 /********************************************************************
4100 * api_spoolss_abortprinter
4101 ********************************************************************/
4103 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
4105 POLICY_HND
*handle
= &q_u
->handle
;
4107 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
4110 /********************************************************************
4111 * called by spoolss_api_setprinter
4112 * when updating a printer description
4113 ********************************************************************/
4114 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
4115 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4116 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
4118 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
4119 struct current_user user
;
4123 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4125 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
4126 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
4127 OUR_HANDLE(handle
)));
4129 result
= WERR_BADFID
;
4133 /* NT seems to like setting the security descriptor even though
4134 nothing may have actually changed. This causes annoying
4135 dialog boxes when the user doesn't have permission to change
4136 the security descriptor. */
4138 nt_printing_getsec(p
->mem_ctx
, Printer
->dev
.handlename
, &old_secdesc_ctr
);
4140 if (DEBUGLEVEL
>= 10) {
4144 the_acl
= old_secdesc_ctr
->sec
->dacl
;
4145 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
4146 PRINTERNAME(snum
), the_acl
->num_aces
));
4148 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4151 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4153 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4154 the_acl
->ace
[i
].info
.mask
));
4157 the_acl
= secdesc_ctr
->sec
->dacl
;
4160 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
4161 PRINTERNAME(snum
), the_acl
->num_aces
));
4163 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
4166 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
4168 DEBUG(10, ("%s 0x%08x\n", sid_str
,
4169 the_acl
->ace
[i
].info
.mask
));
4172 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
4176 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
4178 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
4183 /* Work out which user is performing the operation */
4185 get_current_user(&user
, p
);
4187 /* Check the user has permissions to change the security
4188 descriptor. By experimentation with two NT machines, the user
4189 requires Full Access to the printer to change security
4192 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4193 result
= WERR_ACCESS_DENIED
;
4197 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
4204 /********************************************************************
4205 Do Samba sanity checks on a printer info struct.
4206 this has changed purpose: it now "canonicalises" printer
4207 info from a client rather than just checking it is correct
4208 ********************************************************************/
4210 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
4212 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
4213 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
4215 /* we force some elements to "correct" values */
4216 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname
);
4217 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
4218 global_myname
, lp_servicename(snum
));
4219 fstrcpy(info
->sharename
, lp_servicename(snum
));
4220 info
->attributes
= PRINTER_ATTRIBUTE_SHARED \
4221 | PRINTER_ATTRIBUTE_LOCAL \
4222 | PRINTER_ATTRIBUTE_RAW_ONLY \
4223 | PRINTER_ATTRIBUTE_QUEUED
;
4228 /****************************************************************************
4229 ****************************************************************************/
4230 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
4232 char *cmd
= lp_addprinter_cmd();
4235 pstring driverlocation
;
4240 /* build driver path... only 9X architecture is needed for legacy reasons */
4241 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
4243 /* change \ to \\ for the shell */
4244 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
4246 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
4247 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
4248 printer
->info_2
->portname
, printer
->info_2
->drivername
,
4249 printer
->info_2
->location
, driverlocation
);
4251 /* Convert script args to unix-codepage */
4252 dos_to_unix(command
, True
);
4253 DEBUG(10,("Running [%s]\n", command
));
4254 ret
= smbrun(command
, &fd
);
4255 DEBUGADD(10,("returned [%d]\n", ret
));
4264 /* Get lines and convert them back to dos-codepage */
4265 qlines
= fd_lines_load(fd
, &numlines
, True
);
4266 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4270 /* Set the portname to what the script says the portname should be. */
4271 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
4272 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
4274 /* Send SIGHUP to process group... is there a better way? */
4279 file_lines_free(qlines
);
4283 /* Return true if two devicemodes are equal */
4285 #define DEVMODE_CHECK_INT(field) \
4286 if (d1->field != d2->field) { \
4287 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
4288 d1->field, d2->field)); \
4292 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
4294 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
4297 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
4298 return False
; /* if either is exclusively NULL are not equal */
4301 if (!strequal(d1
->devicename
, d2
->devicename
)) {
4302 DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1
->devicename
, d2
->devicename
));
4306 if (!strequal(d1
->formname
, d2
->formname
)) {
4307 DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1
->formname
, d2
->formname
));
4311 DEVMODE_CHECK_INT(specversion
);
4312 DEVMODE_CHECK_INT(driverversion
);
4313 DEVMODE_CHECK_INT(driverextra
);
4314 DEVMODE_CHECK_INT(orientation
);
4315 DEVMODE_CHECK_INT(papersize
);
4316 DEVMODE_CHECK_INT(paperlength
);
4317 DEVMODE_CHECK_INT(paperwidth
);
4318 DEVMODE_CHECK_INT(scale
);
4319 DEVMODE_CHECK_INT(copies
);
4320 DEVMODE_CHECK_INT(defaultsource
);
4321 DEVMODE_CHECK_INT(printquality
);
4322 DEVMODE_CHECK_INT(color
);
4323 DEVMODE_CHECK_INT(duplex
);
4324 DEVMODE_CHECK_INT(yresolution
);
4325 DEVMODE_CHECK_INT(ttoption
);
4326 DEVMODE_CHECK_INT(collate
);
4327 DEVMODE_CHECK_INT(logpixels
);
4329 DEVMODE_CHECK_INT(fields
);
4330 DEVMODE_CHECK_INT(bitsperpel
);
4331 DEVMODE_CHECK_INT(pelswidth
);
4332 DEVMODE_CHECK_INT(pelsheight
);
4333 DEVMODE_CHECK_INT(displayflags
);
4334 DEVMODE_CHECK_INT(displayfrequency
);
4335 DEVMODE_CHECK_INT(icmmethod
);
4336 DEVMODE_CHECK_INT(icmintent
);
4337 DEVMODE_CHECK_INT(mediatype
);
4338 DEVMODE_CHECK_INT(dithertype
);
4339 DEVMODE_CHECK_INT(reserved1
);
4340 DEVMODE_CHECK_INT(reserved2
);
4341 DEVMODE_CHECK_INT(panningwidth
);
4342 DEVMODE_CHECK_INT(panningheight
);
4344 /* compare the private data if it exists */
4345 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
4348 DEVMODE_CHECK_INT(driverextra
);
4350 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
4351 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
4356 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
4360 /* Return true if two NT_PRINTER_PARAM structures are equal */
4362 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
4363 NT_PRINTER_PARAM
*p2
)
4365 if (!p1
&& !p2
) goto equal
;
4367 if ((!p1
&& p2
) || (p1
&& !p2
)) {
4368 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
4372 /* Compare lists of printer parameters */
4376 NT_PRINTER_PARAM
*q
= p1
;
4378 /* Find the parameter in the second structure */
4382 if (strequal(p1
->value
, q
->value
)) {
4384 if (p1
->type
!= q
->type
) {
4385 DEBUG(10, ("nt_printer_param_equal():"
4386 "types for %s differ (%d != %d)\n",
4387 p1
->value
, p1
->type
,
4392 if (p1
->data_len
!= q
->data_len
) {
4393 DEBUG(10, ("nt_printer_param_equal():"
4394 "len for %s differs (%d != %d)\n",
4395 p1
->value
, p1
->data_len
,
4400 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
4403 DEBUG(10, ("nt_printer_param_equal():"
4404 "data for %s differs\n", p1
->value
));
4414 DEBUG(10, ("nt_printer_param_equal(): param %s "
4415 "does not exist\n", p1
->value
));
4424 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
4428 /********************************************************************
4429 * Called by update_printer when trying to work out whether to
4430 * actually update printer info.
4431 ********************************************************************/
4433 #define PI_CHECK_INT(field) \
4434 if (pi1->field != pi2->field) { \
4435 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
4436 pi1->field, pi2->field)); \
4440 #define PI_CHECK_STR(field) \
4441 if (!strequal(pi1->field, pi2->field)) { \
4442 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
4443 pi1->field, pi2->field)); \
4447 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
4448 NT_PRINTER_INFO_LEVEL
*p2
)
4450 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
4452 /* Trivial conditions */
4454 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
4458 if ((!p1
&& p2
) || (p1
&& !p2
) ||
4459 (!p1
->info_2
&& p2
->info_2
) ||
4460 (p1
->info_2
&& !p2
->info_2
)) {
4461 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
4466 /* Compare two nt_printer_info_level structures. Don't compare
4467 status or cjobs as they seem to have something to do with the
4473 /* Don't check the attributes as we stomp on the value in
4474 check_printer_ok() anyway. */
4477 PI_CHECK_INT(attributes
);
4480 PI_CHECK_INT(priority
);
4481 PI_CHECK_INT(default_priority
);
4482 PI_CHECK_INT(starttime
);
4483 PI_CHECK_INT(untiltime
);
4484 PI_CHECK_INT(averageppm
);
4486 /* Yuck - don't check the printername or servername as the
4487 add_a_printer() code plays games with them. You can't
4488 change the printername or the sharename through this interface
4491 PI_CHECK_STR(sharename
);
4492 PI_CHECK_STR(portname
);
4493 PI_CHECK_STR(drivername
);
4494 PI_CHECK_STR(comment
);
4495 PI_CHECK_STR(location
);
4497 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
4501 PI_CHECK_STR(sepfile
);
4502 PI_CHECK_STR(printprocessor
);
4503 PI_CHECK_STR(datatype
);
4504 PI_CHECK_STR(parameters
);
4506 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
4510 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
4514 PI_CHECK_INT(changeid
);
4515 PI_CHECK_INT(c_setprinter
);
4516 PI_CHECK_INT(setuptime
);
4519 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
4523 /********************************************************************
4524 * called by spoolss_api_setprinter
4525 * when updating a printer description
4526 ********************************************************************/
4528 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
4529 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4530 DEVICEMODE
*devmode
)
4533 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
4534 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4537 DEBUG(8,("update_printer\n"));
4542 DEBUG(0,("Send a mail to samba@samba.org\n"));
4543 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
4544 result
= WERR_UNKNOWN_LEVEL
;
4549 result
= WERR_BADFID
;
4553 if (!get_printer_snum(p
, handle
, &snum
)) {
4554 result
= WERR_BADFID
;
4558 if (!W_ERROR_IS_OK(get_a_printer(&printer
, 2, lp_servicename(snum
))) ||
4559 (!W_ERROR_IS_OK(get_a_printer(&old_printer
, 2, lp_servicename(snum
))))) {
4560 result
= WERR_BADFID
;
4564 DEBUGADD(8,("Converting info_2 struct\n"));
4567 * convert_printer_info converts the incoming
4568 * info from the client and overwrites the info
4569 * just read from the tdb in the pointer 'printer'.
4572 if (!convert_printer_info(info
, printer
, level
)) {
4573 result
= WERR_NOMEM
;
4577 if (info
->info_2
->devmode_ptr
!= 0) {
4578 /* we have a valid devmode
4579 convert it and link it*/
4581 DEBUGADD(8,("Converting the devicemode struct\n"));
4582 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
4583 &printer
->info_2
->devmode
)) {
4584 result
= WERR_NOMEM
;
4589 /* Do sanity check on the requested changes for Samba */
4591 if (!check_printer_ok(printer
->info_2
, snum
)) {
4592 result
= WERR_INVALID_PARAM
;
4596 /* NT likes to call this function even though nothing has actually
4597 changed. Check this so the user doesn't end up with an
4598 annoying permission denied dialog box. */
4600 if (nt_printer_info_level_equal(printer
, old_printer
)) {
4601 DEBUG(3, ("printer info has not changed\n"));
4606 /* Check calling user has permission to update printer description */
4608 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4609 DEBUG(3, ("printer property change denied by security "
4611 result
= WERR_ACCESS_DENIED
;
4615 /* Call addprinter hook */
4617 if (*lp_addprinter_cmd()) {
4618 if ( !add_printer_hook(printer
) ) {
4619 result
= WERR_ACCESS_DENIED
;
4624 /* Update printer info */
4625 result
= add_a_printer(*printer
, 2);
4628 free_a_printer(&printer
, 2);
4629 free_a_printer(&old_printer
, 2);
4631 srv_spoolss_sendnotify(p
, handle
);
4636 /****************************************************************************
4637 ****************************************************************************/
4639 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
4641 POLICY_HND
*handle
= &q_u
->handle
;
4642 uint32 level
= q_u
->level
;
4643 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
4644 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
4645 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
4646 uint32 command
= q_u
->command
;
4648 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4651 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4655 /* check the level */
4658 return control_printer(handle
, command
, p
);
4660 return update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
4662 return update_printer_sec(handle
, level
, info
, p
,
4665 return WERR_UNKNOWN_LEVEL
;
4669 /****************************************************************************
4670 ****************************************************************************/
4672 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
4674 POLICY_HND
*handle
= &q_u
->handle
;
4676 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
4679 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
4683 if (Printer
->notify
.client_connected
==True
)
4684 srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
);
4686 Printer
->notify
.flags
=0;
4687 Printer
->notify
.options
=0;
4688 Printer
->notify
.localmachine
[0]='\0';
4689 Printer
->notify
.printerlocal
=0;
4690 if (Printer
->notify
.option
)
4691 free_spool_notify_option(&Printer
->notify
.option
);
4692 Printer
->notify
.client_connected
=False
;
4697 /****************************************************************************
4698 ****************************************************************************/
4700 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
4702 /* that's an [in out] buffer (despite appearences to the contrary) */
4703 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4706 return WERR_INVALID_PARAM
; /* this is what a NT server
4707 returns for AddJob. AddJob
4708 must fail on non-local
4712 /****************************************************************************
4713 ****************************************************************************/
4714 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
4715 int position
, int snum
)
4721 t
=gmtime(&queue
->time
);
4722 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", global_myname
);
4724 job_info
->jobid
=queue
->job
;
4725 init_unistr(&job_info
->printername
, lp_servicename(snum
));
4726 init_unistr(&job_info
->machinename
, temp_name
);
4727 init_unistr(&job_info
->username
, queue
->user
);
4728 init_unistr(&job_info
->document
, queue
->file
);
4729 init_unistr(&job_info
->datatype
, "RAW");
4730 init_unistr(&job_info
->text_status
, "");
4731 job_info
->status
=nt_printj_status(queue
->status
);
4732 job_info
->priority
=queue
->priority
;
4733 job_info
->position
=position
;
4734 job_info
->totalpages
=0;
4735 job_info
->pagesprinted
=0;
4737 make_systemtime(&job_info
->submitted
, t
);
4740 /****************************************************************************
4741 ****************************************************************************/
4742 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
4743 int position
, int snum
,
4744 NT_PRINTER_INFO_LEVEL
*ntprinter
)
4750 t
=gmtime(&queue
->time
);
4751 slprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", global_myname
);
4753 job_info
->jobid
=queue
->job
;
4755 slprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", global_myname
, ntprinter
->info_2
->printername
);
4757 init_unistr(&job_info
->printername
, chaine
);
4759 init_unistr(&job_info
->machinename
, temp_name
);
4760 init_unistr(&job_info
->username
, queue
->user
);
4761 init_unistr(&job_info
->document
, queue
->file
);
4762 init_unistr(&job_info
->notifyname
, queue
->user
);
4763 init_unistr(&job_info
->datatype
, "RAW");
4764 init_unistr(&job_info
->printprocessor
, "winprint");
4765 init_unistr(&job_info
->parameters
, "");
4766 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
4767 init_unistr(&job_info
->text_status
, "");
4769 /* and here the security descriptor */
4771 job_info
->status
=nt_printj_status(queue
->status
);
4772 job_info
->priority
=queue
->priority
;
4773 job_info
->position
=position
;
4774 job_info
->starttime
=0;
4775 job_info
->untiltime
=0;
4776 job_info
->totalpages
=0;
4777 job_info
->size
=queue
->size
;
4778 make_systemtime(&(job_info
->submitted
), t
);
4779 job_info
->timeelapsed
=0;
4780 job_info
->pagesprinted
=0;
4782 if((job_info
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4789 /****************************************************************************
4790 Enumjobs at level 1.
4791 ****************************************************************************/
4792 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
4793 NEW_BUFFER
*buffer
, uint32 offered
,
4794 uint32
*needed
, uint32
*returned
)
4799 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
4806 for (i
=0; i
<*returned
; i
++)
4807 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
4811 /* check the required size. */
4812 for (i
=0; i
<*returned
; i
++)
4813 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
4815 if (!alloc_buffer_size(buffer
, *needed
)) {
4817 return WERR_INSUFFICIENT_BUFFER
;
4820 /* fill the buffer with the structures */
4821 for (i
=0; i
<*returned
; i
++)
4822 smb_io_job_info_1("", buffer
, &info
[i
], 0);
4827 if (*needed
> offered
) {
4829 return WERR_INSUFFICIENT_BUFFER
;
4835 /****************************************************************************
4836 Enumjobs at level 2.
4837 ****************************************************************************/
4838 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
4839 NEW_BUFFER
*buffer
, uint32 offered
,
4840 uint32
*needed
, uint32
*returned
)
4842 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4847 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
4853 result
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
4854 if (!W_ERROR_IS_OK(result
)) {
4859 for (i
=0; i
<*returned
; i
++)
4860 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
);
4862 free_a_printer(&ntprinter
, 2);
4865 /* check the required size. */
4866 for (i
=0; i
<*returned
; i
++)
4867 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
4869 if (!alloc_buffer_size(buffer
, *needed
)) {
4871 return WERR_INSUFFICIENT_BUFFER
;
4874 /* fill the buffer with the structures */
4875 for (i
=0; i
<*returned
; i
++)
4876 smb_io_job_info_2("", buffer
, &info
[i
], 0);
4879 for (i
= 0; i
< *returned
; i
++)
4880 free_job_info_2(&info
[i
]);
4884 if (*needed
> offered
) {
4886 return WERR_INSUFFICIENT_BUFFER
;
4892 /****************************************************************************
4894 ****************************************************************************/
4896 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
4898 POLICY_HND
*handle
= &q_u
->handle
;
4899 /* uint32 firstjob = q_u->firstjob; - notused. */
4900 /* uint32 numofjobs = q_u->numofjobs; - notused. */
4901 uint32 level
= q_u
->level
;
4902 NEW_BUFFER
*buffer
= NULL
;
4903 uint32 offered
= q_u
->offered
;
4904 uint32
*needed
= &r_u
->needed
;
4905 uint32
*returned
= &r_u
->returned
;
4908 print_status_struct prt_status
;
4909 print_queue_struct
*queue
=NULL
;
4911 /* that's an [in out] buffer */
4912 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4913 buffer
= r_u
->buffer
;
4915 DEBUG(4,("_spoolss_enumjobs\n"));
4920 if (!get_printer_snum(p
, handle
, &snum
))
4923 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
4924 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
4926 if (*returned
== 0) {
4933 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
4935 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
4939 return WERR_UNKNOWN_LEVEL
;
4943 /****************************************************************************
4944 ****************************************************************************/
4946 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
4951 /****************************************************************************
4952 ****************************************************************************/
4954 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
4956 POLICY_HND
*handle
= &q_u
->handle
;
4957 uint32 jobid
= q_u
->jobid
;
4958 /* uint32 level = q_u->level; - notused. */
4959 /* JOB_INFO *ctr = &q_u->ctr; - notused. */
4960 uint32 command
= q_u
->command
;
4962 struct current_user user
;
4964 WERROR errcode
= WERR_BADFUNC
;
4966 if (!get_printer_snum(p
, handle
, &snum
)) {
4970 if (!print_job_exists(jobid
)) {
4971 return WERR_INVALID_PRINTER_NAME
;
4974 get_current_user(&user
, p
);
4977 case JOB_CONTROL_CANCEL
:
4978 case JOB_CONTROL_DELETE
:
4979 if (print_job_delete(&user
, jobid
, &errcode
)) {
4983 case JOB_CONTROL_PAUSE
:
4984 if (print_job_pause(&user
, jobid
, &errcode
)) {
4988 case JOB_CONTROL_RESTART
:
4989 case JOB_CONTROL_RESUME
:
4990 if (print_job_resume(&user
, jobid
, &errcode
)) {
4995 return WERR_UNKNOWN_LEVEL
;
5001 /****************************************************************************
5002 Enumerates all printer drivers at level 1.
5003 ****************************************************************************/
5004 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5009 fstring
*list
= NULL
;
5011 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5012 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
5016 #define MAX_VERSION 4
5018 for (version
=0; version
<MAX_VERSION
; version
++) {
5020 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5021 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5027 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
5028 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
5029 SAFE_FREE(driver_info_1
);
5033 else driver_info_1
= tdi1
;
5036 for (i
=0; i
<ndrivers
; i
++) {
5038 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5039 ZERO_STRUCT(driver
);
5040 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5041 architecture
, version
);
5042 if (!W_ERROR_IS_OK(status
)) {
5046 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
5047 free_a_printer_driver(driver
, 3);
5050 *returned
+=ndrivers
;
5054 /* check the required size. */
5055 for (i
=0; i
<*returned
; i
++) {
5056 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5057 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
5060 if (!alloc_buffer_size(buffer
, *needed
)) {
5061 SAFE_FREE(driver_info_1
);
5062 return WERR_INSUFFICIENT_BUFFER
;
5065 /* fill the buffer with the driver structures */
5066 for (i
=0; i
<*returned
; i
++) {
5067 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5068 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
5071 SAFE_FREE(driver_info_1
);
5073 if (*needed
> offered
) {
5075 return WERR_INSUFFICIENT_BUFFER
;
5081 /****************************************************************************
5082 Enumerates all printer drivers at level 2.
5083 ****************************************************************************/
5084 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5089 fstring
*list
= NULL
;
5091 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5092 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
5096 #define MAX_VERSION 4
5098 for (version
=0; version
<MAX_VERSION
; version
++) {
5100 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5101 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5107 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
5108 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
5109 SAFE_FREE(driver_info_2
);
5113 else driver_info_2
= tdi2
;
5116 for (i
=0; i
<ndrivers
; i
++) {
5119 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5120 ZERO_STRUCT(driver
);
5121 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5122 architecture
, version
);
5123 if (!W_ERROR_IS_OK(status
)) {
5127 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
5128 free_a_printer_driver(driver
, 3);
5131 *returned
+=ndrivers
;
5135 /* check the required size. */
5136 for (i
=0; i
<*returned
; i
++) {
5137 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5138 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
5141 if (!alloc_buffer_size(buffer
, *needed
)) {
5142 SAFE_FREE(driver_info_2
);
5143 return WERR_INSUFFICIENT_BUFFER
;
5146 /* fill the buffer with the form structures */
5147 for (i
=0; i
<*returned
; i
++) {
5148 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5149 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
5152 SAFE_FREE(driver_info_2
);
5154 if (*needed
> offered
) {
5156 return WERR_INSUFFICIENT_BUFFER
;
5162 /****************************************************************************
5163 Enumerates all printer drivers at level 3.
5164 ****************************************************************************/
5165 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5170 fstring
*list
= NULL
;
5172 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5173 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
5177 #define MAX_VERSION 4
5179 for (version
=0; version
<MAX_VERSION
; version
++) {
5181 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
5182 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
5188 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
5189 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
5190 SAFE_FREE(driver_info_3
);
5194 else driver_info_3
= tdi3
;
5197 for (i
=0; i
<ndrivers
; i
++) {
5200 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
5201 ZERO_STRUCT(driver
);
5202 status
= get_a_printer_driver(&driver
, 3, list
[i
],
5203 architecture
, version
);
5204 if (!W_ERROR_IS_OK(status
)) {
5208 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
5209 free_a_printer_driver(driver
, 3);
5212 *returned
+=ndrivers
;
5216 /* check the required size. */
5217 for (i
=0; i
<*returned
; i
++) {
5218 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
5219 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
5222 if (!alloc_buffer_size(buffer
, *needed
)) {
5223 SAFE_FREE(driver_info_3
);
5224 return WERR_INSUFFICIENT_BUFFER
;
5227 /* fill the buffer with the driver structures */
5228 for (i
=0; i
<*returned
; i
++) {
5229 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
5230 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
5233 for (i
=0; i
<*returned
; i
++)
5234 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
5236 SAFE_FREE(driver_info_3
);
5238 if (*needed
> offered
) {
5240 return WERR_INSUFFICIENT_BUFFER
;
5246 /****************************************************************************
5247 Enumerates all printer drivers.
5248 ****************************************************************************/
5250 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
5252 /* UNISTR2 *name = &q_u->name; - notused. */
5253 UNISTR2
*environment
= &q_u
->environment
;
5254 uint32 level
= q_u
->level
;
5255 NEW_BUFFER
*buffer
= NULL
;
5256 uint32 offered
= q_u
->offered
;
5257 uint32
*needed
= &r_u
->needed
;
5258 uint32
*returned
= &r_u
->returned
;
5260 fstring
*list
= NULL
;
5262 fstring architecture
;
5264 /* that's an [in out] buffer */
5265 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5266 buffer
= r_u
->buffer
;
5268 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
5269 fstrcpy(servername
, global_myname
);
5273 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
5277 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
5279 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
5281 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
5285 return WERR_UNKNOWN_LEVEL
;
5289 /****************************************************************************
5290 ****************************************************************************/
5292 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
5294 form
->flag
=list
->flag
;
5295 init_unistr(&form
->name
, list
->name
);
5296 form
->width
=list
->width
;
5297 form
->length
=list
->length
;
5298 form
->left
=list
->left
;
5299 form
->top
=list
->top
;
5300 form
->right
=list
->right
;
5301 form
->bottom
=list
->bottom
;
5304 /****************************************************************************
5305 ****************************************************************************/
5307 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
5309 /* POLICY_HND *handle = &q_u->handle; - notused. */
5310 uint32 level
= q_u
->level
;
5311 NEW_BUFFER
*buffer
= NULL
;
5312 uint32 offered
= q_u
->offered
;
5313 uint32
*needed
= &r_u
->needed
;
5314 uint32
*numofforms
= &r_u
->numofforms
;
5315 uint32 numbuiltinforms
;
5317 nt_forms_struct
*list
=NULL
;
5318 nt_forms_struct
*builtinlist
=NULL
;
5323 /* that's an [in out] buffer */
5324 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5325 buffer
= r_u
->buffer
;
5327 DEBUG(4,("_spoolss_enumforms\n"));
5328 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
5329 DEBUGADD(5,("Info level [%d]\n", level
));
5331 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
5332 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
5333 *numofforms
= get_ntforms(&list
);
5334 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
5335 *numofforms
+= numbuiltinforms
;
5337 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
5341 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
5346 /* construct the list of form structures */
5347 for (i
=0; i
<numbuiltinforms
; i
++) {
5348 DEBUGADD(6,("Filling form number [%d]\n",i
));
5349 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
5352 SAFE_FREE(builtinlist
);
5354 for (; i
<*numofforms
; i
++) {
5355 DEBUGADD(6,("Filling form number [%d]\n",i
));
5356 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
5361 /* check the required size. */
5362 for (i
=0; i
<numbuiltinforms
; i
++) {
5363 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5364 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5366 for (; i
<*numofforms
; i
++) {
5367 DEBUGADD(6,("adding form [%d]'s size\n",i
));
5368 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
5371 *needed
=buffer_size
;
5373 if (!alloc_buffer_size(buffer
, buffer_size
)){
5375 return WERR_INSUFFICIENT_BUFFER
;
5378 /* fill the buffer with the form structures */
5379 for (i
=0; i
<numbuiltinforms
; i
++) {
5380 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5381 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5383 for (; i
<*numofforms
; i
++) {
5384 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
5385 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
5390 if (*needed
> offered
) {
5392 return WERR_INSUFFICIENT_BUFFER
;
5399 SAFE_FREE(builtinlist
);
5400 return WERR_UNKNOWN_LEVEL
;
5405 /****************************************************************************
5406 ****************************************************************************/
5408 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
5410 /* POLICY_HND *handle = &q_u->handle; - notused. */
5411 uint32 level
= q_u
->level
;
5412 UNISTR2
*uni_formname
= &q_u
->formname
;
5413 NEW_BUFFER
*buffer
= NULL
;
5414 uint32 offered
= q_u
->offered
;
5415 uint32
*needed
= &r_u
->needed
;
5417 nt_forms_struct
*list
=NULL
;
5418 nt_forms_struct builtin_form
;
5423 int numofforms
=0, i
=0;
5425 /* that's an [in out] buffer */
5426 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5427 buffer
= r_u
->buffer
;
5429 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
5431 DEBUG(4,("_spoolss_getform\n"));
5432 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
5433 DEBUGADD(5,("Info level [%d]\n", level
));
5435 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
5436 if (!foundBuiltin
) {
5437 numofforms
= get_ntforms(&list
);
5438 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
5440 if (numofforms
== 0)
5447 fill_form_1(&form_1
, &builtin_form
);
5450 /* Check if the requested name is in the list of form structures */
5451 for (i
=0; i
<numofforms
; i
++) {
5453 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
5455 if (strequal(form_name
, list
[i
].name
)) {
5456 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
5457 fill_form_1(&form_1
, &list
[i
]);
5463 if (i
== numofforms
) {
5467 /* check the required size. */
5469 *needed
=spoolss_size_form_1(&form_1
);
5471 if (!alloc_buffer_size(buffer
, buffer_size
)){
5472 return WERR_INSUFFICIENT_BUFFER
;
5475 if (*needed
> offered
) {
5476 return WERR_INSUFFICIENT_BUFFER
;
5479 /* fill the buffer with the form structures */
5480 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
5481 smb_io_form_1("", buffer
, &form_1
, 0);
5487 return WERR_UNKNOWN_LEVEL
;
5491 /****************************************************************************
5492 ****************************************************************************/
5493 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
5495 init_unistr(&port
->port_name
, name
);
5498 /****************************************************************************
5499 ****************************************************************************/
5500 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
5502 init_unistr(&port
->port_name
, name
);
5503 init_unistr(&port
->monitor_name
, "Local Monitor");
5504 init_unistr(&port
->description
, "Local Port");
5505 #define PORT_TYPE_WRITE 1
5506 port
->port_type
=PORT_TYPE_WRITE
;
5510 /****************************************************************************
5512 ****************************************************************************/
5513 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5515 PORT_INFO_1
*ports
=NULL
;
5518 if (*lp_enumports_cmd()) {
5519 char *cmd
= lp_enumports_cmd();
5526 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
5528 DEBUG(10,("Running [%s]\n", command
));
5529 ret
= smbrun(command
, &fd
);
5530 DEBUG(10,("Returned [%d]\n", ret
));
5534 /* Is this the best error to return here? */
5535 return WERR_ACCESS_DENIED
;
5539 qlines
= fd_lines_load(fd
, &numlines
,True
);
5540 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5544 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
5545 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
5546 werror_str(WERR_NOMEM
)));
5547 file_lines_free(qlines
);
5551 for (i
=0; i
<numlines
; i
++) {
5552 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
5553 fill_port_1(&ports
[i
], qlines
[i
]);
5556 file_lines_free(qlines
);
5559 *returned
= numlines
;
5562 *returned
= 1; /* Sole Samba port returned. */
5564 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
5567 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
5569 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
5572 /* check the required size. */
5573 for (i
=0; i
<*returned
; i
++) {
5574 DEBUGADD(6,("adding port [%d]'s size\n", i
));
5575 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
5578 if (!alloc_buffer_size(buffer
, *needed
)) {
5580 return WERR_INSUFFICIENT_BUFFER
;
5583 /* fill the buffer with the ports structures */
5584 for (i
=0; i
<*returned
; i
++) {
5585 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
5586 smb_io_port_1("", buffer
, &ports
[i
], 0);
5591 if (*needed
> offered
) {
5593 return WERR_INSUFFICIENT_BUFFER
;
5599 /****************************************************************************
5601 ****************************************************************************/
5603 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5605 PORT_INFO_2
*ports
=NULL
;
5608 if (*lp_enumports_cmd()) {
5609 char *cmd
= lp_enumports_cmd();
5618 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
5619 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
5621 path
= lp_lockdir();
5623 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
5624 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
5627 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
5628 ret
= smbrun(command
, &fd
);
5629 DEBUGADD(10,("returned [%d]\n", ret
));
5633 /* Is this the best error to return here? */
5634 return WERR_ACCESS_DENIED
;
5638 qlines
= fd_lines_load(fd
, &numlines
,True
);
5639 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5643 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
5644 file_lines_free(qlines
);
5648 for (i
=0; i
<numlines
; i
++) {
5649 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
5650 fill_port_2(&(ports
[i
]), qlines
[i
]);
5653 file_lines_free(qlines
);
5656 *returned
= numlines
;
5662 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
5665 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
5667 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
5670 /* check the required size. */
5671 for (i
=0; i
<*returned
; i
++) {
5672 DEBUGADD(6,("adding port [%d]'s size\n", i
));
5673 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
5676 if (!alloc_buffer_size(buffer
, *needed
)) {
5678 return WERR_INSUFFICIENT_BUFFER
;
5681 /* fill the buffer with the ports structures */
5682 for (i
=0; i
<*returned
; i
++) {
5683 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
5684 smb_io_port_2("", buffer
, &ports
[i
], 0);
5689 if (*needed
> offered
) {
5691 return WERR_INSUFFICIENT_BUFFER
;
5697 /****************************************************************************
5699 ****************************************************************************/
5701 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
5703 /* UNISTR2 *name = &q_u->name; - notused. */
5704 uint32 level
= q_u
->level
;
5705 NEW_BUFFER
*buffer
= NULL
;
5706 uint32 offered
= q_u
->offered
;
5707 uint32
*needed
= &r_u
->needed
;
5708 uint32
*returned
= &r_u
->returned
;
5710 /* that's an [in out] buffer */
5711 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5712 buffer
= r_u
->buffer
;
5714 DEBUG(4,("_spoolss_enumports\n"));
5721 return enumports_level_1(buffer
, offered
, needed
, returned
);
5723 return enumports_level_2(buffer
, offered
, needed
, returned
);
5725 return WERR_UNKNOWN_LEVEL
;
5729 /****************************************************************************
5730 ****************************************************************************/
5731 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
5732 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5733 uint32 unk0
, uint32 unk1
, uint32 unk2
, uint32 unk3
,
5734 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
5737 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5740 WERROR err
= WERR_OK
;
5742 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
5743 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
5747 ZERO_STRUCTP(printer
);
5749 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
5750 if (!convert_printer_info(info
, printer
, 2)) {
5751 free_a_printer(&printer
, 2);
5755 /* check to see if the printer already exists */
5757 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
5758 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
5759 printer
->info_2
->sharename
));
5760 free_a_printer(&printer
, 2);
5761 return WERR_PRINTER_ALREADY_EXISTS
;
5764 if (*lp_addprinter_cmd() )
5765 if ( !add_printer_hook(printer
) ) {
5766 free_a_printer(&printer
,2);
5767 return WERR_ACCESS_DENIED
;
5770 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname
,
5771 printer
->info_2
->sharename
);
5773 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
5774 free_a_printer(&printer
,2);
5775 return WERR_ACCESS_DENIED
;
5778 /* you must be a printer admin to add a new printer */
5779 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5780 free_a_printer(&printer
,2);
5781 return WERR_ACCESS_DENIED
;
5785 * Do sanity check on the requested changes for Samba.
5788 if (!check_printer_ok(printer
->info_2
, snum
)) {
5789 free_a_printer(&printer
,2);
5790 return WERR_INVALID_PARAM
;
5794 * When a printer is created, the drivername bound to the printer is used
5795 * to lookup previously saved driver initialization info, which is then
5796 * bound to the new printer, simulating what happens in the Windows arch.
5798 set_driver_init(printer
, 2);
5800 /* write the ASCII on disk */
5801 err
= add_a_printer(*printer
, 2);
5802 if (!W_ERROR_IS_OK(err
)) {
5803 free_a_printer(&printer
,2);
5807 if (!open_printer_hnd(p
, handle
, name
)) {
5808 /* Handle open failed - remove addition. */
5809 del_a_printer(printer
->info_2
->sharename
);
5810 free_a_printer(&printer
,2);
5811 return WERR_ACCESS_DENIED
;
5814 free_a_printer(&printer
,2);
5816 srv_spoolss_sendnotify(p
, handle
);
5821 /****************************************************************************
5822 ****************************************************************************/
5824 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
5826 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
5827 uint32 level
= q_u
->level
;
5828 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
5829 uint32 unk0
= q_u
->unk0
;
5830 uint32 unk1
= q_u
->unk1
;
5831 uint32 unk2
= q_u
->unk2
;
5832 uint32 unk3
= q_u
->unk3
;
5833 uint32 user_switch
= q_u
->user_switch
;
5834 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
5835 POLICY_HND
*handle
= &r_u
->handle
;
5839 /* we don't handle yet */
5840 /* but I know what to do ... */
5841 return WERR_UNKNOWN_LEVEL
;
5843 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
5844 unk0
, unk1
, unk2
, unk3
,
5845 user_switch
, user
, handle
);
5847 return WERR_UNKNOWN_LEVEL
;
5851 /****************************************************************************
5852 ****************************************************************************/
5854 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
5856 /* UNISTR2 *server_name = &q_u->server_name; - notused. */
5857 uint32 level
= q_u
->level
;
5858 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
5859 WERROR err
= WERR_OK
;
5860 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5861 struct current_user user
;
5863 ZERO_STRUCT(driver
);
5865 get_current_user(&user
, p
);
5867 if (!convert_printer_driver_info(info
, &driver
, level
)) {
5872 DEBUG(5,("Cleaning driver's information\n"));
5873 err
= clean_up_driver_struct(driver
, level
, &user
);
5874 if (!W_ERROR_IS_OK(err
))
5877 DEBUG(5,("Moving driver to final destination\n"));
5878 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
5879 if (W_ERROR_IS_OK(err
))
5880 err
= WERR_ACCESS_DENIED
;
5884 if (add_a_printer_driver(driver
, level
)!=0) {
5885 err
= WERR_ACCESS_DENIED
;
5890 free_a_printer_driver(driver
, level
);
5894 /****************************************************************************
5895 ****************************************************************************/
5896 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
5898 init_unistr(&info
->name
, name
);
5901 /****************************************************************************
5902 ****************************************************************************/
5903 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5907 pstring short_archi
;
5908 DRIVER_DIRECTORY_1
*info
=NULL
;
5910 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
5912 if (get_short_archi(short_archi
, long_archi
)==False
)
5913 return WERR_INVALID_ENVIRONMENT
;
5915 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
5918 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", global_myname
, short_archi
);
5920 DEBUG(4,("printer driver directory: [%s]\n", path
));
5922 fill_driverdir_1(info
, path
);
5924 *needed
+= spoolss_size_driverdir_info_1(info
);
5926 if (!alloc_buffer_size(buffer
, *needed
)) {
5928 return WERR_INSUFFICIENT_BUFFER
;
5931 smb_io_driverdir_1("", buffer
, info
, 0);
5935 if (*needed
> offered
)
5936 return WERR_INSUFFICIENT_BUFFER
;
5941 /****************************************************************************
5942 ****************************************************************************/
5944 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
5946 UNISTR2
*name
= &q_u
->name
;
5947 UNISTR2
*uni_environment
= &q_u
->environment
;
5948 uint32 level
= q_u
->level
;
5949 NEW_BUFFER
*buffer
= NULL
;
5950 uint32 offered
= q_u
->offered
;
5951 uint32
*needed
= &r_u
->needed
;
5953 /* that's an [in out] buffer */
5954 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5955 buffer
= r_u
->buffer
;
5957 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5963 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
5965 return WERR_UNKNOWN_LEVEL
;
5969 /****************************************************************************
5970 ****************************************************************************/
5972 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
5974 POLICY_HND
*handle
= &q_u
->handle
;
5975 uint32 idx
= q_u
->index
;
5976 uint32 in_value_len
= q_u
->valuesize
;
5977 uint32 in_data_len
= q_u
->datasize
;
5978 uint32
*out_max_value_len
= &r_u
->valuesize
;
5979 uint16
**out_value
= &r_u
->value
;
5980 uint32
*out_value_len
= &r_u
->realvaluesize
;
5981 uint32
*out_type
= &r_u
->type
;
5982 uint32
*out_max_data_len
= &r_u
->datasize
;
5983 uint8
**data_out
= &r_u
->data
;
5984 uint32
*out_data_len
= &r_u
->realdatasize
;
5986 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5991 uint32 biggest_valuesize
;
5992 uint32 biggest_datasize
;
5994 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6000 ZERO_STRUCT(printer
);
6004 *out_max_data_len
=0;
6008 DEBUG(5,("spoolss_enumprinterdata\n"));
6011 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6015 if (!get_printer_snum(p
,handle
, &snum
))
6018 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6019 if (!W_ERROR_IS_OK(result
))
6023 * The NT machine wants to know the biggest size of value and data
6025 * cf: MSDN EnumPrinterData remark section
6027 if ( (in_value_len
==0) && (in_data_len
==0) ) {
6028 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
6032 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
6033 * if this parameter size doesn't exist.
6034 * Ok - my opinion here is that the client is not asking for the greatest
6035 * possible size of all the parameters, but is asking specifically for the size needed
6036 * for this specific parameter. In that case we can remove the loop below and
6037 * simplify this lookup code considerably. JF - comments welcome. JRA.
6040 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6042 free_a_printer(&printer
, 2);
6043 return WERR_NO_MORE_ITEMS
;
6050 biggest_valuesize
=0;
6053 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
6054 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
6055 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
6057 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
6063 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
6064 *out_value_len
=2*(1+biggest_valuesize
);
6065 *out_data_len
=biggest_datasize
;
6067 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
6069 free_a_printer(&printer
, 2);
6074 * the value len is wrong in NT sp3
6075 * that's the number of bytes not the number of unicode chars
6078 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
6081 free_a_printer(&printer
, 2);
6083 /* out_value should default to "" or else NT4 has
6084 problems unmarshalling the response */
6086 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6087 if((*out_value
=(uint16
*)malloc(in_value_len
*sizeof(uint8
))) == NULL
)
6090 ZERO_STRUCTP(*out_value
);
6091 *out_value_len
= (uint32
)dos_PutUniCode((char *)*out_value
, "", in_value_len
, True
);
6093 /* the data is counted in bytes */
6094 *out_max_data_len
= in_data_len
;
6095 *out_data_len
= in_data_len
;
6096 if((*data_out
=(uint8
*)malloc(in_data_len
*sizeof(uint8
))) == NULL
)
6099 memset(*data_out
,'\0',in_data_len
);
6101 return WERR_NO_MORE_ITEMS
;
6104 free_a_printer(&printer
, 2);
6108 * - counted in bytes in the request
6109 * - counted in UNICODE chars in the max reply
6110 * - counted in bytes in the real size
6112 * take a pause *before* coding not *during* coding
6115 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
6116 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
,in_value_len
*sizeof(uint8
))) == NULL
) {
6121 *out_value_len
= (uint32
)dos_PutUniCode((char *)*out_value
, value
, in_value_len
, True
);
6125 /* the data is counted in bytes */
6126 *out_max_data_len
=in_data_len
;
6127 if((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) {
6132 memcpy(*data_out
, data
, (size_t)data_len
);
6133 *out_data_len
=data_len
;
6140 /****************************************************************************
6141 ****************************************************************************/
6143 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
6145 POLICY_HND
*handle
= &q_u
->handle
;
6146 UNISTR2
*value
= &q_u
->value
;
6147 uint32 type
= q_u
->type
;
6148 /* uint32 max_len = q_u->max_len; - notused. */
6149 uint8
*data
= q_u
->data
;
6150 uint32 real_len
= q_u
->real_len
;
6151 /* uint32 numeric_data = q_u->numeric_data; - notused. */
6153 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6154 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
6156 WERROR status
= WERR_OK
;
6157 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6159 DEBUG(5,("spoolss_setprinterdata\n"));
6162 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6166 if (!get_printer_snum(p
,handle
, &snum
))
6169 ZERO_STRUCT(old_param
);
6172 * Access check : NT returns "access denied" if you make a
6173 * SetPrinterData call without the necessary privildge.
6174 * we were originally returning OK if nothing changed
6175 * which made Win2k issue **a lot** of SetPrinterData
6176 * when connecting to a printer --jerry
6179 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6180 DEBUG(3, ("security descriptor change denied by existing "
6181 "security descriptor\n"));
6182 status
= WERR_ACCESS_DENIED
;
6186 /* Check if we are making any changes or not. Return true if
6187 nothing is actually changing. This is not needed anymore but
6188 has been left in as an optimization to keep from from
6189 writing to disk as often --jerry */
6191 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6192 if (!W_ERROR_IS_OK(status
))
6195 convert_specific_param(¶m
, value
, type
, data
, real_len
);
6198 if (get_specific_param(*printer
, 2, param
->value
, &old_param
.data
,
6199 &old_param
.type
, (uint32
*)&old_param
.data_len
)) {
6201 if (param
->type
== old_param
.type
&&
6202 param
->data_len
== old_param
.data_len
&&
6203 memcmp(param
->data
, old_param
.data
,
6204 old_param
.data_len
) == 0) {
6206 DEBUG(3, ("setprinterdata hasn't changed\n"));
6212 unlink_specific_param_if_exist(printer
->info_2
, param
);
6215 * When client side code sets a magic printer data key, detect it and save
6216 * the current printer data and the magic key's data (its the DEVMODE) for
6217 * future printer/driver initializations.
6219 if (param
->type
==3 && !strcmp( param
->value
, PHANTOM_DEVMODE_KEY
)) {
6221 * Set devmode and printer initialization info
6223 status
= save_driver_init(printer
, 2, param
);
6226 add_a_specific_param(printer
->info_2
, ¶m
);
6227 status
= mod_a_printer(*printer
, 2);
6231 free_a_printer(&printer
, 2);
6233 free_nt_printer_param(¶m
);
6234 SAFE_FREE(old_param
.data
);
6239 /****************************************************************************
6240 ****************************************************************************/
6242 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
6244 POLICY_HND
*handle
= &q_u
->handle
;
6245 UNISTR2
*value
= &q_u
->valuename
;
6247 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6248 NT_PRINTER_PARAM param
;
6250 WERROR status
= WERR_OK
;
6251 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
6253 DEBUG(5,("spoolss_deleteprinterdata\n"));
6256 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6260 if (!get_printer_snum(p
, handle
, &snum
))
6263 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
6264 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties "
6265 "change denied by existing security descriptor\n"));
6266 return WERR_ACCESS_DENIED
;
6269 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
6270 if (!W_ERROR_IS_OK(status
))
6273 ZERO_STRUCTP(¶m
);
6274 unistr2_to_ascii(param
.value
, value
, sizeof(param
.value
)-1);
6276 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
6277 status
= WERR_INVALID_PARAM
;
6279 status
= mod_a_printer(*printer
, 2);
6281 free_a_printer(&printer
, 2);
6285 /****************************************************************************
6286 ****************************************************************************/
6288 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
6290 POLICY_HND
*handle
= &q_u
->handle
;
6291 /* uint32 level = q_u->level; - notused. */
6292 FORM
*form
= &q_u
->form
;
6293 nt_forms_struct tmpForm
;
6296 nt_forms_struct
*list
=NULL
;
6297 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6299 DEBUG(5,("spoolss_addform\n"));
6302 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6306 /* can't add if builtin */
6307 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
6308 return WERR_INVALID_PARAM
;
6311 count
=get_ntforms(&list
);
6312 if(!add_a_form(&list
, form
, &count
))
6314 write_ntforms(&list
, count
);
6321 /****************************************************************************
6322 ****************************************************************************/
6324 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
6326 POLICY_HND
*handle
= &q_u
->handle
;
6327 UNISTR2
*form_name
= &q_u
->name
;
6328 nt_forms_struct tmpForm
;
6330 WERROR ret
= WERR_OK
;
6331 nt_forms_struct
*list
=NULL
;
6332 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6334 DEBUG(5,("spoolss_deleteform\n"));
6337 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6341 /* can't delete if builtin */
6342 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
6343 return WERR_INVALID_PARAM
;
6346 count
= get_ntforms(&list
);
6347 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
6348 return WERR_INVALID_PARAM
;
6355 /****************************************************************************
6356 ****************************************************************************/
6358 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
6360 POLICY_HND
*handle
= &q_u
->handle
;
6361 /* UNISTR2 *uni_name = &q_u->name; - notused. */
6362 /* uint32 level = q_u->level; - notused. */
6363 FORM
*form
= &q_u
->form
;
6364 nt_forms_struct tmpForm
;
6367 nt_forms_struct
*list
=NULL
;
6368 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6370 DEBUG(5,("spoolss_setform\n"));
6373 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6376 /* can't set if builtin */
6377 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
6378 return WERR_INVALID_PARAM
;
6381 count
=get_ntforms(&list
);
6382 update_a_form(&list
, form
, count
);
6383 write_ntforms(&list
, count
);
6390 /****************************************************************************
6391 enumprintprocessors level 1.
6392 ****************************************************************************/
6393 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6395 PRINTPROCESSOR_1
*info_1
=NULL
;
6397 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
6402 init_unistr(&info_1
->name
, "winprint");
6404 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
6406 if (!alloc_buffer_size(buffer
, *needed
))
6407 return WERR_INSUFFICIENT_BUFFER
;
6409 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
6413 if (*needed
> offered
) {
6415 return WERR_INSUFFICIENT_BUFFER
;
6421 /****************************************************************************
6422 ****************************************************************************/
6424 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
6426 /* UNISTR2 *name = &q_u->name; - notused. */
6427 /* UNISTR2 *environment = &q_u->environment; - notused. */
6428 uint32 level
= q_u
->level
;
6429 NEW_BUFFER
*buffer
= NULL
;
6430 uint32 offered
= q_u
->offered
;
6431 uint32
*needed
= &r_u
->needed
;
6432 uint32
*returned
= &r_u
->returned
;
6434 /* that's an [in out] buffer */
6435 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6436 buffer
= r_u
->buffer
;
6438 DEBUG(5,("spoolss_enumprintprocessors\n"));
6441 * Enumerate the print processors ...
6443 * Just reply with "winprint", to keep NT happy
6444 * and I can use my nice printer checker.
6452 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
6454 return WERR_UNKNOWN_LEVEL
;
6458 /****************************************************************************
6459 enumprintprocdatatypes level 1.
6460 ****************************************************************************/
6461 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6463 PRINTPROCDATATYPE_1
*info_1
=NULL
;
6465 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
6470 init_unistr(&info_1
->name
, "RAW");
6472 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
6474 if (!alloc_buffer_size(buffer
, *needed
))
6475 return WERR_INSUFFICIENT_BUFFER
;
6477 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
6481 if (*needed
> offered
) {
6483 return WERR_INSUFFICIENT_BUFFER
;
6489 /****************************************************************************
6490 ****************************************************************************/
6492 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
6494 /* UNISTR2 *name = &q_u->name; - notused. */
6495 /* UNISTR2 *processor = &q_u->processor; - notused. */
6496 uint32 level
= q_u
->level
;
6497 NEW_BUFFER
*buffer
= NULL
;
6498 uint32 offered
= q_u
->offered
;
6499 uint32
*needed
= &r_u
->needed
;
6500 uint32
*returned
= &r_u
->returned
;
6502 /* that's an [in out] buffer */
6503 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6504 buffer
= r_u
->buffer
;
6506 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
6513 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
6515 return WERR_UNKNOWN_LEVEL
;
6519 /****************************************************************************
6520 enumprintmonitors level 1.
6521 ****************************************************************************/
6523 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6525 PRINTMONITOR_1
*info_1
=NULL
;
6527 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
6532 init_unistr(&info_1
->name
, "Local Port");
6534 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
6536 if (!alloc_buffer_size(buffer
, *needed
))
6537 return WERR_INSUFFICIENT_BUFFER
;
6539 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
6543 if (*needed
> offered
) {
6545 return WERR_INSUFFICIENT_BUFFER
;
6551 /****************************************************************************
6552 enumprintmonitors level 2.
6553 ****************************************************************************/
6554 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6556 PRINTMONITOR_2
*info_2
=NULL
;
6558 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
6563 init_unistr(&info_2
->name
, "Local Port");
6564 init_unistr(&info_2
->environment
, "Windows NT X86");
6565 init_unistr(&info_2
->dll_name
, "localmon.dll");
6567 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
6569 if (!alloc_buffer_size(buffer
, *needed
))
6570 return WERR_INSUFFICIENT_BUFFER
;
6572 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
6576 if (*needed
> offered
) {
6578 return WERR_INSUFFICIENT_BUFFER
;
6584 /****************************************************************************
6585 ****************************************************************************/
6587 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
6589 /* UNISTR2 *name = &q_u->name; - notused. */
6590 uint32 level
= q_u
->level
;
6591 NEW_BUFFER
*buffer
= NULL
;
6592 uint32 offered
= q_u
->offered
;
6593 uint32
*needed
= &r_u
->needed
;
6594 uint32
*returned
= &r_u
->returned
;
6596 /* that's an [in out] buffer */
6597 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6598 buffer
= r_u
->buffer
;
6600 DEBUG(5,("spoolss_enumprintmonitors\n"));
6603 * Enumerate the print monitors ...
6605 * Just reply with "Local Port", to keep NT happy
6606 * and I can use my nice printer checker.
6614 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
6616 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
6618 return WERR_UNKNOWN_LEVEL
;
6622 /****************************************************************************
6623 ****************************************************************************/
6624 static WERROR
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6628 JOB_INFO_1
*info_1
=NULL
;
6630 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
6632 if (info_1
== NULL
) {
6637 for (i
=0; i
<count
&& found
==False
; i
++) {
6638 if (queue
[i
].job
==(int)jobid
)
6645 /* NT treats not found as bad param... yet another bad choice */
6646 return WERR_INVALID_PARAM
;
6649 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
6653 *needed
+= spoolss_size_job_info_1(info_1
);
6655 if (!alloc_buffer_size(buffer
, *needed
)) {
6657 return WERR_INSUFFICIENT_BUFFER
;
6660 smb_io_job_info_1("", buffer
, info_1
, 0);
6664 if (*needed
> offered
)
6665 return WERR_INSUFFICIENT_BUFFER
;
6671 /****************************************************************************
6672 ****************************************************************************/
6673 static WERROR
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
6678 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6681 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
6683 ZERO_STRUCTP(info_2
);
6685 if (info_2
== NULL
) {
6690 for (i
=0; i
<count
&& found
==False
; i
++) {
6691 if (queue
[i
].job
==(int)jobid
)
6698 /* NT treats not found as bad param... yet another bad choice */
6699 return WERR_INVALID_PARAM
;
6702 ret
= get_a_printer(&ntprinter
, 2, lp_servicename(snum
));
6703 if (!W_ERROR_IS_OK(ret
)) {
6708 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
, ntprinter
);
6710 free_a_printer(&ntprinter
, 2);
6713 *needed
+= spoolss_size_job_info_2(info_2
);
6715 if (!alloc_buffer_size(buffer
, *needed
)) {
6717 return WERR_INSUFFICIENT_BUFFER
;
6720 smb_io_job_info_2("", buffer
, info_2
, 0);
6722 free_job_info_2(info_2
);
6725 if (*needed
> offered
)
6726 return WERR_INSUFFICIENT_BUFFER
;
6731 /****************************************************************************
6732 ****************************************************************************/
6734 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
6736 POLICY_HND
*handle
= &q_u
->handle
;
6737 uint32 jobid
= q_u
->jobid
;
6738 uint32 level
= q_u
->level
;
6739 NEW_BUFFER
*buffer
= NULL
;
6740 uint32 offered
= q_u
->offered
;
6741 uint32
*needed
= &r_u
->needed
;
6745 print_queue_struct
*queue
=NULL
;
6746 print_status_struct prt_status
;
6748 /* that's an [in out] buffer */
6749 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6750 buffer
= r_u
->buffer
;
6752 DEBUG(5,("spoolss_getjob\n"));
6756 if (!get_printer_snum(p
, handle
, &snum
))
6759 count
= print_queue_status(snum
, &queue
, &prt_status
);
6761 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
6762 count
, prt_status
.status
, prt_status
.message
));
6766 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
6768 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
6771 return WERR_UNKNOWN_LEVEL
;
6775 /********************************************************************
6776 * spoolss_getprinterdataex
6777 ********************************************************************/
6779 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
6781 POLICY_HND
*handle
= &q_u
->handle
;
6782 uint32 in_size
= q_u
->size
;
6783 uint32
*type
= &r_u
->type
;
6784 uint32
*out_size
= &r_u
->size
;
6785 uint8
**data
= &r_u
->data
;
6786 uint32
*needed
= &r_u
->needed
;
6789 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6792 DEBUG(4,("_spoolss_getprinterdataex\n"));
6794 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
6795 unistr2_to_ascii(value
, &q_u
->valuename
, sizeof(value
) - 1);
6797 /* in case of problem, return some default values */
6804 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, 4*sizeof(uint8
))) == NULL
)
6806 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6811 /* Is the handle to a printer or to the server? */
6813 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6815 DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
6816 return WERR_INVALID_PARAM
;
6821 * From MSDN documentation of GetPrinterDataEx: pass request
6822 * to GetPrinterData if key is "PrinterDriverData". This is
6823 * the only key we really support. Other keys to implement:
6829 if (strcmp(key
, "PrinterDriverData") != 0)
6830 return WERR_INVALID_PARAM
;
6832 DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
6833 found
= getprinterdata_printer(p
, p
->mem_ctx
, handle
, value
,
6834 type
, data
, needed
, in_size
);
6839 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
6841 /* reply this param doesn't exist */
6843 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
)
6849 return WERR_INVALID_PARAM
;
6852 if (*needed
> *out_size
)
6853 return WERR_MORE_DATA
;
6858 /********************************************************************
6859 * spoolss_setprinterdata
6860 ********************************************************************/
6862 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
6864 SPOOL_Q_SETPRINTERDATA q_u_local
;
6865 SPOOL_R_SETPRINTERDATA r_u_local
;
6868 DEBUG(4,("_spoolss_setprinterdataex\n"));
6870 /* From MSDN documentation of SetPrinterDataEx: pass request to
6871 SetPrinterData if key is "PrinterDriverData" */
6873 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
6875 if (strcmp(key
, "PrinterDriverData") == 0)
6876 return WERR_INVALID_PARAM
;
6878 ZERO_STRUCT(q_u_local
);
6879 ZERO_STRUCT(r_u_local
);
6881 /* make a copy to call _spoolss_setprinterdata() */
6883 memcpy(&q_u_local
.handle
, &q_u
->handle
, sizeof(POLICY_HND
));
6884 copy_unistr2(&q_u_local
.value
, &q_u
->value
);
6885 q_u_local
.type
= q_u
->type
;
6886 q_u_local
.max_len
= q_u
->max_len
;
6887 q_u_local
.data
= q_u
->data
;
6888 q_u_local
.real_len
= q_u
->real_len
;
6889 q_u_local
.numeric_data
= q_u
->numeric_data
;
6891 return _spoolss_setprinterdata(p
, &q_u_local
, &r_u_local
);
6894 /********************************************************************
6895 * spoolss_enumprinterkey
6896 ********************************************************************/
6898 /* constants for EnumPrinterKey() */
6899 #define ENUMERATED_KEY_SIZE 19
6901 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
6904 uint16 enumkeys
[ENUMERATED_KEY_SIZE
+1];
6907 char *PrinterKey
= "PrinterDriverData";
6909 DEBUG(4,("_spoolss_enumprinterkey\n"));
6911 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
6914 * we only support enumating all keys (key == "")
6915 * Of course, the only key we support is the "PrinterDriverData"
6918 if (strlen(key
) == 0)
6920 r_u
->needed
= ENUMERATED_KEY_SIZE
*2;
6921 if (q_u
->size
< r_u
->needed
)
6922 return WERR_MORE_DATA
;
6925 for (i
=0; i
<ENUMERATED_KEY_SIZE
-2; i
++)
6927 enumkeys
[i
] = (uint16
)(*ptr
);
6931 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, ENUMERATED_KEY_SIZE
, enumkeys
))
6932 return WERR_BADFILE
;
6937 /* The "PrinterDriverData" key should have no subkeys */
6938 if (strcmp(key
, PrinterKey
) == 0)
6941 if (q_u
->size
< r_u
->needed
)
6942 return WERR_MORE_DATA
;
6944 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, 1, enumkeys
))
6945 return WERR_BADFILE
;
6951 /* The return value for an unknown key is documented in MSDN
6952 EnumPrinterKey description */
6953 return WERR_BADFILE
;
6956 /********************************************************************
6957 * spoolss_enumprinterdataex
6958 ********************************************************************/
6960 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
6962 POLICY_HND
*handle
= &q_u
->handle
;
6963 uint32 in_size
= q_u
->size
;
6966 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
6967 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
6969 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6978 DEBUG(4,("_spoolss_enumprinterdataex\n"));
6981 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
6987 * The only key we support is "PrinterDriverData". This should return
6988 > an array of all the key/value pairs returned by EnumPrinterDataSee
6989 * _spoolss_getprinterdataex() for details --jerry
6992 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
6993 if (strcmp(key
, "PrinterDriverData") != 0)
6995 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
6996 return WERR_INVALID_PARAM
;
7000 if (!get_printer_snum(p
,handle
, &snum
))
7003 ZERO_STRUCT(printer
);
7004 result
= get_a_printer(&printer
, 2, lp_servicename(snum
));
7005 if (!W_ERROR_IS_OK(result
))
7010 * loop through all params and build the array to pass
7011 * back to the client
7018 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
))
7020 PRINTER_ENUM_VALUES
*ptr
;
7023 DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries
, value
));
7025 if ((ptr
=talloc_realloc(p
->mem_ctx
, enum_values
, (num_entries
+1) * sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
7027 DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
7028 result
= WERR_NOMEM
;
7034 init_unistr(&enum_values
[num_entries
].valuename
, value
);
7035 enum_values
[num_entries
].value_len
= (strlen(value
)+1) * 2;
7036 enum_values
[num_entries
].type
= type
;
7039 * NULL terminate REG_SZ
7040 * FIXME!!! We should not be correctly problems in the way
7041 * we store PrinterData here. Need to investogate
7042 * SetPrinterData[Ex] --jerry
7045 if (type
== REG_SZ
) {
7046 /* fix alignment if the string was stored
7047 in a bizarre fashion */
7048 if ((data_len
% 2) == 0)
7051 add_len
= data_len
% 2;
7054 if (!(enum_values
[num_entries
].data
=talloc_zero(p
->mem_ctx
, data_len
+add_len
))) {
7055 DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
7056 result
= WERR_NOMEM
;
7059 memcpy(enum_values
[num_entries
].data
, data
, data_len
);
7060 enum_values
[num_entries
].data_len
= data_len
+ add_len
;
7062 /* keep track of the size of the array in bytes */
7064 needed
+= spoolss_size_printer_enum_values(&enum_values
[num_entries
]);
7070 r_u
->needed
= needed
;
7071 r_u
->returned
= num_entries
;
7073 if (needed
> in_size
) {
7074 result
= WERR_MORE_DATA
;
7078 /* copy data into the reply */
7080 r_u
->ctr
.size
= r_u
->needed
;
7081 r_u
->ctr
.size_of_array
= r_u
->returned
;
7082 r_u
->ctr
.values
= enum_values
;
7087 free_a_printer(&printer
, 2);