3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
8 * Copyright (C) Jean François Micouleau 1998-2000.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 extern int DEBUGLEVEL
;
28 extern pstring global_myname
;
30 #ifndef MAX_OPEN_PRINTER_EXS
31 #define MAX_OPEN_PRINTER_EXS 50
34 #define PRINTER_HANDLE_IS_PRINTER 0
35 #define PRINTER_HANDLE_IS_PRINTSERVER 1
37 /* structure to store the printer handles */
38 /* and a reference to what it's pointing to */
39 /* and the notify info asked about */
40 /* that's the central struct */
41 typedef struct _Printer
{
46 BOOL document_started
;
48 int jobid
; /* jobid in printing backend */
49 POLICY_HND printer_hnd
;
53 fstring printerservername
;
62 SPOOL_NOTIFY_OPTION
*option
;
63 POLICY_HND client_hnd
;
64 uint32 client_connected
;
72 typedef struct _counter_printer_0
{
80 static ubi_dlList Printer_list
;
81 static ubi_dlList counter_list
;
83 static struct cli_state cli
;
84 static uint32 smb_connections
=0;
86 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
87 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v
)
94 return PRINTER_STATUS_PAUSED
;
103 static int nt_printq_status(int v
)
107 return PRINTER_STATUS_PAUSED
;
116 /****************************************************************************
117 initialise printer handle states...
118 ****************************************************************************/
119 void init_printer_hnd(void)
121 ubi_dlInitList(&Printer_list
);
122 ubi_dlInitList(&counter_list
);
125 /****************************************************************************
126 create a unique printer handle
127 ****************************************************************************/
128 static void create_printer_hnd(POLICY_HND
*hnd
)
130 static uint32 prt_hnd_low
= 0;
131 static uint32 prt_hnd_high
= 0;
133 if (hnd
== NULL
) return;
135 /* i severely doubt that prt_hnd_high will ever be non-zero... */
137 if (prt_hnd_low
== 0) prt_hnd_high
++;
139 SIVAL(hnd
->data
, 0 , 0x0); /* first bit must be null */
140 SIVAL(hnd
->data
, 4 , prt_hnd_low
); /* second bit is incrementing */
141 SIVAL(hnd
->data
, 8 , prt_hnd_high
); /* second bit is incrementing */
142 SIVAL(hnd
->data
, 12, time(NULL
)); /* something random */
143 SIVAL(hnd
->data
, 16, sys_getpid()); /* something more random */
146 /****************************************************************************
147 find printer index by handle
148 ****************************************************************************/
149 static Printer_entry
*find_printer_index_by_hnd(const POLICY_HND
*hnd
)
151 Printer_entry
*find_printer
;
153 find_printer
= (Printer_entry
*)ubi_dlFirst(&Printer_list
);
155 for(; find_printer
; find_printer
= (Printer_entry
*)ubi_dlNext(find_printer
)) {
157 if (memcmp(&(find_printer
->printer_hnd
), hnd
, sizeof(*hnd
)) == 0) {
158 DEBUG(4,("Found printer handle \n"));
159 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
164 DEBUG(3,("Whoops, Printer handle not found: "));
165 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
169 /****************************************************************************
171 ****************************************************************************/
172 static void clear_handle(POLICY_HND
*hnd
)
177 /***************************************************************************
178 Disconnect from the client
179 ****************************************************************************/
180 static BOOL
srv_spoolss_replycloseprinter(POLICY_HND
*handle
)
184 /* weird if the test succeds !!! */
185 if (smb_connections
==0) {
186 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
190 if(!cli_spoolss_reply_close_printer(&cli
, handle
, &status
))
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections
==1) {
195 if(!spoolss_disconnect_from_client(&cli
))
198 message_deregister(MSG_PRINTER_NOTIFY
);
206 /****************************************************************************
207 close printer index by handle
208 ****************************************************************************/
209 static BOOL
close_printer_handle(POLICY_HND
*hnd
)
211 Printer_entry
*Printer
= find_printer_index_by_hnd(hnd
);
213 if (!OPEN_HANDLE(Printer
)) {
214 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
218 if (Printer
->notify
.client_connected
==True
)
219 if(!srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
))
220 return ERROR_INVALID_HANDLE
;
223 Printer
->notify
.flags
=0;
224 Printer
->notify
.options
=0;
225 Printer
->notify
.localmachine
[0]='\0';
226 Printer
->notify
.printerlocal
=0;
227 safe_free(Printer
->notify
.option
);
228 Printer
->notify
.option
=NULL
;
229 Printer
->notify
.client_connected
=False
;
233 ubi_dlRemThis(&Printer_list
, Printer
);
240 /****************************************************************************
241 delete a printer given a handle
242 ****************************************************************************/
243 static BOOL
delete_printer_handle(POLICY_HND
*hnd
)
245 Printer_entry
*Printer
= find_printer_index_by_hnd(hnd
);
247 if (!OPEN_HANDLE(Printer
)) {
248 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
252 if (del_a_printer(Printer
->dev
.handlename
) != 0) {
253 DEBUG(3,("Error deleting printer %s\n", Printer
->dev
.handlename
));
257 if (*lp_deleteprinter_cmd()) {
259 pid_t local_pid
= sys_getpid();
260 char *cmd
= lp_deleteprinter_cmd();
267 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
268 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
272 /* Printer->dev.handlename equals portname equals sharename */
273 slprintf(command
, sizeof(command
), "%s \"%s\"", cmd
,
274 Printer
->dev
.handlename
);
275 slprintf(tmp_file
, sizeof(tmp_file
), "%s/smbcmd.%d", path
, local_pid
);
278 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
279 ret
= smbrun(command
, tmp_file
, False
);
284 DEBUGADD(10,("returned [%d]\n", ret
));
285 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file
));
288 /* Send SIGHUP to process group... is there a better way? */
291 if ( ( i
= lp_servicenumber( Printer
->dev
.handlename
) ) >= 0 ) {
292 lp_remove_service( i
);
302 /****************************************************************************
303 return the snum of a printer corresponding to an handle
304 ****************************************************************************/
305 static BOOL
get_printer_snum(POLICY_HND
*hnd
, int *number
)
307 Printer_entry
*Printer
= find_printer_index_by_hnd(hnd
);
309 if (!OPEN_HANDLE(Printer
)) {
310 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd
)));
314 switch (Printer
->printer_type
) {
315 case PRINTER_HANDLE_IS_PRINTER
:
316 DEBUG(4,("short name:%s\n", Printer
->dev
.handlename
));
317 *number
= print_queue_snum(Printer
->dev
.handlename
);
318 return (*number
!= -1);
319 case PRINTER_HANDLE_IS_PRINTSERVER
:
326 /****************************************************************************
327 set printer handle type.
328 ****************************************************************************/
329 static BOOL
set_printer_hnd_accesstype(POLICY_HND
*hnd
, uint32 access_required
)
331 Printer_entry
*Printer
= find_printer_index_by_hnd(hnd
);
333 if (!OPEN_HANDLE(Printer
)) {
334 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd
)));
338 DEBUG(4,("Setting printer access=%x\n", access_required
));
339 Printer
->access
= access_required
;
343 /****************************************************************************
344 Set printer handle type.
345 Check if it's \\server or \\server\printer
346 ****************************************************************************/
348 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
350 DEBUG(3,("Setting printer type=%s\n", handlename
));
352 if ( strlen(handlename
) < 3 ) {
353 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
357 /* it's a print server */
358 if (!strchr(handlename
+2, '\\')) {
359 DEBUGADD(4,("Printer is a print server\n"));
360 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
364 DEBUGADD(4,("Printer is a printer\n"));
365 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
371 /****************************************************************************
372 Set printer handle name.
373 ****************************************************************************/
375 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
377 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
379 int n_services
=lp_numservices();
383 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename
, strlen(handlename
)));
385 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTSERVER
) {
386 ZERO_STRUCT(Printer
->dev
.printerservername
);
387 strncpy(Printer
->dev
.printerservername
, handlename
, strlen(handlename
));
391 if (Printer
->printer_type
!=PRINTER_HANDLE_IS_PRINTER
)
394 aprinter
=strchr(handlename
+2, '\\');
397 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter
, strlen(aprinter
)));
400 * store the Samba share name in it
401 * in back we have the long printer name
402 * need to iterate all the snum and do a
403 * get_a_printer each time to find the printer
404 * faster to do it here than later.
407 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
410 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
413 DEBUGADD(5,("share:%s\n",lp_servicename(snum
)));
415 if (get_a_printer(&printer
, 2, lp_servicename(snum
))!=0)
418 printername
=strchr(printer
->info_2
->printername
+2, '\\');
421 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
422 printer
->info_2
->printername
, aprinter
));
424 if ( strlen(printername
) != strlen(aprinter
) ) {
425 free_a_printer(&printer
, 2);
429 if ( strncasecmp(printername
, aprinter
, strlen(aprinter
))) {
430 free_a_printer(&printer
, 2);
438 * if we haven't found a printer with the given handlename
439 * then it can be a share name as you can open both \\server\printer and
444 * we still check if the printer description file exists as NT won't be happy
445 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
449 DEBUGADD(5,("Printer not found, checking for share now\n"));
451 for (snum
=0;snum
<n_services
&& found
==False
;snum
++) {
453 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
456 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum
)));
458 if (get_a_printer(&printer
, 2, lp_servicename(snum
))!=0)
461 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
462 printer
->info_2
->printername
, aprinter
));
464 if ( strlen(lp_servicename(snum
)) != strlen(aprinter
) ) {
465 free_a_printer(&printer
, 2);
469 if ( strncasecmp(lp_servicename(snum
), aprinter
, strlen(aprinter
))) {
470 free_a_printer(&printer
, 2);
479 DEBUGADD(4,("Printer not found\n"));
484 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
485 printer
->info_2
->printername
, lp_servicename(snum
),snum
));
487 ZERO_STRUCT(Printer
->dev
.handlename
);
488 strncpy(Printer
->dev
.handlename
, lp_servicename(snum
), strlen(lp_servicename(snum
)));
490 free_a_printer(&printer
, 2);
495 /****************************************************************************
496 find first available printer slot. creates a printer handle for you.
497 ****************************************************************************/
499 static BOOL
open_printer_hnd(POLICY_HND
*hnd
, char *name
)
501 Printer_entry
*new_printer
;
503 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
505 create_printer_hnd(hnd
);
507 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
510 ZERO_STRUCTP(new_printer
);
512 new_printer
->open
= True
;
513 new_printer
->notify
.option
=NULL
;
515 memcpy(&new_printer
->printer_hnd
, hnd
, sizeof(*hnd
));
517 ubi_dlAddHead( &Printer_list
, (ubi_dlNode
*)new_printer
);
519 if (!set_printer_hnd_printertype(new_printer
, name
)) {
520 close_printer_handle(hnd
);
524 if (!set_printer_hnd_name(new_printer
, name
)) {
525 close_printer_handle(hnd
);
532 /********************************************************************
533 Return True is the handle is a print server.
534 ********************************************************************/
535 static BOOL
handle_is_printserver(const POLICY_HND
*handle
)
537 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
539 if (!OPEN_HANDLE(Printer
))
542 if (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
548 /****************************************************************************
549 allocate more memory for a BUFFER.
550 ****************************************************************************/
551 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
559 /* damn, I'm doing the reverse operation of prs_grow() :) */
560 if (buffer_size
< prs_data_size(ps
))
563 extra_space
= buffer_size
- prs_data_size(ps
);
566 * save the offset and move to the end of the buffer
567 * prs_grow() checks the extra_space against the offset
569 old_offset
=prs_offset(ps
);
570 prs_set_offset(ps
, prs_data_size(ps
));
572 if (!prs_grow(ps
, extra_space
))
575 prs_set_offset(ps
, old_offset
);
577 buffer
->string_at_end
=prs_data_size(ps
);
582 /***************************************************************************
583 receive the notify message
584 ****************************************************************************/
585 void srv_spoolss_receive_message(int msg_type
, pid_t src
, void *buf
, size_t len
)
589 Printer_entry
*find_printer
;
592 fstrcpy(printer
,buf
);
595 DEBUG(0,("srv_spoolss_receive_message: got null message !\n"));
599 DEBUG(10,("srv_spoolss_receive_message: Got message about printer %s\n", printer
));
601 find_printer
= (Printer_entry
*)ubi_dlFirst(&Printer_list
);
603 /* Iterate the printer list. */
604 for(; find_printer
; find_printer
= (Printer_entry
*)ubi_dlNext(find_printer
)) {
607 * if the entry is the given printer or if it's a printerserver
608 * we send the message
611 if (find_printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
612 if (strcmp(find_printer
->dev
.handlename
, printer
))
615 if (find_printer
->notify
.client_connected
==True
)
616 cli_spoolss_reply_rrpcn(&cli
, &find_printer
->notify
.client_hnd
, PRINTER_CHANGE_ALL
, 0x0, &status
);
621 /***************************************************************************
623 ****************************************************************************/
624 static BOOL
srv_spoolss_sendnotify(POLICY_HND
*handle
)
628 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
630 if (!OPEN_HANDLE(Printer
)) {
631 DEBUG(0,("srv_spoolss_sendnotify: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
635 if (Printer
->printer_type
==PRINTER_HANDLE_IS_PRINTER
)
636 fstrcpy(printer
, Printer
->dev
.handlename
);
638 fstrcpy(printer
, "");
640 /*srv_spoolss_receive_message(printer);*/
641 DEBUG(10,("srv_spoolss_sendnotify: Sending message about printer %s\n", printer
));
643 message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY
, printer
, strlen(printer
) + 1, False
); /* Null terminate... */
648 /********************************************************************
649 * spoolss_open_printer
651 * called from the spoolss dispatcher
652 ********************************************************************/
653 uint32
_spoolss_open_printer_ex( const UNISTR2
*printername
,
654 const PRINTER_DEFAULT
*printer_default
,
655 uint32 user_switch
, SPOOL_USER_CTR user_ctr
,
660 if (printername
== NULL
)
661 return ERROR_INVALID_PRINTER_NAME
;
663 /* some sanity check because you can open a printer or a print server */
664 /* aka: \\server\printer or \\server */
665 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
667 DEBUGADD(3,("checking name: %s\n",name
));
669 if (!open_printer_hnd(handle
, name
))
670 return ERROR_INVALID_PRINTER_NAME
;
673 if (printer_default->datatype_ptr != NULL)
675 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
676 set_printer_hnd_datatype(handle, datatype);
679 set_printer_hnd_datatype(handle, "");
682 if (!set_printer_hnd_accesstype(handle
, printer_default
->access_required
)) {
683 close_printer_handle(handle
);
684 return ERROR_ACCESS_DENIED
;
687 /* Disallow MS AddPrinterWizard if parameter disables it. A Win2k
688 client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
689 Then both Win2k and WinNT clients try an OpenPrinterEx with
690 SERVER_ALL_ACCESS, which we force to fail. Then they try
691 OpenPrinterEx with SERVER_READ which we allow. This lets the
692 client view printer folder, but does not show the MSAPW.
694 Note: this test needs code to check access rights here too. Jeremy
695 could you look at this? */
697 if (handle_is_printserver(handle
) &&
698 !lp_ms_add_printer_wizard()) {
699 if (printer_default
->access_required
== 0)
700 return NT_STATUS_NO_PROBLEMO
;
701 else if (printer_default
->access_required
!= (SERVER_READ
))
702 return ERROR_ACCESS_DENIED
;
705 return NT_STATUS_NO_PROBLEMO
;
708 /****************************************************************************
709 ****************************************************************************/
710 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
711 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
715 uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
724 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
725 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
729 printer
->info_3
=NULL
;
730 uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
);
733 printer
->info_6
=NULL
;
734 uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
);
743 static BOOL
convert_devicemode(const DEVICEMODE
*devmode
, NT_DEVICEMODE
*nt_devmode
)
745 unistr_to_dos(nt_devmode
->devicename
, (const char *)devmode
->devicename
.buffer
, 31);
746 unistr_to_dos(nt_devmode
->formname
, (const char *)devmode
->formname
.buffer
, 31);
748 nt_devmode
->specversion
=devmode
->specversion
;
749 nt_devmode
->driverversion
=devmode
->driverversion
;
750 nt_devmode
->size
=devmode
->size
;
751 nt_devmode
->driverextra
=devmode
->driverextra
;
752 nt_devmode
->fields
=devmode
->fields
;
753 nt_devmode
->orientation
=devmode
->orientation
;
754 nt_devmode
->papersize
=devmode
->papersize
;
755 nt_devmode
->paperlength
=devmode
->paperlength
;
756 nt_devmode
->paperwidth
=devmode
->paperwidth
;
757 nt_devmode
->scale
=devmode
->scale
;
758 nt_devmode
->copies
=devmode
->copies
;
759 nt_devmode
->defaultsource
=devmode
->defaultsource
;
760 nt_devmode
->printquality
=devmode
->printquality
;
761 nt_devmode
->color
=devmode
->color
;
762 nt_devmode
->duplex
=devmode
->duplex
;
763 nt_devmode
->yresolution
=devmode
->yresolution
;
764 nt_devmode
->ttoption
=devmode
->ttoption
;
765 nt_devmode
->collate
=devmode
->collate
;
767 nt_devmode
->logpixels
=devmode
->logpixels
;
768 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
769 nt_devmode
->pelswidth
=devmode
->pelswidth
;
770 nt_devmode
->pelsheight
=devmode
->pelsheight
;
771 nt_devmode
->displayflags
=devmode
->displayflags
;
772 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
773 nt_devmode
->icmmethod
=devmode
->icmmethod
;
774 nt_devmode
->icmintent
=devmode
->icmintent
;
775 nt_devmode
->mediatype
=devmode
->mediatype
;
776 nt_devmode
->dithertype
=devmode
->dithertype
;
777 nt_devmode
->reserved1
=devmode
->reserved1
;
778 nt_devmode
->reserved2
=devmode
->reserved2
;
779 nt_devmode
->panningwidth
=devmode
->panningwidth
;
780 nt_devmode
->panningheight
=devmode
->panningheight
;
782 safe_free(nt_devmode
->private);
783 if (nt_devmode
->driverextra
!= 0) {
784 /* if we had a previous private delete it and make a new one */
785 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
787 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
790 nt_devmode
->private = NULL
;
796 /********************************************************************
797 * api_spoolss_closeprinter
798 ********************************************************************/
799 uint32
_spoolss_closeprinter(POLICY_HND
*handle
)
801 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
803 if (Printer
&& Printer
->document_started
)
804 _spoolss_enddocprinter(handle
); /* print job was not closed */
806 if (!close_printer_handle(handle
))
807 return ERROR_INVALID_HANDLE
;
809 return NT_STATUS_NO_PROBLEMO
;
812 /********************************************************************
813 * api_spoolss_deleteprinter
814 ********************************************************************/
815 uint32
_spoolss_deleteprinter(POLICY_HND
*handle
)
817 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
819 if (Printer
&& Printer
->document_started
)
820 _spoolss_enddocprinter(handle
); /* print job was not closed */
822 if (!delete_printer_handle(handle
))
823 return ERROR_INVALID_HANDLE
;
825 srv_spoolss_sendnotify(handle
);
827 return NT_STATUS_NO_PROBLEMO
;
830 /********************************************************************
831 GetPrinterData on a printer server Handle.
832 ********************************************************************/
833 static BOOL
getprinterdata_printer_server(fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
837 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
839 if (!strcmp(value
, "BeepEnabled")) {
841 if((*data
= (uint8
*)malloc( 4*sizeof(uint8
) )) == NULL
)
843 SIVAL(*data
, 0, 0x01);
848 if (!strcmp(value
, "EventLog")) {
850 if((*data
= (uint8
*)malloc( 4*sizeof(uint8
) )) == NULL
)
852 SIVAL(*data
, 0, 0x1B);
857 if (!strcmp(value
, "NetPopup")) {
859 if((*data
= (uint8
*)malloc( 4*sizeof(uint8
) )) == NULL
)
861 SIVAL(*data
, 0, 0x01);
866 if (!strcmp(value
, "MajorVersion")) {
868 if((*data
= (uint8
*)malloc( 4*sizeof(uint8
) )) == NULL
)
870 SIVAL(*data
, 0, 0x02);
875 if (!strcmp(value
, "DefaultSpoolDirectory")) {
876 pstring string
="You are using a Samba server";
878 *needed
= 2*(strlen(string
)+1);
879 if((*data
= (uint8
*)malloc( ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
881 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
883 /* it's done by hand ready to go on the wire */
884 for (i
=0; i
<strlen(string
); i
++) {
885 (*data
)[2*i
]=string
[i
];
891 if (!strcmp(value
, "Architecture")) {
892 pstring string
="Windows NT x86";
894 *needed
= 2*(strlen(string
)+1);
895 if((*data
= (uint8
*)malloc( ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
897 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
898 for (i
=0; i
<strlen(string
); i
++) {
899 (*data
)[2*i
]=string
[i
];
908 /********************************************************************
909 GetPrinterData on a printer Handle.
910 ********************************************************************/
911 static BOOL
getprinterdata_printer(POLICY_HND
*handle
,
912 fstring value
, uint32
*type
,
913 uint8
**data
, uint32
*needed
, uint32 in_size
)
915 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
919 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
921 DEBUG(5,("getprinterdata_printer\n"));
923 if (!OPEN_HANDLE(Printer
)) {
924 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
928 if(!get_printer_snum(handle
, &snum
))
931 if(get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0)
934 if (!get_specific_param(*printer
, 2, value
, &idata
, type
, &len
)) {
935 free_a_printer(&printer
, 2);
939 free_a_printer(&printer
, 2);
941 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size
));
944 if((*data
= (uint8
*)malloc( in_size
*sizeof(uint8
) )) == NULL
) {
948 memset(*data
, 0, in_size
*sizeof(uint8
));
949 /* copy the min(in_size, len) */
950 memcpy(*data
, idata
, (len
>in_size
)?in_size
:len
*sizeof(uint8
));
957 DEBUG(5,("getprinterdata_printer:copy done\n"));
964 /********************************************************************
965 * spoolss_getprinterdata
966 ********************************************************************/
967 uint32
_spoolss_getprinterdata(POLICY_HND
*handle
, UNISTR2
*valuename
,
976 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
979 * Reminder: when it's a string, the length is in BYTES
980 * even if UNICODE is negociated.
987 /* in case of problem, return some default values */
991 DEBUG(4,("_spoolss_getprinterdata\n"));
993 if (!OPEN_HANDLE(Printer
)) {
994 if((*data
=(uint8
*)malloc(4*sizeof(uint8
))) == NULL
)
995 return ERROR_NOT_ENOUGH_MEMORY
;
996 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
997 return ERROR_INVALID_HANDLE
;
1000 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
1002 if (handle_is_printserver(handle
))
1003 found
=getprinterdata_printer_server(value
, type
, data
, needed
, *out_size
);
1005 found
=getprinterdata_printer(handle
, value
, type
, data
, needed
, *out_size
);
1008 DEBUG(5, ("value not found, allocating %d\n", *out_size
));
1009 /* reply this param doesn't exist */
1011 if((*data
=(uint8
*)malloc(*out_size
*sizeof(uint8
))) == NULL
)
1012 return ERROR_NOT_ENOUGH_MEMORY
;
1013 memset(*data
, '\0', *out_size
*sizeof(uint8
));
1018 return ERROR_INVALID_PARAMETER
;
1021 if (*needed
> *out_size
)
1022 return ERROR_MORE_DATA
;
1024 return NT_STATUS_NO_PROBLEMO
;
1027 /***************************************************************************
1028 connect to the client
1029 ****************************************************************************/
1030 static BOOL
srv_spoolss_replyopenprinter(char *printer
, uint32 localprinter
, uint32 type
, POLICY_HND
*handle
)
1035 * If it's the first connection, contact the client
1036 * and connect to the IPC$ share anonumously
1038 if (smb_connections
==0) {
1039 if(!spoolss_connect_to_client(&cli
, printer
+2)) /* the +2 is to strip the leading 2 backslashs */
1041 message_register(MSG_PRINTER_NOTIFY
, srv_spoolss_receive_message
);
1047 if(!cli_spoolss_reply_open_printer(&cli
, printer
, localprinter
, type
, &status
, handle
))
1053 /********************************************************************
1055 * ReplyFindFirstPrinterChangeNotifyEx
1057 * jfmxxxx: before replying OK: status=0
1058 * should do a rpc call to the workstation asking ReplyOpenPrinter
1059 * have to code it, later.
1061 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
1062 * called from api_spoolss_rffpcnex
1063 ********************************************************************/
1064 uint32
_spoolss_rffpcnex(POLICY_HND
*handle
, uint32 flags
, uint32 options
,
1065 const UNISTR2
*localmachine
, uint32 printerlocal
,
1066 SPOOL_NOTIFY_OPTION
*option
)
1068 /* store the notify value in the printer struct */
1070 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
1072 if (!OPEN_HANDLE(Printer
)) {
1073 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
1074 return ERROR_INVALID_HANDLE
;
1077 Printer
->notify
.flags
=flags
;
1078 Printer
->notify
.options
=options
;
1079 Printer
->notify
.printerlocal
=printerlocal
;
1080 Printer
->notify
.option
=option
;
1081 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
, sizeof(Printer
->notify
.localmachine
)-1);
1083 /* connect to the client machine and send a ReplyOpenPrinter */
1084 if(srv_spoolss_replyopenprinter(Printer
->notify
.localmachine
,
1085 Printer
->notify
.printerlocal
, 1,
1086 &Printer
->notify
.client_hnd
))
1087 Printer
->notify
.client_connected
=True
;
1089 return NT_STATUS_NO_PROBLEMO
;
1092 /*******************************************************************
1093 * fill a notify_info_data with the servername
1094 ********************************************************************/
1095 static void spoolss_notify_server_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
,
1096 NT_PRINTER_INFO_LEVEL
*printer
)
1100 snprintf(temp_name
, sizeof(temp_name
)-1, "\\\\%s", global_myname
);
1102 data
->notify_data
.data
.length
= (uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1103 temp_name
, sizeof(data
->notify_data
.data
.string
), True
) - sizeof(uint16
))/sizeof(uint16
));
1106 /*******************************************************************
1107 * fill a notify_info_data with the printername (not including the servername).
1108 ********************************************************************/
1109 static void spoolss_notify_printer_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
,
1110 NT_PRINTER_INFO_LEVEL
*printer
)
1112 /* the notify name should not contain the \\server\ part */
1113 char *p
= strrchr(printer
->info_2
->printername
, '\\');
1115 p
= printer
->info_2
->printername
;
1120 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1121 p
, sizeof(data
->notify_data
.data
.string
), True
) - sizeof(uint16
))/sizeof(uint16
));
1124 /*******************************************************************
1125 * fill a notify_info_data with the servicename
1126 ********************************************************************/
1127 static void spoolss_notify_share_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1129 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1130 lp_servicename(snum
), sizeof(data
->notify_data
.data
.string
),True
) - sizeof(uint16
))/sizeof(uint16
));
1133 /*******************************************************************
1134 * fill a notify_info_data with the port name
1135 ********************************************************************/
1136 static void spoolss_notify_port_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1138 /* even if it's strange, that's consistant in all the code */
1140 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1141 printer
->info_2
->portname
, sizeof(data
->notify_data
.data
.string
), True
) - sizeof(uint16
))/sizeof(uint16
));
1144 /*******************************************************************
1145 * fill a notify_info_data with the printername
1146 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
1147 * but it doesn't exist, have to see what to do
1148 ********************************************************************/
1149 static void spoolss_notify_driver_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1151 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1152 printer
->info_2
->drivername
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1155 /*******************************************************************
1156 * fill a notify_info_data with the comment
1157 ********************************************************************/
1158 static void spoolss_notify_comment(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1160 if (*printer
->info_2
->comment
== '\0')
1161 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1162 lp_comment(snum
), sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1164 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1165 printer
->info_2
->comment
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1168 /*******************************************************************
1169 * fill a notify_info_data with the comment
1170 * jfm:xxxx incorrect, have to create a new smb.conf option
1171 * location = "Room 1, floor 2, building 3"
1172 ********************************************************************/
1173 static void spoolss_notify_location(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1175 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1176 printer
->info_2
->location
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1179 /*******************************************************************
1180 * fill a notify_info_data with the device mode
1181 * jfm:xxxx don't to it for know but that's a real problem !!!
1182 ********************************************************************/
1183 static void spoolss_notify_devmode(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1187 /*******************************************************************
1188 * fill a notify_info_data with the separator file name
1189 * jfm:xxxx just return no file could add an option to smb.conf
1190 * separator file = "separator.txt"
1191 ********************************************************************/
1192 static void spoolss_notify_sepfile(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1194 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1195 printer
->info_2
->sepfile
, sizeof(data
->notify_data
.data
.string
)-1,True
) - sizeof(uint16
))/sizeof(uint16
));
1198 /*******************************************************************
1199 * fill a notify_info_data with the print processor
1200 * jfm:xxxx return always winprint to indicate we don't do anything to it
1201 ********************************************************************/
1202 static void spoolss_notify_print_processor(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1204 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1205 printer
->info_2
->printprocessor
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1208 /*******************************************************************
1209 * fill a notify_info_data with the print processor options
1210 * jfm:xxxx send an empty string
1211 ********************************************************************/
1212 static void spoolss_notify_parameters(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1214 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1215 printer
->info_2
->parameters
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1218 /*******************************************************************
1219 * fill a notify_info_data with the data type
1220 * jfm:xxxx always send RAW as data type
1221 ********************************************************************/
1222 static void spoolss_notify_datatype(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1224 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1225 printer
->info_2
->datatype
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1228 /*******************************************************************
1229 * fill a notify_info_data with the security descriptor
1230 * jfm:xxxx send an null pointer to say no security desc
1231 * have to implement security before !
1232 ********************************************************************/
1233 static void spoolss_notify_security_desc(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1235 data
->notify_data
.data
.length
=0;
1236 data
->notify_data
.data
.string
[0]=0x00;
1239 /*******************************************************************
1240 * fill a notify_info_data with the attributes
1241 * jfm:xxxx a samba printer is always shared
1242 ********************************************************************/
1243 static void spoolss_notify_attributes(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1245 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
1248 /*******************************************************************
1249 * fill a notify_info_data with the priority
1250 ********************************************************************/
1251 static void spoolss_notify_priority(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1253 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
1256 /*******************************************************************
1257 * fill a notify_info_data with the default priority
1258 ********************************************************************/
1259 static void spoolss_notify_default_priority(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1261 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
1264 /*******************************************************************
1265 * fill a notify_info_data with the start time
1266 ********************************************************************/
1267 static void spoolss_notify_start_time(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1269 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
1272 /*******************************************************************
1273 * fill a notify_info_data with the until time
1274 ********************************************************************/
1275 static void spoolss_notify_until_time(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1277 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
1280 /*******************************************************************
1281 * fill a notify_info_data with the status
1282 ********************************************************************/
1283 static void spoolss_notify_status(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1286 print_queue_struct
*q
=NULL
;
1287 print_status_struct status
;
1289 memset(&status
, 0, sizeof(status
));
1290 count
= print_queue_status(snum
, &q
, &status
);
1291 data
->notify_data
.value
[0]=(uint32
) status
.status
;
1295 /*******************************************************************
1296 * fill a notify_info_data with the number of jobs queued
1297 ********************************************************************/
1298 static void spoolss_notify_cjobs(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1300 print_queue_struct
*q
=NULL
;
1301 print_status_struct status
;
1303 memset(&status
, 0, sizeof(status
));
1304 data
->notify_data
.value
[0] = print_queue_status(snum
, &q
, &status
);
1308 /*******************************************************************
1309 * fill a notify_info_data with the average ppm
1310 ********************************************************************/
1311 static void spoolss_notify_average_ppm(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1313 /* always respond 8 pages per minutes */
1314 /* a little hard ! */
1315 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
1318 /*******************************************************************
1319 * fill a notify_info_data with username
1320 ********************************************************************/
1321 static void spoolss_notify_username(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1323 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1324 queue
->user
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1327 /*******************************************************************
1328 * fill a notify_info_data with job status
1329 ********************************************************************/
1330 static void spoolss_notify_job_status(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1332 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
1335 /*******************************************************************
1336 * fill a notify_info_data with job name
1337 ********************************************************************/
1338 static void spoolss_notify_job_name(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1340 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1341 queue
->file
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1344 /*******************************************************************
1345 * fill a notify_info_data with job status
1346 ********************************************************************/
1347 static void spoolss_notify_job_status_string(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1349 char *p
= "unknown";
1351 switch (queue
->status
) {
1356 p
= ""; /* NT provides the paused string */
1365 data
->notify_data
.data
.length
=(uint32
)((dos_PutUniCode((char *)data
->notify_data
.data
.string
,
1366 p
, sizeof(data
->notify_data
.data
.string
)-1, True
) - sizeof(uint16
))/sizeof(uint16
));
1369 /*******************************************************************
1370 * fill a notify_info_data with job time
1371 ********************************************************************/
1372 static void spoolss_notify_job_time(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1374 data
->notify_data
.value
[0]=0x0;
1377 /*******************************************************************
1378 * fill a notify_info_data with job size
1379 ********************************************************************/
1380 static void spoolss_notify_job_size(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1382 data
->notify_data
.value
[0]=queue
->size
;
1385 /*******************************************************************
1386 * fill a notify_info_data with job position
1387 ********************************************************************/
1388 static void spoolss_notify_job_position(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1390 data
->notify_data
.value
[0]=queue
->job
;
1393 /*******************************************************************
1394 * fill a notify_info_data with submitted time
1395 ********************************************************************/
1396 static void spoolss_notify_submitted_time(int snum
, SPOOL_NOTIFY_INFO_DATA
*data
, print_queue_struct
*queue
, NT_PRINTER_INFO_LEVEL
*printer
)
1400 t
=gmtime(&queue
->time
);
1402 data
->notify_data
.data
.length
= sizeof(SYSTEMTIME
);
1403 make_systemtime((SYSTEMTIME
*)(data
->notify_data
.data
.string
), t
);
1408 struct s_notify_info_data_table
1414 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
1415 print_queue_struct
*queue
,
1416 NT_PRINTER_INFO_LEVEL
*printer
);
1419 struct s_notify_info_data_table notify_info_data_table
[] =
1421 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", POINTER
, spoolss_notify_server_name
},
1422 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
1423 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", POINTER
, spoolss_notify_share_name
},
1424 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
1425 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
1426 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", POINTER
, spoolss_notify_comment
},
1427 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", POINTER
, spoolss_notify_location
},
1428 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
1429 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", POINTER
, spoolss_notify_sepfile
},
1430 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
1431 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
1432 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
1433 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, spoolss_notify_security_desc
},
1434 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE
, spoolss_notify_attributes
},
1435 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
1436 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE
, spoolss_notify_default_priority
},
1437 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
1438 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
1439 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_status
},
1440 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", POINTER
, NULL
},
1441 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", ONE_VALUE
, spoolss_notify_cjobs
},
1442 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE
, spoolss_notify_average_ppm
},
1443 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER
, NULL
},
1444 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER
, NULL
},
1445 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER
, NULL
},
1446 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER
, NULL
},
1447 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", POINTER
, spoolss_notify_printer_name
},
1448 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", POINTER
, spoolss_notify_server_name
},
1449 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", POINTER
, spoolss_notify_port_name
},
1450 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", POINTER
, spoolss_notify_username
},
1451 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", POINTER
, spoolss_notify_username
},
1452 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", POINTER
, spoolss_notify_datatype
},
1453 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER
, spoolss_notify_print_processor
},
1454 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", POINTER
, spoolss_notify_parameters
},
1455 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", POINTER
, spoolss_notify_driver_name
},
1456 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", POINTER
, spoolss_notify_devmode
},
1457 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", ONE_VALUE
, spoolss_notify_job_status
},
1458 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", POINTER
, spoolss_notify_job_status_string
},
1459 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER
, NULL
},
1460 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", POINTER
, spoolss_notify_job_name
},
1461 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", ONE_VALUE
, spoolss_notify_priority
},
1462 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", ONE_VALUE
, spoolss_notify_job_position
},
1463 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", POINTER
, spoolss_notify_submitted_time
},
1464 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", ONE_VALUE
, spoolss_notify_start_time
},
1465 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE
, spoolss_notify_until_time
},
1466 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", ONE_VALUE
, spoolss_notify_job_time
},
1467 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE
, NULL
},
1468 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE
, NULL
},
1469 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE
, spoolss_notify_job_size
},
1470 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_BYTES_PRINTED
, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE
, NULL
},
1471 { END
, END
, "", END
, NULL
}
1474 /*******************************************************************
1475 return the size of info_data structure
1476 ********************************************************************/
1477 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
1481 while (notify_info_data_table
[i
].type
!= END
)
1483 if ( (notify_info_data_table
[i
].type
== type
) &&
1484 (notify_info_data_table
[i
].field
== field
) )
1486 return (notify_info_data_table
[i
].size
);
1493 /*******************************************************************
1494 return the type of notify_info_data
1495 ********************************************************************/
1496 static BOOL
type_of_notify_info_data(uint16 type
, uint16 field
)
1500 while (notify_info_data_table
[i
].type
!= END
)
1502 if ( (notify_info_data_table
[i
].type
== type
) &&
1503 (notify_info_data_table
[i
].field
== field
) )
1505 if (notify_info_data_table
[i
].size
== POINTER
)
1519 /****************************************************************************
1520 ****************************************************************************/
1521 static int search_notify(uint16 type
, uint16 field
, int *value
)
1526 for (j
=0, found
=False
; found
==False
&& notify_info_data_table
[j
].type
!= END
; j
++)
1528 if ( (notify_info_data_table
[j
].type
== type
) &&
1529 (notify_info_data_table
[j
].field
== field
) )
1534 if ( found
&& (notify_info_data_table
[j
].fn
!= NULL
) )
1540 /****************************************************************************
1541 ****************************************************************************/
1542 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
1544 info_data
->type
= type
;
1545 info_data
->field
= field
;
1546 info_data
->reserved
= 0;
1548 info_data
->size
= size_of_notify_info_data(type
, field
);
1549 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
1553 /*******************************************************************
1555 * fill a notify_info struct with info asked
1557 ********************************************************************/
1558 static BOOL
construct_notify_printer_info(SPOOL_NOTIFY_INFO
*info
, int snum
, SPOOL_NOTIFY_OPTION_TYPE
*option_type
, uint32 id
)
1564 SPOOL_NOTIFY_INFO_DATA
*current_data
;
1565 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1566 print_queue_struct
*queue
=NULL
;
1568 DEBUG(4,("construct_notify_printer_info\n"));
1570 type
=option_type
->type
;
1572 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1573 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1574 option_type
->count
, lp_servicename(snum
)));
1576 if (get_a_printer(&printer
, 2, lp_servicename(snum
))!=0)
1579 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
1580 field
= option_type
->fields
[field_num
];
1581 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
1583 if (!search_notify(type
, field
, &j
) )
1586 if((info
->data
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
1589 current_data
=&info
->data
[info
->count
];
1591 construct_info_data(current_data
, type
, field
, id
);
1593 DEBUG(10,("construct_notify_printer_info: calling %s\n",
1594 notify_info_data_table
[j
].name
));
1596 notify_info_data_table
[j
].fn(snum
, current_data
, queue
, printer
);
1601 free_a_printer(&printer
, 2);
1605 /*******************************************************************
1607 * fill a notify_info struct with info asked
1609 ********************************************************************/
1610 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
, SPOOL_NOTIFY_INFO
*info
, int snum
, SPOOL_NOTIFY_OPTION_TYPE
*option_type
, uint32 id
)
1616 SPOOL_NOTIFY_INFO_DATA
*current_data
;
1617 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1619 DEBUG(4,("construct_notify_jobs_info\n"));
1621 type
= option_type
->type
;
1623 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1624 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1625 option_type
->count
));
1627 if (get_a_printer(&printer
, 2, lp_servicename(snum
))!=0)
1630 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
1631 field
= option_type
->fields
[field_num
];
1633 if (!search_notify(type
, field
, &j
) )
1636 if((info
->data
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
1640 current_data
=&(info
->data
[info
->count
]);
1642 construct_info_data(current_data
, type
, field
, id
);
1643 notify_info_data_table
[j
].fn(snum
, current_data
, queue
, printer
);
1647 free_a_printer(&printer
, 2);
1652 * JFM: The enumeration is not that simple, it's even non obvious.
1654 * let's take an example: I want to monitor the PRINTER SERVER for
1655 * the printer's name and the number of jobs currently queued.
1656 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1657 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1659 * I have 3 printers on the back of my server.
1661 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1664 * 1 printer 1 name 1
1665 * 2 printer 1 cjob 1
1666 * 3 printer 2 name 2
1667 * 4 printer 2 cjob 2
1668 * 5 printer 3 name 3
1669 * 6 printer 3 name 3
1671 * that's the print server case, the printer case is even worse.
1676 /*******************************************************************
1678 * enumerate all printers on the printserver
1679 * fill a notify_info struct with info asked
1681 ********************************************************************/
1682 static uint32
printserver_notify_info(const POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
)
1685 Printer_entry
*Printer
=find_printer_index_by_hnd(hnd
);
1686 int n_services
=lp_numservices();
1689 SPOOL_NOTIFY_OPTION
*option
;
1690 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
1692 DEBUG(4,("printserver_notify_info\n"));
1694 option
=Printer
->notify
.option
;
1700 for (i
=0; i
<option
->count
; i
++) {
1701 option_type
=&(option
->ctr
.type
[i
]);
1703 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
1706 for (snum
=0; snum
<n_services
; snum
++)
1707 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
1708 if (construct_notify_printer_info(info
, snum
, option_type
, id
))
1713 * Debugging information, don't delete.
1716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1720 for (i=0; i<info->count; i++) {
1721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1722 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1723 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1727 return NT_STATUS_NO_PROBLEMO
;
1730 /*******************************************************************
1732 * fill a notify_info struct with info asked
1734 ********************************************************************/
1735 static uint32
printer_notify_info(POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
)
1738 Printer_entry
*Printer
=find_printer_index_by_hnd(hnd
);
1741 SPOOL_NOTIFY_OPTION
*option
;
1742 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
1744 print_queue_struct
*queue
=NULL
;
1745 print_status_struct status
;
1747 DEBUG(4,("printer_notify_info\n"));
1749 option
=Printer
->notify
.option
;
1755 get_printer_snum(hnd
, &snum
);
1757 for (i
=0; i
<option
->count
; i
++) {
1758 option_type
=&option
->ctr
.type
[i
];
1760 switch ( option_type
->type
) {
1761 case PRINTER_NOTIFY_TYPE
:
1762 if(construct_notify_printer_info(info
, snum
, option_type
, id
))
1766 case JOB_NOTIFY_TYPE
:
1767 memset(&status
, 0, sizeof(status
));
1768 count
= print_queue_status(snum
, &queue
, &status
);
1769 for (j
=0; j
<count
; j
++)
1770 construct_notify_jobs_info(&queue
[j
], info
, snum
, option_type
, queue
[j
].job
);
1777 * Debugging information, don't delete.
1780 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1781 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1782 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1784 for (i=0; i<info->count; i++) {
1785 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1786 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1787 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1790 return NT_STATUS_NO_PROBLEMO
;
1793 /********************************************************************
1795 ********************************************************************/
1796 uint32
_spoolss_rfnpcnex( POLICY_HND
*handle
, uint32 change
,
1797 SPOOL_NOTIFY_OPTION
*option
, SPOOL_NOTIFY_INFO
*info
)
1799 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
1801 if (!OPEN_HANDLE(Printer
)) {
1802 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle
)));
1803 return ERROR_INVALID_HANDLE
;
1806 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
1808 /* jfm: the change value isn't used right now.
1809 * we will honour it when
1810 * a) we'll be able to send notification to the client
1811 * b) we'll have a way to communicate between the spoolss process.
1813 * same thing for option->flags
1814 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1815 * I don't have a global notification system, I'm sending back all the
1816 * informations even when _NOTHING_ has changed.
1819 /* just discard the SPOOL_NOTIFY_OPTION */
1821 safe_free(option
->ctr
.type
);
1823 switch (Printer
->printer_type
) {
1824 case PRINTER_HANDLE_IS_PRINTSERVER
:
1825 return printserver_notify_info(handle
, info
);
1826 case PRINTER_HANDLE_IS_PRINTER
:
1827 return printer_notify_info(handle
, info
);
1830 return ERROR_INVALID_HANDLE
;
1833 /********************************************************************
1834 * construct_printer_info_0
1835 * fill a printer_info_0 struct
1836 ********************************************************************/
1837 static BOOL
construct_printer_info_0(PRINTER_INFO_0
*printer
, int snum
)
1841 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
1842 counter_printer_0
*session_counter
;
1843 uint32 global_counter
;
1847 print_queue_struct
*queue
=NULL
;
1848 print_status_struct status
;
1850 memset(&status
, 0, sizeof(status
));
1852 if (get_a_printer(&ntprinter
, 2, lp_servicename(snum
)) != 0)
1855 count
= print_queue_status(snum
, &queue
, &status
);
1857 /* check if we already have a counter for this printer */
1858 session_counter
= (counter_printer_0
*)ubi_dlFirst(&counter_list
);
1860 for(; session_counter
; session_counter
= (counter_printer_0
*)ubi_dlNext(session_counter
)) {
1861 if (session_counter
->snum
== snum
)
1865 /* it's the first time, add it to the list */
1866 if (session_counter
==NULL
) {
1867 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
1868 free_a_printer(&ntprinter
, 2);
1871 ZERO_STRUCTP(session_counter
);
1872 session_counter
->snum
=snum
;
1873 session_counter
->counter
=0;
1874 ubi_dlAddHead( &counter_list
, (ubi_dlNode
*)session_counter
);
1878 session_counter
->counter
++;
1881 * the global_counter should be stored in a TDB as it's common to all the clients
1882 * and should be zeroed on samba startup
1884 global_counter
=session_counter
->counter
;
1886 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
1888 init_unistr(&printer
->printername
, chaine
);
1890 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", global_myname
);
1891 init_unistr(&printer
->servername
, chaine
);
1893 printer
->cjobs
= count
;
1894 printer
->total_jobs
= 0;
1895 printer
->total_bytes
= 0;
1897 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
1898 t
=gmtime(&setuptime
);
1900 printer
->year
= t
->tm_year
+1900;
1901 printer
->month
= t
->tm_mon
+1;
1902 printer
->dayofweek
= t
->tm_wday
;
1903 printer
->day
= t
->tm_mday
;
1904 printer
->hour
= t
->tm_hour
;
1905 printer
->minute
= t
->tm_min
;
1906 printer
->second
= t
->tm_sec
;
1907 printer
->milliseconds
= 0;
1909 printer
->global_counter
= global_counter
;
1910 printer
->total_pages
= 0;
1911 printer
->major_version
= 0x0004; /* NT 4 */
1912 printer
->build_version
= 0x0565; /* build 1381 */
1913 printer
->unknown7
= 0x1;
1914 printer
->unknown8
= 0x0;
1915 printer
->unknown9
= 0x0;
1916 printer
->session_counter
= session_counter
->counter
;
1917 printer
->unknown11
= 0x0;
1918 printer
->printer_errors
= 0x0; /* number of print failure */
1919 printer
->unknown13
= 0x0;
1920 printer
->unknown14
= 0x1;
1921 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
1922 printer
->unknown16
= 0x0;
1923 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
1924 printer
->unknown18
= 0x0;
1925 printer
->status
= nt_printq_status(status
.status
);
1926 printer
->unknown20
= 0x0;
1927 printer
->c_setprinter
= ntprinter
->info_2
->c_setprinter
; /* how many times setprinter has been called */
1928 printer
->unknown22
= 0x0;
1929 printer
->unknown23
= 0x6; /* 6 ???*/
1930 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
1931 printer
->unknown25
= 0;
1932 printer
->unknown26
= 0;
1933 printer
->unknown27
= 0;
1934 printer
->unknown28
= 0;
1935 printer
->unknown29
= 0;
1938 free_a_printer(&ntprinter
,2);
1942 /********************************************************************
1943 * construct_printer_info_1
1944 * fill a printer_info_1 struct
1945 ********************************************************************/
1946 static BOOL
construct_printer_info_1(uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
1950 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
1952 if (get_a_printer(&ntprinter
, 2, lp_servicename(snum
)) != 0)
1955 printer
->flags
=flags
;
1957 if (*ntprinter
->info_2
->comment
== '\0') {
1958 init_unistr(&printer
->comment
, lp_comment(snum
));
1959 snprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",global_myname
, ntprinter
->info_2
->printername
,
1960 ntprinter
->info_2
->drivername
, lp_comment(snum
));
1963 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
1964 snprintf(chaine
,sizeof(chaine
)-1,"%s%s,%s,%s",global_myname
, ntprinter
->info_2
->printername
,
1965 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
1968 snprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
1970 init_unistr(&printer
->description
, chaine
);
1971 init_unistr(&printer
->name
, chaine2
);
1973 free_a_printer(&ntprinter
,2);
1978 /****************************************************************************
1979 Free a DEVMODE struct.
1980 ****************************************************************************/
1982 static void free_dev_mode(DEVICEMODE
*dev
)
1988 safe_free(dev
->private);
1993 /****************************************************************************
1994 Create a DEVMODE struct. Returns malloced memory.
1995 ****************************************************************************/
1997 static DEVICEMODE
*construct_dev_mode(int snum
)
2001 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2002 NT_DEVICEMODE
*ntdevmode
= NULL
;
2003 DEVICEMODE
*devmode
= NULL
;
2005 DEBUG(7,("construct_dev_mode\n"));
2007 DEBUGADD(8,("getting printer characteristics\n"));
2009 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
2010 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
2014 ZERO_STRUCTP(devmode
);
2016 if(get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0)
2019 if (printer
->info_2
->devmode
)
2020 ntdevmode
= dup_nt_devicemode(printer
->info_2
->devmode
);
2022 if (ntdevmode
== NULL
)
2025 DEBUGADD(8,("loading DEVICEMODE\n"));
2027 snprintf(adevice
, sizeof(adevice
), printer
->info_2
->printername
);
2028 init_unistr(&devmode
->devicename
, adevice
);
2030 snprintf(aform
, sizeof(aform
), ntdevmode
->formname
);
2031 init_unistr(&devmode
->formname
, aform
);
2033 devmode
->specversion
= ntdevmode
->specversion
;
2034 devmode
->driverversion
= ntdevmode
->driverversion
;
2035 devmode
->size
= ntdevmode
->size
;
2036 devmode
->driverextra
= ntdevmode
->driverextra
;
2037 devmode
->fields
= ntdevmode
->fields
;
2039 devmode
->orientation
= ntdevmode
->orientation
;
2040 devmode
->papersize
= ntdevmode
->papersize
;
2041 devmode
->paperlength
= ntdevmode
->paperlength
;
2042 devmode
->paperwidth
= ntdevmode
->paperwidth
;
2043 devmode
->scale
= ntdevmode
->scale
;
2044 devmode
->copies
= ntdevmode
->copies
;
2045 devmode
->defaultsource
= ntdevmode
->defaultsource
;
2046 devmode
->printquality
= ntdevmode
->printquality
;
2047 devmode
->color
= ntdevmode
->color
;
2048 devmode
->duplex
= ntdevmode
->duplex
;
2049 devmode
->yresolution
= ntdevmode
->yresolution
;
2050 devmode
->ttoption
= ntdevmode
->ttoption
;
2051 devmode
->collate
= ntdevmode
->collate
;
2052 devmode
->icmmethod
= ntdevmode
->icmmethod
;
2053 devmode
->icmintent
= ntdevmode
->icmintent
;
2054 devmode
->mediatype
= ntdevmode
->mediatype
;
2055 devmode
->dithertype
= ntdevmode
->dithertype
;
2057 if (ntdevmode
->private != NULL
) {
2058 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
2062 free_nt_devicemode(&ntdevmode
);
2063 free_a_printer(&printer
,2);
2070 free_nt_devicemode(&ntdevmode
);
2072 free_a_printer(&printer
,2);
2073 free_dev_mode(devmode
);
2078 /********************************************************************
2079 * construct_printer_info_2
2080 * fill a printer_info_2 struct
2081 ********************************************************************/
2083 static BOOL
construct_printer_info_2(PRINTER_INFO_2
*printer
, int snum
)
2086 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2088 print_queue_struct
*queue
=NULL
;
2089 print_status_struct status
;
2090 memset(&status
, 0, sizeof(status
));
2092 if (get_a_printer(&ntprinter
, 2, lp_servicename(snum
)) !=0 )
2095 memset(&status
, 0, sizeof(status
));
2096 count
= print_queue_status(snum
, &queue
, &status
);
2098 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
2099 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
2100 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
2101 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
2102 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
2104 if (*ntprinter
->info_2
->comment
== '\0')
2105 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
2107 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
2109 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
2110 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
2111 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
2112 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
2113 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
2115 printer
->attributes
= ntprinter
->info_2
->attributes
;
2117 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
2118 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
2119 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
2120 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
2121 printer
->status
= nt_printq_status(status
.status
); /* status */
2122 printer
->cjobs
= count
; /* jobs */
2123 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
2125 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
2126 DEBUG(8, ("Returning NULL Devicemode!\n"));
2129 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2130 /* steal the printer info sec_desc structure. [badly done]. */
2131 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2132 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
2133 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
2134 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
2137 printer
->secdesc
= NULL
;
2140 free_a_printer(&ntprinter
, 2);
2145 /********************************************************************
2146 * construct_printer_info_3
2147 * fill a printer_info_3 struct
2148 ********************************************************************/
2149 static BOOL
construct_printer_info_3(PRINTER_INFO_3
**pp_printer
, int snum
)
2151 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
2152 PRINTER_INFO_3
*printer
= NULL
;
2154 if (get_a_printer(&ntprinter
, 2, lp_servicename(snum
)) !=0 )
2158 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
2159 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
2163 ZERO_STRUCTP(printer
);
2165 printer
->flags
= 4; /* These are the components of the SD we are returning. */
2166 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
2167 /* steal the printer info sec_desc structure. [badly done]. */
2168 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
2172 * Set the flags for the components we are returning.
2175 if (printer
->secdesc
->owner_sid
)
2176 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
2178 if (printer
->secdesc
->grp_sid
)
2179 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
2181 if (printer
->secdesc
->dacl
)
2182 printer
->flags
|= DACL_SECURITY_INFORMATION
;
2184 if (printer
->secdesc
->sacl
)
2185 printer
->flags
|= SACL_SECURITY_INFORMATION
;
2188 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
2189 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
2190 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
2193 free_a_printer(&ntprinter
, 2);
2195 *pp_printer
= printer
;
2199 /********************************************************************
2200 Spoolss_enumprinters.
2201 ********************************************************************/
2202 static BOOL
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2206 int n_services
=lp_numservices();
2207 PRINTER_INFO_1
*printers
=NULL
;
2208 PRINTER_INFO_1 current_prt
;
2210 DEBUG(4,("enum_all_printers_info_1\n"));
2212 for (snum
=0; snum
<n_services
; snum
++) {
2213 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
2214 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
2216 if (construct_printer_info_1(flags
, ¤t_prt
, snum
)) {
2217 if((printers
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
2219 return ERROR_NOT_ENOUGH_MEMORY
;
2221 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
2222 memcpy(&(printers
[*returned
]), ¤t_prt
, sizeof(PRINTER_INFO_1
));
2228 /* check the required size. */
2229 for (i
=0; i
<*returned
; i
++)
2230 (*needed
) += spoolss_size_printer_info_1(&(printers
[i
]));
2232 if (!alloc_buffer_size(buffer
, *needed
))
2233 return ERROR_INSUFFICIENT_BUFFER
;
2235 /* fill the buffer with the structures */
2236 for (i
=0; i
<*returned
; i
++)
2237 new_smb_io_printer_info_1("", buffer
, &(printers
[i
]), 0);
2240 safe_free(printers
);
2242 if (*needed
> offered
) {
2244 return ERROR_INSUFFICIENT_BUFFER
;
2247 return NT_STATUS_NO_PROBLEMO
;
2250 /********************************************************************
2251 enum_all_printers_info_1_local.
2252 *********************************************************************/
2253 static BOOL
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2255 DEBUG(4,("enum_all_printers_info_1_local\n"));
2257 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
2260 /********************************************************************
2261 enum_all_printers_info_1_name.
2262 *********************************************************************/
2263 static BOOL
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2266 DEBUG(4,("enum_all_printers_info_1_name\n"));
2268 fstrcpy(temp
, "\\\\");
2269 fstrcat(temp
, global_myname
);
2271 if (strequal(name
, temp
)) {
2272 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
2275 return ERROR_INVALID_NAME
;
2278 /********************************************************************
2279 enum_all_printers_info_1_remote.
2280 *********************************************************************/
2281 static BOOL
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2283 PRINTER_INFO_1
*printer
;
2284 fstring printername
;
2287 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2289 /* JFM: currently it's more a place holder than anything else.
2290 * In the spooler world there is a notion of server registration.
2291 * the print servers are registring (sp ?) on the PDC (in the same domain)
2293 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2296 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
2297 return ERROR_NOT_ENOUGH_MEMORY
;
2301 snprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", global_myname
);
2302 snprintf(desc
, sizeof(desc
)-1,"%s", global_myname
);
2303 snprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
2305 init_unistr(&printer
->description
, desc
);
2306 init_unistr(&printer
->name
, printername
);
2307 init_unistr(&printer
->comment
, comment
);
2308 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
2310 /* check the required size. */
2311 *needed
+= spoolss_size_printer_info_1(printer
);
2313 if (!alloc_buffer_size(buffer
, *needed
)) {
2315 return ERROR_INSUFFICIENT_BUFFER
;
2318 /* fill the buffer with the structures */
2319 new_smb_io_printer_info_1("", buffer
, printer
, 0);
2324 if (*needed
> offered
) {
2326 return ERROR_INSUFFICIENT_BUFFER
;
2329 return NT_STATUS_NO_PROBLEMO
;
2332 /********************************************************************
2333 enum_all_printers_info_1_network.
2334 *********************************************************************/
2335 static BOOL
enum_all_printers_info_1_network(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2337 DEBUG(4,("enum_all_printers_info_1_network\n"));
2339 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
2342 /********************************************************************
2343 * api_spoolss_enumprinters
2345 * called from api_spoolss_enumprinters (see this to understand)
2346 ********************************************************************/
2347 static BOOL
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
2351 int n_services
=lp_numservices();
2352 PRINTER_INFO_2
*printers
=NULL
;
2353 PRINTER_INFO_2 current_prt
;
2355 for (snum
=0; snum
<n_services
; snum
++) {
2356 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
2357 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
2359 if (construct_printer_info_2(¤t_prt
, snum
)) {
2360 if((printers
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
)
2361 return ERROR_NOT_ENOUGH_MEMORY
;
2362 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
2363 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
2369 /* check the required size. */
2370 for (i
=0; i
<*returned
; i
++)
2371 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
2373 if (!alloc_buffer_size(buffer
, *needed
)) {
2374 for (i
=0; i
<*returned
; i
++) {
2375 free_devmode(printers
[i
].devmode
);
2376 free_sec_desc(&printers
[i
].secdesc
);
2378 safe_free(printers
);
2379 return ERROR_INSUFFICIENT_BUFFER
;
2382 /* fill the buffer with the structures */
2383 for (i
=0; i
<*returned
; i
++)
2384 new_smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
2387 for (i
=0; i
<*returned
; i
++) {
2388 free_devmode(printers
[i
].devmode
);
2389 free_sec_desc(&printers
[i
].secdesc
);
2391 safe_free(printers
);
2393 if (*needed
> offered
) {
2395 return ERROR_INSUFFICIENT_BUFFER
;
2398 return NT_STATUS_NO_PROBLEMO
;
2401 /********************************************************************
2402 * handle enumeration of printers at level 1
2403 ********************************************************************/
2404 static uint32
enumprinters_level1( uint32 flags
, fstring name
,
2405 NEW_BUFFER
*buffer
, uint32 offered
,
2406 uint32
*needed
, uint32
*returned
)
2408 /* Not all the flags are equals */
2410 if (flags
& PRINTER_ENUM_LOCAL
)
2411 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
2413 if (flags
& PRINTER_ENUM_NAME
)
2414 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
2416 if (flags
& PRINTER_ENUM_REMOTE
)
2417 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
2419 if (flags
& PRINTER_ENUM_NETWORK
)
2420 return enum_all_printers_info_1_network(buffer
, offered
, needed
, returned
);
2422 return NT_STATUS_NO_PROBLEMO
; /* NT4sp5 does that */
2425 /********************************************************************
2426 * handle enumeration of printers at level 2
2427 ********************************************************************/
2428 static uint32
enumprinters_level2( uint32 flags
, fstring servername
,
2429 NEW_BUFFER
*buffer
, uint32 offered
,
2430 uint32
*needed
, uint32
*returned
)
2434 fstrcpy(temp
, "\\\\");
2435 fstrcat(temp
, global_myname
);
2437 if (flags
& PRINTER_ENUM_LOCAL
) {
2438 if (strequal(servername
, temp
))
2439 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
2441 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
2444 if (flags
& PRINTER_ENUM_NAME
) {
2445 if (strequal(servername
, temp
))
2446 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
2448 return ERROR_INVALID_NAME
;
2451 if (flags
& PRINTER_ENUM_REMOTE
)
2452 return ERROR_INVALID_LEVEL
;
2454 return NT_STATUS_NO_PROBLEMO
;
2457 /********************************************************************
2458 * handle enumeration of printers at level 5
2459 ********************************************************************/
2460 static uint32
enumprinters_level5( uint32 flags
, fstring servername
,
2461 NEW_BUFFER
*buffer
, uint32 offered
,
2462 uint32
*needed
, uint32
*returned
)
2464 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2465 return NT_STATUS_NO_PROBLEMO
;
2468 /********************************************************************
2469 * api_spoolss_enumprinters
2471 * called from api_spoolss_enumprinters (see this to understand)
2472 ********************************************************************/
2473 uint32
_spoolss_enumprinters( uint32 flags
, const UNISTR2
*servername
, uint32 level
,
2474 NEW_BUFFER
*buffer
, uint32 offered
,
2475 uint32
*needed
, uint32
*returned
)
2479 DEBUG(4,("_spoolss_enumprinters\n"));
2486 * flags==PRINTER_ENUM_NAME
2487 * if name=="" then enumerates all printers
2488 * if name!="" then enumerate the printer
2489 * flags==PRINTER_ENUM_REMOTE
2490 * name is NULL, enumerate printers
2491 * Level 2: name!="" enumerates printers, name can't be NULL
2492 * Level 3: doesn't exist
2493 * Level 4: does a local registry lookup
2494 * Level 5: same as Level 2
2497 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
2502 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
2504 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
2506 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
2510 return ERROR_INVALID_LEVEL
;
2514 /****************************************************************************
2515 ****************************************************************************/
2516 static uint32
getprinter_level_0(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2518 PRINTER_INFO_0
*printer
=NULL
;
2520 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
2521 return ERROR_NOT_ENOUGH_MEMORY
;
2523 construct_printer_info_0(printer
, snum
);
2525 /* check the required size. */
2526 *needed
+= spoolss_size_printer_info_0(printer
);
2528 if (!alloc_buffer_size(buffer
, *needed
)) {
2530 return ERROR_INSUFFICIENT_BUFFER
;
2533 /* fill the buffer with the structures */
2534 new_smb_io_printer_info_0("", buffer
, printer
, 0);
2539 if (*needed
> offered
) {
2540 return ERROR_INSUFFICIENT_BUFFER
;
2543 return NT_STATUS_NO_PROBLEMO
;
2546 /****************************************************************************
2547 ****************************************************************************/
2548 static uint32
getprinter_level_1(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2550 PRINTER_INFO_1
*printer
=NULL
;
2552 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
2553 return ERROR_NOT_ENOUGH_MEMORY
;
2555 construct_printer_info_1(PRINTER_ENUM_ICON8
, printer
, snum
);
2557 /* check the required size. */
2558 *needed
+= spoolss_size_printer_info_1(printer
);
2560 if (!alloc_buffer_size(buffer
, *needed
)) {
2562 return ERROR_INSUFFICIENT_BUFFER
;
2565 /* fill the buffer with the structures */
2566 new_smb_io_printer_info_1("", buffer
, printer
, 0);
2571 if (*needed
> offered
) {
2572 return ERROR_INSUFFICIENT_BUFFER
;
2575 return NT_STATUS_NO_PROBLEMO
;
2578 /****************************************************************************
2579 ****************************************************************************/
2580 static uint32
getprinter_level_2(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2582 PRINTER_INFO_2
*printer
=NULL
;
2584 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
2585 return ERROR_NOT_ENOUGH_MEMORY
;
2587 construct_printer_info_2(printer
, snum
);
2589 /* check the required size. */
2590 *needed
+= spoolss_size_printer_info_2(printer
);
2592 if (!alloc_buffer_size(buffer
, *needed
)) {
2593 free_printer_info_2(printer
);
2594 return ERROR_INSUFFICIENT_BUFFER
;
2597 /* fill the buffer with the structures */
2598 if (!new_smb_io_printer_info_2("", buffer
, printer
, 0)) {
2599 free_printer_info_2(printer
);
2600 return ERROR_NOT_ENOUGH_MEMORY
;
2604 free_printer_info_2(printer
);
2606 if (*needed
> offered
) {
2607 return ERROR_INSUFFICIENT_BUFFER
;
2610 return NT_STATUS_NO_PROBLEMO
;
2613 /****************************************************************************
2614 ****************************************************************************/
2615 static uint32
getprinter_level_3(int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2617 PRINTER_INFO_3
*printer
=NULL
;
2619 if (!construct_printer_info_3(&printer
, snum
))
2620 return ERROR_NOT_ENOUGH_MEMORY
;
2622 /* check the required size. */
2623 *needed
+= spoolss_size_printer_info_3(printer
);
2625 if (!alloc_buffer_size(buffer
, *needed
)) {
2626 free_printer_info_3(printer
);
2627 return ERROR_INSUFFICIENT_BUFFER
;
2630 /* fill the buffer with the structures */
2631 new_smb_io_printer_info_3("", buffer
, printer
, 0);
2634 free_printer_info_3(printer
);
2636 if (*needed
> offered
) {
2637 return ERROR_INSUFFICIENT_BUFFER
;
2640 return NT_STATUS_NO_PROBLEMO
;
2643 /****************************************************************************
2644 ****************************************************************************/
2645 uint32
_spoolss_getprinter(POLICY_HND
*handle
, uint32 level
,
2646 NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2652 if (!get_printer_snum(handle
, &snum
))
2653 return ERROR_INVALID_HANDLE
;
2657 return getprinter_level_0(snum
, buffer
, offered
, needed
);
2659 return getprinter_level_1(snum
, buffer
, offered
, needed
);
2661 return getprinter_level_2(snum
, buffer
, offered
, needed
);
2663 return getprinter_level_3(snum
, buffer
, offered
, needed
);
2665 return ERROR_INVALID_LEVEL
;
2669 /********************************************************************
2670 * fill a DRIVER_INFO_1 struct
2671 ********************************************************************/
2672 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
2674 init_unistr( &info
->name
, driver
.info_3
->name
);
2677 /********************************************************************
2678 * construct_printer_driver_info_1
2679 ********************************************************************/
2680 static uint32
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
2682 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2683 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
2685 ZERO_STRUCT(driver
);
2687 if (get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0)
2688 return ERROR_INVALID_PRINTER_NAME
;
2690 if (get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
) != 0)
2691 return ERROR_UNKNOWN_PRINTER_DRIVER
;
2693 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
2695 free_a_printer(&printer
,2);
2697 return NT_STATUS_NO_PROBLEMO
;
2700 /********************************************************************
2701 * construct_printer_driver_info_2
2702 * fill a printer_info_2 struct
2703 ********************************************************************/
2704 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
2706 pstring temp_driverpath
;
2707 pstring temp_datafile
;
2708 pstring temp_configfile
;
2710 info
->version
=driver
.info_3
->cversion
;
2712 init_unistr( &info
->name
, driver
.info_3
->name
);
2713 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
2715 snprintf(temp_driverpath
, sizeof(temp_driverpath
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
2716 init_unistr( &info
->driverpath
, temp_driverpath
);
2718 snprintf(temp_datafile
, sizeof(temp_datafile
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
2719 init_unistr( &info
->datafile
, temp_datafile
);
2721 snprintf(temp_configfile
, sizeof(temp_configfile
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
2722 init_unistr( &info
->configfile
, temp_configfile
);
2725 /********************************************************************
2726 * construct_printer_driver_info_2
2727 * fill a printer_info_2 struct
2728 ********************************************************************/
2729 static uint32
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
2731 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2732 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
2734 ZERO_STRUCT(printer
);
2735 ZERO_STRUCT(driver
);
2737 if (!get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0)
2738 return ERROR_INVALID_PRINTER_NAME
;
2740 if (!get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
) != 0)
2741 return ERROR_UNKNOWN_PRINTER_DRIVER
;
2743 fill_printer_driver_info_2(info
, driver
, servername
);
2745 free_a_printer(&printer
,2);
2747 return NT_STATUS_NO_PROBLEMO
;
2750 /********************************************************************
2751 * copy a strings array and convert to UNICODE
2753 * convert an array of ascii string to a UNICODE string
2754 ********************************************************************/
2755 static void init_unistr_array(uint16
**uni_array
, fstring
*char_array
, char *servername
)
2762 DEBUG(6,("init_unistr_array\n"));
2766 if (char_array
== NULL
)
2770 if (!v
) v
= ""; /* hack to handle null lists */
2772 if (strlen(v
) == 0) break;
2773 snprintf(line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
2774 DEBUGADD(6,("%d:%s:%d\n", i
, line
, strlen(line
)));
2775 if((*uni_array
=Realloc(*uni_array
, (j
+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
2776 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2779 j
+= (dos_PutUniCode((char *)(*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
), True
) / sizeof(uint16
) );
2784 (*uni_array
)[j
]=0x0000;
2787 DEBUGADD(6,("last one:done\n"));
2790 /********************************************************************
2791 * construct_printer_info_3
2792 * fill a printer_info_3 struct
2793 ********************************************************************/
2794 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
2796 pstring temp_driverpath
;
2797 pstring temp_datafile
;
2798 pstring temp_configfile
;
2799 pstring temp_helpfile
;
2803 info
->version
=driver
.info_3
->cversion
;
2805 init_unistr( &info
->name
, driver
.info_3
->name
);
2806 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
2808 snprintf(temp_driverpath
, sizeof(temp_driverpath
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
2809 init_unistr( &info
->driverpath
, temp_driverpath
);
2811 snprintf(temp_datafile
, sizeof(temp_datafile
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
2812 init_unistr( &info
->datafile
, temp_datafile
);
2814 snprintf(temp_configfile
, sizeof(temp_configfile
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
2815 init_unistr( &info
->configfile
, temp_configfile
);
2817 snprintf(temp_helpfile
, sizeof(temp_helpfile
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
2818 init_unistr( &info
->helpfile
, temp_helpfile
);
2820 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
2821 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
2823 info
->dependentfiles
=NULL
;
2824 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
2827 /********************************************************************
2828 * construct_printer_info_3
2829 * fill a printer_info_3 struct
2830 ********************************************************************/
2831 static uint32
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
2833 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2834 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
2836 ZERO_STRUCT(driver
);
2838 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
2839 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status
));
2841 return ERROR_INVALID_PRINTER_NAME
;
2843 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
2844 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status
));
2846 free_a_printer(&printer
,2);
2847 return ERROR_UNKNOWN_PRINTER_DRIVER
;
2850 fill_printer_driver_info_3(info
, driver
, servername
);
2852 free_a_printer(&printer
,2);
2854 return NT_STATUS_NO_PROBLEMO
;
2857 /********************************************************************
2858 * construct_printer_info_6
2859 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
2860 ********************************************************************/
2862 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
2864 pstring temp_driverpath
;
2865 pstring temp_datafile
;
2866 pstring temp_configfile
;
2867 pstring temp_helpfile
;
2871 memset(&nullstr
, '\0', sizeof(fstring
));
2873 info
->version
=driver
.info_3
->cversion
;
2875 init_unistr( &info
->name
, driver
.info_3
->name
);
2876 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
2878 snprintf(temp_driverpath
, sizeof(temp_driverpath
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
2879 init_unistr( &info
->driverpath
, temp_driverpath
);
2881 snprintf(temp_datafile
, sizeof(temp_datafile
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
2882 init_unistr( &info
->datafile
, temp_datafile
);
2884 snprintf(temp_configfile
, sizeof(temp_configfile
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
2885 init_unistr( &info
->configfile
, temp_configfile
);
2887 snprintf(temp_helpfile
, sizeof(temp_helpfile
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
2888 init_unistr( &info
->helpfile
, temp_helpfile
);
2890 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
2891 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
2893 info
->dependentfiles
=NULL
;
2894 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
2896 info
->previousdrivernames
=NULL
;
2897 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
2899 info
->driver_date
.low
=0;
2900 info
->driver_date
.high
=0;
2903 info
->driver_version_low
=0;
2904 info
->driver_version_high
=0;
2906 init_unistr( &info
->mfgname
, "");
2907 init_unistr( &info
->oem_url
, "");
2908 init_unistr( &info
->hardware_id
, "");
2909 init_unistr( &info
->provider
, "");
2912 /********************************************************************
2913 * construct_printer_info_6
2914 * fill a printer_info_6 struct
2915 ********************************************************************/
2916 static uint32
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
2918 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2919 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
2921 ZERO_STRUCT(driver
);
2923 status
=get_a_printer(&printer
, 2, lp_servicename(snum
) );
2924 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status
));
2926 return ERROR_INVALID_PRINTER_NAME
;
2928 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
2929 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status
));
2932 * Is this a W2k client ?
2936 free_a_printer(&printer
,2);
2937 return ERROR_UNKNOWN_PRINTER_DRIVER
;
2940 /* Yes - try again with a WinNT driver. */
2942 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
2943 DEBUG(8,("construct_printer_driver_info_6: status: %d\n", status
));
2945 free_a_printer(&printer
,2);
2946 return ERROR_UNKNOWN_PRINTER_DRIVER
;
2950 fill_printer_driver_info_6(info
, driver
, servername
);
2952 free_a_printer(&printer
,2);
2954 return NT_STATUS_NO_PROBLEMO
;
2957 /****************************************************************************
2958 ****************************************************************************/
2960 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
2962 safe_free(info
->dependentfiles
);
2965 /****************************************************************************
2966 ****************************************************************************/
2968 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
2970 safe_free(info
->dependentfiles
);
2974 /****************************************************************************
2975 ****************************************************************************/
2976 static uint32
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
2978 DRIVER_INFO_1
*info
=NULL
;
2981 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
2982 return ERROR_NOT_ENOUGH_MEMORY
;
2984 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
2985 if (status
!= NT_STATUS_NO_PROBLEMO
) {
2990 /* check the required size. */
2991 *needed
+= spoolss_size_printer_driver_info_1(info
);
2993 if (!alloc_buffer_size(buffer
, *needed
)) {
2995 return ERROR_INSUFFICIENT_BUFFER
;
2998 /* fill the buffer with the structures */
2999 new_smb_io_printer_driver_info_1("", buffer
, info
, 0);
3004 if (*needed
> offered
)
3005 return ERROR_INSUFFICIENT_BUFFER
;
3007 return NT_STATUS_NO_PROBLEMO
;
3010 /****************************************************************************
3011 ****************************************************************************/
3012 static uint32
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3014 DRIVER_INFO_2
*info
=NULL
;
3017 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
3018 return ERROR_NOT_ENOUGH_MEMORY
;
3020 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
3021 if (status
!= NT_STATUS_NO_PROBLEMO
) {
3026 /* check the required size. */
3027 *needed
+= spoolss_size_printer_driver_info_2(info
);
3029 if (!alloc_buffer_size(buffer
, *needed
)) {
3031 return ERROR_INSUFFICIENT_BUFFER
;
3034 /* fill the buffer with the structures */
3035 new_smb_io_printer_driver_info_2("", buffer
, info
, 0);
3040 if (*needed
> offered
)
3041 return ERROR_INSUFFICIENT_BUFFER
;
3043 return NT_STATUS_NO_PROBLEMO
;
3046 /****************************************************************************
3047 ****************************************************************************/
3048 static uint32
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3055 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
3056 if (status
!= NT_STATUS_NO_PROBLEMO
) {
3060 /* check the required size. */
3061 *needed
+= spoolss_size_printer_driver_info_3(&info
);
3063 if (!alloc_buffer_size(buffer
, *needed
)) {
3064 free_printer_driver_info_3(&info
);
3065 return ERROR_INSUFFICIENT_BUFFER
;
3068 /* fill the buffer with the structures */
3069 new_smb_io_printer_driver_info_3("", buffer
, &info
, 0);
3071 free_printer_driver_info_3(&info
);
3073 if (*needed
> offered
)
3074 return ERROR_INSUFFICIENT_BUFFER
;
3076 return NT_STATUS_NO_PROBLEMO
;
3079 /****************************************************************************
3080 ****************************************************************************/
3081 static uint32
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
3088 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
3089 if (status
!= NT_STATUS_NO_PROBLEMO
) {
3093 /* check the required size. */
3094 *needed
+= spoolss_size_printer_driver_info_6(&info
);
3096 if (!alloc_buffer_size(buffer
, *needed
)) {
3097 free_printer_driver_info_6(&info
);
3098 return ERROR_INSUFFICIENT_BUFFER
;
3101 /* fill the buffer with the structures */
3102 new_smb_io_printer_driver_info_6("", buffer
, &info
, 0);
3104 free_printer_driver_info_6(&info
);
3106 if (*needed
> offered
)
3107 return ERROR_INSUFFICIENT_BUFFER
;
3109 return NT_STATUS_NO_PROBLEMO
;
3112 /****************************************************************************
3113 ****************************************************************************/
3114 uint32
_spoolss_getprinterdriver2(POLICY_HND
*handle
, const UNISTR2
*uni_arch
, uint32 level
,
3115 uint32 clientmajorversion
, uint32 clientminorversion
,
3116 NEW_BUFFER
*buffer
, uint32 offered
,
3117 uint32
*needed
, uint32
*servermajorversion
, uint32
*serverminorversion
)
3120 fstring architecture
;
3123 DEBUG(4,("_spoolss_getprinterdriver2\n"));
3126 *servermajorversion
=0;
3127 *serverminorversion
=0;
3129 pstrcpy(servername
, global_myname
);
3130 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
3132 if (!get_printer_snum(handle
, &snum
))
3133 return ERROR_INVALID_HANDLE
;
3137 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3139 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3141 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3143 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
3145 return ERROR_INVALID_LEVEL
;
3149 /****************************************************************************
3150 ****************************************************************************/
3151 uint32
_spoolss_startpageprinter(POLICY_HND
*handle
)
3153 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3155 if (OPEN_HANDLE(Printer
)) {
3156 Printer
->page_started
=True
;
3160 DEBUG(3,("Error in startpageprinter printer handle\n"));
3161 return ERROR_INVALID_HANDLE
;
3164 /****************************************************************************
3165 ****************************************************************************/
3166 uint32
_spoolss_endpageprinter(POLICY_HND
*handle
)
3168 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3170 if (!OPEN_HANDLE(Printer
)) {
3171 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle
)));
3172 return ERROR_INVALID_HANDLE
;
3175 Printer
->page_started
=False
;
3177 return NT_STATUS_NO_PROBLEMO
;
3180 /****************************************************************************
3181 Return a user struct for a pipe user.
3182 ****************************************************************************/
3184 static struct current_user
*get_current_user(struct current_user
*user
, pipes_struct
*p
)
3186 if (p
->ntlmssp_auth_validated
) {
3187 memcpy(user
, &p
->pipe_user
, sizeof(struct current_user
));
3189 extern struct current_user current_user
;
3190 memcpy(user
, ¤t_user
, sizeof(struct current_user
));
3196 /********************************************************************
3197 * api_spoolss_getprinter
3198 * called from the spoolss dispatcher
3200 ********************************************************************/
3201 uint32
_spoolss_startdocprinter(POLICY_HND
*handle
, uint32 level
,
3202 pipes_struct
*p
, DOC_INFO
*docinfo
,
3205 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
3209 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3210 struct current_user user
;
3212 if (!OPEN_HANDLE(Printer
)) {
3213 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3214 return ERROR_INVALID_HANDLE
;
3217 get_current_user(&user
, p
);
3220 * a nice thing with NT is it doesn't listen to what you tell it.
3221 * when asked to send _only_ RAW datas, it tries to send datas
3224 * So I add checks like in NT Server ...
3226 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
3227 * there's a bug in NT client-side code, so we'll fix it in the
3228 * server-side code. *nnnnnggggh!*
3231 if (info_1
->p_datatype
!= 0) {
3232 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
3233 if (strcmp(datatype
, "RAW") != 0) {
3235 return ERROR_INVALID_DATATYPE
;
3239 /* get the share number of the printer */
3240 if (!get_printer_snum(handle
, &snum
)) {
3241 return ERROR_INVALID_HANDLE
;
3244 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
3246 Printer
->jobid
= print_job_start(&user
, snum
, jobname
);
3248 /* An error occured in print_job_start() so return an appropriate
3251 if (Printer
->jobid
== -1) {
3252 return map_nt_error_from_unix(errno
);
3255 Printer
->document_started
=True
;
3256 (*jobid
) = Printer
->jobid
;
3258 srv_spoolss_sendnotify(handle
);
3262 /********************************************************************
3263 * api_spoolss_getprinter
3264 * called from the spoolss dispatcher
3266 ********************************************************************/
3267 uint32
_spoolss_enddocprinter(POLICY_HND
*handle
)
3269 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
3271 if (!OPEN_HANDLE(Printer
)) {
3272 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3273 return ERROR_INVALID_HANDLE
;
3276 Printer
->document_started
=False
;
3277 print_job_end(Printer
->jobid
);
3278 /* error codes unhandled so far ... */
3280 srv_spoolss_sendnotify(handle
);
3285 /****************************************************************************
3286 ****************************************************************************/
3287 uint32
_spoolss_writeprinter( POLICY_HND
*handle
,
3290 uint32
*buffer_written
)
3292 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3294 if (!OPEN_HANDLE(Printer
)) {
3295 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle
)));
3296 return ERROR_INVALID_HANDLE
;
3299 (*buffer_written
) = print_job_write(Printer
->jobid
, (char *)buffer
,
3305 /********************************************************************
3306 * api_spoolss_getprinter
3307 * called from the spoolss dispatcher
3309 ********************************************************************/
3310 static uint32
control_printer(POLICY_HND
*handle
, uint32 command
,
3313 struct current_user user
;
3314 int snum
, errcode
= ERROR_INVALID_FUNCTION
;
3315 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3317 get_current_user(&user
, p
);
3319 if (!OPEN_HANDLE(Printer
)) {
3320 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3321 return ERROR_INVALID_HANDLE
;
3324 if (!get_printer_snum(handle
, &snum
))
3325 return ERROR_INVALID_HANDLE
;
3328 case PRINTER_CONTROL_PAUSE
:
3329 if (print_queue_pause(&user
, snum
, &errcode
)) {
3333 case PRINTER_CONTROL_RESUME
:
3334 case PRINTER_CONTROL_UNPAUSE
:
3335 if (print_queue_resume(&user
, snum
, &errcode
)) {
3339 case PRINTER_CONTROL_PURGE
:
3340 if (print_queue_purge(&user
, snum
, &errcode
)) {
3345 return ERROR_INVALID_LEVEL
;
3351 /********************************************************************
3352 * api_spoolss_abortprinter
3353 ********************************************************************/
3355 uint32
_spoolss_abortprinter(POLICY_HND
*handle
, pipes_struct
*p
)
3357 return control_printer(handle
, PRINTER_CONTROL_PURGE
, p
);
3360 /********************************************************************
3361 * called by spoolss_api_setprinter
3362 * when updating a printer description
3363 ********************************************************************/
3364 static uint32
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
3365 const SPOOL_PRINTER_INFO_LEVEL
*info
,
3366 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
3368 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
3369 struct current_user user
;
3373 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3375 if (!OPEN_HANDLE(Printer
) || !get_printer_snum(handle
, &snum
)) {
3376 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n",
3377 OUR_HANDLE(handle
)));
3379 result
= ERROR_INVALID_HANDLE
;
3383 /* NT seems to like setting the security descriptor even though
3384 nothing may have actually changed. This causes annoying
3385 dialog boxes when the user doesn't have permission to change
3386 the security descriptor. */
3388 nt_printing_getsec(Printer
->dev
.handlename
, &old_secdesc_ctr
);
3390 if (DEBUGLEVEL
>= 10) {
3394 acl
= old_secdesc_ctr
->sec
->dacl
;
3395 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
3396 PRINTERNAME(snum
), acl
->num_aces
));
3398 for (i
= 0; i
< acl
->num_aces
; i
++) {
3401 sid_to_string(sid_str
, &acl
->ace
[i
].sid
);
3403 DEBUG(10, ("%s 0x%08x\n", sid_str
,
3404 acl
->ace
[i
].info
.mask
));
3407 acl
= secdesc_ctr
->sec
->dacl
;
3410 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
3411 PRINTERNAME(snum
), acl
->num_aces
));
3413 for (i
= 0; i
< acl
->num_aces
; i
++) {
3416 sid_to_string(sid_str
, &acl
->ace
[i
].sid
);
3418 DEBUG(10, ("%s 0x%08x\n", sid_str
,
3419 acl
->ace
[i
].info
.mask
));
3422 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
3426 new_secdesc_ctr
= sec_desc_merge(secdesc_ctr
, old_secdesc_ctr
);
3428 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
3429 result
= NT_STATUS_NO_PROBLEMO
;
3433 /* Work out which user is performing the operation */
3435 get_current_user(&user
, p
);
3437 /* Check the user has permissions to change the security
3438 descriptor. By experimentation with two NT machines, the user
3439 requires Full Access to the printer to change security
3442 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
3443 result
= ERROR_ACCESS_DENIED
;
3447 result
= nt_printing_setsec(Printer
->dev
.handlename
, new_secdesc_ctr
);
3450 free_sec_desc_buf(&new_secdesc_ctr
);
3451 free_sec_desc_buf(&old_secdesc_ctr
);
3456 /********************************************************************
3457 Do Samba sanity checks on a printer info struct.
3458 this has changed purpose: it now "canonicalises" printer
3459 info from a client rather than just checking it is correct
3460 ********************************************************************/
3462 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
3464 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s portname=%s drivername=%s comment=%s location=%s\n",
3465 info
->servername
, info
->printername
, info
->sharename
, info
->portname
, info
->drivername
, info
->comment
, info
->location
));
3467 /* we force some elements to "correct" values */
3468 slprintf(info
->servername
, sizeof(info
->servername
), "\\\\%s", global_myname
);
3469 slprintf(info
->printername
, sizeof(info
->printername
), "\\\\%s\\%s",
3470 global_myname
, lp_servicename(snum
));
3471 fstrcpy(info
->sharename
, lp_servicename(snum
));
3472 info
->attributes
= PRINTER_ATTRIBUTE_SHARED \
3473 | PRINTER_ATTRIBUTE_LOCAL \
3474 | PRINTER_ATTRIBUTE_RAW_ONLY \
3475 | PRINTER_ATTRIBUTE_QUEUED
;
3480 /****************************************************************************
3481 ****************************************************************************/
3482 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
3484 pid_t local_pid
= sys_getpid();
3485 char *cmd
= lp_addprinter_cmd();
3490 pstring driverlocation
;
3494 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
3495 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
3499 /* build driver path... only 9X architecture is needed for legacy reasons */
3500 slprintf(driverlocation
, sizeof(driverlocation
)-1, "\\\\%s\\print$\\WIN40\\0",
3502 /* change \ to \\ for the shell */
3503 all_string_sub(driverlocation
,"\\","\\\\",sizeof(pstring
));
3505 slprintf(tmp_file
, sizeof(tmp_file
), "%s/smbcmd.%d", path
, local_pid
);
3506 slprintf(command
, sizeof(command
), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3507 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
3508 printer
->info_2
->portname
, printer
->info_2
->drivername
,
3509 printer
->info_2
->location
, driverlocation
);
3512 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
3513 ret
= smbrun(command
, tmp_file
, False
);
3514 DEBUGADD(10,("returned [%d]\n", ret
));
3522 qlines
= file_lines_load(tmp_file
, &numlines
, True
);
3523 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
3524 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file
));
3528 /* Set the portname to what the script says the portname should be. */
3529 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
3530 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
3532 /* Send SIGHUP to process group... is there a better way? */
3537 file_lines_free(qlines
);
3541 /* Return true if two devicemodes are equal */
3543 #define DEVMODE_CHECK_INT(field) \
3544 if (d1->field != d2->field) { \
3545 DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
3546 d1->field, d2->field)); \
3550 static BOOL
nt_devicemode_equal(NT_DEVICEMODE
*d1
, NT_DEVICEMODE
*d2
)
3552 if (!d1
&& !d2
) goto equal
; /* if both are NULL they are equal */
3555 DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
3556 return False
; /* if either is exclusively NULL are not equal */
3559 if (!strequal(d1
->devicename
, d2
->devicename
) ||
3560 !strequal(d1
->formname
, d2
->formname
)) {
3561 DEBUG(10, ("nt_devicemode_equal(): device,form not equal\n"));
3565 DEVMODE_CHECK_INT(specversion
);
3566 DEVMODE_CHECK_INT(driverversion
);
3567 DEVMODE_CHECK_INT(driverextra
);
3568 DEVMODE_CHECK_INT(orientation
);
3569 DEVMODE_CHECK_INT(papersize
);
3570 DEVMODE_CHECK_INT(paperlength
);
3571 DEVMODE_CHECK_INT(paperwidth
);
3572 DEVMODE_CHECK_INT(scale
);
3573 DEVMODE_CHECK_INT(copies
);
3574 DEVMODE_CHECK_INT(defaultsource
);
3575 DEVMODE_CHECK_INT(printquality
);
3576 DEVMODE_CHECK_INT(color
);
3577 DEVMODE_CHECK_INT(duplex
);
3578 DEVMODE_CHECK_INT(yresolution
);
3579 DEVMODE_CHECK_INT(ttoption
);
3580 DEVMODE_CHECK_INT(collate
);
3581 DEVMODE_CHECK_INT(logpixels
);
3583 DEVMODE_CHECK_INT(fields
);
3584 DEVMODE_CHECK_INT(bitsperpel
);
3585 DEVMODE_CHECK_INT(pelswidth
);
3586 DEVMODE_CHECK_INT(pelsheight
);
3587 DEVMODE_CHECK_INT(displayflags
);
3588 DEVMODE_CHECK_INT(displayfrequency
);
3589 DEVMODE_CHECK_INT(icmmethod
);
3590 DEVMODE_CHECK_INT(icmintent
);
3591 DEVMODE_CHECK_INT(mediatype
);
3592 DEVMODE_CHECK_INT(dithertype
);
3593 DEVMODE_CHECK_INT(reserved1
);
3594 DEVMODE_CHECK_INT(reserved2
);
3595 DEVMODE_CHECK_INT(panningwidth
);
3596 DEVMODE_CHECK_INT(panningheight
);
3598 /* compare the private data if it exists */
3599 if (!d1
->driverextra
&& !d2
->driverextra
) goto equal
;
3602 DEVMODE_CHECK_INT(driverextra
);
3604 if (memcmp(d1
->private, d2
->private, d1
->driverextra
)) {
3605 DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
3610 DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
3614 /* Return true if two NT_PRINTER_PARAM structures are equal */
3616 static BOOL
nt_printer_param_equal(NT_PRINTER_PARAM
*p1
,
3617 NT_PRINTER_PARAM
*p2
)
3619 if (!p1
&& !p2
) goto equal
;
3621 if ((!p1
&& p2
) || (p1
&& !p2
)) {
3622 DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
3626 /* Compare lists of printer parameters */
3630 NT_PRINTER_PARAM
*q
= p1
;
3632 /* Find the parameter in the second structure */
3636 if (strequal(p1
->value
, q
->value
)) {
3638 if (p1
->type
!= q
->type
) {
3639 DEBUG(10, ("nt_printer_param_equal():"
3640 "types for %s differ (%d != %d)\n",
3641 p1
->value
, p1
->type
,
3646 if (p1
->data_len
!= q
->data_len
) {
3647 DEBUG(10, ("nt_printer_param_equal():"
3648 "len for %s differs (%d != %d)\n",
3649 p1
->value
, p1
->data_len
,
3654 if (memcmp(p1
->data
, q
->data
, p1
->data_len
) == 0) {
3657 DEBUG(10, ("nt_printer_param_equal():"
3658 "data for %s differs\n", p1
->value
));
3668 DEBUG(10, ("nt_printer_param_equal(): param %s "
3669 "does not exist\n", p1
->value
));
3678 DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
3682 /********************************************************************
3683 * Called by update_printer when trying to work out whether to
3684 * actually update printer info.
3685 ********************************************************************/
3687 #define PI_CHECK_INT(field) \
3688 if (pi1->field != pi2->field) { \
3689 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
3690 pi1->field, pi2->field)); \
3694 #define PI_CHECK_STR(field) \
3695 if (!strequal(pi1->field, pi2->field)) { \
3696 DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
3697 pi1->field, pi2->field)); \
3701 static BOOL
nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL
*p1
,
3702 NT_PRINTER_INFO_LEVEL
*p2
)
3704 NT_PRINTER_INFO_LEVEL_2
*pi1
, *pi2
;
3706 /* Trivial conditions */
3708 if ((!p1
&& !p2
) || (!p1
->info_2
&& !p2
->info_2
)) {
3712 if ((!p1
&& p2
) || (p1
&& !p2
) ||
3713 (!p1
->info_2
&& p2
->info_2
) ||
3714 (p1
->info_2
&& !p2
->info_2
)) {
3715 DEBUG(10, ("nt_printer_info_level_equal(): info levels "
3720 /* Compare two nt_printer_info_level structures. Don't compare
3721 status or cjobs as they seem to have something to do with the
3727 PI_CHECK_INT(attributes
);
3728 PI_CHECK_INT(priority
);
3729 PI_CHECK_INT(default_priority
);
3730 PI_CHECK_INT(starttime
);
3731 PI_CHECK_INT(untiltime
);
3732 PI_CHECK_INT(averageppm
);
3734 /* Yuck - don't check the printername or servername as the
3735 add_a_printer() code plays games with them. You can't
3736 change the printername or the sharename through this interface
3739 PI_CHECK_STR(sharename
);
3740 PI_CHECK_STR(portname
);
3741 PI_CHECK_STR(drivername
);
3742 PI_CHECK_STR(comment
);
3743 PI_CHECK_STR(location
);
3745 if (!nt_devicemode_equal(pi1
->devmode
, pi2
->devmode
)) {
3749 PI_CHECK_STR(sepfile
);
3750 PI_CHECK_STR(printprocessor
);
3751 PI_CHECK_STR(datatype
);
3752 PI_CHECK_STR(parameters
);
3754 if (!nt_printer_param_equal(pi1
->specific
, pi2
->specific
)) {
3758 if (!sec_desc_equal(pi1
->secdesc_buf
->sec
, pi2
->secdesc_buf
->sec
)) {
3762 PI_CHECK_INT(changeid
);
3763 PI_CHECK_INT(c_setprinter
);
3764 PI_CHECK_INT(setuptime
);
3767 DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
3771 /********************************************************************
3772 * called by spoolss_api_setprinter
3773 * when updating a printer description
3774 ********************************************************************/
3776 static uint32
update_printer(POLICY_HND
*handle
, uint32 level
,
3777 const SPOOL_PRINTER_INFO_LEVEL
*info
,
3778 DEVICEMODE
*devmode
)
3781 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
3782 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3785 DEBUG(8,("update_printer\n"));
3787 result
= NT_STATUS_NO_PROBLEMO
;
3790 DEBUG(0,("Send a mail to samba@samba.org\n"));
3791 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3792 result
= ERROR_INVALID_LEVEL
;
3796 if (!OPEN_HANDLE(Printer
)) {
3797 result
= ERROR_INVALID_HANDLE
;
3801 if (!get_printer_snum(handle
, &snum
)) {
3802 result
= ERROR_INVALID_HANDLE
;
3806 if((get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0) ||
3807 (get_a_printer(&old_printer
, 2, lp_servicename(snum
)) != 0)) {
3808 result
= ERROR_INVALID_HANDLE
;
3812 DEBUGADD(8,("Converting info_2 struct\n"));
3815 * convert_printer_info converts the incoming
3816 * info from the client and overwrites the info
3817 * just read from the tdb in the pointer 'printer'.
3820 convert_printer_info(info
, printer
, level
);
3822 if (info
->info_2
->devmode_ptr
!= 0) {
3823 /* we have a valid devmode
3824 convert it and link it*/
3827 * Ensure printer->info_2->devmode is a valid pointer
3828 * as we will be overwriting it in convert_devicemode().
3831 if (printer
->info_2
->devmode
== NULL
)
3832 printer
->info_2
->devmode
= construct_nt_devicemode(printer
->info_2
->printername
);
3834 DEBUGADD(8,("Converting the devicemode struct\n"));
3835 convert_devicemode(devmode
, printer
->info_2
->devmode
);
3838 if (printer
->info_2
->devmode
!= NULL
)
3839 free_nt_devicemode(&printer
->info_2
->devmode
);
3840 printer
->info_2
->devmode
=NULL
;
3843 /* Do sanity check on the requested changes for Samba */
3845 if (!check_printer_ok(printer
->info_2
, snum
)) {
3846 result
= ERROR_INVALID_PARAMETER
;
3850 /* NT likes to call this function even though nothing has actually
3851 changed. Check this so the user doesn't end up with an
3852 annoying permission denied dialog box. */
3854 if (nt_printer_info_level_equal(printer
, old_printer
)) {
3855 DEBUG(3, ("printer info has not changed\n"));
3856 result
= NT_STATUS_NO_PROBLEMO
;
3860 /* Check calling user has permission to update printer description */
3862 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
3863 DEBUG(3, ("printer property change denied by security "
3865 result
= ERROR_ACCESS_DENIED
;
3869 /* Call addprinter hook */
3871 if (*lp_addprinter_cmd() )
3872 if ( !add_printer_hook(printer
) ) {
3873 result
= ERROR_ACCESS_DENIED
;
3877 /* Update printer info */
3879 if (add_a_printer(*printer
, 2)!=0) {
3880 /* I don't really know what to return here !!! */
3881 result
= ERROR_ACCESS_DENIED
;
3886 free_a_printer(&printer
, 2);
3887 free_a_printer(&old_printer
, 2);
3889 srv_spoolss_sendnotify(handle
);
3894 /****************************************************************************
3895 ****************************************************************************/
3896 uint32
_spoolss_setprinter(POLICY_HND
*handle
, uint32 level
,
3897 const SPOOL_PRINTER_INFO_LEVEL
*info
,
3898 DEVMODE_CTR devmode_ctr
,
3899 SEC_DESC_BUF
*secdesc_ctr
,
3900 uint32 command
, pipes_struct
*p
)
3902 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3904 if (!OPEN_HANDLE(Printer
)) {
3905 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3906 return ERROR_INVALID_HANDLE
;
3909 /* check the level */
3912 return control_printer(handle
, command
, p
);
3914 return update_printer(handle
, level
, info
, devmode_ctr
.devmode
);
3916 return update_printer_sec(handle
, level
, info
, p
,
3919 return ERROR_INVALID_LEVEL
;
3923 /****************************************************************************
3924 ****************************************************************************/
3925 uint32
_spoolss_fcpn(POLICY_HND
*handle
)
3927 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
3929 if (!OPEN_HANDLE(Printer
)) {
3930 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle
)));
3931 return ERROR_INVALID_HANDLE
;
3934 if (Printer
->notify
.client_connected
==True
)
3935 if(!srv_spoolss_replycloseprinter(&Printer
->notify
.client_hnd
))
3936 return ERROR_INVALID_HANDLE
;
3938 Printer
->notify
.flags
=0;
3939 Printer
->notify
.options
=0;
3940 Printer
->notify
.localmachine
[0]='\0';
3941 Printer
->notify
.printerlocal
=0;
3942 if (Printer
->notify
.option
)
3943 safe_free(Printer
->notify
.option
->ctr
.type
);
3944 safe_free(Printer
->notify
.option
);
3945 Printer
->notify
.option
=NULL
;
3946 Printer
->notify
.client_connected
=False
;
3948 return NT_STATUS_NO_PROBLEMO
;
3951 /****************************************************************************
3952 ****************************************************************************/
3953 uint32
_spoolss_addjob(POLICY_HND
*handle
, uint32 level
,
3954 NEW_BUFFER
*buffer
, uint32 offered
,
3958 return ERROR_INVALID_PARAMETER
; /* this is what a NT server
3959 returns for AddJob. AddJob
3960 must fail on non-local
3964 /****************************************************************************
3965 ****************************************************************************/
3966 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
3967 int position
, int snum
)
3973 t
=gmtime(&queue
->time
);
3974 snprintf(temp_name
, sizeof(temp_name
), "\\\\%s", global_myname
);
3976 job_info
->jobid
=queue
->job
;
3977 init_unistr(&job_info
->printername
, lp_servicename(snum
));
3978 init_unistr(&job_info
->machinename
, temp_name
);
3979 init_unistr(&job_info
->username
, queue
->user
);
3980 init_unistr(&job_info
->document
, queue
->file
);
3981 init_unistr(&job_info
->datatype
, "RAW");
3982 init_unistr(&job_info
->text_status
, "");
3983 job_info
->status
=nt_printj_status(queue
->status
);
3984 job_info
->priority
=queue
->priority
;
3985 job_info
->position
=position
;
3986 job_info
->totalpages
=0;
3987 job_info
->pagesprinted
=0;
3989 make_systemtime(&job_info
->submitted
, t
);
3992 /****************************************************************************
3993 ****************************************************************************/
3994 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
3995 int position
, int snum
)
3998 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4002 if (get_a_printer(&ntprinter
, 2, lp_servicename(snum
)) !=0 )
4005 t
=gmtime(&queue
->time
);
4006 snprintf(temp_name
, sizeof(temp_name
), "\\\\%s", global_myname
);
4008 job_info
->jobid
=queue
->job
;
4010 snprintf(chaine
, sizeof(chaine
)-1, "\\\\%s\\%s", global_myname
, ntprinter
->info_2
->printername
);
4012 init_unistr(&job_info
->printername
, chaine
);
4014 init_unistr(&job_info
->machinename
, temp_name
);
4015 init_unistr(&job_info
->username
, queue
->user
);
4016 init_unistr(&job_info
->document
, queue
->file
);
4017 init_unistr(&job_info
->notifyname
, queue
->user
);
4018 init_unistr(&job_info
->datatype
, "RAW");
4019 init_unistr(&job_info
->printprocessor
, "winprint");
4020 init_unistr(&job_info
->parameters
, "");
4021 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
4022 init_unistr(&job_info
->text_status
, "");
4024 /* and here the security descriptor */
4026 job_info
->status
=nt_printj_status(queue
->status
);
4027 job_info
->priority
=queue
->priority
;
4028 job_info
->position
=position
;
4029 job_info
->starttime
=0;
4030 job_info
->untiltime
=0;
4031 job_info
->totalpages
=0;
4032 job_info
->size
=queue
->size
;
4033 make_systemtime(&(job_info
->submitted
), t
);
4034 job_info
->timeelapsed
=0;
4035 job_info
->pagesprinted
=0;
4037 if((job_info
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4038 free_a_printer(&ntprinter
, 2);
4042 free_a_printer(&ntprinter
, 2);
4046 /****************************************************************************
4047 Enumjobs at level 1.
4048 ****************************************************************************/
4049 static uint32
enumjobs_level1(print_queue_struct
*queue
, int snum
,
4050 NEW_BUFFER
*buffer
, uint32 offered
,
4051 uint32
*needed
, uint32
*returned
)
4056 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
4060 return ERROR_NOT_ENOUGH_MEMORY
;
4063 for (i
=0; i
<*returned
; i
++)
4064 fill_job_info_1(&info
[i
], &queue
[i
], i
, snum
);
4068 /* check the required size. */
4069 for (i
=0; i
<*returned
; i
++)
4070 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
4072 if (!alloc_buffer_size(buffer
, *needed
)) {
4074 return ERROR_INSUFFICIENT_BUFFER
;
4077 /* fill the buffer with the structures */
4078 for (i
=0; i
<*returned
; i
++)
4079 new_smb_io_job_info_1("", buffer
, &info
[i
], 0);
4084 if (*needed
> offered
) {
4086 return ERROR_INSUFFICIENT_BUFFER
;
4089 return NT_STATUS_NO_PROBLEMO
;
4092 /****************************************************************************
4093 Enumjobs at level 2.
4094 ****************************************************************************/
4095 static uint32
enumjobs_level2(print_queue_struct
*queue
, int snum
,
4096 NEW_BUFFER
*buffer
, uint32 offered
,
4097 uint32
*needed
, uint32
*returned
)
4102 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
4106 return ERROR_NOT_ENOUGH_MEMORY
;
4109 for (i
=0; i
<*returned
; i
++)
4110 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
);
4114 /* check the required size. */
4115 for (i
=0; i
<*returned
; i
++)
4116 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
4118 if (!alloc_buffer_size(buffer
, *needed
)) {
4120 return ERROR_INSUFFICIENT_BUFFER
;
4123 /* fill the buffer with the structures */
4124 for (i
=0; i
<*returned
; i
++)
4125 new_smb_io_job_info_2("", buffer
, &info
[i
], 0);
4128 free_job_info_2(info
);
4130 if (*needed
> offered
) {
4132 return ERROR_INSUFFICIENT_BUFFER
;
4135 return NT_STATUS_NO_PROBLEMO
;
4138 /****************************************************************************
4140 ****************************************************************************/
4141 uint32
_spoolss_enumjobs( POLICY_HND
*handle
, uint32 firstjob
, uint32 numofjobs
, uint32 level
,
4142 NEW_BUFFER
*buffer
, uint32 offered
,
4143 uint32
*needed
, uint32
*returned
)
4146 print_queue_struct
*queue
=NULL
;
4147 print_status_struct prt_status
;
4149 DEBUG(4,("_spoolss_enumjobs\n"));
4151 ZERO_STRUCT(prt_status
);
4156 if (!get_printer_snum(handle
, &snum
))
4157 return ERROR_INVALID_HANDLE
;
4159 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
4160 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
4162 if (*returned
== 0) {
4164 return NT_STATUS_NO_PROBLEMO
;
4169 return enumjobs_level1(queue
, snum
, buffer
, offered
, needed
, returned
);
4171 return enumjobs_level2(queue
, snum
, buffer
, offered
, needed
, returned
);
4175 return ERROR_INVALID_LEVEL
;
4180 /****************************************************************************
4181 ****************************************************************************/
4182 uint32
_spoolss_schedulejob( POLICY_HND
*handle
, uint32 jobid
)
4187 /****************************************************************************
4188 ****************************************************************************/
4189 uint32
_spoolss_setjob(POLICY_HND
*handle
, uint32 jobid
, uint32 level
,
4190 pipes_struct
*p
, JOB_INFO
*ctr
, uint32 command
)
4192 struct current_user user
;
4193 print_status_struct prt_status
;
4194 int snum
, errcode
= ERROR_INVALID_FUNCTION
;
4196 memset(&prt_status
, 0, sizeof(prt_status
));
4198 if (!get_printer_snum(handle
, &snum
)) {
4199 return ERROR_INVALID_HANDLE
;
4202 if (!print_job_exists(jobid
)) {
4203 return ERROR_INVALID_PRINTER_NAME
;
4206 get_current_user(&user
, p
);
4209 case JOB_CONTROL_CANCEL
:
4210 case JOB_CONTROL_DELETE
:
4211 if (print_job_delete(&user
, jobid
, &errcode
)) {
4215 case JOB_CONTROL_PAUSE
:
4216 if (print_job_pause(&user
, jobid
, &errcode
)) {
4220 case JOB_CONTROL_RESTART
:
4221 case JOB_CONTROL_RESUME
:
4222 if (print_job_resume(&user
, jobid
, &errcode
)) {
4227 return ERROR_INVALID_LEVEL
;
4233 /****************************************************************************
4234 Enumerates all printer drivers at level 1.
4235 ****************************************************************************/
4236 static uint32
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4241 fstring
*list
= NULL
;
4243 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4244 DRIVER_INFO_1
*driver_info_1
=NULL
;
4248 #define MAX_VERSION 4
4250 for (version
=0; version
<MAX_VERSION
; version
++) {
4252 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
4253 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
4256 return ERROR_NOT_ENOUGH_MEMORY
;
4259 if((driver_info_1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
4261 return ERROR_NOT_ENOUGH_MEMORY
;
4265 for (i
=0; i
<ndrivers
; i
++) {
4267 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4268 ZERO_STRUCT(driver
);
4269 if ((status
= get_a_printer_driver(&driver
, 3, list
[i
], architecture
, version
)) != 0) {
4273 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
4274 free_a_printer_driver(driver
, 3);
4277 *returned
+=ndrivers
;
4281 /* check the required size. */
4282 for (i
=0; i
<*returned
; i
++) {
4283 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
4284 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
4287 if (!alloc_buffer_size(buffer
, *needed
)) {
4288 safe_free(driver_info_1
);
4289 return ERROR_INSUFFICIENT_BUFFER
;
4292 /* fill the buffer with the form structures */
4293 for (i
=0; i
<*returned
; i
++) {
4294 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
4295 new_smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
4298 safe_free(driver_info_1
);
4300 if (*needed
> offered
) {
4302 return ERROR_INSUFFICIENT_BUFFER
;
4305 return NT_STATUS_NO_PROBLEMO
;
4308 /****************************************************************************
4309 Enumerates all printer drivers at level 2.
4310 ****************************************************************************/
4311 static uint32
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4316 fstring
*list
= NULL
;
4318 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4319 DRIVER_INFO_2
*driver_info_2
=NULL
;
4323 #define MAX_VERSION 4
4325 for (version
=0; version
<MAX_VERSION
; version
++) {
4327 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
4328 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
4331 return ERROR_NOT_ENOUGH_MEMORY
;
4334 if((driver_info_2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
4336 return ERROR_NOT_ENOUGH_MEMORY
;
4340 for (i
=0; i
<ndrivers
; i
++) {
4343 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4344 ZERO_STRUCT(driver
);
4345 if ((status
= get_a_printer_driver(&driver
, 3, list
[i
], architecture
, version
)) != 0) {
4349 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
4350 free_a_printer_driver(driver
, 3);
4353 *returned
+=ndrivers
;
4357 /* check the required size. */
4358 for (i
=0; i
<*returned
; i
++) {
4359 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
4360 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
4363 if (!alloc_buffer_size(buffer
, *needed
)) {
4364 safe_free(driver_info_2
);
4365 return ERROR_INSUFFICIENT_BUFFER
;
4368 /* fill the buffer with the form structures */
4369 for (i
=0; i
<*returned
; i
++) {
4370 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
4371 new_smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
4374 safe_free(driver_info_2
);
4376 if (*needed
> offered
) {
4378 return ERROR_INSUFFICIENT_BUFFER
;
4381 return NT_STATUS_NO_PROBLEMO
;
4384 /****************************************************************************
4385 Enumerates all printer drivers at level 3.
4386 ****************************************************************************/
4387 static uint32
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4392 fstring
*list
= NULL
;
4394 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4395 DRIVER_INFO_3
*driver_info_3
=NULL
;
4399 #define MAX_VERSION 4
4401 for (version
=0; version
<MAX_VERSION
; version
++) {
4403 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
4404 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
4407 return ERROR_NOT_ENOUGH_MEMORY
;
4410 if((driver_info_3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
4412 return ERROR_NOT_ENOUGH_MEMORY
;
4416 for (i
=0; i
<ndrivers
; i
++) {
4419 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
4420 ZERO_STRUCT(driver
);
4421 if ((status
= get_a_printer_driver(&driver
, 3, list
[i
], architecture
, version
)) != 0) {
4425 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
4426 free_a_printer_driver(driver
, 3);
4429 *returned
+=ndrivers
;
4433 /* check the required size. */
4434 for (i
=0; i
<*returned
; i
++) {
4435 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
4436 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
4439 if (!alloc_buffer_size(buffer
, *needed
)) {
4440 safe_free(driver_info_3
);
4441 return ERROR_INSUFFICIENT_BUFFER
;
4444 /* fill the buffer with the driver structures */
4445 for (i
=0; i
<*returned
; i
++) {
4446 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
4447 new_smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
4450 for (i
=0; i
<*returned
; i
++)
4451 safe_free(driver_info_3
[i
].dependentfiles
);
4453 safe_free(driver_info_3
);
4455 if (*needed
> offered
) {
4457 return ERROR_INSUFFICIENT_BUFFER
;
4460 return NT_STATUS_NO_PROBLEMO
;
4463 /****************************************************************************
4464 Enumerates all printer drivers.
4465 ****************************************************************************/
4466 uint32
_spoolss_enumprinterdrivers( UNISTR2
*name
, UNISTR2
*environment
, uint32 level
,
4467 NEW_BUFFER
*buffer
, uint32 offered
,
4468 uint32
*needed
, uint32
*returned
)
4470 fstring
*list
= NULL
;
4472 fstring architecture
;
4474 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
4475 fstrcpy(servername
, global_myname
);
4479 unistr2_to_ascii(architecture
, environment
, sizeof(architecture
)-1);
4483 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
4485 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
4487 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
4491 return ERROR_INVALID_LEVEL
;
4495 /****************************************************************************
4496 ****************************************************************************/
4497 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
4499 form
->flag
=list
->flag
;
4500 init_unistr(&form
->name
, list
->name
);
4501 form
->width
=list
->width
;
4502 form
->length
=list
->length
;
4503 form
->left
=list
->left
;
4504 form
->top
=list
->top
;
4505 form
->right
=list
->right
;
4506 form
->bottom
=list
->bottom
;
4509 /****************************************************************************
4510 ****************************************************************************/
4511 uint32
_new_spoolss_enumforms( POLICY_HND
*handle
, uint32 level
,
4512 NEW_BUFFER
*buffer
, uint32 offered
,
4513 uint32
*needed
, uint32
*numofforms
)
4515 nt_forms_struct
*list
=NULL
;
4520 DEBUG(4,("_new_spoolss_enumforms\n"));
4521 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
4522 DEBUGADD(5,("Info level [%d]\n", level
));
4524 *numofforms
= get_ntforms(&list
);
4525 DEBUGADD(5,("Number of forms [%d]\n", *numofforms
));
4527 if (*numofforms
== 0) return ERROR_NO_MORE_ITEMS
;
4531 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
4533 return ERROR_NOT_ENOUGH_MEMORY
;
4536 /* construct the list of form structures */
4537 for (i
=0; i
<*numofforms
; i
++) {
4538 DEBUGADD(6,("Filling form number [%d]\n",i
));
4539 fill_form_1(&forms_1
[i
], &list
[i
]);
4544 /* check the required size. */
4545 for (i
=0; i
<*numofforms
; i
++) {
4546 DEBUGADD(6,("adding form [%d]'s size\n",i
));
4547 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
4550 *needed
=buffer_size
;
4552 if (!alloc_buffer_size(buffer
, buffer_size
)){
4554 return ERROR_INSUFFICIENT_BUFFER
;
4557 /* fill the buffer with the form structures */
4558 for (i
=0; i
<*numofforms
; i
++) {
4559 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
4560 new_smb_io_form_1("", buffer
, &forms_1
[i
], 0);
4565 if (*needed
> offered
) {
4567 return ERROR_INSUFFICIENT_BUFFER
;
4570 return NT_STATUS_NO_PROBLEMO
;
4574 return ERROR_INVALID_LEVEL
;
4579 /****************************************************************************
4580 ****************************************************************************/
4581 uint32
_spoolss_getform( POLICY_HND
*handle
, uint32 level
, UNISTR2
*uni_formname
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4583 nt_forms_struct
*list
=NULL
;
4589 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
4591 DEBUG(4,("_spoolss_getform\n"));
4592 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
4593 DEBUGADD(5,("Info level [%d]\n", level
));
4595 numofforms
= get_ntforms(&list
);
4596 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
4598 if (numofforms
== 0)
4599 return ERROR_NO_MORE_ITEMS
;
4604 /* Check if the requested name is in the list of form structures */
4605 for (i
=0; i
<numofforms
; i
++) {
4607 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
4609 if (strequal(form_name
, list
[i
].name
)) {
4610 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
4611 fill_form_1(&form_1
, &list
[i
]);
4618 /* check the required size. */
4620 *needed
=spoolss_size_form_1(&form_1
);
4622 if (!alloc_buffer_size(buffer
, buffer_size
)){
4623 return ERROR_INSUFFICIENT_BUFFER
;
4626 if (*needed
> offered
) {
4627 return ERROR_INSUFFICIENT_BUFFER
;
4630 /* fill the buffer with the form structures */
4631 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
4632 new_smb_io_form_1("", buffer
, &form_1
, 0);
4634 return NT_STATUS_NO_PROBLEMO
;
4638 return ERROR_INVALID_LEVEL
;
4642 /****************************************************************************
4643 ****************************************************************************/
4644 static void fill_port_1(PORT_INFO_1
*port
, char *name
)
4646 init_unistr(&port
->port_name
, name
);
4649 /****************************************************************************
4650 ****************************************************************************/
4651 static void fill_port_2(PORT_INFO_2
*port
, char *name
)
4653 init_unistr(&port
->port_name
, name
);
4654 init_unistr(&port
->monitor_name
, "Local Monitor");
4655 init_unistr(&port
->description
, "Local Port");
4656 #define PORT_TYPE_WRITE 1
4657 port
->port_type
=PORT_TYPE_WRITE
;
4661 /****************************************************************************
4663 ****************************************************************************/
4664 static uint32
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4666 PORT_INFO_1
*ports
=NULL
;
4669 if (*lp_enumports_cmd()) {
4670 pid_t local_pid
= sys_getpid();
4671 char *cmd
= lp_enumports_cmd();
4679 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
4680 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
4684 slprintf(tmp_file
, sizeof(tmp_file
), "%s/smbcmd.%d", path
, local_pid
);
4685 slprintf(command
, sizeof(command
), "%s \"%d\"", cmd
, 1);
4688 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
4689 ret
= smbrun(command
, tmp_file
, False
);
4690 DEBUG(10,("Returned [%d]\n", ret
));
4693 /* Is this the best error to return here? */
4694 return ERROR_ACCESS_DENIED
;
4698 qlines
= file_lines_load(tmp_file
, &numlines
,True
);
4699 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4700 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file
));
4704 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
4705 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY
));
4706 file_lines_free(qlines
);
4707 return ERROR_NOT_ENOUGH_MEMORY
;
4710 for (i
=0; i
<numlines
; i
++) {
4711 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
4712 fill_port_1(&ports
[i
], qlines
[i
]);
4715 file_lines_free(qlines
);
4718 *returned
= numlines
;
4721 *returned
= 1; /* Sole Samba port returned. */
4723 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
4724 return ERROR_NOT_ENOUGH_MEMORY
;
4726 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
4728 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
4731 /* check the required size. */
4732 for (i
=0; i
<*returned
; i
++) {
4733 DEBUGADD(6,("adding port [%d]'s size\n", i
));
4734 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
4737 if (!alloc_buffer_size(buffer
, *needed
)) {
4739 return ERROR_INSUFFICIENT_BUFFER
;
4742 /* fill the buffer with the ports structures */
4743 for (i
=0; i
<*returned
; i
++) {
4744 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
4745 new_smb_io_port_1("", buffer
, &ports
[i
], 0);
4750 if (*needed
> offered
) {
4752 return ERROR_INSUFFICIENT_BUFFER
;
4755 return NT_STATUS_NO_PROBLEMO
;
4758 /****************************************************************************
4760 ****************************************************************************/
4762 static uint32
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4764 PORT_INFO_2
*ports
=NULL
;
4767 if (*lp_enumports_cmd()) {
4768 pid_t local_pid
= sys_getpid();
4769 char *cmd
= lp_enumports_cmd();
4777 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
4778 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
4782 slprintf(tmp_file
, sizeof(tmp_file
), "%s/smbcmd.%d", path
, local_pid
);
4783 slprintf(command
, sizeof(command
), "%s \"%d\"", cmd
, 2);
4786 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
4787 ret
= smbrun(command
, tmp_file
, False
);
4788 DEBUGADD(10,("returned [%d]\n", ret
));
4791 /* Is this the best error to return here? */
4792 return ERROR_ACCESS_DENIED
;
4796 qlines
= file_lines_load(tmp_file
, &numlines
,True
);
4797 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
4798 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file
));
4802 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
4803 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY
));
4804 file_lines_free(qlines
);
4805 return ERROR_NOT_ENOUGH_MEMORY
;
4808 for (i
=0; i
<numlines
; i
++) {
4809 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
4810 fill_port_2(&(ports
[i
]), qlines
[i
]);
4813 file_lines_free(qlines
);
4816 *returned
= numlines
;
4822 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
4823 return ERROR_NOT_ENOUGH_MEMORY
;
4825 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
4827 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
4830 /* check the required size. */
4831 for (i
=0; i
<*returned
; i
++) {
4832 DEBUGADD(6,("adding port [%d]'s size\n", i
));
4833 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
4836 if (!alloc_buffer_size(buffer
, *needed
)) {
4838 return ERROR_INSUFFICIENT_BUFFER
;
4841 /* fill the buffer with the ports structures */
4842 for (i
=0; i
<*returned
; i
++) {
4843 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
4844 new_smb_io_port_2("", buffer
, &ports
[i
], 0);
4849 if (*needed
> offered
) {
4851 return ERROR_INSUFFICIENT_BUFFER
;
4854 return NT_STATUS_NO_PROBLEMO
;
4857 /****************************************************************************
4859 ****************************************************************************/
4860 uint32
_spoolss_enumports( UNISTR2
*name
, uint32 level
,
4861 NEW_BUFFER
*buffer
, uint32 offered
,
4862 uint32
*needed
, uint32
*returned
)
4864 DEBUG(4,("_spoolss_enumports\n"));
4871 return enumports_level_1(buffer
, offered
, needed
, returned
);
4873 return enumports_level_2(buffer
, offered
, needed
, returned
);
4875 return ERROR_INVALID_LEVEL
;
4879 /****************************************************************************
4880 ****************************************************************************/
4881 static uint32
spoolss_addprinterex_level_2( const UNISTR2
*uni_srv_name
,
4882 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4883 uint32 unk0
, uint32 unk1
, uint32 unk2
, uint32 unk3
,
4884 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
4887 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4891 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
4892 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4893 return ERROR_NOT_ENOUGH_MEMORY
;
4896 ZERO_STRUCTP(printer
);
4898 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4899 convert_printer_info(info
, printer
, 2);
4901 if (*lp_addprinter_cmd() )
4902 if ( !add_printer_hook(printer
) ) {
4903 free_a_printer(&printer
,2);
4904 return ERROR_ACCESS_DENIED
;
4907 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname
,
4908 printer
->info_2
->sharename
);
4910 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
4911 free_a_printer(&printer
,2);
4912 return ERROR_ACCESS_DENIED
;
4915 /* you must be a printer admin to add a new printer */
4916 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
4917 free_a_printer(&printer
,2);
4918 return ERROR_ACCESS_DENIED
;
4922 * Do sanity check on the requested changes for Samba.
4925 if (!check_printer_ok(printer
->info_2
, snum
)) {
4926 free_a_printer(&printer
,2);
4927 return ERROR_INVALID_PARAMETER
;
4930 /* write the ASCII on disk */
4931 if (add_a_printer(*printer
, 2) != 0) {
4932 free_a_printer(&printer
,2);
4933 return ERROR_ACCESS_DENIED
;
4936 if (!open_printer_hnd(handle
, name
)) {
4937 /* Handle open failed - remove addition. */
4938 del_a_printer(printer
->info_2
->sharename
);
4939 free_a_printer(&printer
,2);
4940 return ERROR_ACCESS_DENIED
;
4943 free_a_printer(&printer
,2);
4945 srv_spoolss_sendnotify(handle
);
4947 return NT_STATUS_NO_PROBLEMO
;
4950 /****************************************************************************
4951 ****************************************************************************/
4952 uint32
_spoolss_addprinterex( const UNISTR2
*uni_srv_name
, uint32 level
,
4953 const SPOOL_PRINTER_INFO_LEVEL
*info
,
4954 uint32 unk0
, uint32 unk1
, uint32 unk2
, uint32 unk3
,
4955 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
4960 /* we don't handle yet */
4961 /* but I know what to do ... */
4962 return ERROR_INVALID_LEVEL
;
4964 return spoolss_addprinterex_level_2(uni_srv_name
, info
,
4965 unk0
, unk1
, unk2
, unk3
,
4966 user_switch
, user
, handle
);
4968 return ERROR_INVALID_LEVEL
;
4972 /****************************************************************************
4973 ****************************************************************************/
4974 uint32
_spoolss_addprinterdriver(pipes_struct
*p
, const UNISTR2
*server_name
,
4975 uint32 level
, const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
)
4977 uint32 err
= NT_STATUS_NO_PROBLEMO
;
4978 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4979 struct current_user user
;
4981 ZERO_STRUCT(driver
);
4983 get_current_user(&user
, p
);
4985 convert_printer_driver_info(info
, &driver
, level
);
4987 DEBUG(5,("Cleaning driver's information\n"));
4988 if ((err
= clean_up_driver_struct(driver
, level
, &user
)) != NT_STATUS_NO_PROBLEMO
)
4991 DEBUG(5,("Moving driver to final destination\n"));
4992 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
4994 err
= ERROR_ACCESS_DENIED
;
4998 if (add_a_printer_driver(driver
, level
)!=0) {
4999 err
= ERROR_ACCESS_DENIED
;
5004 free_a_printer_driver(driver
, level
);
5008 /****************************************************************************
5009 ****************************************************************************/
5010 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
5012 init_unistr(&info
->name
, name
);
5015 /****************************************************************************
5016 ****************************************************************************/
5017 static uint32
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5021 pstring short_archi
;
5022 DRIVER_DIRECTORY_1
*info
=NULL
;
5024 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
5026 if (get_short_archi(short_archi
, long_archi
)==FALSE
)
5027 return ERROR_INVALID_ENVIRONMENT
;
5029 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
5030 return ERROR_NOT_ENOUGH_MEMORY
;
5032 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", global_myname
, short_archi
);
5034 DEBUG(4,("printer driver directory: [%s]\n", path
));
5036 fill_driverdir_1(info
, path
);
5038 *needed
+= spoolss_size_driverdir_info_1(info
);
5040 if (!alloc_buffer_size(buffer
, *needed
)) {
5042 return ERROR_INSUFFICIENT_BUFFER
;
5045 new_smb_io_driverdir_1("", buffer
, info
, 0);
5049 if (*needed
> offered
)
5050 return ERROR_INSUFFICIENT_BUFFER
;
5052 return NT_STATUS_NO_PROBLEMO
;
5055 /****************************************************************************
5056 ****************************************************************************/
5057 uint32
_spoolss_getprinterdriverdirectory(UNISTR2
*name
, UNISTR2
*uni_environment
, uint32 level
,
5058 NEW_BUFFER
*buffer
, uint32 offered
,
5061 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
5067 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
5069 return ERROR_INVALID_LEVEL
;
5073 /****************************************************************************
5074 ****************************************************************************/
5075 uint32
_spoolss_enumprinterdata(POLICY_HND
*handle
, uint32 idx
,
5076 uint32 in_value_len
, uint32 in_data_len
,
5077 uint32
*out_max_value_len
, uint16
**out_value
, uint32
*out_value_len
,
5079 uint32
*out_max_data_len
, uint8
**data_out
, uint32
*out_data_len
)
5081 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5086 uint32 biggest_valuesize
;
5087 uint32 biggest_datasize
;
5089 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
5094 ZERO_STRUCT(printer
);
5096 *out_max_value_len
=0;
5102 *out_max_data_len
=0;
5106 DEBUG(5,("spoolss_enumprinterdata\n"));
5108 if (!OPEN_HANDLE(Printer
)) {
5109 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5110 return ERROR_INVALID_HANDLE
;
5113 if (!get_printer_snum(handle
, &snum
))
5114 return ERROR_INVALID_HANDLE
;
5116 if (get_a_printer(&printer
, 2, lp_servicename(snum
)) != 0)
5117 return ERROR_INVALID_HANDLE
;
5120 * The NT machine wants to know the biggest size of value and data
5122 * cf: MSDN EnumPrinterData remark section
5124 if ( (in_value_len
==0) && (in_data_len
==0) ) {
5125 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
5129 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS
5130 * if this parameter size doesn't exist.
5131 * Ok - my opinion here is that the client is not asking for the greatest
5132 * possible size of all the parameters, but is asking specifically for the size needed
5133 * for this specific parameter. In that case we can remove the loop below and
5134 * simplify this lookup code considerably. JF - comments welcome. JRA.
5137 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
5139 free_a_printer(&printer
, 2);
5140 return ERROR_NO_MORE_ITEMS
;
5148 biggest_valuesize
=0;
5151 while (get_specific_param_by_index(*printer
, 2, param_index
, value
, &data
, &type
, &data_len
)) {
5152 if (strlen(value
) > biggest_valuesize
) biggest_valuesize
=strlen(value
);
5153 if (data_len
> biggest_datasize
) biggest_datasize
=data_len
;
5155 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
, biggest_datasize
));
5163 * I think this is correct, it doesn't break APW and
5164 * allows Gerald's Win32 test programs to work correctly,
5165 * but may need altering.... JRA.
5168 if (param_index
== 0) {
5169 /* No parameters found. */
5170 free_a_printer(&printer
, 2);
5171 return ERROR_NO_MORE_ITEMS
;
5174 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
5175 *out_value_len
=2*(1+biggest_valuesize
);
5176 *out_data_len
=biggest_datasize
;
5178 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
5180 free_a_printer(&printer
, 2);
5181 return NT_STATUS_NO_PROBLEMO
;
5185 * the value len is wrong in NT sp3
5186 * that's the number of bytes not the number of unicode chars
5189 if (!get_specific_param_by_index(*printer
, 2, idx
, value
, &data
, &type
, &data_len
)) {
5191 free_a_printer(&printer
, 2);
5192 return ERROR_NO_MORE_ITEMS
;
5195 free_a_printer(&printer
, 2);
5199 * - counted in bytes in the request
5200 * - counted in UNICODE chars in the max reply
5201 * - counted in bytes in the real size
5203 * take a pause *before* coding not *during* coding
5206 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
5207 if((*out_value
=(uint16
*)malloc(in_value_len
*sizeof(uint8
))) == NULL
) {
5209 return ERROR_NOT_ENOUGH_MEMORY
;
5212 ZERO_STRUCTP(*out_value
);
5213 *out_value_len
= (uint32
)dos_PutUniCode((char *)*out_value
, value
, in_value_len
, True
);
5217 /* the data is counted in bytes */
5218 *out_max_data_len
=in_data_len
;
5219 if((*data_out
=(uint8
*)malloc(in_data_len
*sizeof(uint8
))) == NULL
) {
5221 return ERROR_NOT_ENOUGH_MEMORY
;
5224 memset(*data_out
,'\0',in_data_len
);
5225 memcpy(*data_out
, data
, (size_t)data_len
);
5226 *out_data_len
=data_len
;
5230 return NT_STATUS_NO_PROBLEMO
;
5233 /****************************************************************************
5234 ****************************************************************************/
5235 uint32
_spoolss_setprinterdata( POLICY_HND
*handle
,
5236 const UNISTR2
*value
,
5241 uint32 numeric_data
)
5243 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5244 NT_PRINTER_PARAM
*param
= NULL
, old_param
;
5246 uint32 status
= 0x0;
5247 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
5249 DEBUG(5,("spoolss_setprinterdata\n"));
5251 if (!OPEN_HANDLE(Printer
)) {
5252 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5253 return ERROR_INVALID_HANDLE
;
5256 if (!get_printer_snum(handle
, &snum
))
5257 return ERROR_INVALID_HANDLE
;
5259 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
5261 return ERROR_INVALID_NAME
;
5263 convert_specific_param(¶m
, value
, type
, data
, real_len
);
5265 /* Check if we are making any changes or not. Return true if
5266 nothing is actually changing. */
5268 ZERO_STRUCT(old_param
);
5270 if (get_specific_param(*printer
, 2, param
->value
, &old_param
.data
,
5271 &old_param
.type
, (unsigned int *)&old_param
.data_len
)) {
5273 if (param
->type
== old_param
.type
&&
5274 param
->data_len
== old_param
.data_len
&&
5275 memcmp(param
->data
, old_param
.data
,
5276 old_param
.data_len
) == 0) {
5278 DEBUG(3, ("setprinterdata hasn't changed\n"));
5279 status
= NT_STATUS_NO_PROBLEMO
;
5286 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5287 DEBUG(3, ("security descriptor change denied by existing "
5288 "security descriptor\n"));
5289 status
= ERROR_ACCESS_DENIED
;
5293 unlink_specific_param_if_exist(printer
->info_2
, param
);
5295 add_a_specific_param(printer
->info_2
, ¶m
);
5296 status
= mod_a_printer(*printer
, 2);
5299 free_a_printer(&printer
, 2);
5301 free_nt_printer_param(¶m
);
5302 safe_free(old_param
.data
);
5307 /****************************************************************************
5308 ****************************************************************************/
5309 uint32
_spoolss_deleteprinterdata( POLICY_HND
*handle
, const UNISTR2
*value
)
5311 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5312 NT_PRINTER_PARAM param
;
5314 uint32 status
= 0x0;
5315 Printer_entry
*Printer
=find_printer_index_by_hnd(handle
);
5317 DEBUG(5,("spoolss_deleteprinterdata\n"));
5319 if (!OPEN_HANDLE(Printer
)) {
5320 DEBUG(0,("_spoolss_deleteprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5321 return ERROR_INVALID_HANDLE
;
5324 if (!get_printer_snum(handle
, &snum
))
5325 return ERROR_INVALID_HANDLE
;
5327 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5328 DEBUG(3, ("_spoolss_deleteprinterdata: security descriptor change denied by existing "
5329 "security descriptor\n"));
5330 return ERROR_ACCESS_DENIED
;
5333 status
= get_a_printer(&printer
, 2, lp_servicename(snum
));
5335 return ERROR_INVALID_NAME
;
5337 ZERO_STRUCTP(¶m
);
5338 unistr2_to_ascii(param
.value
, value
, sizeof(param
.value
)-1);
5340 if(!unlink_specific_param_if_exist(printer
->info_2
, ¶m
))
5341 status
= ERROR_INVALID_PARAMETER
;
5343 status
= mod_a_printer(*printer
, 2);
5345 free_a_printer(&printer
, 2);
5349 /****************************************************************************
5350 ****************************************************************************/
5351 uint32
_spoolss_addform( POLICY_HND
*handle
,
5356 nt_forms_struct
*list
=NULL
;
5357 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
5359 DEBUG(5,("spoolss_addform\n"));
5361 if (!OPEN_HANDLE(Printer
)) {
5362 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5363 return ERROR_INVALID_HANDLE
;
5366 count
=get_ntforms(&list
);
5367 if(!add_a_form(&list
, form
, &count
))
5368 return ERROR_NOT_ENOUGH_MEMORY
;
5369 write_ntforms(&list
, count
);
5376 /****************************************************************************
5377 ****************************************************************************/
5378 uint32
_spoolss_deleteform( POLICY_HND
*handle
, UNISTR2
*form_name
)
5382 nt_forms_struct
*list
=NULL
;
5383 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
5385 DEBUG(5,("spoolss_deleteform\n"));
5387 if (!OPEN_HANDLE(Printer
)) {
5388 DEBUG(0,("_spoolss_deleteform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5389 return ERROR_INVALID_HANDLE
;
5392 count
= get_ntforms(&list
);
5393 if(!delete_a_form(&list
, form_name
, &count
, &ret
))
5394 return ERROR_INVALID_PARAMETER
;
5401 /****************************************************************************
5402 ****************************************************************************/
5403 uint32
_spoolss_setform( POLICY_HND
*handle
,
5404 const UNISTR2
*uni_name
,
5409 nt_forms_struct
*list
=NULL
;
5410 Printer_entry
*Printer
= find_printer_index_by_hnd(handle
);
5412 DEBUG(5,("spoolss_setform\n"));
5414 if (!OPEN_HANDLE(Printer
)) {
5415 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle
)));
5416 return ERROR_INVALID_HANDLE
;
5418 count
=get_ntforms(&list
);
5419 update_a_form(&list
, form
, count
);
5420 write_ntforms(&list
, count
);
5427 /****************************************************************************
5428 enumprintprocessors level 1.
5429 ****************************************************************************/
5430 static uint32
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5432 PRINTPROCESSOR_1
*info_1
=NULL
;
5434 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
5435 return ERROR_NOT_ENOUGH_MEMORY
;
5439 init_unistr(&info_1
->name
, "winprint");
5441 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
5443 if (!alloc_buffer_size(buffer
, *needed
))
5444 return ERROR_INSUFFICIENT_BUFFER
;
5446 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
5450 if (*needed
> offered
) {
5452 return ERROR_INSUFFICIENT_BUFFER
;
5455 return NT_STATUS_NO_PROBLEMO
;
5458 /****************************************************************************
5459 ****************************************************************************/
5460 uint32
_spoolss_enumprintprocessors(UNISTR2
*name
, UNISTR2
*environment
, uint32 level
,
5461 NEW_BUFFER
*buffer
, uint32 offered
,
5462 uint32
*needed
, uint32
*returned
)
5464 DEBUG(5,("spoolss_enumprintprocessors\n"));
5467 * Enumerate the print processors ...
5469 * Just reply with "winprint", to keep NT happy
5470 * and I can use my nice printer checker.
5478 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
5480 return ERROR_INVALID_LEVEL
;
5484 /****************************************************************************
5485 enumprintprocdatatypes level 1.
5486 ****************************************************************************/
5487 static uint32
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5489 PRINTPROCDATATYPE_1
*info_1
=NULL
;
5491 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
5492 return ERROR_NOT_ENOUGH_MEMORY
;
5496 init_unistr(&info_1
->name
, "RAW");
5498 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
5500 if (!alloc_buffer_size(buffer
, *needed
))
5501 return ERROR_INSUFFICIENT_BUFFER
;
5503 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
5507 if (*needed
> offered
) {
5509 return ERROR_INSUFFICIENT_BUFFER
;
5512 return NT_STATUS_NO_PROBLEMO
;
5515 /****************************************************************************
5516 ****************************************************************************/
5517 uint32
_spoolss_enumprintprocdatatypes(UNISTR2
*name
, UNISTR2
*processor
, uint32 level
,
5518 NEW_BUFFER
*buffer
, uint32 offered
,
5519 uint32
*needed
, uint32
*returned
)
5521 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
5528 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
5530 return ERROR_INVALID_LEVEL
;
5534 /****************************************************************************
5535 enumprintmonitors level 1.
5536 ****************************************************************************/
5537 static uint32
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5539 PRINTMONITOR_1
*info_1
=NULL
;
5541 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
5542 return ERROR_NOT_ENOUGH_MEMORY
;
5546 init_unistr(&info_1
->name
, "Local Port");
5548 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
5550 if (!alloc_buffer_size(buffer
, *needed
))
5551 return ERROR_INSUFFICIENT_BUFFER
;
5553 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
5557 if (*needed
> offered
) {
5559 return ERROR_INSUFFICIENT_BUFFER
;
5562 return NT_STATUS_NO_PROBLEMO
;
5565 /****************************************************************************
5566 enumprintmonitors level 2.
5567 ****************************************************************************/
5568 static uint32
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
5570 PRINTMONITOR_2
*info_2
=NULL
;
5572 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
5573 return ERROR_NOT_ENOUGH_MEMORY
;
5577 init_unistr(&info_2
->name
, "Local Port");
5578 init_unistr(&info_2
->environment
, "Windows NT X86");
5579 init_unistr(&info_2
->dll_name
, "localmon.dll");
5581 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
5583 if (!alloc_buffer_size(buffer
, *needed
))
5584 return ERROR_INSUFFICIENT_BUFFER
;
5586 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
5590 if (*needed
> offered
) {
5592 return ERROR_INSUFFICIENT_BUFFER
;
5595 return NT_STATUS_NO_PROBLEMO
;
5598 /****************************************************************************
5599 ****************************************************************************/
5600 uint32
_spoolss_enumprintmonitors(UNISTR2
*name
,uint32 level
,
5601 NEW_BUFFER
*buffer
, uint32 offered
,
5602 uint32
*needed
, uint32
*returned
)
5604 DEBUG(5,("spoolss_enumprintmonitors\n"));
5607 * Enumerate the print monitors ...
5609 * Just reply with "Local Port", to keep NT happy
5610 * and I can use my nice printer checker.
5618 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
5620 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
5622 return ERROR_INVALID_LEVEL
;
5626 /****************************************************************************
5627 ****************************************************************************/
5628 static uint32
getjob_level_1(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5632 JOB_INFO_1
*info_1
=NULL
;
5634 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
5636 if (info_1
== NULL
) {
5638 return ERROR_NOT_ENOUGH_MEMORY
;
5641 for (i
=0; i
<count
&& found
==False
; i
++) {
5642 if (queue
[i
].job
==(int)jobid
)
5649 /* I shoud reply something else ... I can't find the good one */
5650 return NT_STATUS_NO_PROBLEMO
;
5653 fill_job_info_1(info_1
, &(queue
[i
-1]), i
, snum
);
5657 *needed
+= spoolss_size_job_info_1(info_1
);
5659 if (!alloc_buffer_size(buffer
, *needed
)) {
5661 return ERROR_INSUFFICIENT_BUFFER
;
5664 new_smb_io_job_info_1("", buffer
, info_1
, 0);
5668 if (*needed
> offered
)
5669 return ERROR_INSUFFICIENT_BUFFER
;
5671 return NT_STATUS_NO_PROBLEMO
;
5675 /****************************************************************************
5676 ****************************************************************************/
5677 static uint32
getjob_level_2(print_queue_struct
*queue
, int count
, int snum
, uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5682 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
5684 ZERO_STRUCTP(info_2
);
5686 if (info_2
== NULL
) {
5688 return ERROR_NOT_ENOUGH_MEMORY
;
5691 for (i
=0; i
<count
&& found
==False
; i
++) {
5692 if (queue
[i
].job
==(int)jobid
)
5699 /* I shoud reply something else ... I can't find the good one */
5700 return NT_STATUS_NO_PROBLEMO
;
5703 fill_job_info_2(info_2
, &(queue
[i
-1]), i
, snum
);
5707 *needed
+= spoolss_size_job_info_2(info_2
);
5709 if (!alloc_buffer_size(buffer
, *needed
)) {
5711 return ERROR_INSUFFICIENT_BUFFER
;
5714 new_smb_io_job_info_2("", buffer
, info_2
, 0);
5716 free_job_info_2(info_2
);
5718 if (*needed
> offered
)
5719 return ERROR_INSUFFICIENT_BUFFER
;
5721 return NT_STATUS_NO_PROBLEMO
;
5724 /****************************************************************************
5725 ****************************************************************************/
5726 uint32
_spoolss_getjob( POLICY_HND
*handle
, uint32 jobid
, uint32 level
,
5727 NEW_BUFFER
*buffer
, uint32 offered
,
5732 print_queue_struct
*queue
=NULL
;
5733 print_status_struct prt_status
;
5735 DEBUG(5,("spoolss_getjob\n"));
5737 memset(&prt_status
, 0, sizeof(prt_status
));
5741 if (!get_printer_snum(handle
, &snum
))
5742 return ERROR_INVALID_HANDLE
;
5744 count
= print_queue_status(snum
, &queue
, &prt_status
);
5746 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
5747 count
, prt_status
.status
, prt_status
.message
));
5751 return getjob_level_1(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
5753 return getjob_level_2(queue
, count
, snum
, jobid
, buffer
, offered
, needed
);
5756 return ERROR_INVALID_LEVEL
;