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.
28 extern int DEBUGLEVEL;
29 extern pstring global_myname;
31 #ifndef MAX_OPEN_PRINTER_EXS
32 #define MAX_OPEN_PRINTER_EXS 50
35 #define PRINTER_HANDLE_IS_PRINTER 0
36 #define PRINTER_HANDLE_IS_PRINTSERVER 1
38 /* structure to store the printer handles */
39 /* and a reference to what it's pointing to */
40 /* and the notify info asked about */
41 /* that's the central struct */
42 typedef struct _Printer{
47 BOOL document_started;
49 int jobid; /* jobid in printing backend */
50 POLICY_HND printer_hnd;
54 fstring printerservername;
63 SPOOL_NOTIFY_OPTION *option;
71 typedef struct _counter_printer_0 {
79 static ubi_dlList Printer_list;
80 static ubi_dlList counter_list;
83 #define OPEN_HANDLE(pnum) ((pnum!=NULL) && (pnum->open!=False) && (IVAL(pnum->printer_hnd.data,16)==(uint32)sys_getpid()))
84 #define OUR_HANDLE(pnum) ((pnum==NULL)?"NULL":(IVAL(pnum->data,16)==sys_getpid()?"OURS":"OTHER"))
86 /* translate between internal status numbers and NT status numbers */
87 static int nt_printj_status(int v)
91 return PRINTER_STATUS_PAUSED;
100 static int nt_printq_status(int v)
104 return PRINTER_STATUS_ERROR;
113 /****************************************************************************
114 initialise printer handle states...
115 ****************************************************************************/
116 void init_printer_hnd(void)
118 ubi_dlInitList(&Printer_list);
119 ubi_dlInitList(&counter_list);
122 /****************************************************************************
123 create a unique printer handle
124 ****************************************************************************/
125 static void create_printer_hnd(POLICY_HND *hnd)
127 static uint32 prt_hnd_low = 0;
128 static uint32 prt_hnd_high = 0;
130 if (hnd == NULL) return;
132 /* i severely doubt that prt_hnd_high will ever be non-zero... */
134 if (prt_hnd_low == 0) prt_hnd_high++;
136 SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
137 SIVAL(hnd->data, 4 , prt_hnd_low ); /* second bit is incrementing */
138 SIVAL(hnd->data, 8 , prt_hnd_high); /* second bit is incrementing */
139 SIVAL(hnd->data, 12, time(NULL)); /* something random */
140 SIVAL(hnd->data, 16, sys_getpid()); /* something more random */
143 /****************************************************************************
144 find printer index by handle
145 ****************************************************************************/
146 static Printer_entry *find_printer_index_by_hnd(const POLICY_HND *hnd)
148 Printer_entry *find_printer;
150 find_printer = (Printer_entry *)ubi_dlFirst(&Printer_list);
152 for(; find_printer; find_printer = (Printer_entry *)ubi_dlNext(find_printer)) {
154 if (memcmp(&(find_printer->printer_hnd), hnd, sizeof(*hnd)) == 0) {
155 DEBUG(4,("Found printer handle \n"));
156 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
161 DEBUG(3,("Whoops, Printer handle not found: "));
162 /*dump_data(4, hnd->data, sizeof(hnd->data));*/
166 /****************************************************************************
168 ****************************************************************************/
169 static void clear_handle(POLICY_HND *hnd)
174 /****************************************************************************
175 close printer index by handle
176 ****************************************************************************/
177 static BOOL close_printer_handle(POLICY_HND *hnd)
179 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
181 if (!OPEN_HANDLE(Printer)) {
182 DEBUG(0,("close_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
187 Printer->notify.flags=0;
188 Printer->notify.options=0;
189 Printer->notify.localmachine[0]='\0';
190 Printer->notify.printerlocal=0;
191 safe_free(Printer->notify.option);
192 Printer->notify.option=NULL;
196 ubi_dlRemThis(&Printer_list, Printer);
203 /****************************************************************************
204 delete a printer given a handle
205 ****************************************************************************/
206 static BOOL delete_printer_handle(POLICY_HND *hnd)
208 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
210 if (!OPEN_HANDLE(Printer)) {
211 DEBUG(0,("delete_printer_handle: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
215 if (del_a_printer(Printer->dev.handlename) != 0) {
216 DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
220 if (*lp_deleteprinter_cmd()) {
222 pid_t local_pid = sys_getpid();
223 char *cmd = lp_deleteprinter_cmd();
230 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
231 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
235 /* Printer->dev.handlename equals portname equals sharename */
236 slprintf(command, sizeof(command), "%s \"%s\"", cmd,
237 Printer->dev.handlename);
238 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
241 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
242 ret = smbrun(command, tmp_file, False);
247 DEBUGADD(10,("returned [%d]\n", ret));
248 DEBUGADD(10,("Unlinking output file [%s]\n", tmp_file));
251 if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
252 lp_remove_service( i );
262 /****************************************************************************
263 return the snum of a printer corresponding to an handle
264 ****************************************************************************/
265 static BOOL get_printer_snum(POLICY_HND *hnd, int *number)
267 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
269 if (!OPEN_HANDLE(Printer)) {
270 DEBUG(0,("get_printer_snum: Invalid handle (%s)\n", OUR_HANDLE(hnd)));
274 switch (Printer->printer_type) {
275 case PRINTER_HANDLE_IS_PRINTER:
276 DEBUG(4,("short name:%s\n", Printer->dev.handlename));
277 *number = print_queue_snum(Printer->dev.handlename);
278 return (*number != -1);
279 case PRINTER_HANDLE_IS_PRINTSERVER:
288 /****************************************************************************
289 set printer handle type.
290 ****************************************************************************/
291 static BOOL set_printer_hnd_accesstype(POLICY_HND *hnd, uint32 access_required)
293 Printer_entry *Printer = find_printer_index_by_hnd(hnd);
295 if (!OPEN_HANDLE(Printer)) {
296 DEBUG(0,("set_printer_hnd_accesstype: Invalid handle (%s)", OUR_HANDLE(hnd)));
300 DEBUG(4,("Setting printer access=%x\n", access_required));
301 Printer->access = access_required;
305 /****************************************************************************
306 Set printer handle type.
307 Check if it's \\server or \\server\printer
308 ****************************************************************************/
310 static BOOL set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
312 DEBUG(3,("Setting printer type=%s\n", handlename));
314 if ( strlen(handlename) < 3 ) {
315 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
319 /* it's a print server */
320 if (!strchr(handlename+2, '\\')) {
321 DEBUGADD(4,("Printer is a print server\n"));
322 Printer->printer_type = PRINTER_HANDLE_IS_PRINTSERVER;
327 DEBUGADD(4,("Printer is a printer\n"));
328 Printer->printer_type = PRINTER_HANDLE_IS_PRINTER;
335 /****************************************************************************
336 Set printer handle name.
337 ****************************************************************************/
339 static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename)
341 NT_PRINTER_INFO_LEVEL *printer = NULL;
343 int n_services=lp_numservices();
347 DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename)));
349 if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) {
350 ZERO_STRUCT(Printer->dev.printerservername);
351 strncpy(Printer->dev.printerservername, handlename, strlen(handlename));
355 if (Printer->printer_type!=PRINTER_HANDLE_IS_PRINTER)
358 aprinter=strchr(handlename+2, '\\');
361 DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter)));
364 * store the Samba share name in it
365 * in back we have the long printer name
366 * need to iterate all the snum and do a
367 * get_a_printer each time to find the printer
368 * faster to do it here than later.
371 for (snum=0;snum<n_services && found==False;snum++) {
373 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
376 DEBUGADD(5,("share:%s\n",lp_servicename(snum)));
378 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
381 DEBUG(10,("set_printer_hnd_name: name [%s], aprinter [%s]\n",
382 printer->info_2->printername, aprinter ));
384 if ( strlen(printer->info_2->printername) != strlen(aprinter) ) {
385 free_a_printer(&printer, 2);
389 if ( strncasecmp(printer->info_2->printername, aprinter, strlen(aprinter))) {
390 free_a_printer(&printer, 2);
398 * if we haven't found a printer with the given handlename
399 * then it can be a share name as you can open both \\server\printer and
404 * we still check if the printer description file exists as NT won't be happy
405 * if we reply OK in the openprinter call and can't reply in the subsequent RPC calls
409 DEBUGADD(5,("Printer not found, checking for share now\n"));
411 for (snum=0;snum<n_services && found==False;snum++) {
413 if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
416 DEBUGADD(5,("set_printer_hnd_name: share:%s\n",lp_servicename(snum)));
418 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
421 DEBUG(10,("set_printer_hnd_name: printername [%s], aprinter [%s]\n",
422 printer->info_2->printername, aprinter ));
424 if ( strlen(lp_servicename(snum)) != strlen(aprinter) ) {
425 free_a_printer(&printer, 2);
429 if ( strncasecmp(lp_servicename(snum), aprinter, strlen(aprinter))) {
430 free_a_printer(&printer, 2);
439 DEBUGADD(4,("Printer not found\n"));
444 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s[%x]\n",
445 printer->info_2->printername, lp_servicename(snum),snum));
447 ZERO_STRUCT(Printer->dev.handlename);
448 strncpy(Printer->dev.handlename, lp_servicename(snum), strlen(lp_servicename(snum)));
450 free_a_printer(&printer, 2);
455 /****************************************************************************
456 find first available printer slot. creates a printer handle for you.
457 ****************************************************************************/
459 static BOOL open_printer_hnd(POLICY_HND *hnd, char *name)
461 Printer_entry *new_printer;
464 create_printer_hnd(hnd);
466 if((new_printer=(Printer_entry *)malloc(sizeof(Printer_entry))) == NULL)
469 ZERO_STRUCTP(new_printer);
471 new_printer->open = True;
472 new_printer->notify.option=NULL;
474 memcpy(&new_printer->printer_hnd, hnd, sizeof(*hnd));
476 ubi_dlAddHead( &Printer_list, (ubi_dlNode *)new_printer);
478 if (!set_printer_hnd_printertype(new_printer, name)) {
479 close_printer_handle(hnd);
483 if (!set_printer_hnd_name(new_printer, name)) {
484 close_printer_handle(hnd);
491 /********************************************************************
492 Return True is the handle is a print server.
493 ********************************************************************/
494 static BOOL handle_is_printserver(const POLICY_HND *handle)
496 Printer_entry *Printer=find_printer_index_by_hnd(handle);
498 if (!OPEN_HANDLE(Printer))
501 if (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
507 /****************************************************************************
508 allocate more memory for a BUFFER.
509 ****************************************************************************/
510 static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size)
518 /* damn, I'm doing the reverse operation of prs_grow() :) */
519 if (buffer_size < prs_data_size(ps))
522 extra_space = buffer_size - prs_data_size(ps);
525 * save the offset and move to the end of the buffer
526 * prs_grow() checks the extra_space against the offset
528 old_offset=prs_offset(ps);
529 prs_set_offset(ps, prs_data_size(ps));
531 if (!prs_grow(ps, extra_space))
534 prs_set_offset(ps, old_offset);
537 buffer->string_at_end = buffer_size;
539 buffer->string_at_end=prs_data_size(ps);
545 /********************************************************************
546 * spoolss_open_printer
548 * called from the spoolss dispatcher
549 ********************************************************************/
550 uint32 _spoolss_open_printer_ex( const UNISTR2 *printername,
551 const PRINTER_DEFAULT *printer_default,
552 uint32 user_switch, SPOOL_USER_CTR user_ctr,
557 if (printername == NULL)
558 return ERROR_INVALID_PRINTER_NAME;
560 /* some sanity check because you can open a printer or a print server */
561 /* aka: \\server\printer or \\server */
562 unistr2_to_ascii(name, printername, sizeof(name)-1);
564 DEBUGADD(3,("checking name: %s\n",name));
566 if (!open_printer_hnd(handle, name))
567 return ERROR_INVALID_PRINTER_NAME;
570 if (printer_default->datatype_ptr != NULL)
572 unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1);
573 set_printer_hnd_datatype(handle, datatype);
576 set_printer_hnd_datatype(handle, "");
579 if (!set_printer_hnd_accesstype(handle, printer_default->access_required)) {
580 close_printer_handle(handle);
581 return ERROR_ACCESS_DENIED;
584 return NT_STATUS_NO_PROBLEMO;
587 /****************************************************************************
588 ****************************************************************************/
589 static BOOL convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
590 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
594 uni_2_asc_printer_info_2(uni->info_2, &printer->info_2);
603 static BOOL convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
604 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
608 printer->info_3=NULL;
609 uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3);
612 printer->info_6=NULL;
613 uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6);
622 static BOOL convert_devicemode(const DEVICEMODE *devmode, NT_DEVICEMODE *nt_devmode)
624 unistr_to_dos(nt_devmode->devicename, (const char *)devmode->devicename.buffer, 31);
625 unistr_to_dos(nt_devmode->formname, (const char *)devmode->formname.buffer, 31);
627 nt_devmode->specversion=devmode->specversion;
628 nt_devmode->driverversion=devmode->driverversion;
629 nt_devmode->size=devmode->size;
630 nt_devmode->driverextra=devmode->driverextra;
631 nt_devmode->fields=devmode->fields;
632 nt_devmode->orientation=devmode->orientation;
633 nt_devmode->papersize=devmode->papersize;
634 nt_devmode->paperlength=devmode->paperlength;
635 nt_devmode->paperwidth=devmode->paperwidth;
636 nt_devmode->scale=devmode->scale;
637 nt_devmode->copies=devmode->copies;
638 nt_devmode->defaultsource=devmode->defaultsource;
639 nt_devmode->printquality=devmode->printquality;
640 nt_devmode->color=devmode->color;
641 nt_devmode->duplex=devmode->duplex;
642 nt_devmode->yresolution=devmode->yresolution;
643 nt_devmode->ttoption=devmode->ttoption;
644 nt_devmode->collate=devmode->collate;
646 nt_devmode->logpixels=devmode->logpixels;
647 nt_devmode->bitsperpel=devmode->bitsperpel;
648 nt_devmode->pelswidth=devmode->pelswidth;
649 nt_devmode->pelsheight=devmode->pelsheight;
650 nt_devmode->displayflags=devmode->displayflags;
651 nt_devmode->displayfrequency=devmode->displayfrequency;
652 nt_devmode->icmmethod=devmode->icmmethod;
653 nt_devmode->icmintent=devmode->icmintent;
654 nt_devmode->mediatype=devmode->mediatype;
655 nt_devmode->dithertype=devmode->dithertype;
656 nt_devmode->reserved1=devmode->reserved1;
657 nt_devmode->reserved2=devmode->reserved2;
658 nt_devmode->panningwidth=devmode->panningwidth;
659 nt_devmode->panningheight=devmode->panningheight;
661 if (nt_devmode->driverextra != 0) {
662 /* if we had a previous private delete it and make a new one */
663 safe_free(nt_devmode->private);
664 if((nt_devmode->private=(uint8 *)malloc(nt_devmode->driverextra * sizeof(uint8))) == NULL)
666 memcpy(nt_devmode->private, devmode->private, nt_devmode->driverextra);
672 /********************************************************************
673 * api_spoolss_closeprinter
674 ********************************************************************/
675 uint32 _spoolss_closeprinter(POLICY_HND *handle)
677 if (!close_printer_handle(handle))
678 return ERROR_INVALID_HANDLE;
680 return NT_STATUS_NO_PROBLEMO;
683 /********************************************************************
684 * api_spoolss_deleteprinter
685 ********************************************************************/
686 uint32 _spoolss_deleteprinter(POLICY_HND *handle)
688 if (!delete_printer_handle(handle))
689 return ERROR_INVALID_HANDLE;
691 return NT_STATUS_NO_PROBLEMO;
694 /********************************************************************
695 GetPrinterData on a printer server Handle.
696 ********************************************************************/
697 static BOOL getprinterdata_printer_server(fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
701 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
703 if (!strcmp(value, "BeepEnabled")) {
705 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
707 SIVAL(*data, 0, 0x01);
712 if (!strcmp(value, "EventLog")) {
714 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
716 SIVAL(*data, 0, 0x1B);
721 if (!strcmp(value, "NetPopup")) {
723 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
725 SIVAL(*data, 0, 0x01);
730 if (!strcmp(value, "MajorVersion")) {
732 if((*data = (uint8 *)malloc( 4*sizeof(uint8) )) == NULL)
734 SIVAL(*data, 0, 0x02);
739 if (!strcmp(value, "DefaultSpoolDirectory")) {
740 pstring string="You are using a Samba server";
742 *needed = 2*(strlen(string)+1);
743 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
745 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
747 /* it's done by hand ready to go on the wire */
748 for (i=0; i<strlen(string); i++) {
749 (*data)[2*i]=string[i];
755 if (!strcmp(value, "Architecture")) {
756 pstring string="Windows NT x86";
758 *needed = 2*(strlen(string)+1);
759 if((*data = (uint8 *)malloc( ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
761 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
762 for (i=0; i<strlen(string); i++) {
763 (*data)[2*i]=string[i];
772 /********************************************************************
773 GetPrinterData on a printer Handle.
774 ********************************************************************/
775 static BOOL getprinterdata_printer(POLICY_HND *handle,
776 fstring value, uint32 *type,
777 uint8 **data, uint32 *needed, uint32 in_size )
779 NT_PRINTER_INFO_LEVEL *printer = NULL;
783 Printer_entry *Printer = find_printer_index_by_hnd(handle);
785 DEBUG(5,("getprinterdata_printer\n"));
787 if (!OPEN_HANDLE(Printer)) {
788 DEBUG(0,("getprinterdata_printer: Invalid handle (%s).\n", OUR_HANDLE(handle)));
792 if(!get_printer_snum(handle, &snum))
795 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
798 if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
799 free_a_printer(&printer, 2);
803 free_a_printer(&printer, 2);
805 DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
808 if((*data = (uint8 *)malloc( in_size *sizeof(uint8) )) == NULL) {
812 memset(*data, 0, in_size *sizeof(uint8));
813 /* copy the min(in_size, len) */
814 memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
821 DEBUG(5,("getprinterdata_printer:copy done\n"));
828 /********************************************************************
829 * spoolss_getprinterdata
830 ********************************************************************/
831 uint32 _spoolss_getprinterdata(POLICY_HND *handle, UNISTR2 *valuename,
840 Printer_entry *Printer = find_printer_index_by_hnd(handle);
843 * Reminder: when it's a string, the length is in BYTES
844 * even if UNICODE is negociated.
851 /* in case of problem, return some default values */
855 DEBUG(4,("_spoolss_getprinterdata\n"));
857 if (!OPEN_HANDLE(Printer)) {
858 if((*data=(uint8 *)malloc(4*sizeof(uint8))) == NULL)
859 return ERROR_NOT_ENOUGH_MEMORY;
860 DEBUG(0,("_spoolss_getprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
861 return ERROR_INVALID_HANDLE;
864 unistr2_to_ascii(value, valuename, sizeof(value)-1);
866 if (handle_is_printserver(handle))
867 found=getprinterdata_printer_server(value, type, data, needed, *out_size);
869 found=getprinterdata_printer(handle, value, type, data, needed, *out_size);
872 DEBUG(5, ("value not found, allocating %d\n", *out_size));
873 /* reply this param doesn't exist */
875 if((*data=(uint8 *)malloc(*out_size*sizeof(uint8))) == NULL)
876 return ERROR_NOT_ENOUGH_MEMORY;
877 memset(*data, '\0', *out_size*sizeof(uint8));
882 return ERROR_INVALID_PARAMETER;
885 if (*needed > *out_size)
886 return ERROR_INSUFFICIENT_BUFFER;
888 return NT_STATUS_NO_PROBLEMO;
891 /********************************************************************
893 * ReplyFindFirstPrinterChangeNotifyEx
895 * jfmxxxx: before replying OK: status=0
896 * should do a rpc call to the workstation asking ReplyOpenPrinter
897 * have to code it, later.
899 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
900 * called from api_spoolss_rffpcnex
901 ********************************************************************/
902 uint32 _spoolss_rffpcnex(POLICY_HND *handle, uint32 flags, uint32 options,
903 const UNISTR2 *localmachine, uint32 printerlocal,
904 SPOOL_NOTIFY_OPTION *option)
906 /* store the notify value in the printer struct */
908 Printer_entry *Printer=find_printer_index_by_hnd(handle);
910 if (!OPEN_HANDLE(Printer)) {
911 DEBUG(0,("_spoolss_rffpcnex: Invalid handle (%s).\n", OUR_HANDLE(handle)));
912 return ERROR_INVALID_HANDLE;
915 Printer->notify.flags=flags;
916 Printer->notify.options=options;
917 Printer->notify.printerlocal=printerlocal;
918 Printer->notify.option=option;
919 unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
921 return NT_STATUS_NO_PROBLEMO;
924 /*******************************************************************
925 * fill a notify_info_data with the servername
926 ********************************************************************/
927 static void spoolss_notify_server_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
928 NT_PRINTER_INFO_LEVEL *printer)
932 snprintf(temp_name, sizeof(temp_name)-1, "\\\\%s", global_myname);
934 data->notify_data.data.length= (uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
935 temp_name, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
938 /*******************************************************************
939 * fill a notify_info_data with the servicename
940 * jfmxxxx: it's incorrect should be long_printername
941 ********************************************************************/
942 static void spoolss_notify_printer_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue,
943 NT_PRINTER_INFO_LEVEL *printer)
946 data->notify_data.data.length=strlen(lp_servicename(snum));
947 dos_PutUniCode(data->notify_data.data.string, lp_servicename(snum), sizeof(data->notify_data.data.string), True);
949 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
950 printer->info_2->printername, sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
953 /*******************************************************************
954 * fill a notify_info_data with the servicename
955 ********************************************************************/
956 static void spoolss_notify_share_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
958 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
959 lp_servicename(snum), sizeof(data->notify_data.data.string),True) - sizeof(uint16))/sizeof(uint16));
962 /*******************************************************************
963 * fill a notify_info_data with the port name
964 ********************************************************************/
965 static void spoolss_notify_port_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
967 /* even if it's strange, that's consistant in all the code */
969 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
970 lp_servicename(snum), sizeof(data->notify_data.data.string), True) - sizeof(uint16))/sizeof(uint16));
973 /*******************************************************************
974 * fill a notify_info_data with the printername
975 * jfmxxxx: it's incorrect, should be lp_printerdrivername()
976 * but it doesn't exist, have to see what to do
977 ********************************************************************/
978 static void spoolss_notify_driver_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
980 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
981 printer->info_2->drivername, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
984 /*******************************************************************
985 * fill a notify_info_data with the comment
986 ********************************************************************/
987 static void spoolss_notify_comment(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
989 if (*printer->info_2->comment == '\0')
990 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
991 lp_comment(snum), sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
993 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
994 printer->info_2->comment, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
997 /*******************************************************************
998 * fill a notify_info_data with the comment
999 * jfm:xxxx incorrect, have to create a new smb.conf option
1000 * location = "Room 1, floor 2, building 3"
1001 ********************************************************************/
1002 static void spoolss_notify_location(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1004 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1005 printer->info_2->location, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1008 /*******************************************************************
1009 * fill a notify_info_data with the device mode
1010 * jfm:xxxx don't to it for know but that's a real problem !!!
1011 ********************************************************************/
1012 static void spoolss_notify_devmode(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1016 /*******************************************************************
1017 * fill a notify_info_data with the separator file name
1018 * jfm:xxxx just return no file could add an option to smb.conf
1019 * separator file = "separator.txt"
1020 ********************************************************************/
1021 static void spoolss_notify_sepfile(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1023 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1024 printer->info_2->sepfile, sizeof(data->notify_data.data.string)-1,True) - sizeof(uint16))/sizeof(uint16));
1027 /*******************************************************************
1028 * fill a notify_info_data with the print processor
1029 * jfm:xxxx return always winprint to indicate we don't do anything to it
1030 ********************************************************************/
1031 static void spoolss_notify_print_processor(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1033 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1034 printer->info_2->printprocessor, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1037 /*******************************************************************
1038 * fill a notify_info_data with the print processor options
1039 * jfm:xxxx send an empty string
1040 ********************************************************************/
1041 static void spoolss_notify_parameters(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1043 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1044 printer->info_2->parameters, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1047 /*******************************************************************
1048 * fill a notify_info_data with the data type
1049 * jfm:xxxx always send RAW as data type
1050 ********************************************************************/
1051 static void spoolss_notify_datatype(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1053 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1054 printer->info_2->datatype, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1057 /*******************************************************************
1058 * fill a notify_info_data with the security descriptor
1059 * jfm:xxxx send an null pointer to say no security desc
1060 * have to implement security before !
1061 ********************************************************************/
1062 static void spoolss_notify_security_desc(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1064 data->notify_data.data.length=0;
1065 data->notify_data.data.string[0]=0x00;
1068 /*******************************************************************
1069 * fill a notify_info_data with the attributes
1070 * jfm:xxxx a samba printer is always shared
1071 ********************************************************************/
1072 static void spoolss_notify_attributes(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1074 data->notify_data.value[0] = PRINTER_ATTRIBUTE_SHARED \
1075 | PRINTER_ATTRIBUTE_LOCAL \
1076 | PRINTER_ATTRIBUTE_RAW_ONLY ;
1079 /*******************************************************************
1080 * fill a notify_info_data with the priority
1081 ********************************************************************/
1082 static void spoolss_notify_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1084 data->notify_data.value[0] = printer->info_2->priority;
1087 /*******************************************************************
1088 * fill a notify_info_data with the default priority
1089 ********************************************************************/
1090 static void spoolss_notify_default_priority(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1092 data->notify_data.value[0] = printer->info_2->default_priority;
1095 /*******************************************************************
1096 * fill a notify_info_data with the start time
1097 ********************************************************************/
1098 static void spoolss_notify_start_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1100 data->notify_data.value[0] = printer->info_2->starttime;
1103 /*******************************************************************
1104 * fill a notify_info_data with the until time
1105 ********************************************************************/
1106 static void spoolss_notify_until_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1108 data->notify_data.value[0] = printer->info_2->untiltime;
1111 /*******************************************************************
1112 * fill a notify_info_data with the status
1113 ********************************************************************/
1114 static void spoolss_notify_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1117 print_queue_struct *q=NULL;
1118 print_status_struct status;
1120 memset(&status, 0, sizeof(status));
1121 count = print_queue_status(snum, &q, &status);
1122 data->notify_data.value[0]=(uint32) status.status;
1126 /*******************************************************************
1127 * fill a notify_info_data with the number of jobs queued
1128 ********************************************************************/
1129 static void spoolss_notify_cjobs(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1131 print_queue_struct *q=NULL;
1132 print_status_struct status;
1134 memset(&status, 0, sizeof(status));
1135 data->notify_data.value[0] = print_queue_status(snum, &q, &status);
1139 /*******************************************************************
1140 * fill a notify_info_data with the average ppm
1141 ********************************************************************/
1142 static void spoolss_notify_average_ppm(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1144 /* always respond 8 pages per minutes */
1145 /* a little hard ! */
1146 data->notify_data.value[0] = printer->info_2->averageppm;
1149 /*******************************************************************
1150 * fill a notify_info_data with
1151 ********************************************************************/
1152 static void spoolss_notify_username(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1154 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1155 queue->user, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1158 /*******************************************************************
1159 * fill a notify_info_data with
1160 ********************************************************************/
1161 static void spoolss_notify_job_status(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1163 data->notify_data.value[0]=nt_printj_status(queue->status);
1166 /*******************************************************************
1167 * fill a notify_info_data with
1168 ********************************************************************/
1169 static void spoolss_notify_job_name(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1171 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1172 queue->file, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1175 /*******************************************************************
1176 * fill a notify_info_data with
1177 ********************************************************************/
1178 static void spoolss_notify_job_status_string(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1180 char *p = "unknown";
1181 switch (queue->status) {
1195 data->notify_data.data.length=(uint32)((dos_PutUniCode((char *)data->notify_data.data.string,
1196 p, sizeof(data->notify_data.data.string)-1, True) - sizeof(uint16))/sizeof(uint16));
1199 /*******************************************************************
1200 * fill a notify_info_data with
1201 ********************************************************************/
1202 static void spoolss_notify_job_time(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1204 data->notify_data.value[0]=0x0;
1207 /*******************************************************************
1208 * fill a notify_info_data with
1209 ********************************************************************/
1210 static void spoolss_notify_job_size(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1212 data->notify_data.value[0]=queue->size;
1215 /*******************************************************************
1216 * fill a notify_info_data with
1217 ********************************************************************/
1218 static void spoolss_notify_job_position(int snum, SPOOL_NOTIFY_INFO_DATA *data, print_queue_struct *queue, NT_PRINTER_INFO_LEVEL *printer)
1220 data->notify_data.value[0]=queue->job;
1225 struct s_notify_info_data_table
1231 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
1232 print_queue_struct *queue,
1233 NT_PRINTER_INFO_LEVEL *printer);
1236 struct s_notify_info_data_table notify_info_data_table[] =
1238 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
1239 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
1241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
1244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
1245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
1247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
1251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
1252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
1254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
1257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
1258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
1259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
1260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
1261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
1262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
1263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
1264 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
1265 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
1266 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
1267 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
1268 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
1269 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
1270 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
1271 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
1272 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
1273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
1274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
1275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
1276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
1277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
1278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
1279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
1280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, NULL },
1281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
1282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
1283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
1284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, NULL },
1285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, NULL },
1286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
1287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
1288 { END, END, "", END, NULL }
1291 /*******************************************************************
1292 return the size of info_data structure
1293 ********************************************************************/
1294 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
1298 while (notify_info_data_table[i].type != END)
1300 if ( (notify_info_data_table[i].type == type ) &&
1301 (notify_info_data_table[i].field == field ) )
1303 return (notify_info_data_table[i].size);
1311 /*******************************************************************
1312 return the type of notify_info_data
1313 ********************************************************************/
1314 static BOOL type_of_notify_info_data(uint16 type, uint16 field)
1318 while (notify_info_data_table[i].type != END)
1320 if ( (notify_info_data_table[i].type == type ) &&
1321 (notify_info_data_table[i].field == field ) )
1323 if (notify_info_data_table[i].size == POINTER)
1338 /****************************************************************************
1339 ****************************************************************************/
1340 static int search_notify(uint16 type, uint16 field, int *value)
1345 for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
1347 if ( (notify_info_data_table[j].type == type ) &&
1348 (notify_info_data_table[j].field == field ) )
1353 if ( found && (notify_info_data_table[j].fn != NULL) )
1359 /****************************************************************************
1360 ****************************************************************************/
1361 static void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
1363 info_data->type = type;
1364 info_data->field = field;
1365 info_data->reserved = 0;
1367 info_data->size = size_of_notify_info_data(type, field);
1368 info_data->enc_type = type_of_notify_info_data(type, field);
1372 /*******************************************************************
1374 * fill a notify_info struct with info asked
1376 ********************************************************************/
1377 static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1383 SPOOL_NOTIFY_INFO_DATA *current_data;
1384 NT_PRINTER_INFO_LEVEL *printer = NULL;
1385 print_queue_struct *queue=NULL;
1387 DEBUG(4,("construct_notify_printer_info\n"));
1389 type=option_type->type;
1391 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
1392 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1393 option_type->count, lp_servicename(snum)));
1395 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1398 for(field_num=0; field_num<option_type->count; field_num++) {
1399 field = option_type->fields[field_num];
1400 DEBUGADD(4,("notify [%d]: type [%x], field [%x]\n", field_num, type, field));
1402 if (!search_notify(type, field, &j) )
1405 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1408 current_data=&info->data[info->count];
1410 construct_info_data(current_data, type, field, id);
1411 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1416 free_a_printer(&printer, 2);
1420 /*******************************************************************
1422 * fill a notify_info struct with info asked
1424 ********************************************************************/
1425 static BOOL construct_notify_jobs_info(print_queue_struct *queue, SPOOL_NOTIFY_INFO *info, int snum, SPOOL_NOTIFY_OPTION_TYPE *option_type, uint32 id)
1431 SPOOL_NOTIFY_INFO_DATA *current_data;
1432 NT_PRINTER_INFO_LEVEL *printer = NULL;
1434 DEBUG(4,("construct_notify_jobs_info\n"));
1436 type = option_type->type;
1438 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
1439 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
1440 option_type->count));
1442 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1445 for(field_num=0; field_num<option_type->count; field_num++) {
1446 field = option_type->fields[field_num];
1448 if (!search_notify(type, field, &j) )
1451 if((info->data=Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
1455 current_data=&(info->data[info->count]);
1457 construct_info_data(current_data, type, field, id);
1458 notify_info_data_table[j].fn(snum, current_data, queue, printer);
1462 free_a_printer(&printer, 2);
1467 * JFM: The enumeration is not that simple, it's even non obvious.
1469 * let's take an example: I want to monitor the PRINTER SERVER for
1470 * the printer's name and the number of jobs currently queued.
1471 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
1472 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
1474 * I have 3 printers on the back of my server.
1476 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
1479 * 1 printer 1 name 1
1480 * 2 printer 1 cjob 1
1481 * 3 printer 2 name 2
1482 * 4 printer 2 cjob 2
1483 * 5 printer 3 name 3
1484 * 6 printer 3 name 3
1486 * that's the print server case, the printer case is even worse.
1491 /*******************************************************************
1493 * enumerate all printers on the printserver
1494 * fill a notify_info struct with info asked
1496 ********************************************************************/
1497 static uint32 printserver_notify_info(const POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1500 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1501 int n_services=lp_numservices();
1504 SPOOL_NOTIFY_OPTION *option;
1505 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1507 DEBUG(4,("printserver_notify_info\n"));
1509 option=Printer->notify.option;
1515 for (i=0; i<option->count; i++) {
1516 option_type=&(option->ctr.type[i]);
1518 if (option_type->type!=PRINTER_NOTIFY_TYPE)
1521 for (snum=0; snum<n_services; snum++)
1522 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
1523 if (construct_notify_printer_info(info, snum, option_type, id))
1528 * Debugging information, don't delete.
1531 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1532 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1533 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1535 for (i=0; i<info->count; i++) {
1536 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1537 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1538 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1542 return NT_STATUS_NO_PROBLEMO;
1545 /*******************************************************************
1547 * fill a notify_info struct with info asked
1549 ********************************************************************/
1550 static uint32 printer_notify_info(POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info)
1553 Printer_entry *Printer=find_printer_index_by_hnd(hnd);
1556 SPOOL_NOTIFY_OPTION *option;
1557 SPOOL_NOTIFY_OPTION_TYPE *option_type;
1559 print_queue_struct *queue=NULL;
1560 print_status_struct status;
1562 DEBUG(4,("printer_notify_info\n"));
1564 option=Printer->notify.option;
1570 get_printer_snum(hnd, &snum);
1572 for (i=0; i<option->count; i++) {
1573 option_type=&option->ctr.type[i];
1575 switch ( option_type->type ) {
1576 case PRINTER_NOTIFY_TYPE:
1577 if(construct_notify_printer_info(info, snum, option_type, id))
1581 case JOB_NOTIFY_TYPE:
1582 memset(&status, 0, sizeof(status));
1583 count = print_queue_status(snum, &queue, &status);
1584 for (j=0; j<count; j++)
1585 construct_notify_jobs_info(&queue[j], info, snum, option_type, queue[j].job);
1592 * Debugging information, don't delete.
1595 DEBUG(1,("dumping the NOTIFY_INFO\n"));
1596 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
1597 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
1599 for (i=0; i<info->count; i++) {
1600 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
1601 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
1602 info->data[i].id, info->data[i].size, info->data[i].enc_type));
1605 return NT_STATUS_NO_PROBLEMO;
1608 /********************************************************************
1610 ********************************************************************/
1611 uint32 _spoolss_rfnpcnex( POLICY_HND *handle, uint32 change,
1612 SPOOL_NOTIFY_OPTION *option, SPOOL_NOTIFY_INFO *info)
1614 Printer_entry *Printer=find_printer_index_by_hnd(handle);
1616 if (!OPEN_HANDLE(Printer)) {
1617 DEBUG(0,("_spoolss_rfnpcnex: Invalid handle (%s).\n",OUR_HANDLE(handle)));
1618 return ERROR_INVALID_HANDLE;
1621 DEBUG(4,("Printer type %x\n",Printer->printer_type));
1623 /* jfm: the change value isn't used right now.
1624 * we will honour it when
1625 * a) we'll be able to send notification to the client
1626 * b) we'll have a way to communicate between the spoolss process.
1628 * same thing for option->flags
1629 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
1630 * I don't have a global notification system, I'm sending back all the
1631 * informations even when _NOTHING_ has changed.
1634 /* just discard the SPOOL_NOTIFY_OPTION */
1636 safe_free(option->ctr.type);
1638 switch (Printer->printer_type) {
1639 case PRINTER_HANDLE_IS_PRINTSERVER:
1640 return printserver_notify_info(handle, info);
1642 case PRINTER_HANDLE_IS_PRINTER:
1643 return printer_notify_info(handle, info);
1647 return ERROR_INVALID_HANDLE;
1650 /********************************************************************
1651 * construct_printer_info_0
1652 * fill a printer_info_1 struct
1653 ********************************************************************/
1654 static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum, fstring servername)
1658 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1659 counter_printer_0 *session_counter;
1660 uint32 global_counter;
1662 time_t setup_time = time(NULL);
1664 print_queue_struct *queue=NULL;
1665 print_status_struct status;
1667 memset(&status, 0, sizeof(status));
1669 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1672 count = print_queue_status(snum, &queue, &status);
1674 /* check if we already have a counter for this printer */
1675 session_counter = (counter_printer_0 *)ubi_dlFirst(&counter_list);
1677 for(; session_counter; session_counter = (counter_printer_0 *)ubi_dlNext(session_counter)) {
1678 if (session_counter->snum == snum)
1682 /* it's the first time, add it to the list */
1683 if (session_counter==NULL) {
1684 if((session_counter=(counter_printer_0 *)malloc(sizeof(counter_printer_0))) == NULL) {
1685 free_a_printer(&ntprinter, 2);
1688 ZERO_STRUCTP(session_counter);
1689 session_counter->snum=snum;
1690 session_counter->counter=0;
1691 ubi_dlAddHead( &counter_list, (ubi_dlNode *)session_counter);
1695 session_counter->counter++;
1698 * the global_counter should be stored in a TDB as it's common to all the clients
1699 * and should be zeroed on samba startup
1701 global_counter=session_counter->counter;
1703 /* the description and the name are of the form \\server\share */
1704 slprintf(chaine,sizeof(chaine)-1,"\\\\%s\\%s",servername, ntprinter->info_2->printername);
1706 init_unistr(&printer->printername, chaine);
1708 slprintf(chaine,sizeof(chaine)-1,"\\\\%s", servername);
1709 init_unistr(&printer->servername, chaine);
1711 printer->cjobs = count;
1712 printer->total_jobs = 0;
1713 printer->total_bytes = 0;
1715 t=gmtime(&setup_time);
1716 ntprinter->info_2->setuptime = (uint32)setup_time; /* FIXME !! */
1718 printer->year = t->tm_year+1900;
1719 printer->month = t->tm_mon+1;
1720 printer->dayofweek = t->tm_wday;
1721 printer->day = t->tm_mday;
1722 printer->hour = t->tm_hour;
1723 printer->minute = t->tm_min;
1724 printer->second = t->tm_sec;
1725 printer->milliseconds = 0;
1727 printer->global_counter = global_counter;
1728 printer->total_pages = 0;
1729 printer->major_version = 0x0004; /* NT 4 */
1730 printer->build_version = 0x0565; /* build 1381 */
1731 printer->unknown7 = 0x1;
1732 printer->unknown8 = 0x0;
1733 printer->unknown9 = 0x0;
1734 printer->session_counter = session_counter->counter;
1735 printer->unknown11 = 0x0;
1736 printer->printer_errors = 0x0; /* number of print failure */
1737 printer->unknown13 = 0x0;
1738 printer->unknown14 = 0x1;
1739 printer->unknown15 = 0x024a; /* 586 Pentium ? */
1740 printer->unknown16 = 0x0;
1741 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
1742 printer->unknown18 = 0x0;
1743 printer->status = nt_printq_status(status.status);
1744 printer->unknown20 = 0x0;
1745 printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */
1746 printer->unknown22 = 0x0;
1747 printer->unknown23 = 0x6; /* 6 ???*/
1748 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
1749 printer->unknown25 = 0;
1750 printer->unknown26 = 0;
1751 printer->unknown27 = 0;
1752 printer->unknown28 = 0;
1753 printer->unknown29 = 0;
1756 free_a_printer(&ntprinter,2);
1760 /********************************************************************
1761 * construct_printer_info_1
1762 * fill a printer_info_1 struct
1763 ********************************************************************/
1764 static BOOL construct_printer_info_1(fstring server, uint32 flags, PRINTER_INFO_1 *printer, int snum)
1768 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1770 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) != 0)
1773 printer->flags=flags;
1775 if (*ntprinter->info_2->comment == '\0') {
1776 init_unistr(&printer->comment, lp_comment(snum));
1777 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1778 ntprinter->info_2->drivername, lp_comment(snum));
1781 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1782 snprintf(chaine,sizeof(chaine)-1,"%s%s,%s,%s",server, ntprinter->info_2->printername,
1783 ntprinter->info_2->drivername, ntprinter->info_2->comment);
1786 snprintf(chaine2,sizeof(chaine)-1,"%s%s", server, ntprinter->info_2->printername);
1788 init_unistr(&printer->description, chaine);
1789 init_unistr(&printer->name, chaine2);
1791 free_a_printer(&ntprinter,2);
1796 /****************************************************************************
1797 Free a DEVMODE struct.
1798 ****************************************************************************/
1800 static void free_dev_mode(DEVICEMODE *dev)
1806 safe_free(dev->private);
1811 /****************************************************************************
1812 Create a DEVMODE struct. Returns malloced memory.
1813 ****************************************************************************/
1815 static DEVICEMODE *construct_dev_mode(int snum, char *servername)
1819 NT_PRINTER_INFO_LEVEL *printer = NULL;
1820 NT_DEVICEMODE *ntdevmode = NULL;
1821 DEVICEMODE *devmode = NULL;
1823 DEBUG(7,("construct_dev_mode\n"));
1825 DEBUGADD(8,("getting printer characteristics\n"));
1827 if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
1828 DEBUG(0,("construct_dev_mode: malloc fail.\n"));
1832 ZERO_STRUCTP(devmode);
1834 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
1837 if (printer->info_2->devmode)
1838 ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
1841 ntdevmode = construct_nt_devicemode(printer->info_2->printername);
1843 if (ntdevmode == NULL)
1846 DEBUGADD(8,("loading DEVICEMODE\n"));
1848 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, printer->info_2->printername);
1849 init_unistr(&devmode->devicename, adevice);
1851 snprintf(aform, sizeof(aform), ntdevmode->formname);
1852 init_unistr(&devmode->formname, aform);
1854 devmode->specversion = ntdevmode->specversion;
1855 devmode->driverversion = ntdevmode->driverversion;
1856 devmode->size = ntdevmode->size;
1857 devmode->driverextra = ntdevmode->driverextra;
1858 devmode->fields = ntdevmode->fields;
1860 devmode->orientation = ntdevmode->orientation;
1861 devmode->papersize = ntdevmode->papersize;
1862 devmode->paperlength = ntdevmode->paperlength;
1863 devmode->paperwidth = ntdevmode->paperwidth;
1864 devmode->scale = ntdevmode->scale;
1865 devmode->copies = ntdevmode->copies;
1866 devmode->defaultsource = ntdevmode->defaultsource;
1867 devmode->printquality = ntdevmode->printquality;
1868 devmode->color = ntdevmode->color;
1869 devmode->duplex = ntdevmode->duplex;
1870 devmode->yresolution = ntdevmode->yresolution;
1871 devmode->ttoption = ntdevmode->ttoption;
1872 devmode->collate = ntdevmode->collate;
1873 devmode->icmmethod = ntdevmode->icmmethod;
1874 devmode->icmintent = ntdevmode->icmintent;
1875 devmode->mediatype = ntdevmode->mediatype;
1876 devmode->dithertype = ntdevmode->dithertype;
1878 if (ntdevmode->private != NULL) {
1879 if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
1883 free_nt_devicemode(&ntdevmode);
1884 free_a_printer(&printer,2);
1891 free_nt_devicemode(&ntdevmode);
1893 free_a_printer(&printer,2);
1894 free_dev_mode(devmode);
1899 /********************************************************************
1900 * construct_printer_info_2
1901 * fill a printer_info_2 struct
1902 ********************************************************************/
1904 static BOOL construct_printer_info_2(fstring servername, PRINTER_INFO_2 *printer, int snum)
1910 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1912 print_queue_struct *queue=NULL;
1913 print_status_struct status;
1914 memset(&status, 0, sizeof(status));
1916 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
1919 memset(&status, 0, sizeof(status));
1920 count = print_queue_status(snum, &queue, &status);
1922 snprintf(chaine, sizeof(chaine)-1, "%s", servername);
1924 if (strlen(servername)!=0)
1929 snprintf(chaine2, sizeof(chaine)-1, "%s%s%s", servername, sl, ntprinter->info_2->printername);
1931 init_unistr(&printer->servername, chaine); /* servername*/
1932 init_unistr(&printer->printername, chaine2); /* printername*/
1933 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
1934 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
1935 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
1937 if (*ntprinter->info_2->comment == '\0')
1938 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
1940 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
1942 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
1943 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
1944 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
1945 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
1946 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
1948 printer->attributes = ntprinter->info_2->attributes;
1950 printer->priority = ntprinter->info_2->priority; /* priority */
1951 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
1952 printer->starttime = ntprinter->info_2->starttime; /* starttime */
1953 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
1954 printer->status = nt_printq_status(status.status); /* status */
1955 printer->cjobs = count; /* jobs */
1956 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
1958 if((printer->devmode = construct_dev_mode(snum, servername)) == NULL) {
1959 DEBUG(8, ("Returning NULL Devicemode!\n"));
1962 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
1963 /* steal the printer info sec_desc structure. [badly done]. */
1964 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
1965 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen memory. */
1966 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen memory. */
1967 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen memory. */
1970 printer->secdesc = NULL;
1973 free_a_printer(&ntprinter, 2);
1978 /********************************************************************
1979 * construct_printer_info_3
1980 * fill a printer_info_3 struct
1981 ********************************************************************/
1982 static BOOL construct_printer_info_3(fstring servername,
1983 PRINTER_INFO_3 **pp_printer, int snum)
1985 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
1986 PRINTER_INFO_3 *printer = NULL;
1988 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
1992 if ((printer = (PRINTER_INFO_3 *)malloc(sizeof(PRINTER_INFO_3))) == NULL) {
1993 DEBUG(0,("construct_printer_info_3: malloc fail.\n"));
1997 ZERO_STRUCTP(printer);
1999 printer->flags = 4; /* This is the offset to the SEC_DESC. */
2000 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->len != 0) {
2001 /* steal the printer info sec_desc structure. [badly done]. */
2002 printer->secdesc = ntprinter->info_2->secdesc_buf->sec;
2003 ntprinter->info_2->secdesc_buf->sec = NULL; /* Stolen the malloced memory. */
2004 ntprinter->info_2->secdesc_buf->len = 0; /* Stolen the malloced memory. */
2005 ntprinter->info_2->secdesc_buf->max_len = 0; /* Stolen the malloced memory. */
2008 free_a_printer(&ntprinter, 2);
2010 *pp_printer = printer;
2014 /********************************************************************
2015 Spoolss_enumprinters.
2016 ********************************************************************/
2017 static BOOL enum_all_printers_info_1(fstring server, uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2021 int n_services=lp_numservices();
2022 PRINTER_INFO_1 *printers=NULL;
2023 PRINTER_INFO_1 current_prt;
2025 DEBUG(4,("enum_all_printers_info_1\n"));
2027 for (snum=0; snum<n_services; snum++) {
2028 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2029 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2031 if (construct_printer_info_1(server, flags, ¤t_prt, snum)) {
2032 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_1))) == NULL) {
2034 return ERROR_NOT_ENOUGH_MEMORY;
2036 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
2037 memcpy(&(printers[*returned]), ¤t_prt, sizeof(PRINTER_INFO_1));
2043 /* check the required size. */
2044 for (i=0; i<*returned; i++)
2045 (*needed) += spoolss_size_printer_info_1(&(printers[i]));
2047 if (!alloc_buffer_size(buffer, *needed))
2048 return ERROR_INSUFFICIENT_BUFFER;
2050 /* fill the buffer with the structures */
2051 for (i=0; i<*returned; i++)
2052 new_smb_io_printer_info_1("", buffer, &(printers[i]), 0);
2055 safe_free(printers);
2057 if (*needed > offered) {
2059 return ERROR_INSUFFICIENT_BUFFER;
2062 return NT_STATUS_NO_PROBLEMO;
2065 /********************************************************************
2066 enum_all_printers_info_1_local.
2067 *********************************************************************/
2068 static BOOL enum_all_printers_info_1_local(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2071 DEBUG(4,("enum_all_printers_info_1_local\n"));
2073 fstrcpy(temp, "\\\\");
2074 fstrcat(temp, global_myname);
2076 if (!strcmp(name, temp)) {
2077 fstrcat(temp, "\\");
2078 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2081 return enum_all_printers_info_1("", PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2084 /********************************************************************
2085 enum_all_printers_info_1_name.
2086 *********************************************************************/
2087 static BOOL enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2090 DEBUG(4,("enum_all_printers_info_1_name\n"));
2092 fstrcpy(temp, "\\\\");
2093 fstrcat(temp, global_myname);
2095 if (!strcmp(name, temp)) {
2096 fstrcat(temp, "\\");
2097 return enum_all_printers_info_1(temp, PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
2100 return ERROR_INVALID_NAME;
2103 /********************************************************************
2104 enum_all_printers_info_1_remote.
2105 *********************************************************************/
2106 static BOOL enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2108 PRINTER_INFO_1 *printer;
2109 fstring printername;
2112 DEBUG(4,("enum_all_printers_info_1_remote\n"));
2114 /* JFM: currently it's more a place holder than anything else.
2115 * In the spooler world there is a notion of server registration.
2116 * the print servers are registring (sp ?) on the PDC (in the same domain)
2118 * We should have a TDB here. The registration is done thru an undocumented RPC call.
2121 if((printer=(PRINTER_INFO_1 *)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2122 return ERROR_NOT_ENOUGH_MEMORY;
2126 snprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", global_myname);
2127 snprintf(desc, sizeof(desc)-1,"%s", global_myname);
2128 snprintf(comment, sizeof(comment)-1, "Logged on Domain");
2130 init_unistr(&printer->description, desc);
2131 init_unistr(&printer->name, printername);
2132 init_unistr(&printer->comment, comment);
2133 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
2135 /* check the required size. */
2136 *needed += spoolss_size_printer_info_1(printer);
2138 if (!alloc_buffer_size(buffer, *needed)) {
2140 return ERROR_INSUFFICIENT_BUFFER;
2143 /* fill the buffer with the structures */
2144 new_smb_io_printer_info_1("", buffer, printer, 0);
2149 if (*needed > offered) {
2151 return ERROR_INSUFFICIENT_BUFFER;
2154 return NT_STATUS_NO_PROBLEMO;
2157 /********************************************************************
2158 enum_all_printers_info_1_network.
2159 *********************************************************************/
2160 static BOOL enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2163 DEBUG(4,("enum_all_printers_info_1_network\n"));
2165 fstrcpy(temp, "\\\\");
2166 fstrcat(temp, global_myname);
2167 fstrcat(temp, "\\");
2168 return enum_all_printers_info_1(temp, PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
2171 /********************************************************************
2172 * api_spoolss_enumprinters
2174 * called from api_spoolss_enumprinters (see this to understand)
2175 ********************************************************************/
2176 static BOOL enum_all_printers_info_2(fstring servername, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
2180 int n_services=lp_numservices();
2181 PRINTER_INFO_2 *printers=NULL;
2182 PRINTER_INFO_2 current_prt;
2184 for (snum=0; snum<n_services; snum++) {
2185 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
2186 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
2188 if (construct_printer_info_2(servername, ¤t_prt, snum)) {
2189 if((printers=Realloc(printers, (*returned +1)*sizeof(PRINTER_INFO_2))) == NULL)
2190 return ERROR_NOT_ENOUGH_MEMORY;
2191 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned));
2192 memcpy(&printers[*returned], ¤t_prt, sizeof(PRINTER_INFO_2));
2198 /* check the required size. */
2199 for (i=0; i<*returned; i++)
2200 (*needed) += spoolss_size_printer_info_2(&printers[i]);
2202 if (!alloc_buffer_size(buffer, *needed)) {
2203 for (i=0; i<*returned; i++) {
2204 free_devmode(printers[i].devmode);
2205 free_sec_desc(&printers[i].secdesc);
2207 safe_free(printers);
2208 return ERROR_INSUFFICIENT_BUFFER;
2211 /* fill the buffer with the structures */
2212 for (i=0; i<*returned; i++)
2213 new_smb_io_printer_info_2("", buffer, &(printers[i]), 0);
2216 for (i=0; i<*returned; i++) {
2217 free_devmode(printers[i].devmode);
2218 free_sec_desc(&printers[i].secdesc);
2220 safe_free(printers);
2222 if (*needed > offered) {
2224 return ERROR_INSUFFICIENT_BUFFER;
2227 return NT_STATUS_NO_PROBLEMO;
2230 /********************************************************************
2231 * handle enumeration of printers at level 1
2232 ********************************************************************/
2233 static uint32 enumprinters_level1( uint32 flags, fstring name,
2234 NEW_BUFFER *buffer, uint32 offered,
2235 uint32 *needed, uint32 *returned)
2237 /* Not all the flags are equals */
2239 if (flags & PRINTER_ENUM_LOCAL)
2240 return enum_all_printers_info_1_local(name, buffer, offered, needed, returned);
2242 if (flags & PRINTER_ENUM_NAME)
2243 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
2245 if (flags & PRINTER_ENUM_REMOTE)
2246 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
2248 if (flags & PRINTER_ENUM_NETWORK)
2249 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
2251 return NT_STATUS_NO_PROBLEMO; /* NT4sp5 does that */
2254 /********************************************************************
2255 * handle enumeration of printers at level 2
2256 ********************************************************************/
2257 static uint32 enumprinters_level2( uint32 flags, fstring servername,
2258 NEW_BUFFER *buffer, uint32 offered,
2259 uint32 *needed, uint32 *returned)
2263 fstrcpy(temp, "\\\\");
2264 fstrcat(temp, global_myname);
2266 if (flags & PRINTER_ENUM_LOCAL) {
2267 if (!strcmp(servername, temp))
2268 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2270 return enum_all_printers_info_2("", buffer, offered, needed, returned);
2273 if (flags & PRINTER_ENUM_NAME) {
2274 if (!strcmp(servername, temp))
2275 return enum_all_printers_info_2(temp, buffer, offered, needed, returned);
2277 return ERROR_INVALID_NAME;
2280 if (flags & PRINTER_ENUM_REMOTE)
2281 return ERROR_INVALID_LEVEL;
2283 return NT_STATUS_NO_PROBLEMO;
2286 /********************************************************************
2287 * handle enumeration of printers at level 5
2288 ********************************************************************/
2289 static uint32 enumprinters_level5( uint32 flags, fstring servername,
2290 NEW_BUFFER *buffer, uint32 offered,
2291 uint32 *needed, uint32 *returned)
2293 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
2294 return NT_STATUS_NO_PROBLEMO;
2297 /********************************************************************
2298 * api_spoolss_enumprinters
2300 * called from api_spoolss_enumprinters (see this to understand)
2301 ********************************************************************/
2302 uint32 _spoolss_enumprinters( uint32 flags, const UNISTR2 *servername, uint32 level,
2303 NEW_BUFFER *buffer, uint32 offered,
2304 uint32 *needed, uint32 *returned)
2308 DEBUG(4,("_spoolss_enumprinters\n"));
2315 * flags==PRINTER_ENUM_NAME
2316 * if name=="" then enumerates all printers
2317 * if name!="" then enumerate the printer
2318 * flags==PRINTER_ENUM_REMOTE
2319 * name is NULL, enumerate printers
2320 * Level 2: name!="" enumerates printers, name can't be NULL
2321 * Level 3: doesn't exist
2322 * Level 4: does a local registry lookup
2323 * Level 5: same as Level 2
2326 unistr2_to_ascii(name, servername, sizeof(name)-1);
2331 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
2334 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
2337 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
2342 return ERROR_INVALID_LEVEL;
2347 /****************************************************************************
2348 ****************************************************************************/
2349 static uint32 getprinter_level_0(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2351 PRINTER_INFO_0 *printer=NULL;
2353 if((printer=(PRINTER_INFO_0*)malloc(sizeof(PRINTER_INFO_0))) == NULL)
2354 return ERROR_NOT_ENOUGH_MEMORY;
2356 construct_printer_info_0(printer, snum, servername);
2358 /* check the required size. */
2359 *needed += spoolss_size_printer_info_0(printer);
2361 if (!alloc_buffer_size(buffer, *needed)) {
2363 return ERROR_INSUFFICIENT_BUFFER;
2366 /* fill the buffer with the structures */
2367 new_smb_io_printer_info_0("", buffer, printer, 0);
2372 if (*needed > offered) {
2373 return ERROR_INSUFFICIENT_BUFFER;
2376 return NT_STATUS_NO_PROBLEMO;
2379 /****************************************************************************
2380 ****************************************************************************/
2381 static uint32 getprinter_level_1(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2383 PRINTER_INFO_1 *printer=NULL;
2385 if((printer=(PRINTER_INFO_1*)malloc(sizeof(PRINTER_INFO_1))) == NULL)
2386 return ERROR_NOT_ENOUGH_MEMORY;
2388 construct_printer_info_1(servername, PRINTER_ENUM_ICON8, printer, snum);
2390 /* check the required size. */
2391 *needed += spoolss_size_printer_info_1(printer);
2393 if (!alloc_buffer_size(buffer, *needed)) {
2395 return ERROR_INSUFFICIENT_BUFFER;
2398 /* fill the buffer with the structures */
2399 new_smb_io_printer_info_1("", buffer, printer, 0);
2404 if (*needed > offered) {
2405 return ERROR_INSUFFICIENT_BUFFER;
2408 return NT_STATUS_NO_PROBLEMO;
2411 /****************************************************************************
2412 ****************************************************************************/
2413 static uint32 getprinter_level_2(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2415 PRINTER_INFO_2 *printer=NULL;
2418 if((printer=(PRINTER_INFO_2*)malloc(sizeof(PRINTER_INFO_2)))==NULL)
2419 return ERROR_NOT_ENOUGH_MEMORY;
2421 fstrcpy(temp, "\\\\");
2422 fstrcat(temp, servername);
2423 construct_printer_info_2(temp, printer, snum);
2425 /* check the required size. */
2426 *needed += spoolss_size_printer_info_2(printer);
2428 if (!alloc_buffer_size(buffer, *needed)) {
2429 free_printer_info_2(printer);
2430 return ERROR_INSUFFICIENT_BUFFER;
2433 /* fill the buffer with the structures */
2434 if (!new_smb_io_printer_info_2("", buffer, printer, 0)) {
2435 free_printer_info_2(printer);
2436 return ERROR_NOT_ENOUGH_MEMORY;
2440 free_printer_info_2(printer);
2442 if (*needed > offered) {
2443 return ERROR_INSUFFICIENT_BUFFER;
2446 return NT_STATUS_NO_PROBLEMO;
2449 /****************************************************************************
2450 ****************************************************************************/
2451 static uint32 getprinter_level_3(fstring servername, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2453 PRINTER_INFO_3 *printer=NULL;
2456 fstrcpy(temp, "\\\\");
2457 fstrcat(temp, servername);
2458 if (!construct_printer_info_3(temp, &printer, snum))
2459 return ERROR_NOT_ENOUGH_MEMORY;
2461 /* check the required size. */
2462 *needed += spoolss_size_printer_info_3(printer);
2464 if (!alloc_buffer_size(buffer, *needed)) {
2465 free_printer_info_3(printer);
2466 return ERROR_INSUFFICIENT_BUFFER;
2469 /* fill the buffer with the structures */
2470 new_smb_io_printer_info_3("", buffer, printer, 0);
2473 free_printer_info_3(printer);
2475 if (*needed > offered) {
2476 return ERROR_INSUFFICIENT_BUFFER;
2479 return NT_STATUS_NO_PROBLEMO;
2482 /****************************************************************************
2483 ****************************************************************************/
2484 uint32 _spoolss_getprinter(POLICY_HND *handle, uint32 level,
2485 NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2492 pstrcpy(servername, global_myname);
2494 if (!get_printer_snum(handle, &snum))
2495 return ERROR_INVALID_HANDLE;
2499 return getprinter_level_0(servername, snum, buffer, offered, needed);
2501 return getprinter_level_1(servername,snum, buffer, offered, needed);
2503 return getprinter_level_2(servername,snum, buffer, offered, needed);
2505 return getprinter_level_3(servername,snum, buffer, offered, needed);
2507 return ERROR_INVALID_LEVEL;
2512 /********************************************************************
2513 * fill a DRIVER_INFO_1 struct
2514 ********************************************************************/
2515 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
2517 init_unistr( &info->name, driver.info_3->name);
2520 /********************************************************************
2521 * construct_printer_driver_info_1
2522 ********************************************************************/
2523 static uint32 construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
2525 NT_PRINTER_INFO_LEVEL *printer = NULL;
2526 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2528 ZERO_STRUCT(driver);
2530 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2531 return ERROR_INVALID_PRINTER_NAME;
2533 if (get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2534 return ERROR_UNKNOWN_PRINTER_DRIVER;
2536 fill_printer_driver_info_1(info, driver, servername, architecture);
2538 free_a_printer(&printer,2);
2540 return NT_STATUS_NO_PROBLEMO;
2543 /********************************************************************
2544 * construct_printer_driver_info_2
2545 * fill a printer_info_2 struct
2546 ********************************************************************/
2547 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2549 pstring temp_driverpath;
2550 pstring temp_datafile;
2551 pstring temp_configfile;
2553 info->version=driver.info_3->cversion;
2555 init_unistr( &info->name, driver.info_3->name );
2556 init_unistr( &info->architecture, driver.info_3->environment );
2558 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2559 init_unistr( &info->driverpath, temp_driverpath );
2561 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2562 init_unistr( &info->datafile, temp_datafile );
2564 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2565 init_unistr( &info->configfile, temp_configfile );
2568 /********************************************************************
2569 * construct_printer_driver_info_2
2570 * fill a printer_info_2 struct
2571 ********************************************************************/
2572 static uint32 construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
2574 NT_PRINTER_INFO_LEVEL *printer = NULL;
2575 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2577 ZERO_STRUCT(printer);
2578 ZERO_STRUCT(driver);
2580 if (!get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
2581 return ERROR_INVALID_PRINTER_NAME;
2583 if (!get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version) != 0)
2584 return ERROR_UNKNOWN_PRINTER_DRIVER;
2586 fill_printer_driver_info_2(info, driver, servername);
2588 free_a_printer(&printer,2);
2590 return NT_STATUS_NO_PROBLEMO;
2593 /********************************************************************
2594 * copy a strings array and convert to UNICODE
2596 * convert an array of ascii string to a UNICODE string
2597 ********************************************************************/
2598 static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
2605 DEBUG(6,("init_unistr_array\n"));
2609 if (char_array == NULL)
2613 if (!v) v = ""; /* hack to handle null lists */
2615 if (strlen(v) == 0) break;
2616 snprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
2617 DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
2618 if((*uni_array=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
2619 DEBUG(0,("init_unistr_array: Realloc error\n" ));
2622 j += (dos_PutUniCode((char *)(*uni_array+j), line , sizeof(uint16)*strlen(line), True) / sizeof(uint16) );
2627 (*uni_array)[j]=0x0000;
2630 DEBUGADD(6,("last one:done\n"));
2633 /********************************************************************
2634 * construct_printer_info_3
2635 * fill a printer_info_3 struct
2636 ********************************************************************/
2637 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
2639 pstring temp_driverpath;
2640 pstring temp_datafile;
2641 pstring temp_configfile;
2642 pstring temp_helpfile;
2644 info->version=driver.info_3->cversion;
2646 init_unistr( &info->name, driver.info_3->name );
2647 init_unistr( &info->architecture, driver.info_3->environment );
2649 snprintf(temp_driverpath, sizeof(temp_driverpath)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
2650 init_unistr( &info->driverpath, temp_driverpath );
2652 snprintf(temp_datafile, sizeof(temp_datafile)-1, "\\\\%s%s", servername, driver.info_3->datafile);
2653 init_unistr( &info->datafile, temp_datafile );
2655 snprintf(temp_configfile, sizeof(temp_configfile)-1, "\\\\%s%s", servername, driver.info_3->configfile);
2656 init_unistr( &info->configfile, temp_configfile );
2658 snprintf(temp_helpfile, sizeof(temp_helpfile)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
2659 init_unistr( &info->helpfile, temp_helpfile );
2661 init_unistr( &info->monitorname, driver.info_3->monitorname );
2662 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
2664 info->dependentfiles=NULL;
2665 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
2668 /********************************************************************
2669 * construct_printer_info_3
2670 * fill a printer_info_3 struct
2671 ********************************************************************/
2672 static uint32 construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
2674 NT_PRINTER_INFO_LEVEL *printer = NULL;
2675 NT_PRINTER_DRIVER_INFO_LEVEL driver;
2677 ZERO_STRUCT(driver);
2679 status=get_a_printer(&printer, 2, lp_servicename(snum) );
2680 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2682 return ERROR_INVALID_PRINTER_NAME;
2684 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
2685 DEBUG(8,("construct_printer_driver_info_3: status: %d\n", status));
2687 free_a_printer(&printer,2);
2688 return ERROR_UNKNOWN_PRINTER_DRIVER;
2691 fill_printer_driver_info_3(info, driver, servername);
2693 free_a_printer(&printer,2);
2695 return NT_STATUS_NO_PROBLEMO;
2698 /****************************************************************************
2699 ****************************************************************************/
2701 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
2703 safe_free(info->dependentfiles);
2706 /****************************************************************************
2707 ****************************************************************************/
2708 static uint32 getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2710 DRIVER_INFO_1 *info=NULL;
2713 if((info=(DRIVER_INFO_1 *)malloc(sizeof(DRIVER_INFO_1))) == NULL)
2714 return ERROR_NOT_ENOUGH_MEMORY;
2716 status=construct_printer_driver_info_1(info, snum, servername, architecture, version);
2717 if (status != NT_STATUS_NO_PROBLEMO) {
2722 /* check the required size. */
2723 *needed += spoolss_size_printer_driver_info_1(info);
2725 if (!alloc_buffer_size(buffer, *needed)) {
2727 return ERROR_INSUFFICIENT_BUFFER;
2730 /* fill the buffer with the structures */
2731 new_smb_io_printer_driver_info_1("", buffer, info, 0);
2736 if (*needed > offered)
2737 return ERROR_INSUFFICIENT_BUFFER;
2739 return NT_STATUS_NO_PROBLEMO;
2742 /****************************************************************************
2743 ****************************************************************************/
2744 static uint32 getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2746 DRIVER_INFO_2 *info=NULL;
2749 if((info=(DRIVER_INFO_2 *)malloc(sizeof(DRIVER_INFO_2))) == NULL)
2750 return ERROR_NOT_ENOUGH_MEMORY;
2752 status=construct_printer_driver_info_2(info, snum, servername, architecture, version);
2753 if (status != NT_STATUS_NO_PROBLEMO) {
2758 /* check the required size. */
2759 *needed += spoolss_size_printer_driver_info_2(info);
2761 if (!alloc_buffer_size(buffer, *needed)) {
2763 return ERROR_INSUFFICIENT_BUFFER;
2766 /* fill the buffer with the structures */
2767 new_smb_io_printer_driver_info_2("", buffer, info, 0);
2772 if (*needed > offered)
2773 return ERROR_INSUFFICIENT_BUFFER;
2775 return NT_STATUS_NO_PROBLEMO;
2778 /****************************************************************************
2779 ****************************************************************************/
2780 static uint32 getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
2787 status=construct_printer_driver_info_3(&info, snum, servername, architecture, version);
2788 if (status != NT_STATUS_NO_PROBLEMO) {
2792 /* check the required size. */
2793 *needed += spoolss_size_printer_driver_info_3(&info);
2795 if (!alloc_buffer_size(buffer, *needed)) {
2796 free_printer_driver_info_3(&info);
2797 return ERROR_INSUFFICIENT_BUFFER;
2800 /* fill the buffer with the structures */
2801 new_smb_io_printer_driver_info_3("", buffer, &info, 0);
2803 free_printer_driver_info_3(&info);
2805 if (*needed > offered)
2806 return ERROR_INSUFFICIENT_BUFFER;
2808 return NT_STATUS_NO_PROBLEMO;
2811 /****************************************************************************
2812 ****************************************************************************/
2813 uint32 _spoolss_getprinterdriver2(POLICY_HND *handle, const UNISTR2 *uni_arch, uint32 level,
2814 uint32 clientmajorversion, uint32 clientminorversion,
2815 NEW_BUFFER *buffer, uint32 offered,
2816 uint32 *needed, uint32 *servermajorversion, uint32 *serverminorversion)
2819 fstring architecture;
2822 DEBUG(4,("_spoolss_getprinterdriver2\n"));
2825 *servermajorversion=0;
2826 *serverminorversion=0;
2828 pstrcpy(servername, global_myname);
2829 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
2831 if (!get_printer_snum(handle, &snum))
2832 return ERROR_INVALID_HANDLE;
2836 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2839 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2842 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
2845 return ERROR_INVALID_LEVEL;
2850 /****************************************************************************
2851 ****************************************************************************/
2852 uint32 _spoolss_startpageprinter(POLICY_HND *handle)
2854 Printer_entry *Printer = find_printer_index_by_hnd(handle);
2856 if (OPEN_HANDLE(Printer)) {
2857 Printer->page_started=True;
2861 DEBUG(3,("Error in startpageprinter printer handle\n"));
2862 return ERROR_INVALID_HANDLE;
2865 /****************************************************************************
2866 ****************************************************************************/
2867 uint32 _spoolss_endpageprinter(POLICY_HND *handle)
2869 Printer_entry *Printer = find_printer_index_by_hnd(handle);
2871 if (!OPEN_HANDLE(Printer)) {
2872 DEBUG(0,("_spoolss_endpageprinter: Invalid handle (%s).\n",OUR_HANDLE(handle)));
2873 return ERROR_INVALID_HANDLE;
2876 Printer->page_started=False;
2878 return NT_STATUS_NO_PROBLEMO;
2882 /********************************************************************
2883 * api_spoolss_getprinter
2884 * called from the spoolss dispatcher
2886 ********************************************************************/
2887 uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
2888 pipes_struct *p, DOC_INFO *docinfo,
2891 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
2895 Printer_entry *Printer = find_printer_index_by_hnd(handle);
2896 struct current_user user;
2898 if (!OPEN_HANDLE(Printer)) {
2899 DEBUG(0,("_spoolss_startdocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
2900 return ERROR_INVALID_HANDLE;
2903 if (p->ntlmssp_auth_validated) {
2904 memcpy(&user, &p->pipe_user, sizeof(user));
2906 extern struct current_user current_user;
2907 memcpy(&user, ¤t_user, sizeof(user));
2911 * a nice thing with NT is it doesn't listen to what you tell it.
2912 * when asked to send _only_ RAW datas, it tries to send datas
2915 * So I add checks like in NT Server ...
2917 * lkclXXXX jean-francois, i love this kind of thing. oh, well,
2918 * there's a bug in NT client-side code, so we'll fix it in the
2919 * server-side code. *nnnnnggggh!*
2922 if (info_1->p_datatype != 0) {
2923 unistr2_to_ascii(datatype, &info_1->docname, sizeof(datatype));
2924 if (strcmp(datatype, "RAW") != 0) {
2926 return ERROR_INVALID_DATATYPE;
2930 /* get the share number of the printer */
2931 if (!get_printer_snum(handle, &snum)) {
2932 return ERROR_INVALID_HANDLE;
2935 unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
2937 Printer->jobid = print_job_start(&user, snum, jobname);
2939 /* need to map error codes properly - for now give out of
2940 memory as I don't know the correct codes (tridge) */
2941 if (Printer->jobid == -1) {
2942 return ERROR_NOT_ENOUGH_MEMORY;
2945 Printer->document_started=True;
2946 (*jobid) = Printer->jobid;
2951 /********************************************************************
2952 * api_spoolss_getprinter
2953 * called from the spoolss dispatcher
2955 ********************************************************************/
2956 uint32 _spoolss_enddocprinter(POLICY_HND *handle)
2958 Printer_entry *Printer=find_printer_index_by_hnd(handle);
2960 if (!OPEN_HANDLE(Printer)) {
2961 DEBUG(0,("_spoolss_enddocprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
2962 return ERROR_INVALID_HANDLE;
2965 Printer->document_started=False;
2966 print_job_end(Printer->jobid);
2967 /* error codes unhandled so far ... */
2972 /****************************************************************************
2973 ****************************************************************************/
2974 uint32 _spoolss_writeprinter( POLICY_HND *handle,
2977 uint32 *buffer_written)
2979 Printer_entry *Printer = find_printer_index_by_hnd(handle);
2981 if (!OPEN_HANDLE(Printer)) {
2982 DEBUG(0,("_spoolss_writeprinter: Invalid handle (%s)\n",OUR_HANDLE(handle)));
2983 return ERROR_INVALID_HANDLE;
2986 (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer,
2992 /********************************************************************
2993 * api_spoolss_getprinter
2994 * called from the spoolss dispatcher
2996 ********************************************************************/
2997 static uint32 control_printer(POLICY_HND *handle, uint32 command,
3000 struct current_user user;
3003 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3005 if (p->ntlmssp_auth_validated) {
3006 memcpy(&user, &p->pipe_user, sizeof(user));
3008 extern struct current_user current_user;
3009 memcpy(&user, ¤t_user, sizeof(user));
3012 if (!OPEN_HANDLE(Printer)) {
3013 DEBUG(0,("control_printer: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3014 return ERROR_INVALID_HANDLE;
3017 if (!get_printer_snum(handle, &snum) )
3018 return ERROR_INVALID_HANDLE;
3021 case PRINTER_CONTROL_PAUSE:
3022 if (print_queue_pause(&user, snum, &errcode)) {
3026 case PRINTER_CONTROL_RESUME:
3027 case PRINTER_CONTROL_UNPAUSE:
3028 if (print_queue_resume(&user, snum, &errcode)) {
3032 case PRINTER_CONTROL_PURGE:
3033 if (print_queue_purge(&user, snum, &errcode)) {
3040 return (uint32)errcode;
3042 return ERROR_INVALID_FUNCTION;
3045 /********************************************************************
3046 * api_spoolss_abortprinter
3047 ********************************************************************/
3049 uint32 _spoolss_abortprinter(POLICY_HND *handle, pipes_struct *p)
3051 return control_printer(handle, PRINTER_CONTROL_PURGE, p);
3054 /********************************************************************
3055 * called by spoolss_api_setprinter
3056 * when updating a printer description
3057 ********************************************************************/
3058 static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
3059 const SPOOL_PRINTER_INFO_LEVEL *info,
3060 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
3062 struct current_user user;
3066 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3068 if (!OPEN_HANDLE(Printer) || !get_printer_snum(handle, &snum)) {
3069 DEBUG(0,("update_printer_sec: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3070 return ERROR_INVALID_HANDLE;
3073 /* Work out which user is performing the operation */
3074 if (p->ntlmssp_auth_validated) {
3075 memcpy(&user, &p->pipe_user, sizeof(user));
3077 extern struct current_user current_user;
3078 memcpy(&user, ¤t_user, sizeof(user));
3081 /* Check the user has permissions to change the security
3082 descriptor. By experimentation with two NT machines, the user
3083 requires Full Access to the printer to change security
3085 if (!print_access_check(&user, snum, PRINTER_ACE_FULL_CONTROL)) {
3086 result = ERROR_ACCESS_DENIED;
3090 result = nt_printing_setsec(Printer->dev.handlename, secdesc_ctr);
3096 /********************************************************************
3097 Do Samba sanity checks on a printer info struct.
3098 ********************************************************************/
3100 static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
3103 * Ensure that this printer is shared under the correct name
3104 * as this is what Samba insists upon.
3107 if (!(info->attributes & PRINTER_ATTRIBUTE_SHARED)) {
3108 DEBUG(10,("check_printer_ok: SHARED check failed (%x).\n", (unsigned int)info->attributes ));
3112 if (!(info->attributes & PRINTER_ATTRIBUTE_RAW_ONLY)) {
3113 /* NT forgets to set the raw attribute but sends the correct type. */
3114 if (strequal(info->datatype, "RAW"))
3115 info->attributes |= PRINTER_ATTRIBUTE_RAW_ONLY;
3117 DEBUG(10,("check_printer_ok: RAW check failed (%x).\n", (unsigned int)info->attributes ));
3122 if (!strequal(info->sharename, lp_servicename(snum))) {
3123 DEBUG(10,("check_printer_ok: NAME check failed (%s) (%s).\n", info->sharename, lp_servicename(snum)));
3130 /****************************************************************************
3131 ****************************************************************************/
3132 static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
3134 pid_t local_pid = sys_getpid();
3135 char *cmd = lp_addprinter_cmd();
3140 pstring driverlocation;
3144 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
3145 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
3149 /* build driver path... only 9X architecture is needed for legacy reasons */
3150 slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
3152 /* change \ to \\ for the shell */
3153 all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
3155 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
3156 slprintf(command, sizeof(command), "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
3157 cmd, printer->info_2->printername, printer->info_2->sharename,
3158 printer->info_2->portname, printer->info_2->drivername,
3159 printer->info_2->location, driverlocation);
3162 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
3163 ret = smbrun(command, tmp_file, False);
3164 DEBUGADD(10,("returned [%d]\n", ret));
3168 free_a_printer(&printer,2);
3173 qlines = file_lines_load(tmp_file, &numlines);
3174 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
3175 DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
3176 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
3180 // Set the portname to what the script says the portname should be
3181 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
3183 // Send SIGHUP to process group... is there a better way?
3188 file_lines_free(qlines);
3192 /********************************************************************
3193 * called by spoolss_api_setprinter
3194 * when updating a printer description
3195 ********************************************************************/
3197 static uint32 update_printer(POLICY_HND *handle, uint32 level,
3198 const SPOOL_PRINTER_INFO_LEVEL *info,
3199 DEVICEMODE *devmode)
3202 NT_PRINTER_INFO_LEVEL *printer = NULL;
3203 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3206 DEBUG(8,("update_printer\n"));
3208 result = NT_STATUS_NO_PROBLEMO;
3210 /* Check calling user has permission to update printer description */
3213 DEBUG(0,("Send a mail to samba@samba.org\n"));
3214 DEBUGADD(0,("with the following message: update_printer: level!=2\n"));
3215 result = ERROR_INVALID_LEVEL;
3219 if (!OPEN_HANDLE(Printer)) {
3220 result = ERROR_INVALID_HANDLE;
3224 if (!get_printer_snum(handle, &snum)) {
3225 result = ERROR_INVALID_HANDLE;
3229 if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
3230 DEBUG(3, ("printer property change denied by security "
3232 result = ERROR_ACCESS_DENIED;
3236 if(get_a_printer(&printer, 2, lp_servicename(snum)) != 0) {
3237 result = ERROR_INVALID_HANDLE;
3241 DEBUGADD(8,("Converting info_2 struct\n"));
3244 * convert_printer_info converts the incoming
3245 * info from the client and overwrites the info
3246 * just read from the tdb in the pointer 'printer'.
3249 convert_printer_info(info, printer, level);
3251 if (info->info_2->devmode_ptr != 0) {
3252 /* we have a valid devmode
3253 convert it and link it*/
3256 * Ensure printer->info_2->devmode is a valid pointer
3257 * as we will be overwriting it in convert_devicemode().
3260 if (printer->info_2->devmode == NULL)
3261 printer->info_2->devmode = construct_nt_devicemode(printer->info_2->printername);
3263 DEBUGADD(8,("Converting the devicemode struct\n"));
3264 convert_devicemode(devmode, printer->info_2->devmode);
3267 if (printer->info_2->devmode != NULL)
3268 free_nt_devicemode(&printer->info_2->devmode);
3269 printer->info_2->devmode=NULL;
3273 * Do sanity check on the requested changes for Samba.
3276 if (!check_printer_ok(printer->info_2, snum)) {
3277 result = ERROR_INVALID_PARAMETER;
3281 if (*lp_addprinter_cmd() )
3282 if ( !add_printer_hook(printer) ) {
3283 result = ERROR_ACCESS_DENIED;
3287 if (add_a_printer(*printer, 2)!=0) {
3288 /* I don't really know what to return here !!! */
3289 result = ERROR_ACCESS_DENIED;
3294 free_a_printer(&printer, 2);
3299 /****************************************************************************
3300 ****************************************************************************/
3301 uint32 _spoolss_setprinter(POLICY_HND *handle, uint32 level,
3302 const SPOOL_PRINTER_INFO_LEVEL *info,
3303 DEVMODE_CTR devmode_ctr,
3304 SEC_DESC_BUF *secdesc_ctr,
3305 uint32 command, pipes_struct *p)
3307 Printer_entry *Printer = find_printer_index_by_hnd(handle);
3309 if (!OPEN_HANDLE(Printer)) {
3310 DEBUG(0,("_spoolss_setprinter: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3311 return ERROR_INVALID_HANDLE;
3314 /* check the level */
3317 return control_printer(handle, command, p);
3320 return update_printer(handle, level, info, devmode_ctr.devmode);
3323 return update_printer_sec(handle, level, info, p,
3327 return ERROR_INVALID_LEVEL;
3332 /****************************************************************************
3333 ****************************************************************************/
3334 uint32 _spoolss_fcpn(POLICY_HND *handle)
3336 Printer_entry *Printer= find_printer_index_by_hnd(handle);
3338 if (!OPEN_HANDLE(Printer)) {
3339 DEBUG(0,("_spoolss_fcpn: Invalid handle (%s)\n", OUR_HANDLE(handle)));
3340 return ERROR_INVALID_HANDLE;
3343 Printer->notify.flags=0;
3344 Printer->notify.options=0;
3345 Printer->notify.localmachine[0]='\0';
3346 Printer->notify.printerlocal=0;
3347 if (Printer->notify.option)
3348 safe_free(Printer->notify.option->ctr.type);
3349 safe_free(Printer->notify.option);
3350 Printer->notify.option=NULL;
3352 return NT_STATUS_NO_PROBLEMO;
3355 /****************************************************************************
3356 ****************************************************************************/
3357 uint32 _spoolss_addjob(POLICY_HND *handle, uint32 level,
3358 NEW_BUFFER *buffer, uint32 offered,
3362 return ERROR_INVALID_PARAMETER; /* this is what a NT server
3363 returns for AddJob. AddJob
3364 must fail on non-local
3368 /****************************************************************************
3369 ****************************************************************************/
3370 static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue,
3371 int position, int snum)
3376 time_t unixdate = time(NULL);
3378 t=gmtime(&unixdate);
3379 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3381 job_info->jobid=queue->job;
3382 init_unistr(&job_info->printername, lp_servicename(snum));
3383 init_unistr(&job_info->machinename, temp_name);
3384 init_unistr(&job_info->username, queue->user);
3385 init_unistr(&job_info->document, queue->file);
3386 init_unistr(&job_info->datatype, "RAW");
3387 init_unistr(&job_info->text_status, "");
3388 job_info->status=nt_printj_status(queue->status);
3389 job_info->priority=queue->priority;
3390 job_info->position=position;
3391 job_info->totalpages=0;
3392 job_info->pagesprinted=0;
3394 make_systemtime(&job_info->submitted, t);
3397 /****************************************************************************
3398 ****************************************************************************/
3399 static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
3400 int position, int snum)
3403 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3407 time_t unixdate = time(NULL);
3409 if (get_a_printer(&ntprinter, 2, lp_servicename(snum)) !=0 )
3412 t=gmtime(&unixdate);
3413 snprintf(temp_name, sizeof(temp_name), "\\\\%s", global_myname);
3415 job_info->jobid=queue->job;
3417 snprintf(chaine, sizeof(chaine)-1, "\\\\%s\\%s", global_myname, ntprinter->info_2->printername);
3419 init_unistr(&job_info->printername, chaine);
3421 init_unistr(&job_info->machinename, temp_name);
3422 init_unistr(&job_info->username, queue->user);
3423 init_unistr(&job_info->document, queue->file);
3424 init_unistr(&job_info->notifyname, queue->user);
3425 init_unistr(&job_info->datatype, "RAW");
3426 init_unistr(&job_info->printprocessor, "winprint");
3427 init_unistr(&job_info->parameters, "");
3428 init_unistr(&job_info->text_status, "");
3430 /* and here the security descriptor */
3432 job_info->status=nt_printj_status(queue->status);
3433 job_info->priority=queue->priority;
3434 job_info->position=position;
3435 job_info->starttime=0;
3436 job_info->untiltime=0;
3437 job_info->totalpages=0;
3438 job_info->size=queue->size;
3439 make_systemtime(&(job_info->submitted), t);
3440 job_info->timeelapsed=0;
3441 job_info->pagesprinted=0;
3443 if((job_info->devmode = construct_dev_mode(snum, global_myname)) == NULL) {
3444 free_a_printer(&ntprinter, 2);
3448 free_a_printer(&ntprinter, 2);
3452 /****************************************************************************
3453 Enumjobs at level 1.
3454 ****************************************************************************/
3455 static uint32 enumjobs_level1(print_queue_struct *queue, int snum,
3456 NEW_BUFFER *buffer, uint32 offered,
3457 uint32 *needed, uint32 *returned)
3462 info=(JOB_INFO_1 *)malloc(*returned*sizeof(JOB_INFO_1));
3466 return ERROR_NOT_ENOUGH_MEMORY;
3469 for (i=0; i<*returned; i++)
3470 fill_job_info_1(&info[i], &queue[i], i, snum);
3474 /* check the required size. */
3475 for (i=0; i<*returned; i++)
3476 (*needed) += spoolss_size_job_info_1(&info[i]);
3478 if (!alloc_buffer_size(buffer, *needed)) {
3480 return ERROR_INSUFFICIENT_BUFFER;
3483 /* fill the buffer with the structures */
3484 for (i=0; i<*returned; i++)
3485 new_smb_io_job_info_1("", buffer, &info[i], 0);
3490 if (*needed > offered) {
3492 return ERROR_INSUFFICIENT_BUFFER;
3495 return NT_STATUS_NO_PROBLEMO;
3498 /****************************************************************************
3499 Enumjobs at level 2.
3500 ****************************************************************************/
3501 static uint32 enumjobs_level2(print_queue_struct *queue, int snum,
3502 NEW_BUFFER *buffer, uint32 offered,
3503 uint32 *needed, uint32 *returned)
3508 info=(JOB_INFO_2 *)malloc(*returned*sizeof(JOB_INFO_2));
3512 return ERROR_NOT_ENOUGH_MEMORY;
3515 for (i=0; i<*returned; i++)
3516 fill_job_info_2(&(info[i]), &queue[i], i, snum);
3520 /* check the required size. */
3521 for (i=0; i<*returned; i++)
3522 (*needed) += spoolss_size_job_info_2(&info[i]);
3524 if (!alloc_buffer_size(buffer, *needed)) {
3526 return ERROR_INSUFFICIENT_BUFFER;
3529 /* fill the buffer with the structures */
3530 for (i=0; i<*returned; i++)
3531 new_smb_io_job_info_2("", buffer, &info[i], 0);
3536 if (*needed > offered) {
3538 return ERROR_INSUFFICIENT_BUFFER;
3541 return NT_STATUS_NO_PROBLEMO;
3544 /****************************************************************************
3546 ****************************************************************************/
3547 uint32 _spoolss_enumjobs( POLICY_HND *handle, uint32 firstjob, uint32 numofjobs, uint32 level,
3548 NEW_BUFFER *buffer, uint32 offered,
3549 uint32 *needed, uint32 *returned)
3552 print_queue_struct *queue=NULL;
3553 print_status_struct prt_status;
3555 DEBUG(4,("_spoolss_enumjobs\n"));
3557 ZERO_STRUCT(prt_status);
3562 if (!get_printer_snum(handle, &snum))
3563 return ERROR_INVALID_HANDLE;
3565 *returned = print_queue_status(snum, &queue, &prt_status);
3566 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
3570 return enumjobs_level1(queue, snum, buffer, offered, needed, returned);
3573 return enumjobs_level2(queue, snum, buffer, offered, needed, returned);
3578 return ERROR_INVALID_LEVEL;
3584 /****************************************************************************
3585 ****************************************************************************/
3586 uint32 _spoolss_schedulejob( POLICY_HND *handle, uint32 jobid)
3591 /****************************************************************************
3592 ****************************************************************************/
3593 uint32 _spoolss_setjob( POLICY_HND *handle,
3601 struct current_user user;
3603 print_status_struct prt_status;
3605 memset(&prt_status, 0, sizeof(prt_status));
3607 if (!get_printer_snum(handle, &snum)) {
3608 return ERROR_INVALID_HANDLE;
3611 if (!print_job_exists(jobid)) {
3612 return ERROR_INVALID_PRINTER_NAME;
3615 if (p->ntlmssp_auth_validated) {
3616 memcpy(&user, &p->pipe_user, sizeof(user));
3618 extern struct current_user current_user;
3619 memcpy(&user, ¤t_user, sizeof(user));
3623 case JOB_CONTROL_CANCEL:
3624 case JOB_CONTROL_DELETE:
3625 if (print_job_delete(&user, jobid)) return 0x0;
3627 case JOB_CONTROL_PAUSE:
3628 if (print_job_pause(&user, jobid)) return 0x0;
3630 case JOB_CONTROL_RESUME:
3631 if (print_job_resume(&user, jobid)) return 0x0;
3634 return ERROR_INVALID_LEVEL;
3637 return ERROR_INVALID_HANDLE;
3640 /****************************************************************************
3641 Enumerates all printer drivers at level 1.
3642 ****************************************************************************/
3643 static uint32 enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3648 fstring *list = NULL;
3650 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3651 DRIVER_INFO_1 *driver_info_1=NULL;
3655 #define MAX_VERSION 4
3657 for (version=0; version<MAX_VERSION; version++) {
3659 ndrivers=get_ntdrivers(&list, architecture, version);
3660 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3663 return ERROR_NOT_ENOUGH_MEMORY;
3666 if((driver_info_1=(DRIVER_INFO_1 *)Realloc(driver_info_1, (*returned+ndrivers) * sizeof(DRIVER_INFO_1))) == NULL) {
3668 return ERROR_NOT_ENOUGH_MEMORY;
3672 for (i=0; i<ndrivers; i++) {
3673 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3674 ZERO_STRUCT(driver);
3675 get_a_printer_driver(&driver, 3, list[i], architecture, version);
3676 fill_printer_driver_info_1(&(driver_info_1[*returned+i]), driver, servername, architecture );
3679 *returned+=ndrivers;
3683 /* check the required size. */
3684 for (i=0; i<*returned; i++) {
3685 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3686 *needed += spoolss_size_printer_driver_info_1(&(driver_info_1[i]));
3689 if (!alloc_buffer_size(buffer, *needed)) {
3690 safe_free(driver_info_1);
3691 return ERROR_INSUFFICIENT_BUFFER;
3694 /* fill the buffer with the form structures */
3695 for (i=0; i<*returned; i++) {
3696 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3697 new_smb_io_printer_driver_info_1("", buffer, &(driver_info_1[i]), 0);
3700 safe_free(driver_info_1);
3702 if (*needed > offered) {
3704 return ERROR_INSUFFICIENT_BUFFER;
3707 return NT_STATUS_NO_PROBLEMO;
3710 /****************************************************************************
3711 Enumerates all printer drivers at level 2.
3712 ****************************************************************************/
3713 static uint32 enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3718 fstring *list = NULL;
3720 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3721 DRIVER_INFO_2 *driver_info_2=NULL;
3725 #define MAX_VERSION 4
3727 for (version=0; version<MAX_VERSION; version++) {
3729 ndrivers=get_ntdrivers(&list, architecture, version);
3730 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3733 return ERROR_NOT_ENOUGH_MEMORY;
3736 if((driver_info_2=(DRIVER_INFO_2 *)Realloc(driver_info_2, (*returned+ndrivers) * sizeof(DRIVER_INFO_2))) == NULL) {
3738 return ERROR_NOT_ENOUGH_MEMORY;
3742 for (i=0; i<ndrivers; i++) {
3743 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3744 ZERO_STRUCT(driver);
3745 get_a_printer_driver(&driver, 3, list[i], architecture, version);
3746 fill_printer_driver_info_2(&(driver_info_2[*returned+i]), driver, servername);
3749 *returned+=ndrivers;
3753 /* check the required size. */
3754 for (i=0; i<*returned; i++) {
3755 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3756 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
3759 if (!alloc_buffer_size(buffer, *needed)) {
3760 safe_free(driver_info_2);
3761 return ERROR_INSUFFICIENT_BUFFER;
3764 /* fill the buffer with the form structures */
3765 for (i=0; i<*returned; i++) {
3766 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3767 new_smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
3770 safe_free(driver_info_2);
3772 if (*needed > offered) {
3774 return ERROR_INSUFFICIENT_BUFFER;
3777 return NT_STATUS_NO_PROBLEMO;
3780 /****************************************************************************
3781 Enumerates all printer drivers at level 3.
3782 ****************************************************************************/
3783 static uint32 enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3788 fstring *list = NULL;
3790 NT_PRINTER_DRIVER_INFO_LEVEL driver;
3791 DRIVER_INFO_3 *driver_info_3=NULL;
3795 #define MAX_VERSION 4
3797 for (version=0; version<MAX_VERSION; version++) {
3799 ndrivers=get_ntdrivers(&list, architecture, version);
3800 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
3803 return ERROR_NOT_ENOUGH_MEMORY;
3806 if((driver_info_3=(DRIVER_INFO_3 *)Realloc(driver_info_3, (*returned+ndrivers) * sizeof(DRIVER_INFO_3))) == NULL) {
3808 return ERROR_NOT_ENOUGH_MEMORY;
3812 for (i=0; i<ndrivers; i++) {
3813 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
3814 ZERO_STRUCT(driver);
3815 get_a_printer_driver(&driver, 3, list[i], architecture, version);
3816 fill_printer_driver_info_3(&(driver_info_3[*returned+i]), driver, servername);
3819 *returned+=ndrivers;
3823 /* check the required size. */
3824 for (i=0; i<*returned; i++) {
3825 DEBUGADD(6,("adding driver [%d]'s size\n",i));
3826 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
3829 if (!alloc_buffer_size(buffer, *needed)) {
3830 safe_free(driver_info_3);
3831 return ERROR_INSUFFICIENT_BUFFER;
3834 /* fill the buffer with the driver structures */
3835 for (i=0; i<*returned; i++) {
3836 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
3837 new_smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
3840 for (i=0; i<*returned; i++)
3841 safe_free(driver_info_3[i].dependentfiles);
3843 safe_free(driver_info_3);
3845 if (*needed > offered) {
3847 return ERROR_INSUFFICIENT_BUFFER;
3850 return NT_STATUS_NO_PROBLEMO;
3853 /****************************************************************************
3854 Enumerates all printer drivers.
3855 ****************************************************************************/
3856 uint32 _spoolss_enumprinterdrivers( UNISTR2 *name, UNISTR2 *environment, uint32 level,
3857 NEW_BUFFER *buffer, uint32 offered,
3858 uint32 *needed, uint32 *returned)
3860 fstring *list = NULL;
3862 fstring architecture;
3864 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
3865 fstrcpy(servername, global_myname);
3869 unistr2_to_ascii(architecture, environment, sizeof(architecture)-1);
3873 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
3876 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
3879 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
3884 return ERROR_INVALID_LEVEL;
3889 /****************************************************************************
3890 ****************************************************************************/
3891 static void fill_form_1(FORM_1 *form, nt_forms_struct *list, int position)
3893 form->flag=list->flag;
3894 init_unistr(&form->name, list->name);
3895 form->width=list->width;
3896 form->length=list->length;
3897 form->left=list->left;
3898 form->top=list->top;
3899 form->right=list->right;
3900 form->bottom=list->bottom;
3903 /****************************************************************************
3904 ****************************************************************************/
3905 uint32 _new_spoolss_enumforms( POLICY_HND *handle, uint32 level,
3906 NEW_BUFFER *buffer, uint32 offered,
3907 uint32 *needed, uint32 *numofforms)
3909 nt_forms_struct *list=NULL;
3914 DEBUG(4,("_new_spoolss_enumforms\n"));
3915 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
3916 DEBUGADD(5,("Info level [%d]\n", level));
3918 *numofforms = get_ntforms(&list);
3919 DEBUGADD(5,("Number of forms [%d]\n", *numofforms));
3921 if (*numofforms == 0) return ERROR_NO_MORE_ITEMS;
3925 if ((forms_1=(FORM_1 *)malloc(*numofforms * sizeof(FORM_1))) == NULL) {
3927 return ERROR_NOT_ENOUGH_MEMORY;
3930 /* construct the list of form structures */
3931 for (i=0; i<*numofforms; i++) {
3932 DEBUGADD(6,("Filling form number [%d]\n",i));
3933 fill_form_1(&forms_1[i], &list[i], i);
3938 /* check the required size. */
3939 for (i=0; i<*numofforms; i++) {
3940 DEBUGADD(6,("adding form [%d]'s size\n",i));
3941 buffer_size += spoolss_size_form_1(&forms_1[i]);
3944 *needed=buffer_size;
3946 if (!alloc_buffer_size(buffer, buffer_size)){
3948 return ERROR_INSUFFICIENT_BUFFER;
3951 /* fill the buffer with the form structures */
3952 for (i=0; i<*numofforms; i++) {
3953 DEBUGADD(6,("adding form [%d] to buffer\n",i));
3954 new_smb_io_form_1("", buffer, &forms_1[i], 0);
3959 if (*needed > offered) {
3961 return ERROR_INSUFFICIENT_BUFFER;
3964 return NT_STATUS_NO_PROBLEMO;
3968 return ERROR_INVALID_LEVEL;
3973 /****************************************************************************
3974 ****************************************************************************/
3975 static void fill_port_1(PORT_INFO_1 *port, char *name)
3977 init_unistr(&port->port_name, name);
3980 /****************************************************************************
3981 ****************************************************************************/
3982 static void fill_port_2(PORT_INFO_2 *port, char *name)
3984 init_unistr(&port->port_name, name);
3985 init_unistr(&port->monitor_name, "Local Monitor");
3986 init_unistr(&port->description, "Local Port");
3987 #define PORT_TYPE_WRITE 1
3988 port->port_type=PORT_TYPE_WRITE;
3992 /****************************************************************************
3994 ****************************************************************************/
3995 static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
3997 PORT_INFO_1 *ports=NULL;
4000 if (*lp_enumports_cmd()) {
4001 pid_t local_pid = sys_getpid();
4002 char *cmd = lp_enumports_cmd();
4010 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4011 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4015 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4016 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 1);
4019 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4020 ret = smbrun(command, tmp_file, False);
4021 DEBUG(10,("Returned [%d]\n", ret));
4024 // Is this the best error to return here?
4025 return ERROR_ACCESS_DENIED;
4029 qlines = file_lines_load(tmp_file, &numlines);
4030 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4031 DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
4032 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4036 if((ports=(PORT_INFO_1 *)malloc( numlines * sizeof(PORT_INFO_1) )) == NULL) {
4037 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4038 file_lines_free(qlines);
4039 return ERROR_NOT_ENOUGH_MEMORY;
4042 for (i=0; i<numlines; i++) {
4043 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4044 fill_port_1(&ports[i], qlines[i]);
4047 file_lines_free(qlines);
4050 *returned = numlines;
4053 *returned = 1; /* Sole Samba port returned. */
4055 if((ports=(PORT_INFO_1 *)malloc( sizeof(PORT_INFO_1) )) == NULL)
4056 return ERROR_NOT_ENOUGH_MEMORY;
4058 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4060 fill_port_1(&ports[0], SAMBA_PRINTER_PORT_NAME);
4063 /* check the required size. */
4064 for (i=0; i<*returned; i++) {
4065 DEBUGADD(6,("adding port [%d]'s size\n", i));
4066 *needed += spoolss_size_port_info_1(&ports[i]);
4069 if (!alloc_buffer_size(buffer, *needed)) {
4071 return ERROR_INSUFFICIENT_BUFFER;
4074 /* fill the buffer with the ports structures */
4075 for (i=0; i<*returned; i++) {
4076 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4077 new_smb_io_port_1("", buffer, &ports[i], 0);
4082 if (*needed > offered) {
4084 return ERROR_INSUFFICIENT_BUFFER;
4087 return NT_STATUS_NO_PROBLEMO;
4090 /****************************************************************************
4092 ****************************************************************************/
4094 static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4096 PORT_INFO_2 *ports=NULL;
4099 if (*lp_enumports_cmd()) {
4100 pid_t local_pid = sys_getpid();
4101 char *cmd = lp_enumports_cmd();
4109 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME)))
4110 path = lp_pathname(lp_servicenumber(PRINTERS_NAME));
4114 slprintf(tmp_file, sizeof(tmp_file), "%s/smbcmd.%d", path, local_pid);
4115 slprintf(command, sizeof(command), "%s \"%d\"", cmd, 2);
4118 DEBUG(10,("Running [%s > %s]\n", command,tmp_file));
4119 ret = smbrun(command, tmp_file, False);
4120 DEBUGADD(10,("returned [%d]\n", ret));
4123 // Is this the best error to return here?
4124 return ERROR_ACCESS_DENIED;
4128 qlines = file_lines_load(tmp_file, &numlines);
4129 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
4130 DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
4131 DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
4135 if((ports=(PORT_INFO_2 *)malloc( numlines * sizeof(PORT_INFO_2) )) == NULL) {
4136 DEBUG(10,("Returning ERROR_NOT_ENOUGH_MEMORY [%x]\n", ERROR_NOT_ENOUGH_MEMORY));
4137 file_lines_free(qlines);
4138 return ERROR_NOT_ENOUGH_MEMORY;
4141 for (i=0; i<numlines; i++) {
4142 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
4143 fill_port_2(&(ports[i]), qlines[i]);
4146 file_lines_free(qlines);
4149 *returned = numlines;
4155 if((ports=(PORT_INFO_2 *)malloc( sizeof(PORT_INFO_2) )) == NULL)
4156 return ERROR_NOT_ENOUGH_MEMORY;
4158 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME));
4160 fill_port_2(&ports[0], SAMBA_PRINTER_PORT_NAME);
4163 /* check the required size. */
4164 for (i=0; i<*returned; i++) {
4165 DEBUGADD(6,("adding port [%d]'s size\n", i));
4166 *needed += spoolss_size_port_info_2(&ports[i]);
4169 if (!alloc_buffer_size(buffer, *needed)) {
4171 return ERROR_INSUFFICIENT_BUFFER;
4174 /* fill the buffer with the ports structures */
4175 for (i=0; i<*returned; i++) {
4176 DEBUGADD(6,("adding port [%d] to buffer\n", i));
4177 new_smb_io_port_2("", buffer, &ports[i], 0);
4182 if (*needed > offered) {
4184 return ERROR_INSUFFICIENT_BUFFER;
4187 return NT_STATUS_NO_PROBLEMO;
4190 /****************************************************************************
4192 ****************************************************************************/
4193 uint32 _spoolss_enumports( UNISTR2 *name, uint32 level,
4194 NEW_BUFFER *buffer, uint32 offered,
4195 uint32 *needed, uint32 *returned)
4197 DEBUG(4,("_spoolss_enumports\n"));
4204 return enumports_level_1(buffer, offered, needed, returned);
4207 return enumports_level_2(buffer, offered, needed, returned);
4210 return ERROR_INVALID_LEVEL;
4215 /****************************************************************************
4216 ****************************************************************************/
4217 static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
4218 const SPOOL_PRINTER_INFO_LEVEL *info,
4219 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4220 uint32 user_switch, const SPOOL_USER_CTR *user,
4223 NT_PRINTER_INFO_LEVEL *printer = NULL;
4227 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
4228 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
4229 return ERROR_NOT_ENOUGH_MEMORY;
4232 ZERO_STRUCTP(printer);
4234 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
4235 convert_printer_info(info, printer, 2);
4237 if (*lp_addprinter_cmd() )
4238 if ( !add_printer_hook(printer) )
4239 return ERROR_ACCESS_DENIED;
4241 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname,
4242 printer->info_2->sharename);
4244 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
4245 free_a_printer(&printer,2);
4246 return ERROR_ACCESS_DENIED;
4249 /* you must be a printer admin to add a new printer */
4250 if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
4251 free_a_printer(&printer,2);
4252 return ERROR_ACCESS_DENIED;
4256 * Do sanity check on the requested changes for Samba.
4259 if (!check_printer_ok(printer->info_2, snum)) {
4260 free_a_printer(&printer,2);
4261 return ERROR_INVALID_PARAMETER;
4264 /* write the ASCII on disk */
4265 if (add_a_printer(*printer, 2) != 0) {
4266 free_a_printer(&printer,2);
4267 return ERROR_ACCESS_DENIED;
4270 if (!open_printer_hnd(handle, name)) {
4271 /* Handle open failed - remove addition. */
4272 del_a_printer(printer->info_2->sharename);
4273 free_a_printer(&printer,2);
4274 return ERROR_ACCESS_DENIED;
4277 free_a_printer(&printer,2);
4278 return NT_STATUS_NO_PROBLEMO;
4281 /****************************************************************************
4282 ****************************************************************************/
4283 uint32 _spoolss_addprinterex( const UNISTR2 *uni_srv_name, uint32 level,
4284 const SPOOL_PRINTER_INFO_LEVEL *info,
4285 uint32 unk0, uint32 unk1, uint32 unk2, uint32 unk3,
4286 uint32 user_switch, const SPOOL_USER_CTR *user,
4291 /* we don't handle yet */
4292 /* but I know what to do ... */
4293 return ERROR_INVALID_LEVEL;
4296 return spoolss_addprinterex_level_2(uni_srv_name, info,
4297 unk0, unk1, unk2, unk3,
4298 user_switch, user, handle);
4301 return ERROR_INVALID_LEVEL;
4306 /****************************************************************************
4307 ****************************************************************************/
4308 uint32 _spoolss_addprinterdriver(pipes_struct *p, const UNISTR2 *server_name,
4309 uint32 level, const SPOOL_PRINTER_DRIVER_INFO_LEVEL *info)
4311 uint32 err = NT_STATUS_NO_PROBLEMO;
4312 NT_PRINTER_DRIVER_INFO_LEVEL driver;
4313 struct current_user user;
4315 ZERO_STRUCT(driver);
4317 if (p->ntlmssp_auth_validated) {
4318 memcpy(&user, &p->pipe_user, sizeof(user));
4320 extern struct current_user current_user;
4321 memcpy(&user, ¤t_user, sizeof(user));
4324 convert_printer_driver_info(info, &driver, level);
4326 DEBUG(5,("Cleaning driver's information\n"));
4327 clean_up_driver_struct(driver, level);
4329 DEBUG(5,("Moving driver to final destination\n"));
4330 if(!move_driver_to_download_area(driver, level, &user, &err)) {
4332 err = ERROR_ACCESS_DENIED;
4336 if (add_a_printer_driver(driver, level)!=0) {
4337 err = ERROR_ACCESS_DENIED;
4342 free_a_printer_driver(driver, level);
4346 /****************************************************************************
4347 ****************************************************************************/
4348 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
4350 init_unistr(&info->name, name);
4353 /****************************************************************************
4354 ****************************************************************************/
4355 static uint32 getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4359 pstring short_archi;
4360 DRIVER_DIRECTORY_1 *info=NULL;
4362 unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1);
4364 if (get_short_archi(short_archi, long_archi)==FALSE)
4365 return ERROR_INVALID_ENVIRONMENT;
4367 if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL)
4368 return ERROR_NOT_ENOUGH_MEMORY;
4370 slprintf(path, sizeof(path)-1, "\\\\%s\\print$\\%s", global_myname, short_archi);
4372 DEBUG(4,("printer driver directory: [%s]\n", path));
4374 fill_driverdir_1(info, path);
4376 *needed += spoolss_size_driverdir_info_1(info);
4378 if (!alloc_buffer_size(buffer, *needed)) {
4380 return ERROR_INSUFFICIENT_BUFFER;
4383 new_smb_io_driverdir_1("", buffer, info, 0);
4387 if (*needed > offered)
4388 return ERROR_INSUFFICIENT_BUFFER;
4390 return NT_STATUS_NO_PROBLEMO;
4393 /****************************************************************************
4394 ****************************************************************************/
4395 uint32 _spoolss_getprinterdriverdirectory(UNISTR2 *name, UNISTR2 *uni_environment, uint32 level,
4396 NEW_BUFFER *buffer, uint32 offered,
4399 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
4405 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
4408 return ERROR_INVALID_LEVEL;
4413 /****************************************************************************
4414 ****************************************************************************/
4415 uint32 _spoolss_enumprinterdata(POLICY_HND *handle, uint32 idx,
4416 uint32 in_value_len, uint32 in_data_len,
4417 uint32 *out_max_value_len, uint16 **out_value, uint32 *out_value_len,
4419 uint32 *out_max_data_len, uint8 **data_out, uint32 *out_data_len)
4421 NT_PRINTER_INFO_LEVEL *printer = NULL;
4426 uint32 biggest_valuesize;
4427 uint32 biggest_datasize;
4429 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4434 ZERO_STRUCT(printer);
4436 *out_max_value_len=0;
4442 *out_max_data_len=0;
4446 DEBUG(5,("spoolss_enumprinterdata\n"));
4448 if (!OPEN_HANDLE(Printer)) {
4449 DEBUG(0,("_spoolss_enumprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4450 return ERROR_INVALID_HANDLE;
4453 if (!get_printer_snum(handle, &snum))
4454 return ERROR_INVALID_HANDLE;
4456 if (get_a_printer(&printer, 2, lp_servicename(snum)) != 0)
4457 return ERROR_INVALID_HANDLE;
4460 * The NT machine wants to know the biggest size of value and data
4462 * cf: MSDN EnumPrinterData remark section
4464 if ( (in_value_len==0) && (in_data_len==0) ) {
4465 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
4468 biggest_valuesize=0;
4471 while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
4472 if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
4473 if (data_len > biggest_datasize) biggest_datasize=data_len;
4475 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
4481 /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
4482 *out_value_len=2*(1+biggest_valuesize);
4483 *out_data_len=biggest_datasize;
4485 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
4487 free_a_printer(&printer, 2);
4488 return NT_STATUS_NO_PROBLEMO;
4492 * the value len is wrong in NT sp3
4493 * that's the number of bytes not the number of unicode chars
4496 if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
4498 free_a_printer(&printer, 2);
4499 return ERROR_NO_MORE_ITEMS;
4502 free_a_printer(&printer, 2);
4506 * - counted in bytes in the request
4507 * - counted in UNICODE chars in the max reply
4508 * - counted in bytes in the real size
4510 * take a pause *before* coding not *during* coding
4513 *out_max_value_len=(in_value_len/sizeof(uint16));
4514 if((*out_value=(uint16 *)malloc(in_value_len*sizeof(uint8))) == NULL) {
4516 return ERROR_NOT_ENOUGH_MEMORY;
4519 ZERO_STRUCTP(*out_value);
4520 *out_value_len = (uint32)dos_PutUniCode((char *)*out_value, value, in_value_len, True);
4524 /* the data is counted in bytes */
4525 *out_max_data_len=in_data_len;
4526 if((*data_out=(uint8 *)malloc(in_data_len*sizeof(uint8))) == NULL) {
4528 return ERROR_NOT_ENOUGH_MEMORY;
4531 ZERO_STRUCTP(*data_out);
4532 memcpy(*data_out, data, (size_t)data_len);
4533 *out_data_len=data_len;
4537 return NT_STATUS_NO_PROBLEMO;
4540 /****************************************************************************
4541 ****************************************************************************/
4542 uint32 _spoolss_setprinterdata( POLICY_HND *handle,
4543 const UNISTR2 *value,
4548 uint32 numeric_data)
4550 NT_PRINTER_INFO_LEVEL *printer = NULL;
4551 NT_PRINTER_PARAM *param = NULL;
4553 uint32 status = 0x0;
4554 Printer_entry *Printer=find_printer_index_by_hnd(handle);
4556 DEBUG(5,("spoolss_setprinterdata\n"));
4559 if (!OPEN_HANDLE(Printer)) {
4560 DEBUG(0,("_spoolss_setprinterdata: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4561 return ERROR_INVALID_HANDLE;
4564 if (!get_printer_snum(handle, &snum))
4565 return ERROR_INVALID_HANDLE;
4567 if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
4568 DEBUG(3, ("security descriptor change denied by existing "
4569 "security descriptor\n"));
4570 return ERROR_ACCESS_DENIED;
4573 status = get_a_printer(&printer, 2, lp_servicename(snum));
4575 return ERROR_INVALID_NAME;
4577 convert_specific_param(¶m, value , type, data, real_len);
4578 unlink_specific_param_if_exist(printer->info_2, param);
4580 if (!add_a_specific_param(printer->info_2, param))
4581 status = ERROR_INVALID_PARAMETER;
4583 status = add_a_printer(*printer, 2);
4585 free_a_printer(&printer, 2);
4589 /****************************************************************************
4590 ****************************************************************************/
4591 uint32 _spoolss_addform( POLICY_HND *handle,
4596 nt_forms_struct *list=NULL;
4597 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4599 DEBUG(5,("spoolss_addform\n"));
4601 if (!OPEN_HANDLE(Printer)) {
4602 DEBUG(0,("_spoolss_addform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4603 return ERROR_INVALID_HANDLE;
4606 count=get_ntforms(&list);
4607 if(!add_a_form(&list, form, &count))
4608 return ERROR_NOT_ENOUGH_MEMORY;
4609 write_ntforms(&list, count);
4616 /****************************************************************************
4617 ****************************************************************************/
4618 uint32 _spoolss_setform( POLICY_HND *handle,
4619 const UNISTR2 *uni_name,
4624 nt_forms_struct *list=NULL;
4625 Printer_entry *Printer = find_printer_index_by_hnd(handle);
4627 DEBUG(5,("spoolss_setform\n"));
4629 if (!OPEN_HANDLE(Printer)) {
4630 DEBUG(0,("_spoolss_setform: Invalid handle (%s).\n", OUR_HANDLE(handle)));
4631 return ERROR_INVALID_HANDLE;
4633 count=get_ntforms(&list);
4634 update_a_form(&list, form, count);
4635 write_ntforms(&list, count);
4642 /****************************************************************************
4643 enumprintprocessors level 1.
4644 ****************************************************************************/
4645 static uint32 enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4647 PRINTPROCESSOR_1 *info_1=NULL;
4649 if((info_1 = (PRINTPROCESSOR_1 *)malloc(sizeof(PRINTPROCESSOR_1))) == NULL)
4650 return ERROR_NOT_ENOUGH_MEMORY;
4654 init_unistr(&info_1->name, "winprint");
4656 *needed += spoolss_size_printprocessor_info_1(info_1);
4658 if (!alloc_buffer_size(buffer, *needed))
4659 return ERROR_INSUFFICIENT_BUFFER;
4661 smb_io_printprocessor_info_1("", buffer, info_1, 0);
4665 if (*needed > offered) {
4667 return ERROR_INSUFFICIENT_BUFFER;
4670 return NT_STATUS_NO_PROBLEMO;
4673 /****************************************************************************
4674 ****************************************************************************/
4675 uint32 _spoolss_enumprintprocessors(UNISTR2 *name, UNISTR2 *environment, uint32 level,
4676 NEW_BUFFER *buffer, uint32 offered,
4677 uint32 *needed, uint32 *returned)
4679 DEBUG(5,("spoolss_enumprintprocessors\n"));
4682 * Enumerate the print processors ...
4684 * Just reply with "winprint", to keep NT happy
4685 * and I can use my nice printer checker.
4693 return enumprintprocessors_level_1(buffer, offered, needed, returned);
4696 return ERROR_INVALID_LEVEL;
4701 /****************************************************************************
4702 enumprintprocdatatypes level 1.
4703 ****************************************************************************/
4704 static uint32 enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4706 PRINTPROCDATATYPE_1 *info_1=NULL;
4708 if((info_1 = (PRINTPROCDATATYPE_1 *)malloc(sizeof(PRINTPROCDATATYPE_1))) == NULL)
4709 return ERROR_NOT_ENOUGH_MEMORY;
4713 init_unistr(&info_1->name, "RAW");
4715 *needed += spoolss_size_printprocdatatype_info_1(info_1);
4717 if (!alloc_buffer_size(buffer, *needed))
4718 return ERROR_INSUFFICIENT_BUFFER;
4720 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
4724 if (*needed > offered) {
4726 return ERROR_INSUFFICIENT_BUFFER;
4729 return NT_STATUS_NO_PROBLEMO;
4732 /****************************************************************************
4733 ****************************************************************************/
4734 uint32 _spoolss_enumprintprocdatatypes(UNISTR2 *name, UNISTR2 *processor, uint32 level,
4735 NEW_BUFFER *buffer, uint32 offered,
4736 uint32 *needed, uint32 *returned)
4738 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
4745 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
4748 return ERROR_INVALID_LEVEL;
4753 /****************************************************************************
4754 enumprintmonitors level 1.
4755 ****************************************************************************/
4756 static uint32 enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4758 PRINTMONITOR_1 *info_1=NULL;
4760 if((info_1 = (PRINTMONITOR_1 *)malloc(sizeof(PRINTMONITOR_1))) == NULL)
4761 return ERROR_NOT_ENOUGH_MEMORY;
4765 init_unistr(&info_1->name, "Local Port");
4767 *needed += spoolss_size_printmonitor_info_1(info_1);
4769 if (!alloc_buffer_size(buffer, *needed))
4770 return ERROR_INSUFFICIENT_BUFFER;
4772 smb_io_printmonitor_info_1("", buffer, info_1, 0);
4776 if (*needed > offered) {
4778 return ERROR_INSUFFICIENT_BUFFER;
4781 return NT_STATUS_NO_PROBLEMO;
4784 /****************************************************************************
4785 enumprintmonitors level 2.
4786 ****************************************************************************/
4787 static uint32 enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4789 PRINTMONITOR_2 *info_2=NULL;
4791 if((info_2 = (PRINTMONITOR_2 *)malloc(sizeof(PRINTMONITOR_2))) == NULL)
4792 return ERROR_NOT_ENOUGH_MEMORY;
4796 init_unistr(&info_2->name, "Local Port");
4797 init_unistr(&info_2->environment, "Windows NT X86");
4798 init_unistr(&info_2->dll_name, "localmon.dll");
4800 *needed += spoolss_size_printmonitor_info_2(info_2);
4802 if (!alloc_buffer_size(buffer, *needed))
4803 return ERROR_INSUFFICIENT_BUFFER;
4805 smb_io_printmonitor_info_2("", buffer, info_2, 0);
4809 if (*needed > offered) {
4811 return ERROR_INSUFFICIENT_BUFFER;
4814 return NT_STATUS_NO_PROBLEMO;
4817 /****************************************************************************
4818 ****************************************************************************/
4819 uint32 _spoolss_enumprintmonitors(UNISTR2 *name,uint32 level,
4820 NEW_BUFFER *buffer, uint32 offered,
4821 uint32 *needed, uint32 *returned)
4823 DEBUG(5,("spoolss_enumprintmonitors\n"));
4826 * Enumerate the print monitors ...
4828 * Just reply with "Local Port", to keep NT happy
4829 * and I can use my nice printer checker.
4837 return enumprintmonitors_level_1(buffer, offered, needed, returned);
4840 return enumprintmonitors_level_2(buffer, offered, needed, returned);
4843 return ERROR_INVALID_LEVEL;
4848 /****************************************************************************
4849 ****************************************************************************/
4850 static uint32 getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4854 JOB_INFO_1 *info_1=NULL;
4856 info_1=(JOB_INFO_1 *)malloc(sizeof(JOB_INFO_1));
4858 if (info_1 == NULL) {
4860 return ERROR_NOT_ENOUGH_MEMORY;
4863 for (i=0; i<count && found==False; i++) {
4864 if (queue[i].job==(int)jobid)
4871 /* I shoud reply something else ... I can't find the good one */
4872 return NT_STATUS_NO_PROBLEMO;
4875 fill_job_info_1(info_1, &(queue[i-1]), i, snum);
4879 *needed += spoolss_size_job_info_1(info_1);
4881 if (!alloc_buffer_size(buffer, *needed)) {
4883 return ERROR_INSUFFICIENT_BUFFER;
4886 new_smb_io_job_info_1("", buffer, info_1, 0);
4890 if (*needed > offered)
4891 return ERROR_INSUFFICIENT_BUFFER;
4893 return NT_STATUS_NO_PROBLEMO;
4897 /****************************************************************************
4898 ****************************************************************************/
4899 static uint32 getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
4904 info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
4906 ZERO_STRUCTP(info_2);
4908 if (info_2 == NULL) {
4910 return ERROR_NOT_ENOUGH_MEMORY;
4913 for (i=0; i<count && found==False; i++) {
4914 if (queue[i].job==(int)jobid)
4921 /* I shoud reply something else ... I can't find the good one */
4922 return NT_STATUS_NO_PROBLEMO;
4925 fill_job_info_2(info_2, &(queue[i-1]), i, snum);
4929 *needed += spoolss_size_job_info_2(info_2);
4931 if (!alloc_buffer_size(buffer, *needed)) {
4933 return ERROR_INSUFFICIENT_BUFFER;
4936 new_smb_io_job_info_2("", buffer, info_2, 0);
4938 free_dev_mode(info_2->devmode);
4941 if (*needed > offered)
4942 return ERROR_INSUFFICIENT_BUFFER;
4944 return NT_STATUS_NO_PROBLEMO;
4947 /****************************************************************************
4948 ****************************************************************************/
4949 uint32 _spoolss_getjob( POLICY_HND *handle, uint32 jobid, uint32 level,
4950 NEW_BUFFER *buffer, uint32 offered,
4955 print_queue_struct *queue=NULL;
4956 print_status_struct prt_status;
4958 DEBUG(5,("spoolss_getjob\n"));
4960 memset(&prt_status, 0, sizeof(prt_status));
4964 if (!get_printer_snum(handle, &snum))
4965 return ERROR_INVALID_HANDLE;
4967 count = print_queue_status(snum, &queue, &prt_status);
4969 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
4970 count, prt_status.status, prt_status.message));
4974 return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
4977 return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
4981 return ERROR_INVALID_LEVEL;